Got rid of old multires code, brought in multires modifier from
soc-2008-nicholasbishop branch. Note: any old code with multires_test() or multires_level1_test() can just be deleted, not needed by the multires modifier.
This commit is contained in:
@@ -27,42 +27,58 @@
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
struct CustomData;
|
||||
struct EditMesh;
|
||||
struct Multires;
|
||||
struct MultiresLevel;
|
||||
struct DerivedMesh;
|
||||
struct Mesh;
|
||||
struct MFace;
|
||||
struct MultiresModifierData;
|
||||
struct Object;
|
||||
|
||||
/* Level access */
|
||||
struct MultiresLevel *current_level(struct Multires *mr);
|
||||
struct MultiresLevel *multires_level_n(struct Multires *mr, int n);
|
||||
typedef struct MultiresSubsurf {
|
||||
struct MultiresModifierData *mmd;
|
||||
struct Mesh *me;
|
||||
} MultiresSubsurf;
|
||||
|
||||
/* Level control */
|
||||
void multires_add_level(struct Object *ob, struct Mesh *me, const char subdiv_type);
|
||||
void multires_set_level(struct Object *ob, struct Mesh *me, const int render);
|
||||
void multires_free_level(struct MultiresLevel *lvl);
|
||||
typedef struct IndexNode {
|
||||
struct IndexNode *next, *prev;
|
||||
int index;
|
||||
} IndexNode;
|
||||
|
||||
void multires_edge_level_update(struct Object *ob, struct Mesh *me);
|
||||
void create_vert_face_map(ListBase **map, IndexNode **mem, const struct MFace *mface,
|
||||
const int totvert, const int totface);
|
||||
void create_vert_edge_map(ListBase **map, IndexNode **mem, const struct MEdge *medge,
|
||||
const int totvert, const int totedge);
|
||||
|
||||
void multires_free(struct Multires *mr);
|
||||
struct Multires *multires_copy(struct Multires *orig);
|
||||
void multires_create(struct Object *ob, struct Mesh *me);
|
||||
/* MultiresDM */
|
||||
struct Mesh *MultiresDM_get_mesh(struct DerivedMesh *dm);
|
||||
struct DerivedMesh *MultiresDM_new(struct MultiresSubsurf *, struct DerivedMesh*, int, int, int);
|
||||
void *MultiresDM_get_vertnorm(struct DerivedMesh *);
|
||||
void *MultiresDM_get_orco(struct DerivedMesh *);
|
||||
struct MVert *MultiresDM_get_subco(struct DerivedMesh *);
|
||||
struct ListBase *MultiresDM_get_vert_face_map(struct DerivedMesh *);
|
||||
struct ListBase *MultiresDM_get_vert_edge_map(struct DerivedMesh *);
|
||||
int *MultiresDM_get_face_offsets(struct DerivedMesh *);
|
||||
int MultiresDM_get_totlvl(struct DerivedMesh *);
|
||||
int MultiresDM_get_lvl(struct DerivedMesh *);
|
||||
void MultiresDM_set_update(struct DerivedMesh *, void (*)(struct DerivedMesh*));
|
||||
int *MultiresDM_get_flags(struct DerivedMesh *);
|
||||
|
||||
/* CustomData */
|
||||
void multires_delete_layer(struct Object *ob, struct CustomData *cd, const int type, int n);
|
||||
void multires_add_layer(struct Object *ob, struct CustomData *cd, const int type, const int n);
|
||||
void multires_del_lower_customdata(struct Multires *mr, struct MultiresLevel *cr_lvl);
|
||||
void multires_to_mcol(struct MultiresColFace *f, MCol mcol[4]);
|
||||
/* After adding or removing vcolor layers, run this */
|
||||
void multires_load_cols(struct Mesh *me);
|
||||
#define MULTIRES_DM_UPDATE_BLOCK 1
|
||||
#define MULTIRES_DM_UPDATE_ALWAYS 2
|
||||
|
||||
/* Private (used in multires-firstlevel.c) */
|
||||
void multires_level_to_mesh(struct Object *ob, struct Mesh *me, const int render);
|
||||
void multires_update_levels(struct Mesh *me, const int render);
|
||||
void multires_update_first_level(struct Mesh *me, struct EditMesh *em);
|
||||
void multires_update_customdata(struct MultiresLevel *lvl1, struct EditMesh *em, struct CustomData *src,
|
||||
struct CustomData *dst, const int type);
|
||||
void multires_customdata_to_mesh(struct Mesh *me, struct EditMesh *em,
|
||||
struct MultiresLevel *lvl, struct CustomData *src,
|
||||
struct CustomData *dst, const int type);
|
||||
void multires_force_update(struct Object *ob);
|
||||
|
||||
struct DerivedMesh *multires_dm_create_from_derived(struct MultiresModifierData*, struct DerivedMesh*,
|
||||
struct Mesh *, int, int);
|
||||
|
||||
int multiresModifier_switch_level(struct Object *, const int);
|
||||
void multiresModifier_join(struct Object *);
|
||||
void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction);
|
||||
void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int distance,
|
||||
int updateblock, int simple);
|
||||
void multiresModifier_setLevel(void *mmd_v, void *ob_v);
|
||||
int multiresModifier_reshape(struct MultiresModifierData *mmd, struct Object *dst, struct Object *src);
|
||||
|
||||
/* Related to the old multires */
|
||||
struct Multires;
|
||||
void multires_load_old(struct DerivedMesh *, struct Multires *);
|
||||
void multires_free(struct Multires*);
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#ifndef BKE_SCULPT_H
|
||||
#define BKE_SCULPT_H
|
||||
|
||||
struct MFace;
|
||||
struct MVert;
|
||||
struct NumInput;
|
||||
struct RadialControl;
|
||||
struct Scene;
|
||||
@@ -40,6 +42,13 @@ typedef struct SculptSession {
|
||||
struct ProjVert *projverts;
|
||||
|
||||
struct bglMats *mats;
|
||||
|
||||
int multires;
|
||||
int totvert;
|
||||
int totface;
|
||||
struct MVert *mvert;
|
||||
struct MFace *mface;
|
||||
float *face_normals;
|
||||
|
||||
/* An array of lists; array is sized as
|
||||
large as the number of verts in the mesh,
|
||||
|
||||
@@ -32,6 +32,7 @@ struct Mesh;
|
||||
struct Object;
|
||||
struct DerivedMesh;
|
||||
struct EditMesh;
|
||||
struct MultiresSubsurf;
|
||||
struct SubsurfModifierData;
|
||||
|
||||
struct DerivedMesh *subsurf_make_derived_from_derived(
|
||||
@@ -40,6 +41,13 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
|
||||
int useRenderParams, float (*vertCos)[3],
|
||||
int isFinalCalc, int editMode);
|
||||
|
||||
struct DerivedMesh *subsurf_make_derived_from_derived_with_multires(
|
||||
struct DerivedMesh *dm,
|
||||
struct SubsurfModifierData *smd,
|
||||
struct MultiresSubsurf *ms,
|
||||
int useRenderParams, float (*vertCos)[3],
|
||||
int isFinalCalc, int editMode);
|
||||
|
||||
void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_subsurf.h"
|
||||
#include "BKE_texture.h"
|
||||
@@ -83,8 +82,6 @@
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_glutil.h"
|
||||
|
||||
//XXX #include "multires.h"
|
||||
//
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_material.h"
|
||||
@@ -1448,6 +1445,9 @@ CustomDataMask get_viewedit_datamask()
|
||||
if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT)
|
||||
mask |= CD_MASK_MCOL;
|
||||
|
||||
if(G.f & G_SCULPTMODE)
|
||||
mask |= CD_MASK_MDISPS;
|
||||
|
||||
return mask;
|
||||
#endif
|
||||
return 0;
|
||||
@@ -2210,93 +2210,11 @@ DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask da
|
||||
return ob->derivedDeform;
|
||||
}
|
||||
|
||||
/* Move to multires Pin level, returns a copy of the original vertex coords. */
|
||||
float *multires_render_pin(Object *ob, Mesh *me, int *orig_lvl)
|
||||
{
|
||||
float *vert_copy= NULL;
|
||||
|
||||
if(me->mr && !(me->mr->flag & MULTIRES_NO_RENDER)) {
|
||||
MultiresLevel *lvl= NULL;
|
||||
int i;
|
||||
|
||||
/* Make sure all mesh edits are properly stored in the multires data*/
|
||||
//XXX multires_update_levels(me, 1);
|
||||
|
||||
/* Copy the highest level of multires verts */
|
||||
*orig_lvl= me->mr->current;
|
||||
//XXX lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels));
|
||||
vert_copy= MEM_callocN(sizeof(float)*3*lvl->totvert, "multires vert_copy");
|
||||
for(i=0; i<lvl->totvert; ++i)
|
||||
VecCopyf(&vert_copy[i*3], me->mr->verts[i].co);
|
||||
|
||||
/* Goto the pin level for multires */
|
||||
me->mr->newlvl= me->mr->pinlvl;
|
||||
//XXX multires_set_level(ob, me, 1);
|
||||
}
|
||||
|
||||
return vert_copy;
|
||||
}
|
||||
|
||||
/* Propagate the changes to render level - fails if mesh topology changed */
|
||||
void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_copy,
|
||||
const int orig_lvl, CustomDataMask dataMask)
|
||||
{
|
||||
if(me->mr && !(me->mr->flag & MULTIRES_NO_RENDER)) {
|
||||
if((*dm)->getNumVerts(*dm) == me->totvert &&
|
||||
(*dm)->getNumFaces(*dm) == me->totface) {
|
||||
//XXX MultiresLevel *lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels));
|
||||
DerivedMesh *old= NULL;
|
||||
MVert *vertdup= NULL;
|
||||
int i;
|
||||
|
||||
/* Copy the verts into the mesh */
|
||||
vertdup= (*dm)->dupVertArray(*dm);
|
||||
(*dm)->release(*dm);
|
||||
for(i=0; i<me->totvert; ++i)
|
||||
me->mvert[i]= vertdup[i];
|
||||
/* Free vertdup after use*/
|
||||
MEM_freeN(vertdup);
|
||||
/* Go to the render level */
|
||||
me->mr->newlvl= me->mr->renderlvl;
|
||||
//XXX multires_set_level(ob, me, 1);
|
||||
(*dm)= getMeshDerivedMesh(me, ob, NULL);
|
||||
|
||||
/* Some of the data in dm is referenced externally, so make a copy */
|
||||
old= *dm;
|
||||
(*dm)= CDDM_copy(old);
|
||||
old->release(old);
|
||||
|
||||
if(dataMask & CD_MASK_ORCO)
|
||||
add_orco_dm(ob, NULL, *dm, NULL);
|
||||
|
||||
/* Restore the original verts */
|
||||
me->mr->newlvl= BLI_countlist(&me->mr->levels);
|
||||
//XXX multires_set_level(ob, me, 1);
|
||||
//XXX for(i=0; i<lvl->totvert; ++i)
|
||||
//XXX VecCopyf(me->mvert[i].co, &vert_copy[i*3]);
|
||||
}
|
||||
|
||||
if(vert_copy)
|
||||
MEM_freeN(vert_copy);
|
||||
|
||||
me->mr->newlvl= orig_lvl;
|
||||
//XXX multires_set_level(ob, me, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Multires note - if mesh has multires enabled, mesh is first set to the Pin level,
|
||||
where all modifiers are applied, then if the topology hasn't changed, the changes
|
||||
from modifiers are propagated up to the Render level. */
|
||||
DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask dataMask)
|
||||
{
|
||||
DerivedMesh *final;
|
||||
Mesh *me= get_mesh(ob);
|
||||
float *vert_copy= NULL;
|
||||
int orig_lvl= 0;
|
||||
|
||||
vert_copy= multires_render_pin(ob, me, &orig_lvl);
|
||||
mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1);
|
||||
multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask);
|
||||
|
||||
return final;
|
||||
}
|
||||
@@ -2304,13 +2222,8 @@ DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask
|
||||
DerivedMesh *mesh_create_derived_index_render(Scene *scene, Object *ob, CustomDataMask dataMask, int index)
|
||||
{
|
||||
DerivedMesh *final;
|
||||
Mesh *me= get_mesh(ob);
|
||||
float *vert_copy= NULL;
|
||||
int orig_lvl= 0;
|
||||
|
||||
vert_copy= multires_render_pin(ob, me, &orig_lvl);
|
||||
mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, index);
|
||||
multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask);
|
||||
|
||||
return final;
|
||||
}
|
||||
@@ -2339,13 +2252,8 @@ DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob,
|
||||
CustomDataMask dataMask)
|
||||
{
|
||||
DerivedMesh *final;
|
||||
Mesh *me= get_mesh(ob);
|
||||
float *vert_copy= NULL;
|
||||
int orig_lvl= 0;
|
||||
|
||||
vert_copy= multires_render_pin(ob, me, &orig_lvl);
|
||||
mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1);
|
||||
multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask);
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
@@ -52,6 +53,7 @@
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_fluidsim.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
@@ -64,6 +66,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef struct {
|
||||
DerivedMesh dm;
|
||||
@@ -885,6 +888,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
|
||||
{
|
||||
CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
|
||||
DerivedMesh *dm = &cddm->dm;
|
||||
CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
|
||||
int i, *index, alloctype;
|
||||
|
||||
/* this does a referenced copy, the only new layers being ORIGINDEX,
|
||||
@@ -900,11 +904,11 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
|
||||
|
||||
alloctype= CD_REFERENCE;
|
||||
|
||||
CustomData_merge(&mesh->vdata, &dm->vertData, CD_MASK_MESH, alloctype,
|
||||
CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
|
||||
mesh->totvert);
|
||||
CustomData_merge(&mesh->edata, &dm->edgeData, CD_MASK_MESH, alloctype,
|
||||
CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
|
||||
mesh->totedge);
|
||||
CustomData_merge(&mesh->fdata, &dm->faceData, CD_MASK_MESH, alloctype,
|
||||
CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
|
||||
mesh->totface);
|
||||
|
||||
cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
|
||||
@@ -1282,3 +1286,192 @@ MFace *CDDM_get_faces(DerivedMesh *dm)
|
||||
return ((CDDerivedMesh*)dm)->mface;
|
||||
}
|
||||
|
||||
/* Multires DerivedMesh, extends CDDM */
|
||||
typedef struct MultiresDM {
|
||||
CDDerivedMesh cddm;
|
||||
|
||||
MultiresModifierData *mmd;
|
||||
|
||||
int lvl, totlvl;
|
||||
float (*orco)[3];
|
||||
MVert *subco;
|
||||
|
||||
ListBase *vert_face_map, *vert_edge_map;
|
||||
IndexNode *vert_face_map_mem, *vert_edge_map_mem;
|
||||
int *face_offsets;
|
||||
|
||||
Mesh *me;
|
||||
int flags;
|
||||
|
||||
void (*update)(DerivedMesh*);
|
||||
} MultiresDM;
|
||||
|
||||
static void MultiresDM_release(DerivedMesh *dm)
|
||||
{
|
||||
MultiresDM *mrdm = (MultiresDM*)dm;
|
||||
int mvert_layer;
|
||||
|
||||
/* Before freeing, need to update the displacement map */
|
||||
if(dm->needsFree && !(mrdm->flags & MULTIRES_DM_UPDATE_BLOCK))
|
||||
mrdm->update(dm);
|
||||
|
||||
/* If the MVert data is being used as the sculpt undo store, don't free it */
|
||||
mvert_layer = CustomData_get_layer_index(&dm->vertData, CD_MVERT);
|
||||
if(mvert_layer != -1) {
|
||||
CustomDataLayer *cd = &dm->vertData.layers[mvert_layer];
|
||||
if(cd->data == mrdm->mmd->undo_verts)
|
||||
cd->flag |= CD_FLAG_NOFREE;
|
||||
}
|
||||
|
||||
if(DM_release(dm)) {
|
||||
MEM_freeN(mrdm->subco);
|
||||
MEM_freeN(mrdm->orco);
|
||||
if(mrdm->vert_face_map)
|
||||
MEM_freeN(mrdm->vert_face_map);
|
||||
if(mrdm->vert_face_map_mem)
|
||||
MEM_freeN(mrdm->vert_face_map_mem);
|
||||
if(mrdm->vert_edge_map)
|
||||
MEM_freeN(mrdm->vert_edge_map);
|
||||
if(mrdm->vert_edge_map_mem)
|
||||
MEM_freeN(mrdm->vert_edge_map_mem);
|
||||
if(mrdm->face_offsets)
|
||||
MEM_freeN(mrdm->face_offsets);
|
||||
MEM_freeN(mrdm);
|
||||
}
|
||||
}
|
||||
|
||||
DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig, int numVerts, int numEdges, int numFaces)
|
||||
{
|
||||
MultiresDM *mrdm = MEM_callocN(sizeof(MultiresDM), "MultiresDM");
|
||||
CDDerivedMesh *cddm = cdDM_create("MultiresDM CDDM");
|
||||
DerivedMesh *dm = NULL;
|
||||
|
||||
mrdm->cddm = *cddm;
|
||||
MEM_freeN(cddm);
|
||||
dm = &mrdm->cddm.dm;
|
||||
|
||||
mrdm->mmd = ms->mmd;
|
||||
mrdm->me = ms->me;
|
||||
|
||||
if(dm) {
|
||||
MDisps *disps;
|
||||
MVert *mvert;
|
||||
int i;
|
||||
|
||||
DM_from_template(dm, orig, numVerts, numEdges, numFaces);
|
||||
CustomData_free_layers(&dm->faceData, CD_MDISPS, numFaces);
|
||||
|
||||
disps = CustomData_get_layer(&orig->faceData, CD_MDISPS);
|
||||
if(disps)
|
||||
CustomData_add_layer(&dm->faceData, CD_MDISPS, CD_REFERENCE, disps, numFaces);
|
||||
|
||||
|
||||
mvert = CustomData_get_layer(&orig->vertData, CD_MVERT);
|
||||
mrdm->orco = MEM_callocN(sizeof(float) * 3 * orig->getNumVerts(orig), "multires orco");
|
||||
for(i = 0; i < orig->getNumVerts(orig); ++i)
|
||||
VecCopyf(mrdm->orco[i], mvert[i].co);
|
||||
}
|
||||
else
|
||||
DM_init(dm, numVerts, numEdges, numFaces);
|
||||
|
||||
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
|
||||
CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
|
||||
CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
|
||||
|
||||
mrdm->cddm.mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
|
||||
mrdm->cddm.medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
|
||||
mrdm->cddm.mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
|
||||
|
||||
mrdm->lvl = ms->mmd->lvl;
|
||||
mrdm->totlvl = ms->mmd->totlvl;
|
||||
mrdm->subco = MEM_callocN(sizeof(MVert)*numVerts, "multires subdivided verts");
|
||||
mrdm->flags = 0;
|
||||
|
||||
dm->release = MultiresDM_release;
|
||||
|
||||
return dm;
|
||||
}
|
||||
|
||||
Mesh *MultiresDM_get_mesh(DerivedMesh *dm)
|
||||
{
|
||||
return ((MultiresDM*)dm)->me;
|
||||
}
|
||||
|
||||
void *MultiresDM_get_orco(DerivedMesh *dm)
|
||||
{
|
||||
return ((MultiresDM*)dm)->orco;
|
||||
|
||||
}
|
||||
|
||||
MVert *MultiresDM_get_subco(DerivedMesh *dm)
|
||||
{
|
||||
return ((MultiresDM*)dm)->subco;
|
||||
}
|
||||
|
||||
int MultiresDM_get_totlvl(DerivedMesh *dm)
|
||||
{
|
||||
return ((MultiresDM*)dm)->totlvl;
|
||||
}
|
||||
|
||||
int MultiresDM_get_lvl(DerivedMesh *dm)
|
||||
{
|
||||
return ((MultiresDM*)dm)->lvl;
|
||||
}
|
||||
|
||||
void MultiresDM_set_orco(DerivedMesh *dm, float (*orco)[3])
|
||||
{
|
||||
((MultiresDM*)dm)->orco = orco;
|
||||
}
|
||||
|
||||
void MultiresDM_set_update(DerivedMesh *dm, void (*update)(DerivedMesh*))
|
||||
{
|
||||
((MultiresDM*)dm)->update = update;
|
||||
}
|
||||
|
||||
ListBase *MultiresDM_get_vert_face_map(DerivedMesh *dm)
|
||||
{
|
||||
MultiresDM *mrdm = (MultiresDM*)dm;
|
||||
|
||||
if(!mrdm->vert_face_map)
|
||||
create_vert_face_map(&mrdm->vert_face_map, &mrdm->vert_face_map_mem, mrdm->me->mface,
|
||||
mrdm->me->totvert, mrdm->me->totface);
|
||||
|
||||
return mrdm->vert_face_map;
|
||||
}
|
||||
|
||||
ListBase *MultiresDM_get_vert_edge_map(DerivedMesh *dm)
|
||||
{
|
||||
MultiresDM *mrdm = (MultiresDM*)dm;
|
||||
|
||||
if(!mrdm->vert_edge_map)
|
||||
create_vert_edge_map(&mrdm->vert_edge_map, &mrdm->vert_edge_map_mem, mrdm->me->medge,
|
||||
mrdm->me->totvert, mrdm->me->totedge);
|
||||
|
||||
return mrdm->vert_edge_map;
|
||||
}
|
||||
|
||||
int *MultiresDM_get_face_offsets(DerivedMesh *dm)
|
||||
{
|
||||
MultiresDM *mrdm = (MultiresDM*)dm;
|
||||
int i, accum = 0;
|
||||
|
||||
if(!mrdm->face_offsets) {
|
||||
int len = (int)pow(2, mrdm->lvl - 2) - 1;
|
||||
int area = len * len;
|
||||
int t = 1 + len * 3 + area * 3, q = t + len + area;
|
||||
|
||||
mrdm->face_offsets = MEM_callocN(sizeof(int) * mrdm->me->totface, "mrdm face offsets");
|
||||
for(i = 0; i < mrdm->me->totface; ++i) {
|
||||
mrdm->face_offsets[i] = accum;
|
||||
|
||||
accum += (mrdm->me->mface[i].v4 ? q : t);
|
||||
}
|
||||
}
|
||||
|
||||
return mrdm->face_offsets;
|
||||
}
|
||||
|
||||
int *MultiresDM_get_flags(DerivedMesh *dm)
|
||||
{
|
||||
return &((MultiresDM*)dm)->flags;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_mempool.h"
|
||||
@@ -44,6 +45,7 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
/* number of layers to add when growing a CustomData object */
|
||||
@@ -378,6 +380,156 @@ static void layerDefault_origspace_face(void *data, int count)
|
||||
for(i = 0; i < count; i++)
|
||||
osf[i] = default_osf;
|
||||
}
|
||||
|
||||
/* Adapted from sculptmode.c */
|
||||
static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v)
|
||||
{
|
||||
int x, y, x2, y2;
|
||||
const int st_max = st - 1;
|
||||
float urat, vrat, uopp;
|
||||
float d[4][3], d2[2][3];
|
||||
|
||||
if(u < 0)
|
||||
u = 0;
|
||||
else if(u >= st)
|
||||
u = st_max;
|
||||
if(v < 0)
|
||||
v = 0;
|
||||
else if(v >= st)
|
||||
v = st_max;
|
||||
|
||||
x = floor(u);
|
||||
y = floor(v);
|
||||
x2 = x + 1;
|
||||
y2 = y + 1;
|
||||
|
||||
if(x2 >= st) x2 = st_max;
|
||||
if(y2 >= st) y2 = st_max;
|
||||
|
||||
urat = u - x;
|
||||
vrat = v - y;
|
||||
uopp = 1 - urat;
|
||||
|
||||
VecCopyf(d[0], disps[y * st + x]);
|
||||
VecCopyf(d[1], disps[y * st + x2]);
|
||||
VecCopyf(d[2], disps[y2 * st + x]);
|
||||
VecCopyf(d[3], disps[y2 * st + x2]);
|
||||
VecMulf(d[0], uopp);
|
||||
VecMulf(d[1], urat);
|
||||
VecMulf(d[2], uopp);
|
||||
VecMulf(d[3], urat);
|
||||
|
||||
VecAddf(d2[0], d[0], d[1]);
|
||||
VecAddf(d2[1], d[2], d[3]);
|
||||
VecMulf(d2[0], 1 - vrat);
|
||||
VecMulf(d2[1], vrat);
|
||||
|
||||
VecAddf(out, d2[0], d2[1]);
|
||||
}
|
||||
|
||||
static void layerSwap_mdisps(void *data, int *ci)
|
||||
{
|
||||
MDisps *s = data;
|
||||
float (*d)[3] = NULL;
|
||||
int x, y, st;
|
||||
|
||||
if(!(ci[0] == 2 && ci[1] == 3 && ci[2] == 0 && ci[3] == 1)) return;
|
||||
|
||||
d = MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap");
|
||||
st = sqrt(s->totdisp);
|
||||
|
||||
for(y = 0; y < st; ++y) {
|
||||
for(x = 0; x < st; ++x) {
|
||||
VecCopyf(d[(st - y - 1) * st + (st - x - 1)], s->disps[y * st + x]);
|
||||
}
|
||||
}
|
||||
|
||||
if(s->disps)
|
||||
MEM_freeN(s->disps);
|
||||
s->disps = d;
|
||||
}
|
||||
|
||||
static void layerInterp_mdisps(void **sources, float *weights, float *sub_weights,
|
||||
int count, void *dest)
|
||||
{
|
||||
MDisps *d = dest;
|
||||
MDisps *s = NULL;
|
||||
int st, stl;
|
||||
int i, x, y;
|
||||
float crn[4][2];
|
||||
float (*sw)[4] = NULL;
|
||||
|
||||
/* Initialize the destination */
|
||||
for(i = 0; i < d->totdisp; ++i) {
|
||||
float z[3] = {0,0,0};
|
||||
VecCopyf(d->disps[i], z);
|
||||
}
|
||||
|
||||
/* For now, some restrictions on the input */
|
||||
if(count != 1 || !sub_weights) return;
|
||||
|
||||
st = sqrt(d->totdisp);
|
||||
stl = st - 1;
|
||||
|
||||
sw = (void*)sub_weights;
|
||||
for(i = 0; i < 4; ++i) {
|
||||
crn[i][0] = 0 * sw[i][0] + stl * sw[i][1] + stl * sw[i][2] + 0 * sw[i][3];
|
||||
crn[i][1] = 0 * sw[i][0] + 0 * sw[i][1] + stl * sw[i][2] + stl * sw[i][3];
|
||||
}
|
||||
|
||||
s = sources[0];
|
||||
for(y = 0; y < st; ++y) {
|
||||
for(x = 0; x < st; ++x) {
|
||||
/* One suspects this code could be cleaner. */
|
||||
float xl = (float)x / (st - 1);
|
||||
float yl = (float)y / (st - 1);
|
||||
float mid1[2] = {crn[0][0] * (1 - xl) + crn[1][0] * xl,
|
||||
crn[0][1] * (1 - xl) + crn[1][1] * xl};
|
||||
float mid2[2] = {crn[3][0] * (1 - xl) + crn[2][0] * xl,
|
||||
crn[3][1] * (1 - xl) + crn[2][1] * xl};
|
||||
float mid3[2] = {mid1[0] * (1 - yl) + mid2[0] * yl,
|
||||
mid1[1] * (1 - yl) + mid2[1] * yl};
|
||||
|
||||
float srcdisp[3];
|
||||
|
||||
mdisps_bilinear(srcdisp, s->disps, st, mid3[0], mid3[1]);
|
||||
VecCopyf(d->disps[y * st + x], srcdisp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void layerCopy_mdisps(const void *source, void *dest, int count)
|
||||
{
|
||||
int i;
|
||||
const MDisps *s = source;
|
||||
MDisps *d = dest;
|
||||
|
||||
for(i = 0; i < count; ++i) {
|
||||
if(s[i].disps) {
|
||||
d[i].disps = MEM_dupallocN(s[i].disps);
|
||||
d[i].totdisp = s[i].totdisp;
|
||||
}
|
||||
else {
|
||||
d[i].disps = NULL;
|
||||
d[i].totdisp = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void layerFree_mdisps(void *data, int count, int size)
|
||||
{
|
||||
int i;
|
||||
MDisps *d = data;
|
||||
|
||||
for(i = 0; i < count; ++i) {
|
||||
if(d[i].disps)
|
||||
MEM_freeN(d[i].disps);
|
||||
d[i].disps = NULL;
|
||||
d[i].totdisp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
static void layerDefault_mloopcol(void *data, int count)
|
||||
@@ -553,23 +705,26 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
||||
{sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL},
|
||||
{sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL},
|
||||
{sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol},
|
||||
{sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
{sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||
{sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps,
|
||||
layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL}
|
||||
};
|
||||
|
||||
const char *LAYERTYPENAMES[CD_NUMTYPES] = {
|
||||
"CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace",
|
||||
"CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty",
|
||||
"CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent"};
|
||||
"CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV",
|
||||
"CDMloopCol", "CDTangent", "CDMDisps"};
|
||||
|
||||
const CustomDataMask CD_MASK_BAREMESH =
|
||||
CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE;
|
||||
const CustomDataMask CD_MASK_MESH =
|
||||
CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
|
||||
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL |
|
||||
CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
|
||||
CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS;
|
||||
const CustomDataMask CD_MASK_EDITMESH =
|
||||
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
|
||||
CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
|
||||
CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS;
|
||||
const CustomDataMask CD_MASK_DERIVEDMESH =
|
||||
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
|
||||
CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_subsurf.h"
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_library.h"
|
||||
@@ -137,8 +136,6 @@ void free_mesh(Mesh *me)
|
||||
if(me->bb) MEM_freeN(me->bb);
|
||||
if(me->mselect) MEM_freeN(me->mselect);
|
||||
if(me->edit_mesh) MEM_freeN(me->edit_mesh);
|
||||
|
||||
if(me->mr) multires_free(me->mr);
|
||||
}
|
||||
|
||||
void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
|
||||
@@ -222,9 +219,6 @@ Mesh *copy_mesh(Mesh *me)
|
||||
}
|
||||
}
|
||||
|
||||
if(me->mr)
|
||||
men->mr= multires_copy(me->mr);
|
||||
|
||||
men->mselect= NULL;
|
||||
|
||||
men->bb= MEM_dupallocN(men->bb);
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_fluidsim.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_lattice.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_material.h"
|
||||
@@ -6173,7 +6174,6 @@ static void particleSystemModifier_deformVerts(
|
||||
DerivedMesh *dm = derivedData;
|
||||
ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
|
||||
ParticleSystem * psys=0;
|
||||
Mesh *me;
|
||||
int needsFree=0;
|
||||
|
||||
if(ob->particlesystem.first)
|
||||
@@ -6181,14 +6181,6 @@ static void particleSystemModifier_deformVerts(
|
||||
else
|
||||
return;
|
||||
|
||||
/* multires check */
|
||||
if(ob->type == OB_MESH) {
|
||||
me= (Mesh*)ob->data;
|
||||
if(me->mr && me->mr->current != 1)
|
||||
modifier_setError(md,
|
||||
"Particles only supported on first multires level.");
|
||||
}
|
||||
|
||||
if(!psys_check_enabled(ob, psys))
|
||||
return;
|
||||
|
||||
@@ -7738,6 +7730,58 @@ static void meshdeformModifier_deformVertsEM(
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
/* Multires */
|
||||
static void multiresModifier_initData(ModifierData *md)
|
||||
{
|
||||
MultiresModifierData *mmd = (MultiresModifierData*)md;
|
||||
|
||||
mmd->lvl = mmd->totlvl = 1;
|
||||
}
|
||||
|
||||
static void multiresModifier_freeData(ModifierData *md)
|
||||
{
|
||||
MultiresModifierData *mmd = (MultiresModifierData*)md;
|
||||
|
||||
if(mmd->undo_verts)
|
||||
MEM_freeN(mmd->undo_verts);
|
||||
}
|
||||
|
||||
static void multiresModifier_copyData(ModifierData *md, ModifierData *target)
|
||||
{
|
||||
MultiresModifierData *mmd = (MultiresModifierData*) md;
|
||||
MultiresModifierData *tmmd = (MultiresModifierData*) target;
|
||||
|
||||
tmmd->totlvl = mmd->totlvl;
|
||||
tmmd->lvl = mmd->lvl;
|
||||
}
|
||||
|
||||
static DerivedMesh *multiresModifier_applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm,
|
||||
int useRenderParams, int isFinalCalc)
|
||||
{
|
||||
MultiresModifierData *mmd = (MultiresModifierData*)md;
|
||||
Mesh *me = get_mesh(ob);
|
||||
DerivedMesh *final;
|
||||
|
||||
/* TODO: for now just skip a level1 mesh */
|
||||
if(mmd->lvl == 1)
|
||||
return dm;
|
||||
|
||||
final = multires_dm_create_from_derived(mmd, dm, me, useRenderParams, isFinalCalc);
|
||||
if(mmd->undo_signal && mmd->undo_verts && mmd->undo_verts_tot == final->getNumVerts(final)) {
|
||||
int i;
|
||||
MVert *dst = CDDM_get_verts(final);
|
||||
for(i = 0; i < mmd->undo_verts_tot; ++i) {
|
||||
VecCopyf(dst[i].co, mmd->undo_verts[i].co);
|
||||
}
|
||||
CDDM_calc_normals(final);
|
||||
|
||||
MEM_freeN(mmd->undo_verts);
|
||||
mmd->undo_signal = 0;
|
||||
mmd->undo_verts = NULL;
|
||||
}
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
/* Shrinkwrap */
|
||||
|
||||
@@ -8338,6 +8382,14 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
|
||||
mti->foreachObjectLink = simpledeformModifier_foreachObjectLink;
|
||||
mti->updateDepgraph = simpledeformModifier_updateDepgraph;
|
||||
|
||||
mti = INIT_TYPE(Multires);
|
||||
mti->type = eModifierTypeType_Constructive;
|
||||
mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData;
|
||||
mti->initData = multiresModifier_initData;
|
||||
mti->freeData = multiresModifier_freeData;
|
||||
mti->copyData = multiresModifier_copyData;
|
||||
mti->applyModifier = multiresModifier_applyModifier;
|
||||
|
||||
typeArrInit = 0;
|
||||
#undef INIT_TYPE
|
||||
}
|
||||
|
||||
@@ -1,411 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2006 by Nicholas Bishop
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*
|
||||
* Deals with the first-level data in multires (edge flags, weights, and UVs)
|
||||
*
|
||||
* multires.h
|
||||
*
|
||||
*/
|
||||
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
//XXX #include "BIF_editmesh.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_multires.h"
|
||||
|
||||
#include "BLI_editVert.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl);
|
||||
MTFace *subdivide_mtfaces(MTFace *src, MultiresLevel *lvl);
|
||||
void multires_update_edge_flags(Mesh *me, EditMesh *em);
|
||||
void eed_to_medge_flag(EditEdge *eed, short *flag, char *crease);
|
||||
|
||||
/*********** Generic ***********/
|
||||
|
||||
CustomDataMask cdmask(const int type)
|
||||
{
|
||||
if(type == CD_MDEFORMVERT)
|
||||
return CD_MASK_MDEFORMVERT;
|
||||
else if(type == CD_MTFACE)
|
||||
return CD_MASK_MTFACE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char type_ok(const int type)
|
||||
{
|
||||
return (type == CD_MDEFORMVERT) || (type == CD_MTFACE);
|
||||
}
|
||||
|
||||
/* Copy vdata or fdata from Mesh or EditMesh to Multires. */
|
||||
void multires_update_customdata(MultiresLevel *lvl1, EditMesh *em, CustomData *src, CustomData *dst, const int type)
|
||||
{
|
||||
if(src && dst && type_ok(type)) {
|
||||
const int tot= (type == CD_MDEFORMVERT ? lvl1->totvert : lvl1->totface);
|
||||
int i;
|
||||
|
||||
CustomData_free(dst, tot);
|
||||
|
||||
if(CustomData_has_layer(src, type)) {
|
||||
if(em) {
|
||||
EditVert *eve= em->verts.first;
|
||||
EditFace *efa= em->faces.first;
|
||||
CustomData_copy(src, dst, cdmask(type), CD_CALLOC, tot);
|
||||
for(i=0; i<tot; ++i) {
|
||||
if(type == CD_MDEFORMVERT) {
|
||||
CustomData_from_em_block(&em->vdata, dst, eve->data, i);
|
||||
eve= eve->next;
|
||||
}
|
||||
else if(type == CD_MTFACE) {
|
||||
CustomData_from_em_block(&em->fdata, dst, efa->data, i);
|
||||
efa= efa->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
CustomData_copy(src, dst, cdmask(type), CD_DUPLICATE, tot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Uses subdivide_dverts or subdivide_mtfaces to subdivide src to match lvl_end. Does not free src. */
|
||||
void *subdivide_customdata_to_level(void *src, MultiresLevel *lvl_start,
|
||||
MultiresLevel *lvl_end, const int type)
|
||||
{
|
||||
if(src && lvl_start && lvl_end && type_ok(type)) {
|
||||
MultiresLevel *lvl;
|
||||
void *cr_data= NULL, *pr_data= NULL;
|
||||
|
||||
pr_data= src;
|
||||
for(lvl= lvl_start; lvl && lvl != lvl_end; lvl= lvl->next) {
|
||||
if(type == CD_MDEFORMVERT)
|
||||
cr_data= subdivide_dverts(pr_data, lvl);
|
||||
else if(type == CD_MTFACE)
|
||||
cr_data= subdivide_mtfaces(pr_data, lvl);
|
||||
|
||||
/* Free previous subdivision level's data */
|
||||
if(lvl != lvl_start) {
|
||||
if(type == CD_MDEFORMVERT)
|
||||
free_dverts(pr_data, lvl->totvert);
|
||||
else if(type == CD_MTFACE)
|
||||
MEM_freeN(pr_data);
|
||||
}
|
||||
|
||||
pr_data= cr_data;
|
||||
cr_data= NULL;
|
||||
}
|
||||
|
||||
return pr_data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Directly copy src into dst (handles both Mesh and EditMesh) */
|
||||
void customdata_to_mesh(Mesh *me, EditMesh *em, CustomData *src, CustomData *dst, const int tot, const int type)
|
||||
{
|
||||
if(me && me->mr && src && dst && type_ok(type)) {
|
||||
if(em) {
|
||||
int i;
|
||||
EditVert *eve= em->verts.first;
|
||||
EditFace *efa= em->faces.first;
|
||||
CustomData_copy(src, dst, cdmask(type), CD_CALLOC, 0);
|
||||
|
||||
for(i=0; i<tot; ++i) {
|
||||
if(type == CD_MDEFORMVERT) {
|
||||
CustomData_to_em_block(src, dst, i, &eve->data);
|
||||
eve= eve->next;
|
||||
}
|
||||
else if(type == CD_MTFACE) {
|
||||
CustomData_to_em_block(src, dst, i, &efa->data);
|
||||
efa= efa->next;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CustomData_merge(src, dst, cdmask(type), CD_DUPLICATE, tot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Subdivide vdata or fdata from Multires into either Mesh or EditMesh. */
|
||||
void multires_customdata_to_mesh(Mesh *me, EditMesh *em, MultiresLevel *lvl, CustomData *src,
|
||||
CustomData *dst, const int type)
|
||||
{
|
||||
if(me && me->mr && lvl && src && dst && type_ok(type) &&
|
||||
CustomData_has_layer(src, type)) {
|
||||
const int tot= (type == CD_MDEFORMVERT ? lvl->totvert : lvl->totface);
|
||||
if(lvl == me->mr->levels.first) {
|
||||
customdata_to_mesh(me, em, src, dst, tot, type);
|
||||
}
|
||||
else {
|
||||
CustomData cdf;
|
||||
const int count = CustomData_number_of_layers(src, type);
|
||||
int i;
|
||||
|
||||
/* Construct a new CustomData containing the subdivided data */
|
||||
CustomData_copy(src, &cdf, cdmask(type), CD_ASSIGN, tot);
|
||||
for(i=0; i<count; ++i) {
|
||||
void *layer= CustomData_get_layer_n(&cdf, type, i);
|
||||
CustomData_set_layer_n(&cdf, type, i,
|
||||
subdivide_customdata_to_level(layer, me->mr->levels.first, lvl, type));
|
||||
}
|
||||
|
||||
customdata_to_mesh(me, em, &cdf, dst, tot, type);
|
||||
CustomData_free(&cdf, tot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Subdivide the first-level customdata up to cr_lvl, then delete the original data */
|
||||
void multires_del_lower_customdata(Multires *mr, MultiresLevel *cr_lvl)
|
||||
{
|
||||
MultiresLevel *lvl1= mr->levels.first;
|
||||
MDeformVert *dverts= NULL;
|
||||
CustomData cdf;
|
||||
int i;
|
||||
|
||||
/* dverts */
|
||||
dverts= subdivide_customdata_to_level(CustomData_get(&mr->vdata, 0, CD_MDEFORMVERT),
|
||||
lvl1, cr_lvl, CD_MDEFORMVERT);
|
||||
if(dverts) {
|
||||
CustomData_free_layers(&mr->vdata, CD_MDEFORMVERT, lvl1->totvert);
|
||||
CustomData_add_layer(&mr->vdata, CD_MDEFORMVERT, CD_ASSIGN, dverts, cr_lvl->totvert);
|
||||
}
|
||||
|
||||
/* mtfaces */
|
||||
CustomData_copy(&mr->fdata, &cdf, CD_MASK_MTFACE, CD_ASSIGN, cr_lvl->totface);
|
||||
for(i=0; i<CustomData_number_of_layers(&mr->fdata, CD_MTFACE); ++i) {
|
||||
MTFace *mtfaces=
|
||||
subdivide_customdata_to_level(CustomData_get_layer_n(&mr->fdata, CD_MTFACE, i),
|
||||
lvl1, cr_lvl, CD_MTFACE);
|
||||
if(mtfaces)
|
||||
CustomData_set_layer_n(&cdf, CD_MTFACE, i, mtfaces);
|
||||
}
|
||||
|
||||
CustomData_free(&mr->fdata, lvl1->totface);
|
||||
mr->fdata= cdf;
|
||||
}
|
||||
|
||||
/* Update all special first-level data, if the first-level is active */
|
||||
void multires_update_first_level(Mesh *me, EditMesh *em)
|
||||
{
|
||||
if(me && me->mr && me->mr->current == 1) {
|
||||
multires_update_customdata(me->mr->levels.first, em, em ? &em->vdata : &me->vdata,
|
||||
&me->mr->vdata, CD_MDEFORMVERT);
|
||||
multires_update_customdata(me->mr->levels.first, em, em ? &em->fdata : &me->fdata,
|
||||
&me->mr->fdata, CD_MTFACE);
|
||||
multires_update_edge_flags(me, em);
|
||||
}
|
||||
}
|
||||
|
||||
/*********** Multires.edge_flags ***********/
|
||||
void multires_update_edge_flags(Mesh *me, EditMesh *em)
|
||||
{
|
||||
MultiresLevel *lvl= me->mr->levels.first;
|
||||
EditEdge *eed= NULL;
|
||||
int i;
|
||||
|
||||
if(em) eed= em->edges.first;
|
||||
for(i=0; i<lvl->totedge; ++i) {
|
||||
if(em) {
|
||||
me->mr->edge_flags[i]= 0;
|
||||
eed_to_medge_flag(eed, &me->mr->edge_flags[i], &me->mr->edge_creases[i]);
|
||||
eed= eed->next;
|
||||
}
|
||||
else {
|
||||
me->mr->edge_flags[i]= me->medge[i].flag;
|
||||
me->mr->edge_creases[i]= me->medge[i].crease;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********** Multires.vdata ***********/
|
||||
|
||||
/* MDeformVert */
|
||||
|
||||
/* Add each weight from in to out. Scale each weight by w. */
|
||||
void multires_add_dvert(MDeformVert *out, const MDeformVert *in, const float w)
|
||||
{
|
||||
if(out && in) {
|
||||
int i, j;
|
||||
char found;
|
||||
|
||||
for(i=0; i<in->totweight; ++i) {
|
||||
found= 0;
|
||||
for(j=0; j<out->totweight; ++j) {
|
||||
if(out->dw[j].def_nr==in->dw[i].def_nr) {
|
||||
out->dw[j].weight += in->dw[i].weight * w;
|
||||
found= 1;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
MDeformWeight *newdw= MEM_callocN(sizeof(MDeformWeight)*(out->totweight+1),
|
||||
"multires dvert");
|
||||
if(out->dw) {
|
||||
memcpy(newdw, out->dw, sizeof(MDeformWeight)*out->totweight);
|
||||
MEM_freeN(out->dw);
|
||||
}
|
||||
|
||||
out->dw= newdw;
|
||||
out->dw[out->totweight].weight= in->dw[i].weight * w;
|
||||
out->dw[out->totweight].def_nr= in->dw[i].def_nr;
|
||||
|
||||
++out->totweight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Takes an input array of dverts and subdivides them (linear) using the topology of lvl */
|
||||
MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl)
|
||||
{
|
||||
if(lvl && lvl->next) {
|
||||
MDeformVert *out = MEM_callocN(sizeof(MDeformVert)*lvl->next->totvert, "dvert prop array");
|
||||
int i, j;
|
||||
|
||||
/* Copy lower level */
|
||||
for(i=0; i<lvl->totvert; ++i)
|
||||
multires_add_dvert(&out[i], &src[i], 1);
|
||||
/* Edge verts */
|
||||
for(i=0; i<lvl->totedge; ++i) {
|
||||
for(j=0; j<2; ++j)
|
||||
multires_add_dvert(&out[lvl->totvert+i], &src[lvl->edges[i].v[j]],0.5);
|
||||
}
|
||||
|
||||
/* Face verts */
|
||||
for(i=0; i<lvl->totface; ++i) {
|
||||
for(j=0; j<(lvl->faces[i].v[3]?4:3); ++j)
|
||||
multires_add_dvert(&out[lvl->totvert + lvl->totedge + i],
|
||||
&src[lvl->faces[i].v[j]],
|
||||
lvl->faces[i].v[3]?0.25:(1.0f/3.0f));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********** Multires.fdata ***********/
|
||||
|
||||
/* MTFace */
|
||||
|
||||
void multires_uv_avg2(float out[2], const float a[2], const float b[2])
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<2; ++i)
|
||||
out[i] = (a[i] + b[i]) / 2.0f;
|
||||
}
|
||||
|
||||
/* Takes an input array of mtfaces and subdivides them (linear) using the topology of lvl */
|
||||
MTFace *subdivide_mtfaces(MTFace *src, MultiresLevel *lvl)
|
||||
{
|
||||
if(lvl && lvl->next) {
|
||||
MTFace *out= MEM_callocN(sizeof(MultiresColFace)*lvl->next->totface,"Multirescolfaces");
|
||||
int i, j, curf;
|
||||
|
||||
for(i=0, curf=0; i<lvl->totface; ++i) {
|
||||
const char sides= lvl->faces[i].v[3]?4:3;
|
||||
float cntr[2]= {0, 0};
|
||||
|
||||
/* Find average uv coord of the current face */
|
||||
for(j=0; j<sides; ++j) {
|
||||
cntr[0]+= src[i].uv[j][0];
|
||||
cntr[1]+= src[i].uv[j][1];
|
||||
}
|
||||
cntr[0]/= sides;
|
||||
cntr[1]/= sides;
|
||||
|
||||
for(j=0; j<sides; ++j, ++curf) {
|
||||
out[curf]= src[i];
|
||||
|
||||
multires_uv_avg2(out[curf].uv[0], src[i].uv[j], src[i].uv[j==0?sides-1:j-1]);
|
||||
|
||||
out[curf].uv[1][0]= src[i].uv[j][0];
|
||||
out[curf].uv[1][1]= src[i].uv[j][1];
|
||||
|
||||
multires_uv_avg2(out[curf].uv[2], src[i].uv[j], src[i].uv[j==sides-1?0:j+1]);
|
||||
|
||||
out[curf].uv[3][0]= cntr[0];
|
||||
out[curf].uv[3][1]= cntr[1];
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void multires_delete_layer(Object *ob, CustomData *cd, const int type, int n)
|
||||
{
|
||||
Mesh *me= ob->data;
|
||||
|
||||
if(me && me->mr && cd) {
|
||||
MultiresLevel *lvl1= me->mr->levels.first;
|
||||
|
||||
multires_update_levels(me, 0);
|
||||
|
||||
CustomData_set_layer_active(cd, type, n);
|
||||
CustomData_free_layer_active(cd, type, lvl1->totface);
|
||||
|
||||
multires_level_to_mesh(ob, me, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void multires_add_layer(Object *ob, CustomData *cd, const int type, const int n)
|
||||
{
|
||||
Mesh *me= ob->data;
|
||||
|
||||
if(me && me->mr && cd) {
|
||||
multires_update_levels(me, 0);
|
||||
|
||||
if(CustomData_has_layer(cd, type))
|
||||
CustomData_add_layer(cd, type, CD_DUPLICATE, CustomData_get_layer(cd, type),
|
||||
current_level(me->mr)->totface);
|
||||
else
|
||||
CustomData_add_layer(cd, type, CD_DEFAULT, NULL, current_level(me->mr)->totface);
|
||||
|
||||
CustomData_set_layer_active(cd, type, n);
|
||||
multires_level_to_mesh(ob, me, 0);
|
||||
}
|
||||
}
|
||||
@@ -32,53 +32,1248 @@
|
||||
#include "DNA_key_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_vec_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_editVert.h"
|
||||
|
||||
#include "BKE_cdderivedmesh.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_multires.h"
|
||||
|
||||
//XXX #include "editmesh.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_subsurf.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Returns the active multires level (currently applied to the mesh) */
|
||||
MultiresLevel *current_level(Multires *mr)
|
||||
void create_vert_face_map(ListBase **map, IndexNode **mem, const MFace *mface, const int totvert, const int totface)
|
||||
{
|
||||
return BLI_findlink(&mr->levels, mr->current - 1);
|
||||
}
|
||||
|
||||
/* Returns the nth multires level, starting at 1 */
|
||||
MultiresLevel *multires_level_n(Multires *mr, int n)
|
||||
{
|
||||
if(mr)
|
||||
return BLI_findlink(&mr->levels, n - 1);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Free and clear the temporary connectivity data */
|
||||
static void multires_free_temp_data(MultiresLevel *lvl)
|
||||
{
|
||||
if(lvl) {
|
||||
if(lvl->edge_boundary_states) MEM_freeN(lvl->edge_boundary_states);
|
||||
if(lvl->vert_edge_map) MEM_freeN(lvl->vert_edge_map);
|
||||
if(lvl->vert_face_map) MEM_freeN(lvl->vert_face_map);
|
||||
if(lvl->map_mem) MEM_freeN(lvl->map_mem);
|
||||
|
||||
lvl->edge_boundary_states = NULL;
|
||||
lvl->vert_edge_map = lvl->vert_face_map = NULL;
|
||||
lvl->map_mem = NULL;
|
||||
int i,j;
|
||||
IndexNode *node = NULL;
|
||||
|
||||
(*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert face map");
|
||||
(*mem) = MEM_callocN(sizeof(IndexNode) * totface*4, "vert face map mem");
|
||||
node = *mem;
|
||||
|
||||
/* Find the users */
|
||||
for(i = 0; i < totface; ++i){
|
||||
for(j = 0; j < (mface[i].v4?4:3); ++j, ++node) {
|
||||
node->index = i;
|
||||
BLI_addtail(&(*map)[((unsigned int*)(&mface[i]))[j]], node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create_vert_edge_map(ListBase **map, IndexNode **mem, const MEdge *medge, const int totvert, const int totedge)
|
||||
{
|
||||
int i, j;
|
||||
IndexNode *node = NULL;
|
||||
|
||||
(*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert edge map");
|
||||
(*mem) = MEM_callocN(sizeof(IndexNode) * totedge * 2, "vert edge map mem");
|
||||
node = *mem;
|
||||
|
||||
/* Find the users */
|
||||
for(i = 0; i < totedge; ++i){
|
||||
for(j = 0; j < 2; ++j, ++node) {
|
||||
node->index = i;
|
||||
BLI_addtail(&(*map)[((unsigned int*)(&medge[i].v1))[j]], node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* MULTIRES MODIFIER */
|
||||
static const int multires_max_levels = 13;
|
||||
static const int multires_quad_tot[] = {4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409};
|
||||
static const int multires_side_tot[] = {2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097};
|
||||
|
||||
int multiresModifier_switch_level(Object *ob, const int distance)
|
||||
{
|
||||
ModifierData *md = NULL;
|
||||
MultiresModifierData *mmd = NULL;
|
||||
|
||||
for(md = ob->modifiers.first; md; md = md->next) {
|
||||
if(md->type == eModifierType_Multires)
|
||||
mmd = (MultiresModifierData*)md;
|
||||
}
|
||||
|
||||
if(mmd) {
|
||||
mmd->lvl += distance;
|
||||
if(mmd->lvl < 1) mmd->lvl = 1;
|
||||
else if(mmd->lvl > mmd->totlvl) mmd->lvl = mmd->totlvl;
|
||||
/* XXX: DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
||||
object_handle_update(ob);*/
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX */
|
||||
#if 0
|
||||
void multiresModifier_join(Object *ob)
|
||||
{
|
||||
Base *base = NULL;
|
||||
int highest_lvl = 0;
|
||||
|
||||
/* First find the highest level of subdivision */
|
||||
base = FIRSTBASE;
|
||||
while(base) {
|
||||
if(TESTBASELIB_BGMODE(base) && base->object->type==OB_MESH) {
|
||||
ModifierData *md;
|
||||
for(md = base->object->modifiers.first; md; md = md->next) {
|
||||
if(md->type == eModifierType_Multires) {
|
||||
int totlvl = ((MultiresModifierData*)md)->totlvl;
|
||||
if(totlvl > highest_lvl)
|
||||
highest_lvl = totlvl;
|
||||
|
||||
/* Ensure that all updates are processed */
|
||||
multires_force_update(base->object);
|
||||
}
|
||||
}
|
||||
}
|
||||
base = base->next;
|
||||
}
|
||||
|
||||
/* No multires meshes selected */
|
||||
if(highest_lvl == 0)
|
||||
return;
|
||||
|
||||
/* Subdivide all the displacements to the highest level */
|
||||
base = FIRSTBASE;
|
||||
while(base) {
|
||||
if(TESTBASELIB_BGMODE(base) && base->object->type==OB_MESH) {
|
||||
ModifierData *md = NULL;
|
||||
MultiresModifierData *mmd = NULL;
|
||||
|
||||
for(md = base->object->modifiers.first; md; md = md->next) {
|
||||
if(md->type == eModifierType_Multires)
|
||||
mmd = (MultiresModifierData*)md;
|
||||
}
|
||||
|
||||
/* If the object didn't have multires enabled, give it a new modifier */
|
||||
if(!mmd) {
|
||||
md = base->object->modifiers.first;
|
||||
|
||||
while(md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
|
||||
md = md->next;
|
||||
|
||||
mmd = (MultiresModifierData*)modifier_new(eModifierType_Multires);
|
||||
BLI_insertlinkbefore(&base->object->modifiers, md, mmd);
|
||||
}
|
||||
|
||||
if(mmd)
|
||||
multiresModifier_subdivide(mmd, base->object, highest_lvl - mmd->totlvl, 0, 0);
|
||||
}
|
||||
base = base->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returns 0 on success, 1 if the src's totvert doesn't match */
|
||||
int multiresModifier_reshape(MultiresModifierData *mmd, Object *dst, Object *src)
|
||||
{
|
||||
Mesh *src_me = get_mesh(src);
|
||||
DerivedMesh *mrdm = dst->derivedFinal;
|
||||
|
||||
if(mrdm && mrdm->getNumVerts(mrdm) == src_me->totvert) {
|
||||
MVert *mvert = CDDM_get_verts(mrdm);
|
||||
int i;
|
||||
|
||||
for(i = 0; i < src_me->totvert; ++i)
|
||||
VecCopyf(mvert[i].co, src_me->mvert[i].co);
|
||||
mrdm->needsFree = 1;
|
||||
*MultiresDM_get_flags(mrdm) |= MULTIRES_DM_UPDATE_ALWAYS;
|
||||
mrdm->release(mrdm);
|
||||
dst->derivedFinal = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void Mat3FromColVecs(float mat[][3], float v1[3], float v2[3], float v3[3])
|
||||
{
|
||||
VecCopyf(mat[0], v1);
|
||||
VecCopyf(mat[1], v2);
|
||||
VecCopyf(mat[2], v3);
|
||||
}
|
||||
|
||||
static DerivedMesh *multires_subdisp_pre(DerivedMesh *mrdm, int distance, int simple)
|
||||
{
|
||||
DerivedMesh *final;
|
||||
SubsurfModifierData smd;
|
||||
|
||||
memset(&smd, 0, sizeof(SubsurfModifierData));
|
||||
smd.levels = distance;
|
||||
if(simple)
|
||||
smd.subdivType = ME_SIMPLE_SUBSURF;
|
||||
|
||||
final = subsurf_make_derived_from_derived_with_multires(mrdm, &smd, NULL, 0, NULL, 0, 0);
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
static void VecAddUf(float a[3], float b[3])
|
||||
{
|
||||
a[0] += b[0];
|
||||
a[1] += b[1];
|
||||
a[2] += b[2];
|
||||
}
|
||||
|
||||
static void multires_subdisp(DerivedMesh *orig, Mesh *me, DerivedMesh *final, int lvl, int totlvl,
|
||||
int totsubvert, int totsubedge, int totsubface, int addverts)
|
||||
{
|
||||
DerivedMesh *mrdm;
|
||||
MultiresModifierData mmd_sub;
|
||||
MVert *mvs = CDDM_get_verts(final);
|
||||
MVert *mvd, *mvd_f1, *mvs_f1, *mvd_f3, *mvd_f4;
|
||||
MVert *mvd_f2, *mvs_f2, *mvs_e1, *mvd_e1, *mvs_e2;
|
||||
int totvert;
|
||||
int slo1 = multires_side_tot[lvl - 1];
|
||||
int sll = slo1 / 2;
|
||||
int slo2 = multires_side_tot[totlvl - 2];
|
||||
int shi2 = multires_side_tot[totlvl - 1];
|
||||
int skip = multires_side_tot[totlvl - lvl] - 1;
|
||||
int i, j, k;
|
||||
|
||||
mmd_sub.lvl = mmd_sub.totlvl = totlvl;
|
||||
mrdm = multires_dm_create_from_derived(&mmd_sub, orig, me, 0, 0);
|
||||
|
||||
mvd = CDDM_get_verts(mrdm);
|
||||
/* Need to map from ccg to mrdm */
|
||||
totvert = mrdm->getNumVerts(mrdm);
|
||||
|
||||
if(!addverts) {
|
||||
for(i = 0; i < totvert; ++i) {
|
||||
float z[3] = {0,0,0};
|
||||
VecCopyf(mvd[i].co, z);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load base verts */
|
||||
for(i = 0; i < me->totvert; ++i)
|
||||
VecAddUf(mvd[totvert - me->totvert + i].co, mvs[totvert - me->totvert + i].co);
|
||||
|
||||
mvd_f1 = mvd;
|
||||
mvs_f1 = mvs;
|
||||
mvd_f2 = mvd;
|
||||
mvs_f2 = mvs + totvert - totsubvert;
|
||||
mvs_e1 = mvs + totsubface * (skip-1) * (skip-1);
|
||||
|
||||
for(i = 0; i < me->totface; ++i) {
|
||||
const int end = me->mface[i].v4 ? 4 : 3;
|
||||
int x, y, x2, y2, mov;
|
||||
|
||||
mvd_f1 += 1 + end * (slo2-2); //center+edgecross
|
||||
mvd_f3 = mvd_f4 = mvd_f1;
|
||||
|
||||
for(j = 0; j < end; ++j) {
|
||||
mvd_f1 += (skip/2 - 1) * (slo2 - 2) + (skip/2 - 1);
|
||||
/* Update sub faces */
|
||||
for(y = 0; y < sll; ++y) {
|
||||
for(x = 0; x < sll; ++x) {
|
||||
/* Face center */
|
||||
VecAddUf(mvd_f1->co, mvs_f1->co);
|
||||
mvs_f1 += 1;
|
||||
|
||||
/* Now we hold the center of the subface at mvd_f1
|
||||
and offset it to the edge cross and face verts */
|
||||
|
||||
/* Edge cross */
|
||||
for(k = 0; k < 4; ++k) {
|
||||
if(k == 0) mov = -1;
|
||||
else if(k == 1) mov = slo2 - 2;
|
||||
else if(k == 2) mov = 1;
|
||||
else if(k == 3) mov = -(slo2 - 2);
|
||||
|
||||
for(x2 = 1; x2 < skip/2; ++x2) {
|
||||
VecAddUf((mvd_f1 + mov * x2)->co, mvs_f1->co);
|
||||
++mvs_f1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main face verts */
|
||||
for(k = 0; k < 4; ++k) {
|
||||
int movx, movy;
|
||||
|
||||
if(k == 0) { movx = -1; movy = -(slo2 - 2); }
|
||||
else if(k == 1) { movx = slo2 - 2; movy = -1; }
|
||||
else if(k == 2) { movx = 1; movy = slo2 - 2; }
|
||||
else if(k == 3) { movx = -(slo2 - 2); movy = 1; }
|
||||
|
||||
for(y2 = 1; y2 < skip/2; ++y2) {
|
||||
for(x2 = 1; x2 < skip/2; ++x2) {
|
||||
VecAddUf((mvd_f1 + movy * y2 + movx * x2)->co, mvs_f1->co);
|
||||
++mvs_f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mvd_f1 += skip;
|
||||
}
|
||||
mvd_f1 += (skip - 1) * (slo2 - 2) - 1;
|
||||
}
|
||||
mvd_f1 -= (skip - 1) * (slo2 - 2) - 1 + skip;
|
||||
mvd_f1 += (slo2 - 2) * (skip/2-1) + skip/2-1 + 1;
|
||||
}
|
||||
|
||||
/* update face center verts */
|
||||
VecAddUf(mvd_f2->co, mvs_f2->co);
|
||||
|
||||
mvd_f2 += 1;
|
||||
mvs_f2 += 1;
|
||||
|
||||
/* update face edge verts */
|
||||
for(j = 0; j < end; ++j) {
|
||||
MVert *restore;
|
||||
|
||||
/* Super-face edge cross */
|
||||
for(k = 0; k < skip-1; ++k) {
|
||||
VecAddUf(mvd_f2->co, mvs_e1->co);
|
||||
mvd_f2++;
|
||||
mvs_e1++;
|
||||
}
|
||||
for(x = 1; x < sll; ++x) {
|
||||
VecAddUf(mvd_f2->co, mvs_f2->co);
|
||||
mvd_f2++;
|
||||
mvs_f2++;
|
||||
|
||||
for(k = 0; k < skip-1; ++k) {
|
||||
VecAddUf(mvd_f2->co, mvs_e1->co);
|
||||
mvd_f2++;
|
||||
mvs_e1++;
|
||||
}
|
||||
}
|
||||
|
||||
restore = mvs_e1;
|
||||
for(y = 0; y < sll - 1; ++y) {
|
||||
for(x = 0; x < sll; ++x) {
|
||||
for(k = 0; k < skip - 1; ++k) {
|
||||
VecAddUf(mvd_f3[(skip-1)+(y*skip) + (x*skip+k)*(slo2-2)].co,
|
||||
mvs_e1->co);
|
||||
++mvs_e1;
|
||||
}
|
||||
mvs_e1 += skip-1;
|
||||
}
|
||||
}
|
||||
|
||||
mvs_e1 = restore + skip - 1;
|
||||
for(y = 0; y < sll - 1; ++y) {
|
||||
for(x = 0; x < sll; ++x) {
|
||||
for(k = 0; k < skip - 1; ++k) {
|
||||
VecAddUf(mvd_f3[(slo2-2)*(skip-1)+(x*skip)+k + y*skip*(slo2-2)].co,
|
||||
mvs_e1->co);
|
||||
++mvs_e1;
|
||||
}
|
||||
mvs_e1 += skip - 1;
|
||||
}
|
||||
}
|
||||
|
||||
mvd_f3 += (slo2-2)*(slo2-2);
|
||||
mvs_e1 -= skip - 1;
|
||||
}
|
||||
|
||||
/* update base (2) face verts */
|
||||
for(j = 0; j < end; ++j) {
|
||||
mvd_f2 += (slo2 - 1) * (skip - 1);
|
||||
for(y = 0; y < sll - 1; ++y) {
|
||||
for(x = 0; x < sll - 1; ++x) {
|
||||
VecAddUf(mvd_f2->co, mvs_f2->co);
|
||||
mvd_f2 += skip;
|
||||
++mvs_f2;
|
||||
}
|
||||
mvd_f2 += (slo2 - 1) * (skip - 1);
|
||||
}
|
||||
mvd_f2 -= (skip - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* edges */
|
||||
mvd_e1 = mvd + totvert - me->totvert - me->totedge * (shi2-2);
|
||||
mvs_e2 = mvs + totvert - me->totvert - me->totedge * (slo1-2);
|
||||
for(i = 0; i < me->totedge; ++i) {
|
||||
for(j = 0; j < skip - 1; ++j) {
|
||||
VecAddUf(mvd_e1->co, mvs_e1->co);
|
||||
mvd_e1++;
|
||||
mvs_e1++;
|
||||
}
|
||||
for(j = 0; j < slo1 - 2; j++) {
|
||||
VecAddUf(mvd_e1->co, mvs_e2->co);
|
||||
mvd_e1++;
|
||||
mvs_e2++;
|
||||
|
||||
for(k = 0; k < skip - 1; ++k) {
|
||||
VecAddUf(mvd_e1->co, mvs_e1->co);
|
||||
mvd_e1++;
|
||||
mvs_e1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final->needsFree = 1;
|
||||
final->release(final);
|
||||
mrdm->needsFree = 1;
|
||||
*MultiresDM_get_flags(mrdm) |= MULTIRES_DM_UPDATE_ALWAYS;
|
||||
mrdm->release(mrdm);
|
||||
}
|
||||
|
||||
/* direction=1 for delete higher, direction=0 for lower (not implemented yet) */
|
||||
void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object *ob, int direction)
|
||||
{
|
||||
Mesh *me = get_mesh(ob);
|
||||
int distance = mmd->totlvl - mmd->lvl;
|
||||
MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
|
||||
|
||||
multires_force_update(ob);
|
||||
|
||||
if(mdisps && distance > 0 && direction == 1) {
|
||||
int skip = multires_side_tot[distance] - 1;
|
||||
int st = multires_side_tot[mmd->totlvl - 1];
|
||||
int totdisp = multires_quad_tot[mmd->lvl - 1];
|
||||
int i, j, x, y;
|
||||
|
||||
for(i = 0; i < me->totface; ++i) {
|
||||
float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires del disps");
|
||||
|
||||
for(j = 0, y = 0; y < st; y += skip) {
|
||||
for(x = 0; x < st; x += skip) {
|
||||
VecCopyf(disps[j], mdisps[i].disps[y * st + x]);
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(mdisps[i].disps);
|
||||
mdisps[i].disps = disps;
|
||||
mdisps[i].totdisp = totdisp;
|
||||
}
|
||||
}
|
||||
|
||||
mmd->totlvl = mmd->lvl;
|
||||
}
|
||||
|
||||
void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int distance, int updateblock, int simple)
|
||||
{
|
||||
DerivedMesh *final = NULL;
|
||||
int totsubvert, totsubface, totsubedge;
|
||||
Mesh *me = get_mesh(ob);
|
||||
MDisps *mdisps;
|
||||
int i;
|
||||
|
||||
if(distance == 0)
|
||||
return;
|
||||
|
||||
if(mmd->totlvl > multires_max_levels)
|
||||
mmd->totlvl = multires_max_levels;
|
||||
if(mmd->lvl > multires_max_levels)
|
||||
mmd->lvl = multires_max_levels;
|
||||
|
||||
multires_force_update(ob);
|
||||
|
||||
mmd->lvl = mmd->totlvl;
|
||||
mmd->totlvl += distance;
|
||||
|
||||
mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
|
||||
if(!mdisps)
|
||||
mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface);
|
||||
|
||||
if(mdisps->disps && !updateblock && mmd->totlvl > 2) {
|
||||
DerivedMesh *orig, *mrdm;
|
||||
MultiresModifierData mmd_sub;
|
||||
|
||||
orig = CDDM_from_mesh(me, NULL);
|
||||
mmd_sub.lvl = mmd_sub.totlvl = mmd->lvl;
|
||||
mrdm = multires_dm_create_from_derived(&mmd_sub, orig, me, 0, 0);
|
||||
totsubvert = mrdm->getNumVerts(mrdm);
|
||||
totsubedge = mrdm->getNumEdges(mrdm);
|
||||
totsubface = mrdm->getNumFaces(mrdm);
|
||||
orig->needsFree = 1;
|
||||
orig->release(orig);
|
||||
|
||||
final = multires_subdisp_pre(mrdm, distance, simple);
|
||||
mrdm->needsFree = 1;
|
||||
*MultiresDM_get_flags(mrdm) |= MULTIRES_DM_UPDATE_BLOCK;
|
||||
mrdm->release(mrdm);
|
||||
}
|
||||
|
||||
for(i = 0; i < me->totface; ++i) {
|
||||
const int totdisp = multires_quad_tot[mmd->totlvl - 1];
|
||||
float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps");
|
||||
|
||||
if(mdisps[i].disps)
|
||||
MEM_freeN(mdisps[i].disps);
|
||||
|
||||
mdisps[i].disps = disps;
|
||||
mdisps[i].totdisp = totdisp;
|
||||
}
|
||||
|
||||
|
||||
if(final) {
|
||||
DerivedMesh *orig;
|
||||
|
||||
orig = CDDM_from_mesh(me, NULL);
|
||||
|
||||
multires_subdisp(orig, me, final, mmd->lvl, mmd->totlvl, totsubvert, totsubedge, totsubface, 0);
|
||||
|
||||
orig->needsFree = 1;
|
||||
orig->release(orig);
|
||||
}
|
||||
|
||||
mmd->lvl = mmd->totlvl;
|
||||
}
|
||||
|
||||
typedef struct DisplacerEdges {
|
||||
/* DerivedMesh index at the start of each edge (using face x/y directions to define the start) */
|
||||
int base[4];
|
||||
/* 1 if edge moves in the positive x or y direction, -1 otherwise */
|
||||
int dir[4];
|
||||
} DisplacerEdges;
|
||||
|
||||
typedef struct DisplacerSpill {
|
||||
/* Index of face (in base mesh), -1 for none */
|
||||
int face;
|
||||
|
||||
/* Spill flag */
|
||||
/* 1 = Negative variable axis */
|
||||
/* 2 = Near fixed axis */
|
||||
/* 4 = Flip axes */
|
||||
int f;
|
||||
|
||||
/* Neighboring edges */
|
||||
DisplacerEdges edges;
|
||||
} DisplacerSpill;
|
||||
|
||||
typedef struct MultiresDisplacer {
|
||||
Mesh *me;
|
||||
MDisps *grid;
|
||||
MFace *face;
|
||||
|
||||
int dm_first_base_vert_index;
|
||||
|
||||
int spacing;
|
||||
int sidetot, interior_st, disp_st;
|
||||
int sidendx;
|
||||
int type;
|
||||
int invert;
|
||||
MVert *subco;
|
||||
int subco_index, face_index;
|
||||
float weight;
|
||||
|
||||
/* Valence for each corner */
|
||||
int valence[4];
|
||||
|
||||
/* Neighboring edges for current face */
|
||||
DisplacerEdges edges_primary;
|
||||
|
||||
/* Neighboring faces */
|
||||
DisplacerSpill spill_x, spill_y;
|
||||
|
||||
int *face_offsets;
|
||||
|
||||
int x, y, ax, ay;
|
||||
} MultiresDisplacer;
|
||||
|
||||
static int mface_v(MFace *f, int v)
|
||||
{
|
||||
return v == 0 ? f->v1 : v == 1 ? f->v2 : v == 2 ? f->v3 : v == 3 ? f->v4 : -1;
|
||||
}
|
||||
|
||||
/* Get the edges (and their directions) */
|
||||
static void find_displacer_edges(MultiresDisplacer *d, DerivedMesh *dm, DisplacerEdges *de, MFace *f)
|
||||
{
|
||||
ListBase *emap = MultiresDM_get_vert_edge_map(dm);
|
||||
IndexNode *n;
|
||||
int i, end = f->v4 ? 4 : 3;
|
||||
int offset = dm->getNumVerts(dm) - d->me->totvert - d->me->totedge * d->interior_st;
|
||||
|
||||
for(i = 0; i < end; ++i) {
|
||||
int vcur = mface_v(f, i);
|
||||
int vnext = mface_v(f, i == end - 1 ? 0 : i + 1);
|
||||
|
||||
de->dir[i] = 1;
|
||||
|
||||
for(n = emap[vcur].first; n; n = n->next) {
|
||||
MEdge *e = &d->me->medge[n->index];
|
||||
|
||||
if(e->v1 == vnext || e->v2 == vnext) {
|
||||
de->base[i] = n->index * d->interior_st;
|
||||
if(((i == 0 || i == 1) && e->v1 == vnext) ||
|
||||
((i == 2 || i == 3) && e->v2 == vnext)) {
|
||||
de->dir[i] = -1;
|
||||
de->base[i] += d->interior_st - 1;
|
||||
}
|
||||
de->base[i] += offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns in out the corners [0-3] that use v1 and v2 */
|
||||
void find_face_corners(MFace *f, int v1, int v2, int out[2])
|
||||
{
|
||||
int i, end = f->v4 ? 4 : 3;
|
||||
|
||||
for(i = 0; i < end; ++i) {
|
||||
int corner = mface_v(f, i);
|
||||
if(corner == v1)
|
||||
out[0] = i;
|
||||
if(corner == v2)
|
||||
out[1] = i;
|
||||
}
|
||||
}
|
||||
|
||||
static void multires_displacer_get_spill_faces(MultiresDisplacer *d, DerivedMesh *dm, MFace *mface)
|
||||
{
|
||||
ListBase *map = MultiresDM_get_vert_face_map(dm);
|
||||
IndexNode *n1, *n2;
|
||||
int v4 = d->face->v4 ? d->face->v4 : d->face->v1;
|
||||
int crn[2], lv;
|
||||
|
||||
memset(&d->spill_x, 0, sizeof(DisplacerSpill));
|
||||
memset(&d->spill_y, 0, sizeof(DisplacerSpill));
|
||||
d->spill_x.face = d->spill_y.face = -1;
|
||||
|
||||
for(n1 = map[d->face->v3].first; n1; n1 = n1->next) {
|
||||
if(n1->index == d->face_index)
|
||||
continue;
|
||||
|
||||
for(n2 = map[d->face->v2].first; n2; n2 = n2->next) {
|
||||
if(n1->index == n2->index)
|
||||
d->spill_x.face = n1->index;
|
||||
}
|
||||
for(n2 = map[v4].first; n2; n2 = n2->next) {
|
||||
if(n1->index == n2->index)
|
||||
d->spill_y.face = n1->index;
|
||||
}
|
||||
}
|
||||
|
||||
if(d->spill_x.face != -1) {
|
||||
/* Neighbor of v2/v3 found, find flip and orientation */
|
||||
find_face_corners(&mface[d->spill_x.face], d->face->v2, d->face->v3, crn);
|
||||
lv = mface[d->spill_x.face].v4 ? 3 : 2;
|
||||
|
||||
if(crn[0] == 0 && crn[1] == lv)
|
||||
d->spill_x.f = 0+2+0;
|
||||
else if(crn[0] == lv && crn[1] == 0)
|
||||
d->spill_x.f = 1+2+0;
|
||||
else if(crn[0] == 1 && crn[1] == 0)
|
||||
d->spill_x.f = 1+2+4;
|
||||
else if(crn[0] == 0 && crn[1] == 1)
|
||||
d->spill_x.f = 0+2+4;
|
||||
else if(crn[0] == 2 && crn[1] == 1)
|
||||
d->spill_x.f = 1+0+0;
|
||||
else if(crn[0] == 1 && crn[1] == 2)
|
||||
d->spill_x.f = 0+0+0;
|
||||
else if(crn[0] == 3 && crn[1] == 2)
|
||||
d->spill_x.f = 0+0+4;
|
||||
else if(crn[0] == 2 && crn[1] == 3)
|
||||
d->spill_x.f = 1+0+4;
|
||||
|
||||
find_displacer_edges(d, dm, &d->spill_x.edges, &mface[d->spill_x.face]);
|
||||
}
|
||||
|
||||
if(d->spill_y.face != -1) {
|
||||
/* Neighbor of v3/v4 found, find flip and orientation */
|
||||
find_face_corners(&mface[d->spill_y.face], d->face->v3, v4, crn);
|
||||
lv = mface[d->spill_y.face].v4 ? 3 : 2;
|
||||
|
||||
if(crn[0] == 1 && crn[1] == 0)
|
||||
d->spill_y.f = 1+2+0;
|
||||
else if(crn[0] == 0 && crn[1] == 1)
|
||||
d->spill_y.f = 0+2+0;
|
||||
else if(crn[0] == 2 && crn[1] == 1)
|
||||
d->spill_y.f = 1+0+4;
|
||||
else if(crn[0] == 1 && crn[1] == 2)
|
||||
d->spill_y.f = 0+0+4;
|
||||
else if(crn[0] == 3 && crn[1] == 2)
|
||||
d->spill_y.f = 0+0+0;
|
||||
else if(crn[0] == 2 && crn[1] == 3)
|
||||
d->spill_y.f = 1+0+0;
|
||||
else if(crn[0] == 0 && crn[1] == lv)
|
||||
d->spill_y.f = 0+2+4;
|
||||
else if(crn[0] == lv && crn[1] == 0)
|
||||
d->spill_y.f = 1+2+4;
|
||||
|
||||
find_displacer_edges(d, dm, &d->spill_y.edges, &mface[d->spill_y.face]);
|
||||
}
|
||||
}
|
||||
|
||||
static void find_corner_valences(MultiresDisplacer *d, DerivedMesh *dm)
|
||||
{
|
||||
int i;
|
||||
|
||||
d->valence[3] = -1;
|
||||
|
||||
/* Set the vertex valence for the corners */
|
||||
for(i = 0; i < (d->face->v4 ? 4 : 3); ++i)
|
||||
d->valence[i] = BLI_countlist(&MultiresDM_get_vert_edge_map(dm)[mface_v(d->face, i)]);
|
||||
}
|
||||
|
||||
static void multires_displacer_init(MultiresDisplacer *d, DerivedMesh *dm,
|
||||
const int face_index, const int invert)
|
||||
{
|
||||
Mesh *me = MultiresDM_get_mesh(dm);
|
||||
|
||||
d->me = me;
|
||||
d->face = me->mface + face_index;
|
||||
d->face_index = face_index;
|
||||
d->face_offsets = MultiresDM_get_face_offsets(dm);
|
||||
/* Get the multires grid from customdata */
|
||||
d->grid = CustomData_get_layer(&me->fdata, CD_MDISPS);
|
||||
if(d->grid)
|
||||
d->grid += face_index;
|
||||
|
||||
d->spacing = pow(2, MultiresDM_get_totlvl(dm) - MultiresDM_get_lvl(dm));
|
||||
d->sidetot = multires_side_tot[MultiresDM_get_lvl(dm) - 1];
|
||||
d->interior_st = d->sidetot - 2;
|
||||
d->disp_st = multires_side_tot[MultiresDM_get_totlvl(dm) - 1];
|
||||
d->invert = invert;
|
||||
|
||||
multires_displacer_get_spill_faces(d, dm, me->mface);
|
||||
find_displacer_edges(d, dm, &d->edges_primary, d->face);
|
||||
find_corner_valences(d, dm);
|
||||
|
||||
d->dm_first_base_vert_index = dm->getNumVerts(dm) - me->totvert;
|
||||
}
|
||||
|
||||
static void multires_displacer_weight(MultiresDisplacer *d, const float w)
|
||||
{
|
||||
d->weight = w;
|
||||
}
|
||||
|
||||
static void multires_displacer_anchor(MultiresDisplacer *d, const int type, const int side_index)
|
||||
{
|
||||
d->sidendx = side_index;
|
||||
d->x = d->y = d->sidetot / 2;
|
||||
d->type = type;
|
||||
|
||||
if(type == 2) {
|
||||
if(side_index == 0)
|
||||
d->y -= 1;
|
||||
else if(side_index == 1)
|
||||
d->x += 1;
|
||||
else if(side_index == 2)
|
||||
d->y += 1;
|
||||
else if(side_index == 3)
|
||||
d->x -= 1;
|
||||
}
|
||||
else if(type == 3) {
|
||||
if(side_index == 0) {
|
||||
d->x -= 1;
|
||||
d->y -= 1;
|
||||
}
|
||||
else if(side_index == 1) {
|
||||
d->x += 1;
|
||||
d->y -= 1;
|
||||
}
|
||||
else if(side_index == 2) {
|
||||
d->x += 1;
|
||||
d->y += 1;
|
||||
}
|
||||
else if(side_index == 3) {
|
||||
d->x -= 1;
|
||||
d->y += 1;
|
||||
}
|
||||
}
|
||||
|
||||
d->ax = d->x;
|
||||
d->ay = d->y;
|
||||
}
|
||||
|
||||
static void multires_displacer_anchor_edge(MultiresDisplacer *d, int v1, int v2, int x)
|
||||
{
|
||||
d->type = 4;
|
||||
|
||||
if(v1 == d->face->v1) {
|
||||
d->x = 0;
|
||||
d->y = 0;
|
||||
if(v2 == d->face->v2)
|
||||
d->x += x;
|
||||
else if(v2 == d->face->v3) {
|
||||
if(x < d->sidetot / 2)
|
||||
d->y = x;
|
||||
else {
|
||||
d->x = x;
|
||||
d->y = d->sidetot - 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
d->y += x;
|
||||
}
|
||||
else if(v1 == d->face->v2) {
|
||||
d->x = d->sidetot - 1;
|
||||
d->y = 0;
|
||||
if(v2 == d->face->v1)
|
||||
d->x -= x;
|
||||
else
|
||||
d->y += x;
|
||||
}
|
||||
else if(v1 == d->face->v3) {
|
||||
d->x = d->sidetot - 1;
|
||||
d->y = d->sidetot - 1;
|
||||
if(v2 == d->face->v2)
|
||||
d->y -= x;
|
||||
else if(v2 == d->face->v1) {
|
||||
if(x < d->sidetot / 2)
|
||||
d->x -= x;
|
||||
else {
|
||||
d->x = 0;
|
||||
d->y -= x;
|
||||
}
|
||||
}
|
||||
else
|
||||
d->x -= x;
|
||||
}
|
||||
else if(v1 == d->face->v4) {
|
||||
d->x = 0;
|
||||
d->y = d->sidetot - 1;
|
||||
if(v2 == d->face->v3)
|
||||
d->x += x;
|
||||
else
|
||||
d->y -= x;
|
||||
}
|
||||
}
|
||||
|
||||
static void multires_displacer_anchor_vert(MultiresDisplacer *d, const int v)
|
||||
{
|
||||
const int e = d->sidetot - 1;
|
||||
|
||||
d->type = 5;
|
||||
|
||||
d->x = d->y = 0;
|
||||
if(v == d->face->v2)
|
||||
d->x = e;
|
||||
else if(v == d->face->v3)
|
||||
d->x = d->y = e;
|
||||
else if(v == d->face->v4)
|
||||
d->y = e;
|
||||
}
|
||||
|
||||
static void multires_displacer_jump(MultiresDisplacer *d)
|
||||
{
|
||||
if(d->sidendx == 0) {
|
||||
d->x -= 1;
|
||||
d->y = d->ay;
|
||||
}
|
||||
else if(d->sidendx == 1) {
|
||||
d->x = d->ax;
|
||||
d->y -= 1;
|
||||
}
|
||||
else if(d->sidendx == 2) {
|
||||
d->x += 1;
|
||||
d->y = d->ay;
|
||||
}
|
||||
else if(d->sidendx == 3) {
|
||||
d->x = d->ax;
|
||||
d->y += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Treating v1 as (0,0) and v3 as (st-1,st-1),
|
||||
returns the index of the vertex at (x,y).
|
||||
If x or y is >= st, wraps over to the adjacent face,
|
||||
or if there is no adjacent face, returns -2. */
|
||||
static int multires_index_at_loc(int face_index, int x, int y, MultiresDisplacer *d, DisplacerEdges *de)
|
||||
{
|
||||
int coord_edge = d->sidetot - 1; /* Max value of x/y at edge of grid */
|
||||
int mid = d->sidetot / 2;
|
||||
int lim = mid - 1;
|
||||
int qtot = lim * lim;
|
||||
int base = d->face_offsets[face_index];
|
||||
|
||||
/* Edge spillover */
|
||||
if(x == d->sidetot || y == d->sidetot) {
|
||||
int flags, v_axis, f_axis, lx, ly;
|
||||
|
||||
if(x == d->sidetot && d->spill_x.face != -1) {
|
||||
flags = d->spill_x.f;
|
||||
|
||||
/* Handle triangle seam between v1 and v3 */
|
||||
if(!d->me->mface[d->spill_x.face].v4 &&
|
||||
((flags == 2 && y >= mid) || (flags == 3 && y < mid)))
|
||||
flags += 2;
|
||||
|
||||
v_axis = (flags & 1) ? d->sidetot - 1 - y : y;
|
||||
f_axis = (flags & 2) ? 1 : d->sidetot - 2;
|
||||
lx = f_axis, ly = v_axis;
|
||||
|
||||
if(flags & 4) {
|
||||
lx = v_axis;
|
||||
ly = f_axis;
|
||||
}
|
||||
|
||||
return multires_index_at_loc(d->spill_x.face, lx, ly, d, &d->spill_x.edges);
|
||||
}
|
||||
else if(y == d->sidetot && d->spill_y.face != -1) {
|
||||
flags = d->spill_y.f;
|
||||
|
||||
/* Handle triangle seam between v1 and v3 */
|
||||
if(!d->me->mface[d->spill_y.face].v4 &&
|
||||
((flags == 6 && x >= mid) || (flags == 7 && x < mid)))
|
||||
flags = ~flags;
|
||||
|
||||
v_axis = (flags & 1) ? x : d->sidetot - 1 - x;
|
||||
f_axis = (flags & 2) ? 1 : d->sidetot - 2;
|
||||
lx = v_axis, ly = f_axis;
|
||||
|
||||
if(flags & 4) {
|
||||
lx = f_axis;
|
||||
ly = v_axis;
|
||||
}
|
||||
|
||||
return multires_index_at_loc(d->spill_y.face, lx, ly, d, &d->spill_y.edges);
|
||||
}
|
||||
else
|
||||
return -2;
|
||||
}
|
||||
/* Corners */
|
||||
else if(x == 0 && y == 0)
|
||||
return d->dm_first_base_vert_index + d->face->v1;
|
||||
else if(x == coord_edge && y == 0)
|
||||
return d->dm_first_base_vert_index + d->face->v2;
|
||||
else if(x == coord_edge && y == coord_edge)
|
||||
return d->dm_first_base_vert_index + d->face->v3;
|
||||
else if(x == 0 && y == coord_edge)
|
||||
return d->dm_first_base_vert_index + d->face->v4;
|
||||
/* Edges */
|
||||
else if(x == 0) {
|
||||
if(d->face->v4)
|
||||
return de->base[3] + de->dir[3] * (y - 1);
|
||||
else
|
||||
return de->base[2] + de->dir[2] * (y - 1);
|
||||
}
|
||||
else if(y == 0)
|
||||
return de->base[0] + de->dir[0] * (x - 1);
|
||||
else if(x == d->sidetot - 1)
|
||||
return de->base[1] + de->dir[1] * (y - 1);
|
||||
else if(y == d->sidetot - 1)
|
||||
return de->base[2] + de->dir[2] * (x - 1);
|
||||
/* Face center */
|
||||
else if(x == mid && y == mid)
|
||||
return base;
|
||||
/* Cross */
|
||||
else if(x == mid && y < mid)
|
||||
return base + (mid - y);
|
||||
else if(y == mid && x > mid)
|
||||
return base + lim + (x - mid);
|
||||
else if(x == mid && y > mid)
|
||||
return base + lim*2 + (y - mid);
|
||||
else if(y == mid && x < mid) {
|
||||
if(d->face->v4)
|
||||
return base + lim*3 + (mid - x);
|
||||
else
|
||||
return base + lim*2 + (mid - x);
|
||||
}
|
||||
/* Quarters */
|
||||
else {
|
||||
int offset = base + lim * (d->face->v4 ? 4 : 3);
|
||||
if(x < mid && y < mid)
|
||||
return offset + ((mid - x - 1)*lim + (mid - y));
|
||||
else if(x > mid && y < mid)
|
||||
return offset + qtot + ((mid - y - 1)*lim + (x - mid));
|
||||
else if(x > mid && y > mid)
|
||||
return offset + qtot*2 + ((x - mid - 1)*lim + (y - mid));
|
||||
else if(x < mid && y > mid)
|
||||
return offset + qtot*3 + ((y - mid - 1)*lim + (mid - x));
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Calculate the TS matrix used for applying displacements.
|
||||
Uses the undisplaced subdivided mesh's curvature to find a
|
||||
smoothly normal and tangents. */
|
||||
static void calc_disp_mat(MultiresDisplacer *d, float mat[3][3])
|
||||
{
|
||||
int u = multires_index_at_loc(d->face_index, d->x + 1, d->y, d, &d->edges_primary);
|
||||
int v = multires_index_at_loc(d->face_index, d->x, d->y + 1, d, &d->edges_primary);
|
||||
float norm[3], t1[3], t2[3], inv[3][3];
|
||||
MVert *base = d->subco + d->subco_index;
|
||||
|
||||
//printf("f=%d, x=%d, y=%d, i=%d, u=%d, v=%d ", d->face_index, d->x, d->y, d->subco_index, u, v);
|
||||
|
||||
norm[0] = base->no[0] / 32767.0f;
|
||||
norm[1] = base->no[1] / 32767.0f;
|
||||
norm[2] = base->no[2] / 32767.0f;
|
||||
|
||||
/* Special handling for vertices of valence 3 */
|
||||
if(d->valence[1] == 3 && d->x == d->sidetot - 1 && d->y == 0)
|
||||
u = -1;
|
||||
else if(d->valence[2] == 3 && d->x == d->sidetot - 1 && d->y == d->sidetot - 1)
|
||||
u = v = -1;
|
||||
else if(d->valence[3] == 3 && d->x == 0 && d->y == d->sidetot - 1)
|
||||
v = -1;
|
||||
|
||||
/* If either u or v is -2, it's on a boundary. In this
|
||||
case, back up by one row/column and use the same
|
||||
vector as the preceeding sub-edge. */
|
||||
|
||||
if(u < 0) {
|
||||
u = multires_index_at_loc(d->face_index, d->x - 1, d->y, d, &d->edges_primary);
|
||||
VecSubf(t1, base->co, d->subco[u].co);
|
||||
}
|
||||
else
|
||||
VecSubf(t1, d->subco[u].co, base->co);
|
||||
|
||||
if(v < 0) {
|
||||
v = multires_index_at_loc(d->face_index, d->x, d->y - 1, d, &d->edges_primary);
|
||||
VecSubf(t2, base->co, d->subco[v].co);
|
||||
}
|
||||
else
|
||||
VecSubf(t2, d->subco[v].co, base->co);
|
||||
|
||||
//printf("uu=%d, vv=%d\n", u, v);
|
||||
|
||||
Normalize(t1);
|
||||
Normalize(t2);
|
||||
Mat3FromColVecs(mat, t1, t2, norm);
|
||||
|
||||
if(d->invert) {
|
||||
Mat3Inv(inv, mat);
|
||||
Mat3CpyMat3(mat, inv);
|
||||
}
|
||||
}
|
||||
|
||||
static void multires_displace(MultiresDisplacer *d, float co[3])
|
||||
{
|
||||
float disp[3], mat[3][3];
|
||||
float *data;
|
||||
MVert *subco = &d->subco[d->subco_index];
|
||||
|
||||
if(!d->grid || !d->grid->disps) return;
|
||||
|
||||
data = d->grid->disps[(d->y * d->spacing) * d->disp_st + (d->x * d->spacing)];
|
||||
|
||||
if(d->invert)
|
||||
VecSubf(disp, co, subco->co);
|
||||
else
|
||||
VecCopyf(disp, data);
|
||||
|
||||
|
||||
/* Apply ts matrix to displacement */
|
||||
calc_disp_mat(d, mat);
|
||||
Mat3MulVecfl(mat, disp);
|
||||
|
||||
if(d->invert) {
|
||||
VecCopyf(data, disp);
|
||||
|
||||
}
|
||||
else {
|
||||
if(d->type == 4 || d->type == 5)
|
||||
VecMulf(disp, d->weight);
|
||||
VecAddf(co, co, disp);
|
||||
}
|
||||
|
||||
if(d->type == 2) {
|
||||
if(d->sidendx == 0)
|
||||
d->y -= 1;
|
||||
else if(d->sidendx == 1)
|
||||
d->x += 1;
|
||||
else if(d->sidendx == 2)
|
||||
d->y += 1;
|
||||
else if(d->sidendx == 3)
|
||||
d->x -= 1;
|
||||
}
|
||||
else if(d->type == 3) {
|
||||
if(d->sidendx == 0)
|
||||
d->y -= 1;
|
||||
else if(d->sidendx == 1)
|
||||
d->x += 1;
|
||||
else if(d->sidendx == 2)
|
||||
d->y += 1;
|
||||
else if(d->sidendx == 3)
|
||||
d->x -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void multiresModifier_disp_run(DerivedMesh *dm, MVert *subco, int invert)
|
||||
{
|
||||
const int lvl = MultiresDM_get_lvl(dm);
|
||||
const int gridFaces = multires_side_tot[lvl - 2] - 1;
|
||||
const int edgeSize = multires_side_tot[lvl - 1] - 1;
|
||||
MVert *mvert = CDDM_get_verts(dm);
|
||||
MEdge *medge = MultiresDM_get_mesh(dm)->medge;
|
||||
MFace *mface = MultiresDM_get_mesh(dm)->mface;
|
||||
ListBase *map = MultiresDM_get_vert_face_map(dm);
|
||||
Mesh *me = MultiresDM_get_mesh(dm);
|
||||
MultiresDisplacer d;
|
||||
int i, S, x, y;
|
||||
|
||||
d.subco = subco;
|
||||
d.subco_index = 0;
|
||||
|
||||
for(i = 0; i < me->totface; ++i) {
|
||||
const int numVerts = mface[i].v4 ? 4 : 3;
|
||||
|
||||
/* Center */
|
||||
multires_displacer_init(&d, dm, i, invert);
|
||||
multires_displacer_anchor(&d, 1, 0);
|
||||
multires_displace(&d, mvert->co);
|
||||
++mvert;
|
||||
++d.subco_index;
|
||||
|
||||
/* Cross */
|
||||
for(S = 0; S < numVerts; ++S) {
|
||||
multires_displacer_anchor(&d, 2, S);
|
||||
for(x = 1; x < gridFaces; ++x) {
|
||||
multires_displace(&d, mvert->co);
|
||||
++mvert;
|
||||
++d.subco_index;
|
||||
}
|
||||
}
|
||||
|
||||
/* Quarters */
|
||||
for(S = 0; S < numVerts; S++) {
|
||||
multires_displacer_anchor(&d, 3, S);
|
||||
for(y = 1; y < gridFaces; y++) {
|
||||
for(x = 1; x < gridFaces; x++) {
|
||||
multires_displace(&d, mvert->co);
|
||||
++mvert;
|
||||
++d.subco_index;
|
||||
}
|
||||
multires_displacer_jump(&d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < me->totedge; ++i) {
|
||||
const MEdge *e = &medge[i];
|
||||
for(x = 1; x < edgeSize; ++x) {
|
||||
IndexNode *n1, *n2;
|
||||
int numFaces = 0;
|
||||
for(n1 = map[e->v1].first; n1; n1 = n1->next) {
|
||||
for(n2 = map[e->v2].first; n2; n2 = n2->next) {
|
||||
if(n1->index == n2->index)
|
||||
++numFaces;
|
||||
}
|
||||
}
|
||||
multires_displacer_weight(&d, 1.0f / numFaces);
|
||||
/* TODO: Better to have these loops outside the x loop */
|
||||
for(n1 = map[e->v1].first; n1; n1 = n1->next) {
|
||||
for(n2 = map[e->v2].first; n2; n2 = n2->next) {
|
||||
if(n1->index == n2->index) {
|
||||
multires_displacer_init(&d, dm, n1->index, invert);
|
||||
multires_displacer_anchor_edge(&d, e->v1, e->v2, x);
|
||||
multires_displace(&d, mvert->co);
|
||||
}
|
||||
}
|
||||
}
|
||||
++mvert;
|
||||
++d.subco_index;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < me->totvert; ++i) {
|
||||
IndexNode *n;
|
||||
multires_displacer_weight(&d, 1.0f / BLI_countlist(&map[i]));
|
||||
for(n = map[i].first; n; n = n->next) {
|
||||
multires_displacer_init(&d, dm, n->index, invert);
|
||||
multires_displacer_anchor_vert(&d, i);
|
||||
multires_displace(&d, mvert->co);
|
||||
}
|
||||
++mvert;
|
||||
++d.subco_index;
|
||||
}
|
||||
|
||||
if(!invert)
|
||||
CDDM_calc_normals(dm);
|
||||
}
|
||||
|
||||
static void multiresModifier_update(DerivedMesh *dm)
|
||||
{
|
||||
Mesh *me;
|
||||
MDisps *mdisps;
|
||||
|
||||
if(!(G.f & G_SCULPTMODE) && !(*MultiresDM_get_flags(dm) & MULTIRES_DM_UPDATE_ALWAYS)) return;
|
||||
|
||||
me = MultiresDM_get_mesh(dm);
|
||||
mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
|
||||
|
||||
if(mdisps) {
|
||||
const int lvl = MultiresDM_get_lvl(dm);
|
||||
const int totlvl = MultiresDM_get_totlvl(dm);
|
||||
|
||||
if(lvl < totlvl) {
|
||||
/* Propagate disps upwards */
|
||||
DerivedMesh *final, *subco_dm, *orig;
|
||||
MVert *verts_new = NULL, *cur_lvl_orig_verts = NULL;
|
||||
MultiresModifierData mmd;
|
||||
int i;
|
||||
|
||||
orig = CDDM_from_mesh(me, NULL);
|
||||
|
||||
/* Regenerate the current level's vertex coordinates
|
||||
(includes older displacements but not new sculpts) */
|
||||
mmd.totlvl = totlvl;
|
||||
mmd.lvl = lvl;
|
||||
subco_dm = multires_dm_create_from_derived(&mmd, orig, me, 0, 0);
|
||||
*MultiresDM_get_flags(subco_dm) |= MULTIRES_DM_UPDATE_BLOCK;
|
||||
cur_lvl_orig_verts = CDDM_get_verts(subco_dm);
|
||||
|
||||
/* Subtract the original vertex cos from the new vertex cos */
|
||||
verts_new = CDDM_get_verts(dm);
|
||||
for(i = 0; i < dm->getNumVerts(dm); ++i)
|
||||
VecSubf(verts_new[i].co, verts_new[i].co, cur_lvl_orig_verts[i].co);
|
||||
|
||||
final = multires_subdisp_pre(dm, totlvl - lvl, 0);
|
||||
|
||||
multires_subdisp(orig, me, final, lvl, totlvl, dm->getNumVerts(dm), dm->getNumEdges(dm),
|
||||
dm->getNumFaces(dm), 1);
|
||||
|
||||
subco_dm->release(subco_dm);
|
||||
orig->release(orig);
|
||||
}
|
||||
else
|
||||
multiresModifier_disp_run(dm, MultiresDM_get_subco(dm), 1);
|
||||
}
|
||||
}
|
||||
|
||||
void multires_force_update(Object *ob)
|
||||
{
|
||||
if(ob->derivedFinal) {
|
||||
ob->derivedFinal->needsFree =1;
|
||||
ob->derivedFinal->release(ob->derivedFinal);
|
||||
ob->derivedFinal = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, DerivedMesh *dm, Mesh *me,
|
||||
int useRenderParams, int isFinalCalc)
|
||||
{
|
||||
SubsurfModifierData smd;
|
||||
MultiresSubsurf ms;
|
||||
DerivedMesh *result;
|
||||
int i;
|
||||
|
||||
ms.mmd = mmd;
|
||||
ms.me = me;
|
||||
|
||||
memset(&smd, 0, sizeof(SubsurfModifierData));
|
||||
smd.levels = smd.renderLevels = mmd->lvl - 1;
|
||||
smd.flags |= eSubsurfModifierFlag_SubsurfUv;
|
||||
|
||||
result = subsurf_make_derived_from_derived_with_multires(dm, &smd, &ms, useRenderParams, NULL, isFinalCalc, 0);
|
||||
for(i = 0; i < result->getNumVerts(result); ++i)
|
||||
MultiresDM_get_subco(result)[i] = CDDM_get_verts(result)[i];
|
||||
multiresModifier_disp_run(result, MultiresDM_get_subco(result), 0);
|
||||
MultiresDM_set_update(result, multiresModifier_update);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**** Old Multires code ****
|
||||
***************************/
|
||||
|
||||
/* Does not actually free lvl itself */
|
||||
void multires_free_level(MultiresLevel *lvl)
|
||||
{
|
||||
@@ -86,8 +1281,6 @@ void multires_free_level(MultiresLevel *lvl)
|
||||
if(lvl->faces) MEM_freeN(lvl->faces);
|
||||
if(lvl->edges) MEM_freeN(lvl->edges);
|
||||
if(lvl->colfaces) MEM_freeN(lvl->colfaces);
|
||||
|
||||
multires_free_temp_data(lvl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,1191 +1310,289 @@ void multires_free(Multires *mr)
|
||||
}
|
||||
}
|
||||
|
||||
static MultiresLevel *multires_level_copy(MultiresLevel *orig)
|
||||
static void create_old_vert_face_map(ListBase **map, IndexNode **mem, const MultiresFace *mface,
|
||||
const int totvert, const int totface)
|
||||
{
|
||||
if(orig) {
|
||||
MultiresLevel *lvl= MEM_dupallocN(orig);
|
||||
|
||||
lvl->next= lvl->prev= NULL;
|
||||
lvl->faces= MEM_dupallocN(orig->faces);
|
||||
lvl->colfaces= MEM_dupallocN(orig->colfaces);
|
||||
lvl->edges= MEM_dupallocN(orig->edges);
|
||||
lvl->edge_boundary_states = NULL;
|
||||
lvl->vert_edge_map= lvl->vert_face_map= NULL;
|
||||
lvl->map_mem= NULL;
|
||||
|
||||
return lvl;
|
||||
int i,j;
|
||||
IndexNode *node = NULL;
|
||||
|
||||
(*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert face map");
|
||||
(*mem) = MEM_callocN(sizeof(IndexNode) * totface*4, "vert face map mem");
|
||||
node = *mem;
|
||||
|
||||
/* Find the users */
|
||||
for(i = 0; i < totface; ++i){
|
||||
for(j = 0; j < (mface[i].v[3]?4:3); ++j, ++node) {
|
||||
node->index = i;
|
||||
BLI_addtail(&(*map)[mface[i].v[j]], node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void create_old_vert_edge_map(ListBase **map, IndexNode **mem, const MultiresEdge *medge,
|
||||
const int totvert, const int totedge)
|
||||
{
|
||||
int i,j;
|
||||
IndexNode *node = NULL;
|
||||
|
||||
(*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert edge map");
|
||||
(*mem) = MEM_callocN(sizeof(IndexNode) * totedge*2, "vert edge map mem");
|
||||
node = *mem;
|
||||
|
||||
/* Find the users */
|
||||
for(i = 0; i < totedge; ++i){
|
||||
for(j = 0; j < 2; ++j, ++node) {
|
||||
node->index = i;
|
||||
BLI_addtail(&(*map)[medge[i].v[j]], node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static MultiresFace *find_old_face(ListBase *map, MultiresFace *faces, int v1, int v2, int v3, int v4)
|
||||
{
|
||||
IndexNode *n1;
|
||||
int v[4] = {v1, v2, v3, v4}, i, j;
|
||||
|
||||
for(n1 = map[v1].first; n1; n1 = n1->next) {
|
||||
int fnd[4] = {0, 0, 0, 0};
|
||||
|
||||
for(i = 0; i < 4; ++i) {
|
||||
for(j = 0; j < 4; ++j) {
|
||||
if(v[i] == faces[n1->index].v[j])
|
||||
fnd[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(fnd[0] && fnd[1] && fnd[2] && fnd[3])
|
||||
return &faces[n1->index];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Multires *multires_copy(Multires *orig)
|
||||
static MultiresEdge *find_old_edge(ListBase *map, MultiresEdge *edges, int v1, int v2)
|
||||
{
|
||||
const CustomDataMask vdata_mask= CD_MASK_MDEFORMVERT;
|
||||
IndexNode *n1, *n2;
|
||||
|
||||
if(orig) {
|
||||
Multires *mr= MEM_dupallocN(orig);
|
||||
MultiresLevel *lvl;
|
||||
|
||||
mr->levels.first= mr->levels.last= NULL;
|
||||
|
||||
for(lvl= orig->levels.first; lvl; lvl= lvl->next)
|
||||
BLI_addtail(&mr->levels, multires_level_copy(lvl));
|
||||
|
||||
mr->verts= MEM_dupallocN(orig->verts);
|
||||
|
||||
lvl= mr->levels.first;
|
||||
if(lvl) {
|
||||
CustomData_copy(&orig->vdata, &mr->vdata, vdata_mask, CD_DUPLICATE, lvl->totvert);
|
||||
CustomData_copy(&orig->fdata, &mr->fdata, CD_MASK_MTFACE, CD_DUPLICATE, lvl->totface);
|
||||
mr->edge_flags= MEM_dupallocN(orig->edge_flags);
|
||||
mr->edge_creases= MEM_dupallocN(orig->edge_creases);
|
||||
for(n1 = map[v1].first; n1; n1 = n1->next) {
|
||||
for(n2 = map[v2].first; n2; n2 = n2->next) {
|
||||
if(n1->index == n2->index)
|
||||
return &edges[n1->index];
|
||||
}
|
||||
|
||||
return mr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void multires_get_vert(MVert *out, EditVert *eve, MVert *m, int i)
|
||||
static void multires_load_old_edges(ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, int v1, int v2, int mov)
|
||||
{
|
||||
if(eve) {
|
||||
VecCopyf(out->co, eve->co);
|
||||
out->flag= 0;
|
||||
if(eve->f & SELECT) out->flag |= 1;
|
||||
if(eve->h) out->flag |= ME_HIDE;
|
||||
eve->tmp.l= i;
|
||||
}
|
||||
else
|
||||
*out= *m;
|
||||
}
|
||||
int emid = find_old_edge(emap[2], lvl->edges, v1, v2)->mid;
|
||||
vvmap[dst + mov] = emid;
|
||||
|
||||
void eed_to_medge_flag(EditEdge *eed, short *flag, char *crease)
|
||||
{
|
||||
if(!eed || !flag) return;
|
||||
|
||||
/* Would be nice if EditMesh edge flags could be unified with Mesh flags! */
|
||||
*flag= (eed->f & SELECT) | ME_EDGERENDER;
|
||||
if(eed->f2<2) *flag |= ME_EDGEDRAW;
|
||||
if(eed->f2==0) *flag |= ME_LOOSEEDGE;
|
||||
if(eed->sharp) *flag |= ME_SHARP;
|
||||
if(eed->seam) *flag |= ME_SEAM;
|
||||
//XXX if(eed->h & EM_FGON) *flag |= ME_FGON;
|
||||
if(eed->h & 1) *flag |= ME_HIDE;
|
||||
|
||||
*crease= (char)(255.0*eed->crease);
|
||||
}
|
||||
|
||||
static void multires_get_edge(MultiresEdge *e, EditEdge *eed, MEdge *m, short *flag, char *crease)
|
||||
{
|
||||
if(eed) {
|
||||
e->v[0]= eed->v1->tmp.l;
|
||||
e->v[1]= eed->v2->tmp.l;
|
||||
eed_to_medge_flag(eed, flag, crease);
|
||||
} else {
|
||||
e->v[0]= m->v1;
|
||||
e->v[1]= m->v2;
|
||||
*flag= m->flag;
|
||||
*crease= m->crease;
|
||||
if(lvl->next->next) {
|
||||
multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v1, emid, mov / 2);
|
||||
multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v2, emid, -mov / 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void multires_get_face(MultiresFace *f, CustomData *fdata, int findex, EditFace *efa, MFace *m)
|
||||
static void multires_load_old_faces(ListBase **fmap, ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst,
|
||||
int v1, int v2, int v3, int v4, int st2, int st3)
|
||||
{
|
||||
if(efa) {
|
||||
MFace tmp;
|
||||
int j;
|
||||
tmp.v1= efa->v1->tmp.l;
|
||||
tmp.v2= efa->v2->tmp.l;
|
||||
tmp.v3= efa->v3->tmp.l;
|
||||
tmp.v4= 0;
|
||||
if(efa->v4) tmp.v4= efa->v4->tmp.l;
|
||||
test_index_face(&tmp, fdata, findex, efa->v4?4:3);
|
||||
for(j=0; j<4; ++j) f->v[j]= (&tmp.v1)[j];
|
||||
int fmid;
|
||||
int emid13, emid14, emid23, emid24;
|
||||
|
||||
/* Flags */
|
||||
f->flag= efa->flag;
|
||||
if(efa->f & 1) f->flag |= ME_FACE_SEL;
|
||||
else f->flag &= ~ME_FACE_SEL;
|
||||
if(efa->h) f->flag |= ME_HIDE;
|
||||
f->mat_nr= efa->mat_nr;
|
||||
} else {
|
||||
f->v[0]= m->v1;
|
||||
f->v[1]= m->v2;
|
||||
f->v[2]= m->v3;
|
||||
f->v[3]= m->v4;
|
||||
f->flag= m->flag;
|
||||
f->mat_nr= m->mat_nr;
|
||||
}
|
||||
}
|
||||
if(lvl && lvl->next) {
|
||||
fmid = find_old_face(fmap[1], lvl->faces, v1, v2, v3, v4)->mid;
|
||||
vvmap[dst] = fmid;
|
||||
|
||||
/* For manipulating vertex colors / uvs */
|
||||
static void mcol_to_multires(MultiresColFace *mrf, MCol *mcol)
|
||||
{
|
||||
char i;
|
||||
for(i=0; i<4; ++i) {
|
||||
mrf->col[i].a= mcol[i].a;
|
||||
mrf->col[i].r= mcol[i].r;
|
||||
mrf->col[i].g= mcol[i].g;
|
||||
mrf->col[i].b= mcol[i].b;
|
||||
}
|
||||
}
|
||||
emid13 = find_old_edge(emap[1], lvl->edges, v1, v3)->mid;
|
||||
emid14 = find_old_edge(emap[1], lvl->edges, v1, v4)->mid;
|
||||
emid23 = find_old_edge(emap[1], lvl->edges, v2, v3)->mid;
|
||||
emid24 = find_old_edge(emap[1], lvl->edges, v2, v4)->mid;
|
||||
|
||||
/* 1 <= count <= 4 */
|
||||
static void multires_col_avg(MultiresCol *avg, MultiresCol cols[4], char count)
|
||||
{
|
||||
unsigned i;
|
||||
avg->a= avg->r= avg->g= avg->b= 0;
|
||||
for(i=0; i<count; ++i) {
|
||||
avg->a+= cols[i].a;
|
||||
avg->r+= cols[i].r;
|
||||
avg->g+= cols[i].g;
|
||||
avg->b+= cols[i].b;
|
||||
}
|
||||
avg->a/= count;
|
||||
avg->r/= count;
|
||||
avg->g/= count;
|
||||
avg->b/= count;
|
||||
}
|
||||
|
||||
static void multires_col_avg2(MultiresCol *avg, MultiresCol *c1, MultiresCol *c2)
|
||||
{
|
||||
MultiresCol in[2];
|
||||
in[0]= *c1;
|
||||
in[1]= *c2;
|
||||
multires_col_avg(avg,in,2);
|
||||
}
|
||||
multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst + st2 * st3 + st3,
|
||||
fmid, v2, emid23, emid24, st2, st3 / 2);
|
||||
|
||||
void multires_load_cols(Mesh *me)
|
||||
{
|
||||
MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1), *cur;
|
||||
EditMesh *em= me->edit_mesh;
|
||||
CustomData *src= em ? &em->fdata : &me->fdata;
|
||||
EditFace *efa= NULL;
|
||||
unsigned i,j;
|
||||
multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst - st2 * st3 + st3,
|
||||
emid14, emid24, fmid, v4, st2, st3 / 2);
|
||||
|
||||
if(!CustomData_has_layer(src, CD_MCOL) && !CustomData_has_layer(src, CD_MTFACE)) return;
|
||||
multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst + st2 * st3 - st3,
|
||||
emid13, emid23, v3, fmid, st2, st3 / 2);
|
||||
|
||||
/* Add texcol data */
|
||||
for(cur= me->mr->levels.first; cur; cur= cur->next)
|
||||
if(!cur->colfaces)
|
||||
cur->colfaces= MEM_callocN(sizeof(MultiresColFace)*cur->totface,"ColFaces");
|
||||
multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst - st2 * st3 - st3,
|
||||
v1, fmid, emid13, emid14, st2, st3 / 2);
|
||||
|
||||
me->mr->use_col= CustomData_has_layer(src, CD_MCOL);
|
||||
|
||||
if(em) efa= em->faces.first;
|
||||
for(i=0; i<lvl->totface; ++i) {
|
||||
MultiresColFace *f= &lvl->colfaces[i];
|
||||
|
||||
if(me->mr->use_col)
|
||||
mcol_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4]);
|
||||
|
||||
if(em) efa= efa->next;
|
||||
}
|
||||
|
||||
/* Update higher levels */
|
||||
lvl= lvl->next;
|
||||
while(lvl) {
|
||||
MultiresColFace *cf= lvl->colfaces;
|
||||
for(i=0; i<lvl->prev->totface; ++i) {
|
||||
const char sides= lvl->prev->faces[i].v[3]?4:3;
|
||||
MultiresCol cntr;
|
||||
|
||||
/* Find average color of 4 (or 3 for triangle) verts */
|
||||
multires_col_avg(&cntr,lvl->prev->colfaces[i].col,sides);
|
||||
|
||||
for(j=0; j<sides; ++j) {
|
||||
MultiresColFace *pf= &lvl->prev->colfaces[i];
|
||||
|
||||
multires_col_avg2(&cf->col[0],
|
||||
&pf->col[j],
|
||||
&pf->col[j==0?sides-1:j-1]);
|
||||
cf->col[1]= pf->col[j];
|
||||
multires_col_avg2(&cf->col[2],
|
||||
&pf->col[j],
|
||||
&pf->col[j==sides-1?0:j+1]);
|
||||
cf->col[3]= cntr;
|
||||
|
||||
++cf;
|
||||
}
|
||||
if(lvl->next->next) {
|
||||
multires_load_old_edges(emap, lvl->next, vvmap, dst, emid24, fmid, st3);
|
||||
multires_load_old_edges(emap, lvl->next, vvmap, dst, emid13, fmid, -st3);
|
||||
multires_load_old_edges(emap, lvl->next, vvmap, dst, emid14, fmid, -st2 * st3);
|
||||
multires_load_old_edges(emap, lvl->next, vvmap, dst, emid23, fmid, st2 * st3);
|
||||
}
|
||||
lvl= lvl->next;
|
||||
}
|
||||
|
||||
/* Update lower levels */
|
||||
lvl= me->mr->levels.last;
|
||||
lvl= lvl->prev;
|
||||
while(lvl) {
|
||||
unsigned curf= 0;
|
||||
for(i=0; i<lvl->totface; ++i) {
|
||||
MultiresFace *f= &lvl->faces[i];
|
||||
for(j=0; j<(f->v[3]?4:3); ++j) {
|
||||
lvl->colfaces[i].col[j]= lvl->next->colfaces[curf].col[1];
|
||||
++curf;
|
||||
}
|
||||
}
|
||||
lvl= lvl->prev;
|
||||
}
|
||||
}
|
||||
|
||||
void multires_create(Object *ob, Mesh *me)
|
||||
/* Loads a multires object stored in the old Multires struct into the new format */
|
||||
void multires_load_old(DerivedMesh *dm, Multires *mr)
|
||||
{
|
||||
MultiresLevel *lvl;
|
||||
EditMesh *em= me->edit_mesh;
|
||||
EditVert *eve= NULL;
|
||||
EditFace *efa= NULL;
|
||||
EditEdge *eed= NULL;
|
||||
int i;
|
||||
|
||||
lvl= MEM_callocN(sizeof(MultiresLevel), "multires level");
|
||||
MultiresLevel *lvl, *lvl1;
|
||||
MVert *vsrc, *vdst;
|
||||
int src, dst;
|
||||
int totlvl = MultiresDM_get_totlvl(dm);
|
||||
int st = multires_side_tot[totlvl - 2] - 1;
|
||||
int extedgelen = multires_side_tot[totlvl - 1] - 2;
|
||||
int *vvmap; // inorder for dst, map to src
|
||||
int crossedgelen;
|
||||
int i, j, s, x, totvert, tottri, totquad;
|
||||
|
||||
if(me->pv) mesh_pmv_off(ob, me);
|
||||
src = 0;
|
||||
dst = 0;
|
||||
vsrc = mr->verts;
|
||||
vdst = CDDM_get_verts(dm);
|
||||
totvert = dm->getNumVerts(dm);
|
||||
vvmap = MEM_callocN(sizeof(int) * totvert, "multires vvmap");
|
||||
|
||||
me->mr= MEM_callocN(sizeof(Multires), "multires data");
|
||||
|
||||
BLI_addtail(&me->mr->levels,lvl);
|
||||
me->mr->current= 1;
|
||||
me->mr->level_count= 1;
|
||||
me->mr->edgelvl= 1;
|
||||
me->mr->pinlvl= 1;
|
||||
me->mr->renderlvl= 1;
|
||||
|
||||
/* Load mesh (or editmesh) into multires data */
|
||||
|
||||
/* Load vertices and vdata (MDeformVerts) */
|
||||
lvl->totvert= em ? BLI_countlist(&em->verts) : me->totvert;
|
||||
me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert,"multires verts");
|
||||
multires_update_customdata(me->mr->levels.first, em, em ? &em->vdata : &me->vdata,
|
||||
&me->mr->vdata, CD_MDEFORMVERT);
|
||||
if(em) eve= em->verts.first;
|
||||
for(i=0; i<lvl->totvert; ++i) {
|
||||
multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i);
|
||||
if(em) eve= eve->next;
|
||||
lvl1 = mr->levels.first;
|
||||
/* Load base verts */
|
||||
for(i = 0; i < lvl1->totvert; ++i) {
|
||||
vvmap[totvert - lvl1->totvert + i] = src;
|
||||
++src;
|
||||
}
|
||||
|
||||
/* Load faces and fdata (MTFaces) */
|
||||
lvl->totface= em ? BLI_countlist(&em->faces) : me->totface;
|
||||
lvl->faces= MEM_callocN(sizeof(MultiresFace)*lvl->totface,"multires faces");
|
||||
multires_update_customdata(me->mr->levels.first, em, em ? &em->fdata : &me->fdata,
|
||||
&me->mr->fdata, CD_MTFACE);
|
||||
if(em) efa= em->faces.first;
|
||||
for(i=0; i<lvl->totface; ++i) {
|
||||
multires_get_face(&lvl->faces[i], &me->mr->fdata, i, efa, &me->mface[i]);
|
||||
if(em) efa= efa->next;
|
||||
}
|
||||
/* Original edges */
|
||||
dst = totvert - lvl1->totvert - extedgelen * lvl1->totedge;
|
||||
for(i = 0; i < lvl1->totedge; ++i) {
|
||||
int ldst = dst + extedgelen * i;
|
||||
int lsrc = src;
|
||||
lvl = lvl1->next;
|
||||
|
||||
/* Load edges and edge_flags */
|
||||
lvl->totedge= em ? BLI_countlist(&em->edges) : me->totedge;
|
||||
lvl->edges= MEM_callocN(sizeof(MultiresEdge)*lvl->totedge,"multires edges");
|
||||
me->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "multires edge flags");
|
||||
me->mr->edge_creases= MEM_callocN(sizeof(short)*lvl->totedge, "multires edge creases");
|
||||
if(em) eed= em->edges.first;
|
||||
for(i=0; i<lvl->totedge; ++i) {
|
||||
multires_get_edge(&lvl->edges[i], eed, &me->medge[i], &me->mr->edge_flags[i], &me->mr->edge_creases[i]);
|
||||
if(em) eed= eed->next;
|
||||
}
|
||||
for(j = 2; j <= mr->level_count; ++j) {
|
||||
int base = multires_side_tot[totlvl - j] - 2;
|
||||
int skip = multires_side_tot[totlvl - j + 1] - 1;
|
||||
int st = multires_side_tot[j - 2] - 1;
|
||||
|
||||
multires_load_cols(me);
|
||||
}
|
||||
for(x = 0; x < st; ++x)
|
||||
vvmap[ldst + base + x * skip] = lsrc + st * i + x;
|
||||
|
||||
typedef struct MultiresMapNode {
|
||||
struct MultiresMapNode *next, *prev;
|
||||
unsigned Index;
|
||||
} MultiresMapNode;
|
||||
|
||||
/* Produces temporary connectivity data for the multires lvl */
|
||||
static void multires_calc_temp_data(MultiresLevel *lvl)
|
||||
{
|
||||
unsigned i, j, emax;
|
||||
MultiresMapNode *indexnode= NULL;
|
||||
|
||||
lvl->map_mem= MEM_mallocN(sizeof(MultiresMapNode)*(lvl->totedge*2 + lvl->totface*4), "map_mem");
|
||||
indexnode= lvl->map_mem;
|
||||
|
||||
/* edge map */
|
||||
lvl->vert_edge_map= MEM_callocN(sizeof(ListBase)*lvl->totvert,"vert_edge_map");
|
||||
for(i=0; i<lvl->totedge; ++i) {
|
||||
for(j=0; j<2; ++j, ++indexnode) {
|
||||
indexnode->Index= i;
|
||||
BLI_addtail(&lvl->vert_edge_map[lvl->edges[i].v[j]], indexnode);
|
||||
lsrc += lvl->totvert - lvl->prev->totvert;
|
||||
lvl = lvl->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* face map */
|
||||
lvl->vert_face_map= MEM_callocN(sizeof(ListBase)*lvl->totvert,"vert_face_map");
|
||||
for(i=0; i<lvl->totface; ++i){
|
||||
for(j=0; j<(lvl->faces[i].v[3]?4:3); ++j, ++indexnode) {
|
||||
indexnode->Index= i;
|
||||
BLI_addtail(&lvl->vert_face_map[lvl->faces[i].v[j]], indexnode);
|
||||
}
|
||||
/* Center points */
|
||||
dst = 0;
|
||||
for(i = 0; i < lvl1->totface; ++i) {
|
||||
int sides = lvl1->faces[i].v[3] ? 4 : 3;
|
||||
|
||||
vvmap[dst] = src + lvl1->totedge + i;
|
||||
dst += 1 + sides * (st - 1) * st;
|
||||
}
|
||||
|
||||
/* edge boundaries */
|
||||
emax = (lvl->prev ? (lvl->prev->totedge * 2) : lvl->totedge);
|
||||
lvl->edge_boundary_states= MEM_callocN(sizeof(char)*lvl->totedge, "edge_boundary_states");
|
||||
for(i=0; i<emax; ++i) {
|
||||
MultiresMapNode *n1= lvl->vert_face_map[lvl->edges[i].v[0]].first;
|
||||
unsigned total= 0;
|
||||
|
||||
lvl->edge_boundary_states[i] = 1;
|
||||
while(n1 && lvl->edge_boundary_states[i] == 1) {
|
||||
MultiresMapNode *n2= lvl->vert_face_map[lvl->edges[i].v[1]].first;
|
||||
while(n2) {
|
||||
if(n1->Index == n2->Index) {
|
||||
++total;
|
||||
|
||||
if(total > 1) {
|
||||
lvl->edge_boundary_states[i] = 0;
|
||||
break;
|
||||
|
||||
/* The rest is only for level 3 and up */
|
||||
if(lvl1->next && lvl1->next->next) {
|
||||
ListBase **fmap, **emap;
|
||||
IndexNode **fmem, **emem;
|
||||
|
||||
/* Face edge cross */
|
||||
tottri = totquad = 0;
|
||||
crossedgelen = multires_side_tot[totlvl - 2] - 2;
|
||||
dst = 0;
|
||||
for(i = 0; i < lvl1->totface; ++i) {
|
||||
int sides = lvl1->faces[i].v[3] ? 4 : 3;
|
||||
|
||||
lvl = lvl1->next->next;
|
||||
++dst;
|
||||
|
||||
for(j = 3; j <= mr->level_count; ++j) {
|
||||
int base = multires_side_tot[totlvl - j] - 2;
|
||||
int skip = multires_side_tot[totlvl - j + 1] - 1;
|
||||
int st = pow(2, j - 2);
|
||||
int st2 = pow(2, j - 3);
|
||||
int lsrc = lvl->prev->totvert;
|
||||
|
||||
/* Skip exterior edge verts */
|
||||
lsrc += lvl1->totedge * st;
|
||||
|
||||
/* Skip earlier face edge crosses */
|
||||
lsrc += st2 * (tottri * 3 + totquad * 4);
|
||||
|
||||
for(s = 0; s < sides; ++s) {
|
||||
for(x = 0; x < st2; ++x) {
|
||||
vvmap[dst + crossedgelen * (s + 1) - base - x * skip - 1] = lsrc;
|
||||
++lsrc;
|
||||
}
|
||||
}
|
||||
|
||||
n2= n2->next;
|
||||
}
|
||||
n1= n1->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* CATMULL-CLARK
|
||||
============= */
|
||||
|
||||
typedef struct MultiApplyData {
|
||||
/* Smooth faces */
|
||||
float *corner1, *corner2, *corner3, *corner4;
|
||||
char quad;
|
||||
|
||||
/* Smooth edges */
|
||||
char boundary;
|
||||
float edge_face_neighbor_midpoints_accum[3];
|
||||
unsigned edge_face_neighbor_midpoints_total;
|
||||
float *endpoint1, *endpoint2;
|
||||
|
||||
/* Smooth verts */
|
||||
/* uses 'char boundary' */
|
||||
float *original;
|
||||
int edge_count;
|
||||
float vert_face_neighbor_midpoints_average[3];
|
||||
float vert_edge_neighbor_midpoints_average[3];
|
||||
float boundary_edges_average[3];
|
||||
} MultiApplyData;
|
||||
|
||||
/* Simply averages the four corners of a polygon. */
|
||||
static float catmullclark_smooth_face(MultiApplyData *data, const unsigned i)
|
||||
{
|
||||
const float total= data->corner1[i]+data->corner2[i]+data->corner3[i];
|
||||
return data->quad ? (total+data->corner4[i])/4 : total/3;
|
||||
}
|
||||
|
||||
static float catmullclark_smooth_edge(MultiApplyData *data, const unsigned i)
|
||||
{
|
||||
float accum= 0;
|
||||
unsigned count= 2;
|
||||
|
||||
accum+= data->endpoint1[i] + data->endpoint2[i];
|
||||
|
||||
if(!data->boundary) {
|
||||
accum+= data->edge_face_neighbor_midpoints_accum[i];
|
||||
count+= data->edge_face_neighbor_midpoints_total;
|
||||
}
|
||||
|
||||
return accum / count;
|
||||
}
|
||||
|
||||
static float catmullclark_smooth_vert(MultiApplyData *data, const unsigned i)
|
||||
{
|
||||
if(data->boundary) {
|
||||
return data->original[i]*0.75 + data->boundary_edges_average[i]*0.25;
|
||||
} else {
|
||||
return (data->vert_face_neighbor_midpoints_average[i] +
|
||||
2*data->vert_edge_neighbor_midpoints_average[i] +
|
||||
data->original[i]*(data->edge_count-3))/data->edge_count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Call func count times, passing in[i] as the input and storing the output in out[i] */
|
||||
static void multi_apply(float *out, MultiApplyData *data,
|
||||
const unsigned count, float (*func)(MultiApplyData *, const unsigned))
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<count; ++i)
|
||||
out[i]= func(data,i);
|
||||
}
|
||||
|
||||
static short multires_vert_is_boundary(MultiresLevel *lvl, unsigned v)
|
||||
{
|
||||
MultiresMapNode *node= lvl->vert_edge_map[v].first;
|
||||
while(node) {
|
||||
if(lvl->edge_boundary_states[node->Index])
|
||||
return 1;
|
||||
node= node->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define GET_FLOAT(array, i, j, stride) (((float*)((char*)(array)+((i)*(stride))))[(j)])
|
||||
|
||||
static void edge_face_neighbor_midpoints_accum(MultiApplyData *data, MultiresLevel *lvl,
|
||||
void *array, const char stride, const MultiresEdge *e)
|
||||
{
|
||||
ListBase *neighbors1= &lvl->vert_face_map[e->v[0]];
|
||||
ListBase *neighbors2= &lvl->vert_face_map[e->v[1]];
|
||||
MultiresMapNode *n1, *n2;
|
||||
unsigned j,count= 0;
|
||||
float *out= data->edge_face_neighbor_midpoints_accum;
|
||||
|
||||
out[0]=out[1]=out[2]= 0;
|
||||
|
||||
for(n1= neighbors1->first; n1; n1= n1->next) {
|
||||
for(n2= neighbors2->first; n2; n2= n2->next) {
|
||||
if(n1->Index == n2->Index) {
|
||||
for(j=0; j<3; ++j)
|
||||
out[j]+= GET_FLOAT(array,lvl->faces[n1->Index].mid,j,stride);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data->edge_face_neighbor_midpoints_total= count;
|
||||
}
|
||||
|
||||
static void vert_face_neighbor_midpoints_average(MultiApplyData *data, MultiresLevel *lvl,
|
||||
void *array, const char stride, const unsigned i)
|
||||
{
|
||||
ListBase *neighbors= &lvl->vert_face_map[i];
|
||||
MultiresMapNode *n1;
|
||||
unsigned j,count= 0;
|
||||
float *out= data->vert_face_neighbor_midpoints_average;
|
||||
|
||||
out[0]=out[1]=out[2]= 0;
|
||||
|
||||
for(n1= neighbors->first; n1; n1= n1->next) {
|
||||
for(j=0; j<3; ++j)
|
||||
out[j]+= GET_FLOAT(array,lvl->faces[n1->Index].mid,j,stride);
|
||||
++count;
|
||||
}
|
||||
for(j=0; j<3; ++j) out[j]/= count;
|
||||
}
|
||||
|
||||
static void vert_edge_neighbor_midpoints_average(MultiApplyData *data, MultiresLevel *lvl,
|
||||
void *array, const char stride, const unsigned i)
|
||||
{
|
||||
ListBase *neighbors= &lvl->vert_edge_map[i];
|
||||
MultiresMapNode *n1;
|
||||
unsigned j,count= 0;
|
||||
float *out= data->vert_edge_neighbor_midpoints_average;
|
||||
|
||||
out[0]=out[1]=out[2]= 0;
|
||||
|
||||
for(n1= neighbors->first; n1; n1= n1->next) {
|
||||
for(j=0; j<3; ++j)
|
||||
out[j]+= (GET_FLOAT(array,lvl->edges[n1->Index].v[0],j,stride) +
|
||||
GET_FLOAT(array,lvl->edges[n1->Index].v[1],j,stride)) / 2;
|
||||
++count;
|
||||
}
|
||||
for(j=0; j<3; ++j) out[j]/= count;
|
||||
}
|
||||
|
||||
static void boundary_edges_average(MultiApplyData *data, MultiresLevel *lvl,
|
||||
void *array, const char stride, const unsigned i)
|
||||
{
|
||||
ListBase *neighbors= &lvl->vert_edge_map[i];
|
||||
MultiresMapNode *n1;
|
||||
unsigned j,count= 0;
|
||||
float *out= data->boundary_edges_average;
|
||||
|
||||
out[0]=out[1]=out[2]= 0;
|
||||
|
||||
for(n1= neighbors->first; n1; n1= n1->next) {
|
||||
const MultiresEdge *e= &lvl->edges[n1->Index];
|
||||
const unsigned end= e->v[0]==i ? e->v[1] : e->v[0];
|
||||
|
||||
if(lvl->edge_boundary_states[n1->Index]) {
|
||||
for(j=0; j<3; ++j)
|
||||
out[j]+= GET_FLOAT(array,end,j,stride);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
for(j=0; j<3; ++j) out[j]/= count;
|
||||
}
|
||||
|
||||
/* END CATMULL-CLARK
|
||||
================= */
|
||||
|
||||
/* Update vertex locations and vertex flags */
|
||||
static void multires_update_vertices(Mesh *me, EditMesh *em)
|
||||
{
|
||||
MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL,
|
||||
*last_lvl= me->mr->levels.last;
|
||||
vec3f *pr_deltas= NULL, *cr_deltas= NULL, *swap_deltas= NULL;
|
||||
EditVert *eve= NULL;
|
||||
MultiApplyData data;
|
||||
int i, j;
|
||||
|
||||
/* XXX added this to prevent crash, but if it works? (ton) */
|
||||
if(me->mr->verts==NULL)
|
||||
return;
|
||||
|
||||
/* Prepare deltas */
|
||||
pr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 1");
|
||||
cr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 2");
|
||||
|
||||
/* Calculate initial deltas -- current mesh subtracted from current level*/
|
||||
if(em) eve= em->verts.first;
|
||||
for(i=0; i<cr_lvl->totvert; ++i) {
|
||||
if(em) {
|
||||
VecSubf(&cr_deltas[i].x, eve->co, me->mr->verts[i].co);
|
||||
eve= eve->next;
|
||||
} else
|
||||
VecSubf(&cr_deltas[i].x, me->mvert[i].co, me->mr->verts[i].co);
|
||||
}
|
||||
|
||||
|
||||
/* Copy current level's vertex flags and clear the rest */
|
||||
if(em) eve= em->verts.first;
|
||||
for(i=0; i < last_lvl->totvert; ++i) {
|
||||
if(i < cr_lvl->totvert) {
|
||||
MVert mvflag;
|
||||
multires_get_vert(&mvflag, eve, &me->mvert[i], i);
|
||||
if(em) eve= eve->next;
|
||||
me->mr->verts[i].flag= mvflag.flag;
|
||||
}
|
||||
else
|
||||
me->mr->verts[i].flag= 0;
|
||||
}
|
||||
|
||||
/* If already on the highest level, copy current verts (including flags) into current level */
|
||||
if(cr_lvl == last_lvl) {
|
||||
if(em)
|
||||
eve= em->verts.first;
|
||||
for(i=0; i<cr_lvl->totvert; ++i) {
|
||||
multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i);
|
||||
if(em) eve= eve->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update higher levels */
|
||||
pr_lvl= BLI_findlink(&me->mr->levels,me->mr->current-1);
|
||||
cr_lvl= pr_lvl->next;
|
||||
while(cr_lvl) {
|
||||
multires_calc_temp_data(pr_lvl);
|
||||
|
||||
/* Swap the old/new deltas */
|
||||
swap_deltas= pr_deltas;
|
||||
pr_deltas= cr_deltas;
|
||||
cr_deltas= swap_deltas;
|
||||
|
||||
/* Calculate and add new deltas
|
||||
============================ */
|
||||
for(i=0; i<pr_lvl->totface; ++i) {
|
||||
const MultiresFace *f= &pr_lvl->faces[i];
|
||||
data.corner1= &pr_deltas[f->v[0]].x;
|
||||
data.corner2= &pr_deltas[f->v[1]].x;
|
||||
data.corner3= &pr_deltas[f->v[2]].x;
|
||||
data.corner4= &pr_deltas[f->v[3]].x;
|
||||
data.quad= f->v[3] ? 1 : 0;
|
||||
multi_apply(&cr_deltas[f->mid].x, &data, 3, catmullclark_smooth_face);
|
||||
|
||||
for(j=0; j<(data.quad?4:3); ++j)
|
||||
me->mr->verts[f->mid].flag |= me->mr->verts[f->v[j]].flag;
|
||||
}
|
||||
|
||||
for(i=0; i<pr_lvl->totedge; ++i) {
|
||||
const MultiresEdge *e= &pr_lvl->edges[i];
|
||||
data.boundary= pr_lvl->edge_boundary_states[i];
|
||||
edge_face_neighbor_midpoints_accum(&data,pr_lvl,cr_deltas,sizeof(vec3f),e);
|
||||
data.endpoint1= &pr_deltas[e->v[0]].x;
|
||||
data.endpoint2= &pr_deltas[e->v[1]].x;
|
||||
multi_apply(&cr_deltas[e->mid].x, &data, 3, catmullclark_smooth_edge);
|
||||
|
||||
for(j=0; j<2; ++j)
|
||||
me->mr->verts[e->mid].flag |= me->mr->verts[e->v[j]].flag;
|
||||
}
|
||||
|
||||
for(i=0; i<pr_lvl->totvert; ++i) {
|
||||
data.boundary= multires_vert_is_boundary(pr_lvl,i);
|
||||
data.original= &pr_deltas[i].x;
|
||||
data.edge_count= BLI_countlist(&pr_lvl->vert_edge_map[i]);
|
||||
if(data.boundary)
|
||||
boundary_edges_average(&data,pr_lvl,pr_deltas,sizeof(vec3f),i);
|
||||
else {
|
||||
vert_face_neighbor_midpoints_average(&data,pr_lvl,cr_deltas,sizeof(vec3f),i);
|
||||
vert_edge_neighbor_midpoints_average(&data,pr_lvl,pr_deltas,sizeof(vec3f),i);
|
||||
}
|
||||
multi_apply(&cr_deltas[i].x, &data, 3, catmullclark_smooth_vert);
|
||||
}
|
||||
|
||||
/* Apply deltas to vertex locations */
|
||||
for(i=0; (cr_lvl == last_lvl) && (i < cr_lvl->totvert); ++i) {
|
||||
VecAddf(me->mr->verts[i].co,
|
||||
me->mr->verts[i].co,
|
||||
&cr_deltas[i].x);
|
||||
}
|
||||
|
||||
multires_free_temp_data(pr_lvl);
|
||||
|
||||
pr_lvl= pr_lvl->next;
|
||||
cr_lvl= cr_lvl->next;
|
||||
}
|
||||
if(pr_deltas) MEM_freeN(pr_deltas);
|
||||
if(cr_deltas) MEM_freeN(cr_deltas);
|
||||
|
||||
}
|
||||
|
||||
static void multires_update_faces(Mesh *me, EditMesh *em)
|
||||
{
|
||||
MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL,
|
||||
*last_lvl= me->mr->levels.last;
|
||||
char *pr_flag_damaged= NULL, *cr_flag_damaged= NULL, *or_flag_damaged= NULL,
|
||||
*pr_mat_damaged= NULL, *cr_mat_damaged= NULL, *or_mat_damaged= NULL, *swap= NULL;
|
||||
EditFace *efa= NULL;
|
||||
unsigned i,j,curf;
|
||||
|
||||
/* Find for each face whether flag/mat has changed */
|
||||
pr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1");
|
||||
cr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1");
|
||||
pr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1");
|
||||
cr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1");
|
||||
if(em) efa= em->faces.first;
|
||||
for(i=0; i<cr_lvl->totface; ++i) {
|
||||
MultiresFace mftmp;
|
||||
multires_get_face(&mftmp, &me->mr->fdata, i, efa, &me->mface[i]);
|
||||
if(cr_lvl->faces[i].flag != mftmp.flag)
|
||||
cr_flag_damaged[i]= 1;
|
||||
if(cr_lvl->faces[i].mat_nr != mftmp.mat_nr)
|
||||
cr_mat_damaged[i]= 1;
|
||||
|
||||
/* Update current level */
|
||||
cr_lvl->faces[i].flag= mftmp.flag;
|
||||
cr_lvl->faces[i].mat_nr= mftmp.mat_nr;
|
||||
|
||||
if(em) efa= efa->next;
|
||||
}
|
||||
or_flag_damaged= MEM_dupallocN(cr_flag_damaged);
|
||||
or_mat_damaged= MEM_dupallocN(cr_mat_damaged);
|
||||
|
||||
/* Update lower levels */
|
||||
cr_lvl= cr_lvl->prev;
|
||||
while(cr_lvl) {
|
||||
swap= pr_flag_damaged;
|
||||
pr_flag_damaged= cr_flag_damaged;
|
||||
cr_flag_damaged= swap;
|
||||
|
||||
swap= pr_mat_damaged;
|
||||
pr_mat_damaged= cr_mat_damaged;
|
||||
cr_mat_damaged= swap;
|
||||
|
||||
curf= 0;
|
||||
for(i=0; i<cr_lvl->totface; ++i) {
|
||||
const int sides= cr_lvl->faces[i].v[3] ? 4 : 3;
|
||||
|
||||
/* Check damages */
|
||||
for(j=0; j<sides; ++j, ++curf) {
|
||||
if(pr_flag_damaged[curf]) {
|
||||
cr_lvl->faces[i].flag= cr_lvl->next->faces[curf].flag;
|
||||
cr_flag_damaged[i]= 1;
|
||||
}
|
||||
if(pr_mat_damaged[curf]) {
|
||||
cr_lvl->faces[i].mat_nr= cr_lvl->next->faces[curf].mat_nr;
|
||||
cr_mat_damaged[i]= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cr_lvl= cr_lvl->prev;
|
||||
}
|
||||
|
||||
/* Clear to original damages */
|
||||
if(cr_flag_damaged) MEM_freeN(cr_flag_damaged);
|
||||
if(cr_mat_damaged) MEM_freeN(cr_mat_damaged);
|
||||
cr_flag_damaged= or_flag_damaged;
|
||||
cr_mat_damaged= or_mat_damaged;
|
||||
|
||||
/* Update higher levels */
|
||||
pr_lvl= current_level(me->mr);
|
||||
cr_lvl= pr_lvl->next;
|
||||
while(cr_lvl) {
|
||||
swap= pr_flag_damaged;
|
||||
pr_flag_damaged= cr_flag_damaged;
|
||||
cr_flag_damaged= swap;
|
||||
|
||||
swap= pr_mat_damaged;
|
||||
pr_mat_damaged= cr_mat_damaged;
|
||||
cr_mat_damaged= swap;
|
||||
|
||||
/* Update faces */
|
||||
for(i=0, curf= 0; i<pr_lvl->totface; ++i) {
|
||||
const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3;
|
||||
for(j=0; j<sides; ++j, ++curf) {
|
||||
if(pr_flag_damaged[i]) {
|
||||
cr_lvl->faces[curf].flag= pr_lvl->faces[i].flag;
|
||||
cr_flag_damaged[curf]= 1;
|
||||
}
|
||||
if(pr_mat_damaged[i]) {
|
||||
cr_lvl->faces[curf].mat_nr= pr_lvl->faces[i].mat_nr;
|
||||
cr_mat_damaged[curf]= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pr_lvl= pr_lvl->next;
|
||||
cr_lvl= cr_lvl->next;
|
||||
}
|
||||
|
||||
if(pr_flag_damaged) MEM_freeN(pr_flag_damaged);
|
||||
if(cr_flag_damaged) MEM_freeN(cr_flag_damaged);
|
||||
if(pr_mat_damaged) MEM_freeN(pr_mat_damaged);
|
||||
if(cr_mat_damaged) MEM_freeN(cr_mat_damaged);
|
||||
}
|
||||
|
||||
static void multires_update_colors(Mesh *me, EditMesh *em)
|
||||
{
|
||||
MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1);
|
||||
MultiresCol *pr_deltas= NULL, *cr_deltas= NULL;
|
||||
CustomData *src= em ? &em->fdata : &me->fdata;
|
||||
EditFace *efa= NULL;
|
||||
unsigned i,j,curf= 0;
|
||||
|
||||
if(me->mr->use_col) {
|
||||
/* Calc initial deltas */
|
||||
cr_deltas= MEM_callocN(sizeof(MultiresCol)*lvl->totface*4,"initial color/uv deltas");
|
||||
|
||||
if(em) efa= em->faces.first;
|
||||
for(i=0; i<lvl->totface; ++i) {
|
||||
MCol *col= em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4];
|
||||
for(j=0; j<4; ++j) {
|
||||
if(me->mr->use_col) {
|
||||
cr_deltas[i*4+j].a= col[j].a - lvl->colfaces[i].col[j].a;
|
||||
cr_deltas[i*4+j].r= col[j].r - lvl->colfaces[i].col[j].r;
|
||||
cr_deltas[i*4+j].g= col[j].g - lvl->colfaces[i].col[j].g;
|
||||
cr_deltas[i*4+j].b= col[j].b - lvl->colfaces[i].col[j].b;
|
||||
}
|
||||
}
|
||||
if(em) efa= efa->next;
|
||||
}
|
||||
|
||||
/* Update current level */
|
||||
if(em) efa= em->faces.first;
|
||||
for(i=0; i<lvl->totface; ++i) {
|
||||
MultiresColFace *f= &lvl->colfaces[i];
|
||||
|
||||
if(me->mr->use_col)
|
||||
mcol_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4]);
|
||||
|
||||
if(em) efa= efa->next;
|
||||
}
|
||||
|
||||
/* Update higher levels */
|
||||
lvl= lvl->next;
|
||||
while(lvl) {
|
||||
/* Set up new deltas, but keep the ones from the previous level */
|
||||
if(pr_deltas) MEM_freeN(pr_deltas);
|
||||
pr_deltas= cr_deltas;
|
||||
cr_deltas= MEM_callocN(sizeof(MultiresCol)*lvl->totface*4,"color deltas");
|
||||
|
||||
curf= 0;
|
||||
for(i=0; i<lvl->prev->totface; ++i) {
|
||||
const char sides= lvl->prev->faces[i].v[3]?4:3;
|
||||
MultiresCol cntr;
|
||||
|
||||
/* Find average color of 4 (or 3 for triangle) verts */
|
||||
multires_col_avg(&cntr,&pr_deltas[i*4],sides);
|
||||
|
||||
for(j=0; j<sides; ++j) {
|
||||
multires_col_avg2(&cr_deltas[curf*4],
|
||||
&pr_deltas[i*4+j],
|
||||
&pr_deltas[i*4+(j==0?sides-1:j-1)]);
|
||||
cr_deltas[curf*4+1]= pr_deltas[i*4+j];
|
||||
multires_col_avg2(&cr_deltas[curf*4+2],
|
||||
&pr_deltas[i*4+j],
|
||||
&pr_deltas[i*4+(j==sides-1?0:j+1)]);
|
||||
cr_deltas[curf*4+3]= cntr;
|
||||
++curf;
|
||||
}
|
||||
lvl = lvl->next;
|
||||
}
|
||||
|
||||
for(i=0; i<lvl->totface; ++i) {
|
||||
for(j=0; j<4; ++j) {
|
||||
lvl->colfaces[i].col[j].a+= cr_deltas[i*4+j].a;
|
||||
lvl->colfaces[i].col[j].r+= cr_deltas[i*4+j].r;
|
||||
lvl->colfaces[i].col[j].g+= cr_deltas[i*4+j].g;
|
||||
lvl->colfaces[i].col[j].b+= cr_deltas[i*4+j].b;
|
||||
}
|
||||
dst += sides * (st - 1) * st;
|
||||
|
||||
if(sides == 4) ++totquad;
|
||||
else ++tottri;
|
||||
|
||||
}
|
||||
|
||||
/* calculate vert to edge/face maps for each level (except the last) */
|
||||
fmap = MEM_callocN(sizeof(ListBase*) * (mr->level_count-1), "multires fmap");
|
||||
emap = MEM_callocN(sizeof(ListBase*) * (mr->level_count-1), "multires emap");
|
||||
fmem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires fmem");
|
||||
emem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires emem");
|
||||
lvl = lvl1;
|
||||
for(i = 0; i < mr->level_count - 1; ++i) {
|
||||
create_old_vert_face_map(fmap + i, fmem + i, lvl->faces, lvl->totvert, lvl->totface);
|
||||
create_old_vert_edge_map(emap + i, emem + i, lvl->edges, lvl->totvert, lvl->totedge);
|
||||
lvl = lvl->next;
|
||||
}
|
||||
|
||||
/* Interior face verts */
|
||||
lvl = lvl1->next->next;
|
||||
dst = 0;
|
||||
for(j = 0; j < lvl1->totface; ++j) {
|
||||
int sides = lvl1->faces[j].v[3] ? 4 : 3;
|
||||
int ldst = dst + 1 + sides * (st - 1);
|
||||
|
||||
for(s = 0; s < sides; ++s) {
|
||||
int st2 = multires_side_tot[totlvl - 2] - 2;
|
||||
int st3 = multires_side_tot[totlvl - 3] - 2;
|
||||
int st4 = st3 == 0 ? 1 : (st3 + 1) / 2;
|
||||
int mid = ldst + st2 * st3 + st3;
|
||||
int cv = lvl1->faces[j].v[s];
|
||||
int nv = lvl1->faces[j].v[s == sides - 1 ? 0 : s + 1];
|
||||
int pv = lvl1->faces[j].v[s == 0 ? sides - 1 : s - 1];
|
||||
|
||||
multires_load_old_faces(fmap, emap, lvl1->next, vvmap, mid,
|
||||
vvmap[dst], cv,
|
||||
find_old_edge(emap[0], lvl1->edges, pv, cv)->mid,
|
||||
find_old_edge(emap[0], lvl1->edges, cv, nv)->mid,
|
||||
st2, st4);
|
||||
|
||||
ldst += (st - 1) * (st - 1);
|
||||
}
|
||||
|
||||
lvl= lvl->next;
|
||||
|
||||
dst = ldst;
|
||||
}
|
||||
if(pr_deltas) MEM_freeN(pr_deltas);
|
||||
if(cr_deltas) MEM_freeN(cr_deltas);
|
||||
|
||||
/* Update lower levels */
|
||||
lvl= me->mr->levels.last;
|
||||
lvl= lvl->prev;
|
||||
while(lvl) {
|
||||
MultiresColFace *nf= lvl->next->colfaces;
|
||||
for(i=0; i<lvl->totface; ++i) {
|
||||
MultiresFace *f= &lvl->faces[i];
|
||||
for(j=0; j<(f->v[3]?4:3); ++j) {
|
||||
lvl->colfaces[i].col[j]= nf->col[1];
|
||||
++nf;
|
||||
}
|
||||
}
|
||||
lvl= lvl->prev;
|
||||
|
||||
lvl = lvl->next;
|
||||
|
||||
for(i = 0; i < mr->level_count - 1; ++i) {
|
||||
MEM_freeN(fmap[i]);
|
||||
MEM_freeN(fmem[i]);
|
||||
MEM_freeN(emap[i]);
|
||||
MEM_freeN(emem[i]);
|
||||
}
|
||||
|
||||
MEM_freeN(fmap);
|
||||
MEM_freeN(emap);
|
||||
MEM_freeN(fmem);
|
||||
MEM_freeN(emem);
|
||||
}
|
||||
}
|
||||
|
||||
void multires_update_levels(Mesh *me, const int render)
|
||||
{
|
||||
EditMesh *em= render ? NULL : me->edit_mesh;
|
||||
|
||||
multires_update_first_level(me, em);
|
||||
multires_update_vertices(me, em);
|
||||
multires_update_faces(me, em);
|
||||
multires_update_colors(me, em);
|
||||
}
|
||||
|
||||
static void check_colors(Mesh *me)
|
||||
{
|
||||
CustomData *src= me->edit_mesh ? &me->edit_mesh->fdata : &me->fdata;
|
||||
const char col= CustomData_has_layer(src, CD_MCOL);
|
||||
|
||||
/* Check if vertex colors have been deleted or added */
|
||||
if(me->mr->use_col && !col)
|
||||
me->mr->use_col= 0;
|
||||
else if(!me->mr->use_col && col) {
|
||||
me->mr->use_col= 1;
|
||||
multires_load_cols(me);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int find_mid_edge(ListBase *vert_edge_map,
|
||||
MultiresLevel *lvl,
|
||||
const unsigned int v1,
|
||||
const unsigned int v2 )
|
||||
{
|
||||
MultiresMapNode *n= vert_edge_map[v1].first;
|
||||
while(n) {
|
||||
if(lvl->edges[n->Index].v[0]==v2 ||
|
||||
lvl->edges[n->Index].v[1]==v2)
|
||||
return lvl->edges[n->Index].mid;
|
||||
|
||||
n= n->next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static float clamp_component(const float c)
|
||||
{
|
||||
if(c<0) return 0;
|
||||
else if(c>255) return 255;
|
||||
else return c;
|
||||
}
|
||||
|
||||
void multires_to_mcol(MultiresColFace *f, MCol mcol[4])
|
||||
{
|
||||
unsigned char j;
|
||||
for(j=0; j<4; ++j) {
|
||||
mcol->a= clamp_component(f->col[j].a);
|
||||
mcol->r= clamp_component(f->col[j].r);
|
||||
mcol->g= clamp_component(f->col[j].g);
|
||||
mcol->b= clamp_component(f->col[j].b);
|
||||
++mcol;
|
||||
}
|
||||
}
|
||||
|
||||
void multires_level_to_mesh(Object *ob, Mesh *me, const int render)
|
||||
{
|
||||
MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1);
|
||||
EditMesh *em= render ? NULL : me->edit_mesh;
|
||||
int i;
|
||||
|
||||
if(em)
|
||||
return;
|
||||
|
||||
CustomData_free_layer_active(&me->vdata, CD_MVERT, me->totvert);
|
||||
CustomData_free_layer_active(&me->edata, CD_MEDGE, me->totedge);
|
||||
CustomData_free_layer_active(&me->fdata, CD_MFACE, me->totface);
|
||||
CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
|
||||
CustomData_free_layers(&me->fdata, CD_MTFACE, me->totface);
|
||||
CustomData_free_layers(&me->fdata, CD_MCOL, me->totface);
|
||||
|
||||
me->totvert= lvl->totvert;
|
||||
me->totface= lvl->totface;
|
||||
me->totedge= lvl->totedge;
|
||||
|
||||
CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert);
|
||||
CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge);
|
||||
CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface);
|
||||
mesh_update_customdata_pointers(me);
|
||||
|
||||
/* Vertices/Edges/Faces */
|
||||
|
||||
for(i=0; i<lvl->totvert; ++i) {
|
||||
me->mvert[i]= me->mr->verts[i];
|
||||
}
|
||||
for(i=0; i<lvl->totedge; ++i) {
|
||||
me->medge[i].v1= lvl->edges[i].v[0];
|
||||
me->medge[i].v2= lvl->edges[i].v[1];
|
||||
me->medge[i].flag &= ~ME_HIDE;
|
||||
}
|
||||
for(i=0; i<lvl->totface; ++i) {
|
||||
me->mface[i].v1= lvl->faces[i].v[0];
|
||||
me->mface[i].v2= lvl->faces[i].v[1];
|
||||
me->mface[i].v3= lvl->faces[i].v[2];
|
||||
me->mface[i].v4= lvl->faces[i].v[3];
|
||||
me->mface[i].flag= lvl->faces[i].flag;
|
||||
me->mface[i].flag &= ~ME_HIDE;
|
||||
me->mface[i].mat_nr= lvl->faces[i].mat_nr;
|
||||
}
|
||||
|
||||
/* Edge flags */
|
||||
if(lvl==me->mr->levels.first) {
|
||||
for(i=0; i<lvl->totedge; ++i) {
|
||||
me->medge[i].flag= me->mr->edge_flags[i];
|
||||
me->medge[i].crease= me->mr->edge_creases[i];
|
||||
}
|
||||
} else {
|
||||
MultiresLevel *lvl1= me->mr->levels.first;
|
||||
const int last= lvl1->totedge * pow(2, me->mr->current-1);
|
||||
for(i=0; i<last; ++i) {
|
||||
const int ndx= i / pow(2, me->mr->current-1);
|
||||
|
||||
me->medge[i].flag= me->mr->edge_flags[ndx];
|
||||
me->medge[i].crease= me->mr->edge_creases[ndx];
|
||||
}
|
||||
}
|
||||
|
||||
multires_customdata_to_mesh(me, em, lvl, &me->mr->vdata, em ? &em->vdata : &me->vdata, CD_MDEFORMVERT);
|
||||
multires_customdata_to_mesh(me, em, lvl, &me->mr->fdata, em ? &em->fdata : &me->fdata, CD_MTFACE);
|
||||
|
||||
/* Colors */
|
||||
if(me->mr->use_col) {
|
||||
CustomData *src= &me->fdata;
|
||||
|
||||
if(me->mr->use_col) me->mcol= CustomData_add_layer(src, CD_MCOL, CD_CALLOC, NULL, me->totface);
|
||||
|
||||
for(i=0; i<lvl->totface; ++i) {
|
||||
if(me->mr->use_col)
|
||||
multires_to_mcol(&lvl->colfaces[i], &me->mcol[i*4]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mesh_update_customdata_pointers(me);
|
||||
|
||||
multires_edge_level_update(ob,me);
|
||||
// XXX do this in caller DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
|
||||
}
|
||||
|
||||
void multires_add_level(Object *ob, Mesh *me, const char subdiv_type)
|
||||
{
|
||||
int i,j, curf, cure;
|
||||
MultiresLevel *lvl= NULL;
|
||||
MultiApplyData data;
|
||||
MVert *oldverts= NULL;
|
||||
|
||||
lvl= MEM_callocN(sizeof(MultiresLevel), "multireslevel");
|
||||
if(me->pv) mesh_pmv_off(ob, me);
|
||||
|
||||
check_colors(me);
|
||||
multires_update_levels(me, 0);
|
||||
|
||||
++me->mr->level_count;
|
||||
BLI_addtail(&me->mr->levels,lvl);
|
||||
|
||||
/* Create vertices
|
||||
=============== */
|
||||
lvl->totvert= lvl->prev->totvert + lvl->prev->totedge + lvl->prev->totface;
|
||||
oldverts= me->mr->verts;
|
||||
me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert, "multitres verts");
|
||||
/* Copy old verts */
|
||||
for(i=0; i<lvl->prev->totvert; ++i)
|
||||
me->mr->verts[i]= oldverts[i];
|
||||
/* Create new edge verts */
|
||||
for(i=0; i<lvl->prev->totedge; ++i) {
|
||||
VecMidf(me->mr->verts[lvl->prev->totvert + i].co,
|
||||
oldverts[lvl->prev->edges[i].v[0]].co,
|
||||
oldverts[lvl->prev->edges[i].v[1]].co);
|
||||
lvl->prev->edges[i].mid= lvl->prev->totvert + i;
|
||||
}
|
||||
/* Create new face verts */
|
||||
for(i=0; i<lvl->prev->totface; ++i) {
|
||||
lvl->prev->faces[i].mid= lvl->prev->totvert + lvl->prev->totedge + i;
|
||||
}
|
||||
|
||||
multires_calc_temp_data(lvl->prev);
|
||||
|
||||
/* Create faces
|
||||
============ */
|
||||
/* Allocate all the new faces (each triangle creates three, and
|
||||
each quad creates four */
|
||||
lvl->totface= 0;
|
||||
for(i=0; i<lvl->prev->totface; ++i)
|
||||
lvl->totface+= lvl->prev->faces[i].v[3] ? 4 : 3;
|
||||
lvl->faces= MEM_callocN(sizeof(MultiresFace)*lvl->totface,"multires faces");
|
||||
|
||||
curf= 0;
|
||||
for(i=0; i<lvl->prev->totface; ++i) {
|
||||
const int max= lvl->prev->faces[i].v[3] ? 3 : 2;
|
||||
|
||||
for(j=0; j<max+1; ++j) {
|
||||
lvl->faces[curf].v[0]= find_mid_edge(lvl->prev->vert_edge_map,lvl->prev,
|
||||
lvl->prev->faces[i].v[j],
|
||||
lvl->prev->faces[i].v[j==0?max:j-1]);
|
||||
lvl->faces[curf].v[1]= lvl->prev->faces[i].v[j];
|
||||
lvl->faces[curf].v[2]= find_mid_edge(lvl->prev->vert_edge_map,lvl->prev,
|
||||
lvl->prev->faces[i].v[j],
|
||||
lvl->prev->faces[i].v[j==max?0:j+1]);
|
||||
lvl->faces[curf].v[3]= lvl->prev->totvert + lvl->prev->totedge + i;
|
||||
lvl->faces[curf].flag= lvl->prev->faces[i].flag;
|
||||
lvl->faces[curf].mat_nr= lvl->prev->faces[i].mat_nr;
|
||||
|
||||
++curf;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create edges
|
||||
============ */
|
||||
/* Figure out how many edges to allocate */
|
||||
lvl->totedge= lvl->prev->totedge*2;
|
||||
for(i=0; i<lvl->prev->totface; ++i)
|
||||
lvl->totedge+= lvl->prev->faces[i].v[3]?4:3;
|
||||
lvl->edges= MEM_callocN(sizeof(MultiresEdge)*lvl->totedge,"multires edges");
|
||||
|
||||
for(i=0; i<lvl->prev->totedge; ++i) {
|
||||
lvl->edges[i*2].v[0]= lvl->prev->edges[i].v[0];
|
||||
lvl->edges[i*2].v[1]= lvl->prev->edges[i].mid;
|
||||
lvl->edges[i*2+1].v[0]= lvl->prev->edges[i].mid;
|
||||
lvl->edges[i*2+1].v[1]= lvl->prev->edges[i].v[1];
|
||||
}
|
||||
/* Add edges inside of old polygons */
|
||||
curf= 0;
|
||||
cure= lvl->prev->totedge*2;
|
||||
for(i=0; i<lvl->prev->totface; ++i) {
|
||||
for(j=0; j<(lvl->prev->faces[i].v[3]?4:3); ++j) {
|
||||
lvl->edges[cure].v[0]= lvl->faces[curf].v[2];
|
||||
lvl->edges[cure].v[1]= lvl->faces[curf].v[3];
|
||||
++cure;
|
||||
++curf;
|
||||
}
|
||||
}
|
||||
|
||||
/* Smooth vertices
|
||||
=============== */
|
||||
for(i=0; i<lvl->prev->totface; ++i) {
|
||||
const MultiresFace *f= &lvl->prev->faces[i];
|
||||
data.corner1= oldverts[f->v[0]].co;
|
||||
data.corner2= oldverts[f->v[1]].co;
|
||||
data.corner3= oldverts[f->v[2]].co;
|
||||
data.corner4= oldverts[f->v[3]].co;
|
||||
data.quad= f->v[3] ? 1 : 0;
|
||||
multi_apply(me->mr->verts[f->mid].co, &data, 3, catmullclark_smooth_face);
|
||||
}
|
||||
|
||||
if(subdiv_type == 0) {
|
||||
for(i=0; i<lvl->prev->totedge; ++i) {
|
||||
const MultiresEdge *e= &lvl->prev->edges[i];
|
||||
data.boundary= lvl->prev->edge_boundary_states[i];
|
||||
edge_face_neighbor_midpoints_accum(&data,lvl->prev, me->mr->verts, sizeof(MVert),e);
|
||||
data.endpoint1= oldverts[e->v[0]].co;
|
||||
data.endpoint2= oldverts[e->v[1]].co;
|
||||
multi_apply(me->mr->verts[e->mid].co, &data, 3, catmullclark_smooth_edge);
|
||||
}
|
||||
|
||||
for(i=0; i<lvl->prev->totvert; ++i) {
|
||||
data.boundary= multires_vert_is_boundary(lvl->prev,i);
|
||||
data.original= oldverts[i].co;
|
||||
data.edge_count= BLI_countlist(&lvl->prev->vert_edge_map[i]);
|
||||
if(data.boundary)
|
||||
boundary_edges_average(&data,lvl->prev, oldverts, sizeof(MVert),i);
|
||||
else {
|
||||
vert_face_neighbor_midpoints_average(&data,lvl->prev, me->mr->verts,
|
||||
sizeof(MVert),i);
|
||||
vert_edge_neighbor_midpoints_average(&data,lvl->prev, oldverts,
|
||||
sizeof(MVert),i);
|
||||
}
|
||||
multi_apply(me->mr->verts[i].co, &data, 3, catmullclark_smooth_vert);
|
||||
}
|
||||
}
|
||||
|
||||
multires_free_temp_data(lvl->prev);
|
||||
MEM_freeN(oldverts);
|
||||
|
||||
/* Vertex Colors
|
||||
============= */
|
||||
curf= 0;
|
||||
if(me->mr->use_col) {
|
||||
MultiresColFace *cf= MEM_callocN(sizeof(MultiresColFace)*lvl->totface,"Multirescolfaces");
|
||||
lvl->colfaces= cf;
|
||||
for(i=0; i<lvl->prev->totface; ++i) {
|
||||
const char sides= lvl->prev->faces[i].v[3]?4:3;
|
||||
MultiresCol cntr;
|
||||
|
||||
/* Find average color of 4 (or 3 for triangle) verts */
|
||||
multires_col_avg(&cntr,lvl->prev->colfaces[i].col,sides);
|
||||
|
||||
for(j=0; j<sides; ++j) {
|
||||
multires_col_avg2(&cf->col[0],
|
||||
&lvl->prev->colfaces[i].col[j],
|
||||
&lvl->prev->colfaces[i].col[j==0?sides-1:j-1]);
|
||||
cf->col[1]= lvl->prev->colfaces[i].col[j];
|
||||
multires_col_avg2(&cf->col[2],
|
||||
&lvl->prev->colfaces[i].col[j],
|
||||
&lvl->prev->colfaces[i].col[j==sides-1?0:j+1]);
|
||||
cf->col[3]= cntr;
|
||||
|
||||
++cf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
me->mr->newlvl= me->mr->level_count;
|
||||
me->mr->current= me->mr->newlvl;
|
||||
/* Unless the render level has been set to something other than the
|
||||
highest level (by the user), increment the render level to match
|
||||
the highest available level */
|
||||
if(me->mr->renderlvl == me->mr->level_count - 1) me->mr->renderlvl= me->mr->level_count;
|
||||
|
||||
multires_level_to_mesh(ob, me, 0);
|
||||
}
|
||||
|
||||
void multires_set_level(Object *ob, Mesh *me, const int render)
|
||||
{
|
||||
if(me->pv) mesh_pmv_off(ob, me);
|
||||
|
||||
check_colors(me);
|
||||
multires_update_levels(me, render);
|
||||
|
||||
me->mr->current= me->mr->newlvl;
|
||||
if(me->mr->current<1) me->mr->current= 1;
|
||||
else if(me->mr->current>me->mr->level_count) me->mr->current= me->mr->level_count;
|
||||
|
||||
multires_level_to_mesh(ob, me, render);
|
||||
}
|
||||
|
||||
/* Update the edge visibility flags to only show edges on or below the edgelvl */
|
||||
void multires_edge_level_update(Object *ob, Mesh *me)
|
||||
{
|
||||
if(!me->edit_mesh) {
|
||||
MultiresLevel *cr_lvl= BLI_findlink(&me->mr->levels,me->mr->current-1);
|
||||
MultiresLevel *edge_lvl= BLI_findlink(&me->mr->levels,me->mr->edgelvl-1);
|
||||
const int threshold= edge_lvl->totedge * pow(2, me->mr->current - me->mr->edgelvl);
|
||||
unsigned i;
|
||||
|
||||
for(i=0; i<cr_lvl->totedge; ++i) {
|
||||
const int ndx= me->pv ? me->pv->edge_map[i] : i;
|
||||
if(ndx != -1) { /* -1= hidden edge */
|
||||
if(me->mr->edgelvl >= me->mr->current || i<threshold)
|
||||
me->medge[ndx].flag |= ME_EDGEDRAW | ME_EDGERENDER;
|
||||
else
|
||||
me->medge[ndx].flag &= ~ME_EDGEDRAW & ~ME_EDGERENDER;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX do this in caller DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
}
|
||||
|
||||
/* Transfer verts */
|
||||
for(i = 0; i < totvert; ++i)
|
||||
VecCopyf(vdst[i].co, vsrc[vvmap[i]].co);
|
||||
|
||||
MEM_freeN(vvmap);
|
||||
}
|
||||
|
||||
@@ -707,7 +707,6 @@ void sculptsession_free(Scene *sce)
|
||||
}
|
||||
}
|
||||
|
||||
/* Default curve approximates 0.5 * (cos(pi * x) + 1), with 0 <= x <= 1 */
|
||||
void sculpt_reset_curve(SculptData *sd)
|
||||
{
|
||||
CurveMap *cm = NULL;
|
||||
@@ -719,21 +718,15 @@ void sculpt_reset_curve(SculptData *sd)
|
||||
|
||||
if(cm->curve)
|
||||
MEM_freeN(cm->curve);
|
||||
cm->curve= MEM_callocN(6*sizeof(CurveMapPoint), "curve points");
|
||||
cm->curve= MEM_callocN(3*sizeof(CurveMapPoint), "curve points");
|
||||
cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
|
||||
cm->totpoint= 6;
|
||||
cm->totpoint= 3;
|
||||
cm->curve[0].x= 0;
|
||||
cm->curve[0].y= 1;
|
||||
cm->curve[1].x= 0.1;
|
||||
cm->curve[1].y= 0.97553;
|
||||
cm->curve[2].x= 0.3;
|
||||
cm->curve[2].y= 0.79389;
|
||||
cm->curve[3].x= 0.9;
|
||||
cm->curve[3].y= 0.02447;
|
||||
cm->curve[4].x= 0.7;
|
||||
cm->curve[4].y= 0.20611;
|
||||
cm->curve[5].x= 1;
|
||||
cm->curve[5].y= 0;
|
||||
cm->curve[1].x= 0.33;
|
||||
cm->curve[1].y= 0.33;
|
||||
cm->curve[2].x= 1;
|
||||
cm->curve[2].y= 0;
|
||||
|
||||
curvemapping_changed(sd->cumap, 0);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_subsurf.h"
|
||||
|
||||
@@ -471,7 +472,7 @@ static void calc_ss_weights(int gridFaces,
|
||||
|
||||
static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
|
||||
int drawInteriorEdges, int useSubsurfUv,
|
||||
DerivedMesh *dm)
|
||||
DerivedMesh *dm, MultiresSubsurf *ms)
|
||||
{
|
||||
DerivedMesh *result;
|
||||
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
||||
@@ -524,14 +525,21 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
|
||||
}
|
||||
ccgFaceIterator_free(fi);
|
||||
|
||||
if(dm) {
|
||||
result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss),
|
||||
ccgSubSurf_getNumFinalEdges(ss),
|
||||
ccgSubSurf_getNumFinalFaces(ss));
|
||||
} else {
|
||||
result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss),
|
||||
ccgSubSurf_getNumFinalEdges(ss),
|
||||
ccgSubSurf_getNumFinalFaces(ss));
|
||||
if(ms) {
|
||||
result = MultiresDM_new(ms, dm, ccgSubSurf_getNumFinalVerts(ss),
|
||||
ccgSubSurf_getNumFinalEdges(ss),
|
||||
ccgSubSurf_getNumFinalFaces(ss));
|
||||
}
|
||||
else {
|
||||
if(dm) {
|
||||
result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss),
|
||||
ccgSubSurf_getNumFinalEdges(ss),
|
||||
ccgSubSurf_getNumFinalFaces(ss));
|
||||
} else {
|
||||
result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss),
|
||||
ccgSubSurf_getNumFinalEdges(ss),
|
||||
ccgSubSurf_getNumFinalFaces(ss));
|
||||
}
|
||||
}
|
||||
|
||||
// load verts
|
||||
@@ -557,11 +565,12 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
|
||||
++mvert;
|
||||
++origIndex;
|
||||
i++;
|
||||
|
||||
|
||||
for(S = 0; S < numVerts; S++) {
|
||||
int prevS = (S - 1 + numVerts) % numVerts;
|
||||
int nextS = (S + 1) % numVerts;
|
||||
int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
|
||||
|
||||
for(x = 1; x < gridFaces; x++) {
|
||||
float w[4];
|
||||
w[prevS] = weight[x][0][0];
|
||||
@@ -571,6 +580,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
|
||||
DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i);
|
||||
VecCopyf(mvert->co,
|
||||
ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
|
||||
|
||||
*origIndex = ORIGINDEX_NONE;
|
||||
++mvert;
|
||||
++origIndex;
|
||||
@@ -582,6 +592,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
|
||||
int prevS = (S - 1 + numVerts) % numVerts;
|
||||
int nextS = (S + 1) % numVerts;
|
||||
int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
|
||||
|
||||
for(y = 1; y < gridFaces; y++) {
|
||||
for(x = 1; x < gridFaces; x++) {
|
||||
float w[4];
|
||||
@@ -2565,9 +2576,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
|
||||
|
||||
/***/
|
||||
|
||||
struct DerivedMesh *subsurf_make_derived_from_derived(
|
||||
struct DerivedMesh *subsurf_make_derived_from_derived_with_multires(
|
||||
struct DerivedMesh *dm,
|
||||
struct SubsurfModifierData *smd,
|
||||
struct MultiresSubsurf *ms,
|
||||
int useRenderParams, float (*vertCos)[3],
|
||||
int isFinalCalc, int editMode)
|
||||
{
|
||||
@@ -2599,7 +2611,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
|
||||
ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
|
||||
|
||||
result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges,
|
||||
useSubsurfUv, dm);
|
||||
useSubsurfUv, dm, ms);
|
||||
|
||||
ccgSubSurf_free(ss);
|
||||
|
||||
@@ -2630,7 +2642,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
|
||||
|
||||
|
||||
return ss_to_cdderivedmesh(ss, 0, drawInteriorEdges,
|
||||
useSubsurfUv, dm);
|
||||
useSubsurfUv, dm, ms);
|
||||
|
||||
/*return (DerivedMesh *)getCCGDerivedMesh(smd->mCache,
|
||||
drawInteriorEdges,
|
||||
@@ -2650,7 +2662,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
|
||||
useSubsurfUv, dm);*/
|
||||
|
||||
result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges,
|
||||
useSubsurfUv, dm);
|
||||
useSubsurfUv, dm, ms);
|
||||
|
||||
ccgSubSurf_free(ss);
|
||||
|
||||
@@ -2659,6 +2671,15 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
|
||||
}
|
||||
}
|
||||
|
||||
struct DerivedMesh *subsurf_make_derived_from_derived(
|
||||
struct DerivedMesh *dm,
|
||||
struct SubsurfModifierData *smd,
|
||||
int useRenderParams, float (*vertCos)[3],
|
||||
int isFinalCalc, int editMode)
|
||||
{
|
||||
return subsurf_make_derived_from_derived_with_multires(dm, smd, NULL, useRenderParams, vertCos, isFinalCalc, editMode);
|
||||
}
|
||||
|
||||
void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3])
|
||||
{
|
||||
/* Finds the subsurf limit positions for the verts in a mesh
|
||||
|
||||
@@ -125,6 +125,7 @@
|
||||
#include "BKE_main.h" // for Main
|
||||
#include "BKE_mesh.h" // for ME_ defines (patching)
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_node.h" // for tree type defines
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
@@ -2803,6 +2804,19 @@ static void direct_link_dverts(FileData *fd, int count, MDeformVert *mdverts)
|
||||
}
|
||||
}
|
||||
|
||||
static void direct_link_mdisps(FileData *fd, int count, MDisps *mdisps)
|
||||
{
|
||||
if(mdisps) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < count; ++i) {
|
||||
mdisps[i].disps = newdataadr(fd, mdisps[i].disps);
|
||||
if(!mdisps[i].disps)
|
||||
mdisps[i].totdisp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void direct_link_customdata(FileData *fd, CustomData *data, int count)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -2814,6 +2828,8 @@ static void direct_link_customdata(FileData *fd, CustomData *data, int count)
|
||||
|
||||
if (CustomData_verify_versions(data, i)) {
|
||||
layer->data = newdataadr(fd, layer->data);
|
||||
if(layer->type == CD_MDISPS)
|
||||
direct_link_mdisps(fd, count, layer->data);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@@ -2866,11 +2882,6 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
|
||||
direct_link_dverts(fd, lvl->totvert, CustomData_get(&mesh->mr->vdata, 0, CD_MDEFORMVERT));
|
||||
direct_link_customdata(fd, &mesh->mr->fdata, lvl->totface);
|
||||
|
||||
if(mesh->mr->edge_flags)
|
||||
mesh->mr->edge_flags= newdataadr(fd, mesh->mr->edge_flags);
|
||||
if(mesh->mr->edge_creases)
|
||||
mesh->mr->edge_creases= newdataadr(fd, mesh->mr->edge_creases);
|
||||
|
||||
if(!mesh->mr->edge_flags)
|
||||
mesh->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "Multires Edge Flags");
|
||||
if(!mesh->mr->edge_creases)
|
||||
@@ -2883,9 +2894,6 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
|
||||
lvl->faces= newdataadr(fd, lvl->faces);
|
||||
lvl->edges= newdataadr(fd, lvl->edges);
|
||||
lvl->colfaces= newdataadr(fd, lvl->colfaces);
|
||||
lvl->edge_boundary_states= NULL;
|
||||
lvl->vert_face_map = lvl->vert_edge_map = NULL;
|
||||
lvl->map_mem= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3273,6 +3281,12 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
|
||||
SWITCH_INT(mmd->dynverts[a])
|
||||
}
|
||||
}
|
||||
else if (md->type==eModifierType_Multires) {
|
||||
MultiresModifierData *mmd = (MultiresModifierData*) md;
|
||||
|
||||
mmd->undo_verts = newdataadr(fd, mmd->undo_verts);
|
||||
mmd->undo_signal = !!mmd->undo_verts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8491,8 +8505,78 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
strcpy(tx->nodetree->id.name, "NTTexture Nodetree");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* TODO: should be moved into one of the version blocks once this branch moves to trunk and we can
|
||||
bump the version (or sub-version.) */
|
||||
{
|
||||
Object *ob;
|
||||
int i;
|
||||
|
||||
for(ob = main->object.first; ob; ob = ob->id.next) {
|
||||
|
||||
if(ob->type == OB_MESH) {
|
||||
Mesh *me = newlibadr(fd, lib, ob->data);
|
||||
void *olddata = ob->data;
|
||||
ob->data = me;
|
||||
|
||||
if(me && me->mr) {
|
||||
MultiresLevel *lvl;
|
||||
ModifierData *md;
|
||||
MultiresModifierData *mmd;
|
||||
DerivedMesh *dm, *orig;
|
||||
|
||||
/* Load original level into the mesh */
|
||||
lvl = me->mr->levels.first;
|
||||
CustomData_free_layers(&me->vdata, CD_MVERT, lvl->totvert);
|
||||
CustomData_free_layers(&me->edata, CD_MEDGE, lvl->totedge);
|
||||
CustomData_free_layers(&me->fdata, CD_MFACE, lvl->totface);
|
||||
me->totvert = lvl->totvert;
|
||||
me->totedge = lvl->totedge;
|
||||
me->totface = lvl->totface;
|
||||
me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert);
|
||||
me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge);
|
||||
me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface);
|
||||
memcpy(me->mvert, me->mr->verts, sizeof(MVert) * me->totvert);
|
||||
for(i = 0; i < me->totedge; ++i) {
|
||||
me->medge[i].v1 = lvl->edges[i].v[0];
|
||||
me->medge[i].v2 = lvl->edges[i].v[1];
|
||||
}
|
||||
for(i = 0; i < me->totface; ++i) {
|
||||
me->mface[i].v1 = lvl->faces[i].v[0];
|
||||
me->mface[i].v2 = lvl->faces[i].v[1];
|
||||
me->mface[i].v3 = lvl->faces[i].v[2];
|
||||
me->mface[i].v4 = lvl->faces[i].v[3];
|
||||
}
|
||||
|
||||
/* Add a multires modifier to the object */
|
||||
md = ob->modifiers.first;
|
||||
while(md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
|
||||
md = md->next;
|
||||
mmd = (MultiresModifierData*)modifier_new(eModifierType_Multires);
|
||||
BLI_insertlinkbefore(&ob->modifiers, md, mmd);
|
||||
|
||||
multiresModifier_subdivide(mmd, ob, me->mr->level_count - 1, 1, 0);
|
||||
|
||||
mmd->lvl = mmd->totlvl;
|
||||
orig = CDDM_from_mesh(me, NULL);
|
||||
dm = multires_dm_create_from_derived(mmd, orig, me, 0, 0);
|
||||
|
||||
multires_load_old(dm, me->mr);
|
||||
|
||||
*MultiresDM_get_flags(dm) |= MULTIRES_DM_UPDATE_ALWAYS;
|
||||
dm->release(dm);
|
||||
orig->release(orig);
|
||||
|
||||
/* Remove the old multires */
|
||||
multires_free(me->mr);
|
||||
me->mr = NULL;
|
||||
}
|
||||
|
||||
ob->data = olddata;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
||||
/* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
|
||||
|
||||
|
||||
@@ -852,7 +852,7 @@ static void write_constraint_channels(WriteData *wd, ListBase *chanbase)
|
||||
|
||||
}
|
||||
|
||||
static void write_modifiers(WriteData *wd, ListBase *modbase)
|
||||
static void write_modifiers(WriteData *wd, ListBase *modbase, int write_undo)
|
||||
{
|
||||
ModifierData *md;
|
||||
|
||||
@@ -903,10 +903,16 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
|
||||
writestruct(wd, DATA, "MDefInfluence", mmd->totinfluence, mmd->dyninfluences);
|
||||
writedata(wd, DATA, sizeof(int)*mmd->totvert, mmd->dynverts);
|
||||
}
|
||||
else if (md->type==eModifierType_Multires) {
|
||||
MultiresModifierData *mmd = (MultiresModifierData*) md;
|
||||
|
||||
if(mmd->undo_verts && write_undo)
|
||||
writestruct(wd, DATA, "MVert", mmd->undo_verts_tot, mmd->undo_verts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void write_objects(WriteData *wd, ListBase *idbase)
|
||||
static void write_objects(WriteData *wd, ListBase *idbase, int write_undo)
|
||||
{
|
||||
Object *ob;
|
||||
|
||||
@@ -940,7 +946,7 @@ static void write_objects(WriteData *wd, ListBase *idbase)
|
||||
writestruct(wd, DATA, "BulletSoftBody", 1, ob->bsoft);
|
||||
|
||||
write_particlesystems(wd, &ob->particlesystem);
|
||||
write_modifiers(wd, &ob->modifiers);
|
||||
write_modifiers(wd, &ob->modifiers, write_undo);
|
||||
}
|
||||
ob= ob->id.next;
|
||||
}
|
||||
@@ -1138,7 +1144,7 @@ static void write_curves(WriteData *wd, ListBase *idbase)
|
||||
static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist)
|
||||
{
|
||||
if (dvlist) {
|
||||
int i;
|
||||
int i;
|
||||
|
||||
/* Write the dvert list */
|
||||
writestruct(wd, DATA, "MDeformVert", count, dvlist);
|
||||
@@ -1151,6 +1157,19 @@ static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist)
|
||||
}
|
||||
}
|
||||
|
||||
static void write_mdisps(WriteData *wd, int count, MDisps *mdlist)
|
||||
{
|
||||
if(mdlist) {
|
||||
int i;
|
||||
|
||||
writestruct(wd, DATA, "MDisps", count, mdlist);
|
||||
for(i = 0; i < count; ++i) {
|
||||
if(mdlist[i].disps)
|
||||
writedata(wd, DATA, sizeof(float)*3*mdlist[i].totdisp, mdlist[i].disps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void write_customdata(WriteData *wd, int count, CustomData *data, int partial_type, int partial_count)
|
||||
{
|
||||
int i;
|
||||
@@ -1166,6 +1185,9 @@ static void write_customdata(WriteData *wd, int count, CustomData *data, int par
|
||||
/* layer types that allocate own memory need special handling */
|
||||
write_dverts(wd, count, layer->data);
|
||||
}
|
||||
else if (layer->type == CD_MDISPS) {
|
||||
write_mdisps(wd, count, layer->data);
|
||||
}
|
||||
else {
|
||||
CustomData_file_write_info(layer->type, &structname, &structnum);
|
||||
if (structnum) {
|
||||
@@ -1186,7 +1208,6 @@ static void write_customdata(WriteData *wd, int count, CustomData *data, int par
|
||||
static void write_meshs(WriteData *wd, ListBase *idbase)
|
||||
{
|
||||
Mesh *mesh;
|
||||
MultiresLevel *lvl;
|
||||
|
||||
mesh= idbase->first;
|
||||
while(mesh) {
|
||||
@@ -1212,29 +1233,6 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
|
||||
write_customdata(wd, mesh->totface, &mesh->fdata, -1, 0);
|
||||
}
|
||||
|
||||
/* Multires data */
|
||||
writestruct(wd, DATA, "Multires", 1, mesh->mr);
|
||||
if(mesh->mr) {
|
||||
lvl= mesh->mr->levels.first;
|
||||
if(lvl) {
|
||||
write_customdata(wd, lvl->totvert, &mesh->mr->vdata, -1, 0);
|
||||
write_customdata(wd, lvl->totface, &mesh->mr->fdata, -1, 0);
|
||||
writedata(wd, DATA, sizeof(short)*lvl->totedge, mesh->mr->edge_flags);
|
||||
writedata(wd, DATA, sizeof(char)*lvl->totedge, mesh->mr->edge_creases);
|
||||
}
|
||||
|
||||
for(; lvl; lvl= lvl->next) {
|
||||
writestruct(wd, DATA, "MultiresLevel", 1, lvl);
|
||||
writestruct(wd, DATA, "MultiresFace", lvl->totface, lvl->faces);
|
||||
writestruct(wd, DATA, "MultiresEdge", lvl->totedge, lvl->edges);
|
||||
writestruct(wd, DATA, "MultiresColFace", lvl->totface, lvl->colfaces);
|
||||
}
|
||||
|
||||
lvl= mesh->mr->levels.last;
|
||||
if(lvl)
|
||||
writestruct(wd, DATA, "MVert", lvl->totvert, mesh->mr->verts);
|
||||
}
|
||||
|
||||
/* PMV data */
|
||||
if(mesh->pv) {
|
||||
writestruct(wd, DATA, "PartialVisibility", 1, mesh->pv);
|
||||
@@ -2098,7 +2096,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
|
||||
write_groups (wd, &mainvar->group);
|
||||
write_armatures(wd, &mainvar->armature);
|
||||
write_actions (wd, &mainvar->action);
|
||||
write_objects (wd, &mainvar->object);
|
||||
write_objects (wd, &mainvar->object, (current != NULL));
|
||||
write_materials(wd, &mainvar->mat);
|
||||
write_textures (wd, &mainvar->tex);
|
||||
write_meshs (wd, &mainvar->mesh);
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2006 by Nicholas Bishop
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef MULTIRES_H
|
||||
#define MULTIRES_H
|
||||
|
||||
struct CustomData;
|
||||
struct EditMesh;
|
||||
struct Object;
|
||||
struct MDeformVert;
|
||||
struct Mesh;
|
||||
struct MultiresLevel;
|
||||
struct Multires;
|
||||
struct uiBlock;
|
||||
|
||||
/* For canceling operations that don't work with multires on or on a non-base level */
|
||||
int multires_test();
|
||||
int multires_level1_test();
|
||||
|
||||
void multires_draw_interface(struct uiBlock *block, unsigned short cx, unsigned short cy);
|
||||
|
||||
void multires_make(void *ob, void *me);
|
||||
void multires_delete(void *ob, void *me);
|
||||
void multires_level_to_editmesh(struct Object *ob, struct Mesh *me, const int render);
|
||||
void multires_finish_mesh_update(struct Object *ob);
|
||||
void multires_subdivide(void *ob, void *me);
|
||||
void multires_del_lower(void *ob, void *me);
|
||||
void multires_del_higher(void *ob, void *me);
|
||||
void multires_set_level_cb(void *ob, void *me);
|
||||
void multires_edge_level_update_cb(void *ob, void *me);
|
||||
int multires_modifier_warning();
|
||||
|
||||
#endif
|
||||
@@ -56,7 +56,6 @@
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_texture.h"
|
||||
#include "BKE_utildefines.h"
|
||||
@@ -628,14 +627,8 @@ static void make_tfaces(Object *ob)
|
||||
Mesh *me= ob->data;
|
||||
|
||||
if(!me->mtface) {
|
||||
if(me->mr) {
|
||||
multires_add_layer(ob, &me->mr->fdata, CD_MTFACE,
|
||||
CustomData_number_of_layers(&me->fdata, CD_MTFACE));
|
||||
}
|
||||
else {
|
||||
me->mtface= CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT,
|
||||
NULL, me->totface);
|
||||
}
|
||||
me->mtface= CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT,
|
||||
NULL, me->totface);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_softbody.h"
|
||||
@@ -97,7 +96,6 @@ static void waitcursor() {}
|
||||
static void error() {}
|
||||
static int pupmenu() {return 0;}
|
||||
static void key_to_mesh() {}
|
||||
static int multires_test() {return 0;}
|
||||
static void adduplicate() {}
|
||||
|
||||
|
||||
@@ -1443,7 +1441,6 @@ void separate_mesh(Scene *scene, Object *obedit)
|
||||
ListBase edve, eded, edvl;
|
||||
|
||||
if(obedit==NULL) return;
|
||||
if(multires_test()) return;
|
||||
|
||||
waitcursor(1);
|
||||
|
||||
@@ -1572,8 +1569,6 @@ void separate_material(Scene *scene, Object *obedit)
|
||||
EditMesh *em;
|
||||
unsigned char curr_mat;
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
me= obedit->data;
|
||||
em= me->edit_mesh;
|
||||
if(me->key) {
|
||||
@@ -1620,7 +1615,6 @@ void separate_mesh_loose(Scene *scene, Object *obedit)
|
||||
return;
|
||||
}
|
||||
|
||||
if(multires_test()) return;
|
||||
waitcursor(1);
|
||||
|
||||
/* we are going to abuse the system as follows:
|
||||
@@ -1830,11 +1824,6 @@ typedef struct EditSelectionC{
|
||||
int index;
|
||||
}EditSelectionC;
|
||||
|
||||
typedef struct EM_MultiresUndo {
|
||||
int users;
|
||||
Multires *mr;
|
||||
} EM_MultiresUndo;
|
||||
|
||||
typedef struct UndoMesh {
|
||||
EditVertC *verts;
|
||||
EditEdgeC *edges;
|
||||
@@ -1845,7 +1834,6 @@ typedef struct UndoMesh {
|
||||
RetopoPaintData *retopo_paint_data;
|
||||
char retopo_mode;
|
||||
CustomData vdata, edata, fdata;
|
||||
EM_MultiresUndo *mru;
|
||||
} UndoMesh;
|
||||
|
||||
/* for callbacks */
|
||||
@@ -1865,14 +1853,6 @@ static void free_undoMesh(void *umv)
|
||||
CustomData_free(&um->vdata, um->totvert);
|
||||
CustomData_free(&um->edata, um->totedge);
|
||||
CustomData_free(&um->fdata, um->totface);
|
||||
if(um->mru) {
|
||||
--um->mru->users;
|
||||
if(um->mru->users==0) {
|
||||
multires_free(um->mru->mr);
|
||||
um->mru->mr= NULL;
|
||||
MEM_freeN(um->mru);
|
||||
}
|
||||
}
|
||||
MEM_freeN(um);
|
||||
}
|
||||
|
||||
@@ -1973,25 +1953,6 @@ static void *editMesh_to_undoMesh(void *emv)
|
||||
// XXX um->retopo_paint_data= retopo_paint_data_copy(em->retopo_paint_data);
|
||||
// um->retopo_mode= scene->toolsettings->retopo_mode;
|
||||
|
||||
{
|
||||
Multires *mr= NULL; // XXX old-style multires
|
||||
UndoMesh *prev= NULL; // XXX undo_editmode_get_prev(obedit);
|
||||
|
||||
um->mru= NULL;
|
||||
|
||||
if(mr) {
|
||||
if(prev && prev->mru && prev->mru->mr && prev->mru->mr->current == mr->current) {
|
||||
um->mru= prev->mru;
|
||||
++um->mru->users;
|
||||
}
|
||||
else {
|
||||
um->mru= MEM_callocN(sizeof(EM_MultiresUndo), "EM_MultiresUndo");
|
||||
um->mru->users= 1;
|
||||
um->mru->mr= multires_copy(mr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return um;
|
||||
}
|
||||
|
||||
@@ -2101,12 +2062,6 @@ static void undoMesh_to_editMesh(void *umv, void *emv)
|
||||
// retopo_paint_view_update(G.vd);
|
||||
// }
|
||||
|
||||
{
|
||||
Mesh *me= NULL; // XXX;
|
||||
multires_free(me->mr);
|
||||
me->mr= NULL;
|
||||
if(um->mru && um->mru->mr) me->mr= multires_copy(um->mru->mr);
|
||||
}
|
||||
}
|
||||
|
||||
static void *getEditMesh(bContext *C)
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
#include "BIF_retopo.h"
|
||||
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_multires.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "mesh_intern.h"
|
||||
@@ -138,8 +137,6 @@ void add_click_mesh(Scene *scene, Object *obedit, EditMesh *em)
|
||||
float min[3], max[3];
|
||||
int done= 0;
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
INIT_MINMAX(min, max);
|
||||
|
||||
for(v1= em->verts.first;v1; v1=v1->next) {
|
||||
@@ -610,8 +607,6 @@ void addedgeface_mesh(EditMesh *em)
|
||||
EditFace *efa;
|
||||
short amount=0;
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
/* how many selected ? */
|
||||
if(em->selectmode & SCE_SELECT_EDGE) {
|
||||
/* in edge mode finding selected vertices means flushing down edge codes... */
|
||||
@@ -741,8 +736,6 @@ void addedgeface_mesh(EditMesh *em)
|
||||
void adduplicate_mesh(Scene *scene, Object *obedit, EditMesh *em)
|
||||
{
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
waitcursor(1);
|
||||
|
||||
adduplicateflag(em, SELECT);
|
||||
@@ -1250,8 +1243,6 @@ void add_primitiveMesh(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em,
|
||||
/* this function also comes from an info window */
|
||||
// XXX if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
|
||||
|
||||
if (obedit && obedit->type==OB_MESH && multires_test()) return;
|
||||
|
||||
/* if editmode exists for other type, it exits */
|
||||
check_editmode(OB_MESH);
|
||||
|
||||
|
||||
@@ -79,7 +79,6 @@ editmesh_mods.c, UI level access, no geometry changes
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "ED_multires.h"
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_view3d.h"
|
||||
@@ -3346,8 +3345,6 @@ void editmesh_mark_seam(EditMesh *em, int clear)
|
||||
{
|
||||
EditEdge *eed;
|
||||
|
||||
// XXX if(multires_level1_test()) return;
|
||||
|
||||
/* auto-enable seams drawing */
|
||||
if(clear==0) {
|
||||
if(!(G.f & G_DRAWSEAMS)) {
|
||||
@@ -3391,8 +3388,6 @@ void editmesh_mark_sharp(EditMesh *em, int set)
|
||||
}
|
||||
#endif
|
||||
|
||||
// XXX if(multires_level1_test()) return;
|
||||
|
||||
if(set) {
|
||||
eed= em->edges.first;
|
||||
while(eed) {
|
||||
|
||||
@@ -78,7 +78,6 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
|
||||
|
||||
#include "BMF_Api.h"
|
||||
|
||||
#include "ED_multires.h"
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
@@ -143,8 +142,6 @@ void convert_to_triface(EditMesh *em, int direction)
|
||||
EditFace *efa, *efan, *next;
|
||||
float fac;
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
efa= em->faces.last;
|
||||
while(efa) {
|
||||
next= efa->prev;
|
||||
@@ -196,8 +193,6 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
|
||||
struct facesort *vlsortblock, *vsb, *vsb1;
|
||||
int a, b, test, amount;
|
||||
|
||||
if(multires_test()) return 0;
|
||||
|
||||
|
||||
/* flag 128 is cleared, count */
|
||||
|
||||
@@ -499,8 +494,6 @@ void xsortvert_flag(bContext *C, int flag)
|
||||
ListBase tbase;
|
||||
int i, amount;
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
em_setup_viewcontext(C, &vc);
|
||||
|
||||
amount = BLI_countlist(&vc.em->verts);
|
||||
@@ -540,8 +533,6 @@ void hashvert_flag(EditMesh *em, int flag)
|
||||
ListBase tbase;
|
||||
int amount, a, b;
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
/* count */
|
||||
eve= em->verts.first;
|
||||
amount= 0;
|
||||
@@ -600,8 +591,6 @@ void extrude_mesh(Object *obedit, EditMesh *em)
|
||||
float nor[3]= {0.0, 0.0, 0.0};
|
||||
short nr, transmode= 0;
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
if(em->selectmode & SCE_SELECT_VERTEX) {
|
||||
if(G.totvertsel==0) nr= 0;
|
||||
else if(G.totvertsel==1) nr= 4;
|
||||
@@ -673,8 +662,6 @@ void extrude_mesh(Object *obedit, EditMesh *em)
|
||||
void split_mesh(EditMesh *em)
|
||||
{
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
if(okee(" Split ")==0) return;
|
||||
|
||||
waitcursor(1);
|
||||
@@ -698,8 +685,6 @@ void extrude_repeat_mesh(View3D *v3d, Object *obedit, EditMesh *em, int steps, f
|
||||
float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0};
|
||||
short a;
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
/* dvec */
|
||||
dvec[0]= v3d->persinv[2][0];
|
||||
dvec[1]= v3d->persinv[2][1];
|
||||
@@ -737,8 +722,6 @@ void spin_mesh(View3D *v3d, Object *obedit, EditMesh *em, int steps, float degr,
|
||||
float phi;
|
||||
short a,ok;
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
/* imat and center and size */
|
||||
Mat3CpyMat4(bmat, obedit->obmat);
|
||||
Mat3Inv(imat,bmat);
|
||||
@@ -821,8 +804,6 @@ void screw_mesh(Object *obedit, EditMesh *em, int steps, int turns)
|
||||
EditEdge *eed;
|
||||
float dvec[3], nor[3];
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
/* clear flags */
|
||||
eve= em->verts.first;
|
||||
while(eve) {
|
||||
@@ -933,8 +914,6 @@ void delete_mesh(Object *obedit, EditMesh *em)
|
||||
int count;
|
||||
char *str="Erase";
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
event= pupmenu("Erase %t|Vertices%x10|Edges%x1|Faces%x2|All%x3|Edges & Faces%x4|Only Faces%x5|Edge Loop%x6");
|
||||
if(event<1) return;
|
||||
|
||||
@@ -1078,8 +1057,6 @@ void fill_mesh(EditMesh *em)
|
||||
short ok;
|
||||
|
||||
if(em==NULL) return;
|
||||
if(multires_test()) return;
|
||||
|
||||
waitcursor(1);
|
||||
|
||||
/* copy all selected vertices */
|
||||
@@ -2372,8 +2349,6 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float rad, int beaut
|
||||
ModifierData *md= obedit->modifiers.first;
|
||||
int ctrl= 0; // XXX
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
//Set faces f1 to 0 cause we need it later
|
||||
for(ef=em->faces.first;ef;ef = ef->next) ef->f1 = 0;
|
||||
for(eve=em->verts.first; eve; eve=eve->next) {
|
||||
@@ -2930,8 +2905,6 @@ void beauty_fill(EditMesh *em)
|
||||
float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
|
||||
int totedge, ok, notbeauty=8, onedone, vindex[4];
|
||||
|
||||
if(multires_test()) return;
|
||||
|
||||
/* - all selected edges with two faces
|
||||
* - find the faces: store them in edges (using datablock)
|
||||
* - per edge: - test convex
|
||||
@@ -3238,9 +3211,6 @@ void join_triangles(EditMesh *em)
|
||||
float limit = 0.0f; // XXX scene->toolsettings->jointrilimit;
|
||||
int i, ok, totedge=0, totseledge=0, complexedges, vindex[4];
|
||||
|
||||
/*test for multi-resolution data*/
|
||||
if(multires_test()) return;
|
||||
|
||||
/*if we take a long time on very dense meshes we want waitcursor to display*/
|
||||
waitcursor(1);
|
||||
|
||||
@@ -5586,8 +5556,6 @@ int collapseEdges(EditMesh *em)
|
||||
|
||||
mergecount = 0;
|
||||
|
||||
if(multires_test()) return 0;
|
||||
|
||||
build_edgecollection(em, &allcollections);
|
||||
groupcount = BLI_countlist(&allcollections);
|
||||
|
||||
@@ -5646,8 +5614,6 @@ int merge_firstlast(EditMesh *em, int first, int uvmerge)
|
||||
EditVert *eve,*mergevert;
|
||||
EditSelection *ese;
|
||||
|
||||
if(multires_test()) return 0;
|
||||
|
||||
/* do sanity check in mergemenu in edit.c ?*/
|
||||
if(first == 0){
|
||||
ese = em->selected.last;
|
||||
@@ -5681,8 +5647,6 @@ int merge_target(EditMesh *em, int target, int uvmerge)
|
||||
{
|
||||
EditVert *eve;
|
||||
|
||||
if(multires_test()) return 0;
|
||||
|
||||
if(target) snap_sel_to_curs();
|
||||
else snap_to_center();
|
||||
|
||||
|
||||
@@ -98,7 +98,6 @@
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mball.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
@@ -2285,9 +2284,6 @@ void ED_object_exit_editmode(bContext *C, int flag)
|
||||
if(freedata) obedit= NULL;
|
||||
scene->obedit= obedit; // XXX for context
|
||||
|
||||
if(ob->type==OB_MESH && get_mesh(ob)->mr)
|
||||
multires_edge_level_update(ob, get_mesh(ob));
|
||||
|
||||
/* also flush ob recalc, doesn't take much overhead, but used for particles */
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_OB|OB_RECALC_DATA);
|
||||
|
||||
|
||||
@@ -74,7 +74,8 @@ typedef struct CustomData {
|
||||
#define CD_MLOOPUV 16
|
||||
#define CD_MLOOPCOL 17
|
||||
#define CD_TANGENT 18
|
||||
#define CD_NUMTYPES 19
|
||||
#define CD_MDISPS 19
|
||||
#define CD_NUMTYPES 20
|
||||
/* fake type, derivedmesh wants CustomDataMask for weightpaint too, is not stored */
|
||||
#define CD_WEIGHTPAINT 30
|
||||
|
||||
@@ -98,6 +99,7 @@ typedef struct CustomData {
|
||||
#define CD_MASK_MLOOPUV (1 << CD_MLOOPUV)
|
||||
#define CD_MASK_MLOOPCOL (1 << CD_MLOOPCOL)
|
||||
#define CD_MASK_TANGENT (1 << CD_TANGENT)
|
||||
#define CD_MASK_MDISPS (1 << CD_MDISPS)
|
||||
|
||||
/* derivedmesh wants CustomDataMask for weightpaint too, is not customdata though */
|
||||
#define CD_MASK_WEIGHTPAINT (1 << CD_WEIGHTPAINT)
|
||||
|
||||
@@ -117,7 +117,14 @@ typedef struct OrigSpaceFace {
|
||||
float uv[4][2];
|
||||
} OrigSpaceFace;
|
||||
|
||||
/* Multiresolution modeling */
|
||||
typedef struct MDisps {
|
||||
/* Strange bug in SDNA: if disps pointer comes first, it fails to see totdisp */
|
||||
int totdisp;
|
||||
char pad[4];
|
||||
float (*disps)[3];
|
||||
} MDisps;
|
||||
|
||||
/** Multires structs kept for compatibility with old files **/
|
||||
typedef struct MultiresCol {
|
||||
float a, r, g, b;
|
||||
} MultiresCol;
|
||||
@@ -143,15 +150,9 @@ typedef struct MultiresLevel {
|
||||
MultiresColFace *colfaces;
|
||||
MultiresEdge *edges;
|
||||
|
||||
/* Temporary connectivity data */
|
||||
char *edge_boundary_states;
|
||||
struct ListBase *vert_edge_map;
|
||||
struct ListBase *vert_face_map;
|
||||
struct MultiresMapNode *map_mem;
|
||||
|
||||
unsigned int totvert, totface, totedge, pad;
|
||||
|
||||
/* Kept for compatibility with older files */
|
||||
/* Kept for compatibility with even older files */
|
||||
MVert *verts;
|
||||
} MultiresLevel;
|
||||
|
||||
@@ -169,6 +170,8 @@ typedef struct Multires {
|
||||
char *edge_creases;
|
||||
} Multires;
|
||||
|
||||
/** End Multires **/
|
||||
|
||||
typedef struct PartialVisibility {
|
||||
unsigned int *vert_map; /* vert_map[Old Index]= New Index */
|
||||
int *edge_map; /* edge_map[Old Index]= New Index, -1= hidden */
|
||||
@@ -266,7 +269,4 @@ typedef struct PartialVisibility {
|
||||
#define TF_PIN3 64
|
||||
#define TF_PIN4 128
|
||||
|
||||
/* multires->flag */
|
||||
#define MULTIRES_NO_RENDER 1
|
||||
|
||||
#endif
|
||||
|
||||
@@ -39,6 +39,7 @@ typedef enum ModifierType {
|
||||
eModifierType_Fluidsim,
|
||||
eModifierType_Mask,
|
||||
eModifierType_SimpleDeform,
|
||||
eModifierType_Multires,
|
||||
NUM_MODIFIER_TYPES
|
||||
} ModifierType;
|
||||
|
||||
@@ -517,6 +518,17 @@ typedef struct ExplodeModifierData {
|
||||
float protect;
|
||||
} ExplodeModifierData;
|
||||
|
||||
typedef struct MultiresModifierData {
|
||||
ModifierData modifier;
|
||||
|
||||
struct MVert *undo_verts; /* Store DerivedMesh vertices for multires undo */
|
||||
int undo_verts_tot; /* Length of undo_verts array */
|
||||
char undo_signal; /* If true, signals to replace verts with undo verts */
|
||||
|
||||
char lvl, totlvl;
|
||||
char simple;
|
||||
} MultiresModifierData;
|
||||
|
||||
typedef struct FluidsimModifierData {
|
||||
ModifierData modifier;
|
||||
|
||||
|
||||
@@ -30,10 +30,194 @@
|
||||
#include "rna_internal.h"
|
||||
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#endif
|
||||
static float rna_IK_Min_X_get(PointerRNA *ptr)
|
||||
{
|
||||
bPoseChannel *pchan= (bPoseChannel*)ptr->id.data;
|
||||
|
||||
return pchan->limitmin[0];
|
||||
}
|
||||
|
||||
static float rna_IK_Min_Y_get(PointerRNA *ptr)
|
||||
{
|
||||
bPoseChannel *pchan= (bPoseChannel*)ptr->id.data;
|
||||
|
||||
return pchan->limitmin[1];
|
||||
}
|
||||
|
||||
static float rna_IK_Min_Z_get(PointerRNA *ptr)
|
||||
{
|
||||
bPoseChannel *pchan= (bPoseChannel*)ptr->id.data;
|
||||
|
||||
return pchan->limitmin[2];
|
||||
}
|
||||
|
||||
static void rna_IK_Min_X_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
bPoseChannel *pchan= (bPoseChannel*)ptr->id.data;
|
||||
|
||||
pchan->limitmin[0] = value;
|
||||
}
|
||||
|
||||
static void rna_IK_Min_Y_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
bPoseChannel *pchan= (bPoseChannel*)ptr->id.data;
|
||||
|
||||
pchan->limitmin[1] = value;
|
||||
}
|
||||
|
||||
static void rna_IK_Min_Z_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
bPoseChannel *pchan= (bPoseChannel*)ptr->id.data;
|
||||
|
||||
pchan->limitmin[2] = value;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* users shouldn't be editing pose channel data directly -- better to set ipos and let blender calc pose_channel stuff */
|
||||
/* it's going to be weird for users to find IK flags and other such here, instead of in bone where they would expect them
|
||||
-- is there any way to put a doc in bone, pointing them here? */
|
||||
|
||||
static void RNA_def_pose_channel(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem prop_iklimit_items[] = {
|
||||
{BONE_IK_NO_XDOF, "IKNOXDOF", "No X DoF", "Prevent motion around X axis."},
|
||||
{BONE_IK_NO_YDOF, "IKNOYDOF", "No Y DoF", "Prevent motion around Y axis."},
|
||||
{BONE_IK_NO_ZDOF, "IKNOZDOF", "No Z DoF", "Prevent motion around Z axis."},
|
||||
{BONE_IK_XLIMIT, "IKXLIMIT", "X Limit", "Limit motion around X axis."},
|
||||
{BONE_IK_YLIMIT, "IKYLIMIT", "Y Limit", "Limit motion around Y axis."},
|
||||
{BONE_IK_ZLIMIT, "IKZLIMIT", "Z Limit", "Limit motion around Z axis."},
|
||||
{0, NULL, NULL, NULL}};
|
||||
|
||||
srna= RNA_def_struct(brna, "bPoseChannel", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Pose Channel", "Member of the 'Pose' type.");
|
||||
|
||||
/* cosntraints (collection) */
|
||||
prop= RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "constraints", NULL);
|
||||
RNA_def_property_struct_type(prop, "bConstraint");
|
||||
RNA_def_property_ui_text(prop, "Constraints", "Constraints that act on this PoseChannel.");
|
||||
|
||||
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NOT_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Name", "");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
|
||||
prop= RNA_def_property(srna, "ikflag", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, prop_iklimit_items);
|
||||
RNA_def_property_ui_text(prop, "IK Limits", "");
|
||||
|
||||
prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "selectflag", BONE_SELECTED);
|
||||
RNA_def_property_ui_text(prop, "Selected", "");
|
||||
|
||||
prop= RNA_def_property(srna, "protected", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "protectflag", POSE_LOCKED);
|
||||
RNA_def_property_ui_text(prop, "Protected", "Protect channel from being transformed.");
|
||||
|
||||
prop= RNA_def_property(srna, "action_group_index", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "agrp_index");
|
||||
RNA_def_property_ui_text(prop, "Action Group Index", "Action Group this pose channel belogs to (0=no group).");
|
||||
|
||||
prop= RNA_def_property(srna, "path_start_frame", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "pathsf");
|
||||
RNA_def_property_flag(prop, PROP_NOT_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Bone Paths Calculation Start Frame", "Starting frame of range of frames to use for Bone Path calculations.");
|
||||
|
||||
prop= RNA_def_property(srna, "path_end_frame", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "pathef");
|
||||
RNA_def_property_flag(prop, PROP_NOT_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Bone Paths Calculation End Frame", "End frame of range of frames to use for Bone Path calculations.");
|
||||
|
||||
prop= RNA_def_property(srna, "bone", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "Bone");
|
||||
RNA_def_property_flag(prop, PROP_NOT_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Bone", "Bone associated with this Pose Channel.");
|
||||
|
||||
prop= RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "bPoseChannel");
|
||||
RNA_def_property_flag(prop, PROP_NOT_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Parent", "Parent of this pose channel.");
|
||||
|
||||
prop= RNA_def_property(srna, "child", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "bPoseChannel");
|
||||
RNA_def_property_flag(prop, PROP_NOT_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Parent", "Child of this pose channel.");
|
||||
|
||||
prop= RNA_def_property(srna, "channel_matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_struct_type(prop, "chan_mat");
|
||||
RNA_def_property_flag(prop, PROP_NOT_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Channel Matrix", "4x4 matrix, before constraints.");
|
||||
|
||||
/* kaito says this should be not user-editable; I disagree; power users should be able to force this in python; he's the boss. */
|
||||
prop= RNA_def_property(srna, "pose_matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_struct_type(prop, "pose_mat");
|
||||
RNA_def_property_flag(prop, PROP_NOT_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Pose Matrix", "Final 4x4 matrix for this channel.");
|
||||
|
||||
prop= RNA_def_property(srna, "constraint_inverse_matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_struct_type(prop, "constinv");
|
||||
RNA_def_property_flag(prop, PROP_NOT_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Constraint Inverse Matrix", "4x4 matrix, defines transform from final position to unconstrained position.");
|
||||
|
||||
prop= RNA_def_property(srna, "pose_head", PROP_FLOAT, PROP_VECTOR);
|
||||
RNA_def_property_flag(prop, PROP_NOT_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Pose Head Position", "Location of head of the channel's bone.");
|
||||
|
||||
prop= RNA_def_property(srna, "pose_tail", PROP_FLOAT, PROP_VECTOR);
|
||||
RNA_def_property_flag(prop, PROP_NOT_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Pose Tail Position", "Location of tail of the channel's bone.");
|
||||
|
||||
prop= RNA_def_property(srna, "ik_min_x", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "limitmin");
|
||||
RNA_def_property_range(prop, -180.0f, 180.0f);
|
||||
RNA_def_property_float_funcs(prop, "rna_IK_Min_X_get", "rna_IK_Min_X_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "IK Minimum Limit X", "Minimum X angle for IK Limit");
|
||||
|
||||
prop= RNA_def_property(srna, "ik_min_y", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "limitmin");
|
||||
RNA_def_property_range(prop, -180.0f, 180.0f);
|
||||
RNA_def_property_float_funcs(prop, "rna_IK_Min_Y_get", "rna_IK_Min_Y_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "IK Minimum Limit Y", "Minimum Y angle for IK Limit");
|
||||
|
||||
prop= RNA_def_property(srna, "ik_min_z", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "limitmin");
|
||||
RNA_def_property_range(prop, -180.0f, 180.0f);
|
||||
RNA_def_property_float_funcs(prop, "rna_IK_Min_Z_get", "rna_IK_Min_Z_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "IK Minimum Limit Z", "Minimum Z angle for IK Limit");
|
||||
|
||||
prop= RNA_def_property(srna, "ik_max_x", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "limitmax");
|
||||
RNA_def_property_range(prop, -180.0f, 180.0f);
|
||||
RNA_def_property_float_funcs(prop, "rna_IK_Max_X_get", "rna_IK_Max_X_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "IK Maximum Limit X", "Maximum X angle for IK Limit");
|
||||
|
||||
prop= RNA_def_property(srna, "ik_max_y", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "limitmax");
|
||||
RNA_def_property_range(prop, -180.0f, 180.0f);
|
||||
RNA_def_property_float_funcs(prop, "rna_IK_Max_Y_get", "rna_IK_Max_Y_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "IK Maximum Limit Y", "Maximum Y angle for IK Limit");
|
||||
|
||||
prop= RNA_def_property(srna, "ik_max_z", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "limitmax");
|
||||
RNA_def_property_range(prop, -180.0f, 180.0f);
|
||||
RNA_def_property_float_funcs(prop, "rna_IK_Max_Z_get", "rna_IK_Max_Z_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "IK Maximum Limit Z", "Maximum Z angle for IK Limit");
|
||||
|
||||
// float limitmin[3], limitmax[3]; /* DOF constraint */
|
||||
// float stiffness[3]; /* DOF stiffness */
|
||||
// float ikstretch;
|
||||
|
||||
// float *path; /* totpath x 3 x float */
|
||||
// struct Object *custom; /* draws custom object instead of this channel */
|
||||
};
|
||||
|
||||
void RNA_def_action(BlenderRNA *brna)
|
||||
{
|
||||
@@ -45,3 +229,5 @@ void RNA_def_action(BlenderRNA *brna)
|
||||
RNA_def_struct_ui_text(srna, "Action", "DOC_BROKEN");
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -505,7 +505,6 @@ typedef struct LampRen {
|
||||
#define R_LAMPHALO 8
|
||||
#define R_GLOB_NOPUNOFLIP 16
|
||||
#define R_NEED_TANGENT 32
|
||||
#define R_SKIP_MULTIRES 64
|
||||
#define R_BAKE_TRACE 128
|
||||
#define R_BAKING 256
|
||||
|
||||
|
||||
@@ -99,7 +99,6 @@
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "envmap.h"
|
||||
//XXX #include "multires.h"
|
||||
#include "occlusion.h"
|
||||
#include "render_types.h"
|
||||
#include "rendercore.h"
|
||||
@@ -3077,13 +3076,6 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
|
||||
if(need_orco)
|
||||
mask |= CD_MASK_ORCO;
|
||||
|
||||
if(me->mr) {
|
||||
if(re->flag & R_SKIP_MULTIRES)
|
||||
me->mr->flag |= MULTIRES_NO_RENDER;
|
||||
else
|
||||
me->mr->flag &= ~MULTIRES_NO_RENDER;
|
||||
}
|
||||
|
||||
dm= mesh_create_derived_render(re->scene, ob, mask);
|
||||
if(dm==NULL) return; /* in case duplicated object fails? */
|
||||
|
||||
@@ -5432,8 +5424,6 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob)
|
||||
re->flag |= R_GLOB_NOPUNOFLIP;
|
||||
re->flag |= R_BAKING;
|
||||
re->excludeob= actob;
|
||||
if(type == RE_BAKE_LIGHT)
|
||||
re->flag |= R_SKIP_MULTIRES;
|
||||
if(actob)
|
||||
re->flag |= R_BAKE_TRACE;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user