Large fix for multires. Changed UV coordinates (MTFaces) to be special first-level data in multires. The data is now stored in a standard CustomData struct in Multires, rather than being stored for each level. (The UVs can now only be edited on level 1.) Changes allow multiple sets of UVs to work correctly. This change should also decrease multires memory usage some (though only when UVs are being used, of course.)

Changes to CustomData:
Some functions would only return the current active layer, added extra variants that take an index to select the level (modeled after CustomData_get_layer_n.)

Still todo:
* UVs are being interpolated linearly, should probably offer Catmull-Clark subdivision like Subsurf modifier.
* Vertex Colors still don't support multiple customdata layers.
* Editing UV data on levels other than 1 should be disabled in the interface (same for weights)
This commit is contained in:
Nicholas Bishop 2007-01-10 06:09:10 +00:00
parent 3f5bd9b391
commit 043be07050
8 changed files with 485 additions and 242 deletions

View File

@ -169,6 +169,7 @@ void CustomData_swap(struct CustomData *data, int index, int *corner_indices);
*/
void *CustomData_get(const struct CustomData *data, int index, int type);
void *CustomData_em_get(const struct CustomData *data, void *block, int type);
void *CustomData_em_get_n(const struct CustomData *data, void *block, int type, int n);
/* gets a pointer to the active or first layer of type
* returns NULL if there is no layer of type
@ -188,11 +189,14 @@ void CustomData_set(const struct CustomData *data, int index, int type,
void *source);
void CustomData_em_set(struct CustomData *data, void *block, int type,
void *source);
void CustomData_em_set_n(struct CustomData *data, void *block, int type, int n,
void *source);
/* set the pointer of to the first layer of type. the old data is not freed.
* returns the value of ptr if the layer is found, NULL otherwise
*/
void *CustomData_set_layer(const struct CustomData *data, int type, void *ptr);
void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, void *ptr);
/* sets the nth layer of type as active */
void CustomData_set_layer_active(struct CustomData *data, int type, int n);

View File

@ -965,6 +965,17 @@ void *CustomData_set_layer(const CustomData *data, int type, void *ptr)
return ptr;
}
void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, void *ptr)
{
/* get the layer index of the first layer of type */
int layer_index = CustomData_get_layer_index(data, type);
if(layer_index < 0) return NULL;
data->layers[layer_index+n].data = ptr;
return ptr;
}
void CustomData_set(const CustomData *data, int index, int type, void *source)
{
void *dest = CustomData_get(data, index, type);
@ -1070,6 +1081,17 @@ void *CustomData_em_get(const CustomData *data, void *block, int type)
return (char *)block + data->layers[layer_index].offset;
}
void *CustomData_em_get_n(const CustomData *data, void *block, int type, int n)
{
int layer_index;
/* get the layer index of the first layer of type */
layer_index = CustomData_get_active_layer_index(data, type);
if(layer_index < 0) return NULL;
return (char *)block + data->layers[layer_index+n].offset;
}
void CustomData_em_set(CustomData *data, void *block, int type, void *source)
{
void *dest = CustomData_em_get(data, block, type);
@ -1083,6 +1105,19 @@ void CustomData_em_set(CustomData *data, void *block, int type, void *source)
memcpy(dest, source, typeInfo->size);
}
void CustomData_em_set_n(CustomData *data, void *block, int type, int n, void *source)
{
void *dest = CustomData_em_get_n(data, block, type, n);
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if(!dest) return;
if(typeInfo->copy)
typeInfo->copy(source, dest, 1);
else
memcpy(dest, source, typeInfo->size);
}
void CustomData_em_interp(CustomData *data, void **src_blocks, float *weights,
float *sub_weights, int count, void *dest_block)
{

View File

@ -2530,6 +2530,7 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
direct_link_customdata(fd, &mesh->mr->vdata, lvl->totvert);
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);
@ -2538,17 +2539,10 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
mesh->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "Multires Edge Flags");
for(; lvl; lvl= lvl->next) {
int i;
lvl->verts= newdataadr(fd, lvl->verts);
lvl->faces= newdataadr(fd, lvl->faces);
lvl->edges= newdataadr(fd, lvl->edges);
lvl->texcolfaces= newdataadr(fd, lvl->texcolfaces);
if(lvl->texcolfaces) {
for(i=0; i<lvl->totface; ++i)
lvl->texcolfaces[i].tex_page= newdataadr(fd, lvl->texcolfaces[i].tex_page);
}
lvl->colfaces= newdataadr(fd, lvl->colfaces);
/* Recalculating the maps is faster than reading them from the file */
multires_calc_level_maps(lvl);

View File

@ -1176,6 +1176,7 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
lvl= mesh->mr->levels.first;
if(lvl) {
write_customdata(wd, lvl->totvert, &mesh->mr->vdata);
write_customdata(wd, lvl->totface, &mesh->mr->fdata);
writedata(wd, DATA, sizeof(short)*lvl->totedge, mesh->mr->edge_flags);
}
for(; lvl; lvl= lvl->next) {
@ -1183,7 +1184,7 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, "MVert", lvl->totvert, lvl->verts);
writestruct(wd, DATA, "MultiresFace", lvl->totface, lvl->faces);
writestruct(wd, DATA, "MultiresEdge", lvl->totedge, lvl->edges);
writestruct(wd, DATA, "MultiresTexColFace", lvl->totface, lvl->texcolfaces);
writestruct(wd, DATA, "MultiresColFace", lvl->totface, lvl->colfaces);
}
}

View File

@ -30,11 +30,13 @@
#ifndef MULTIRES_H
#define MULTIRES_H
struct uiBlock;
struct CustomData;
struct Object;
struct MDeformVert;
struct Mesh;
struct MultiresLevel;
struct Multires;
struct uiBlock;
void multires_draw_interface(struct uiBlock *block, unsigned short cx, unsigned short cy);
void multires_disp_map(void *, void*);
@ -42,16 +44,28 @@ void multires_disp_map(void *, void*);
void multires_make(void *ob, void *me);
void multires_delete(void *ob, void *me);
struct Multires *multires_copy(struct Multires *orig);
void multires_free(Multires *mr);
void multires_free_level(MultiresLevel *lvl);
void multires_free(struct Multires *mr);
void multires_free_level(struct MultiresLevel *lvl);
void multires_del_lower(void *ob, void *me);
void multires_del_higher(void *ob, void *me);
void multires_add_level(void *ob, void *me);
void multires_set_level(void *ob, void *me);
void multires_update_levels(Mesh *me);
void multires_level_to_mesh(Object *ob, Mesh *me);
void multires_calc_level_maps(MultiresLevel *lvl);
void multires_update_levels(struct Mesh *me);
void multires_level_to_mesh(struct Object *ob, struct Mesh *me);
void multires_calc_level_maps(struct MultiresLevel *lvl);
void multires_edge_level_update(void *ob, void *me);
int multires_modifier_warning();
/* multires-firstlevel.c */
/* Generic */
typedef enum FirstLevelType {
FirstLevelType_Vert, FirstLevelType_Face
} FirstLevelType;
void multires_update_customdata(struct MultiresLevel *lvl1, struct CustomData *src,
struct CustomData *dst, const FirstLevelType type);
void multires_customdata_to_mesh(struct Mesh *me, struct EditMesh *em, struct MultiresLevel *lvl,
struct CustomData *src, struct CustomData *dst, const FirstLevelType type);
void multires_del_lower_customdata(struct Multires *mr, struct MultiresLevel *cr_lvl);
#endif

View File

@ -88,8 +88,12 @@ typedef struct MTFace {
/* Multiresolution modeling */
typedef struct MultiresCol {
float a, r, g, b, u, v;
float a, r, g, b;
} MultiresCol;
typedef struct MultiresColFace {
/* vertex colors */
MultiresCol col[4];
} MultiresColFace;
typedef struct MultiresFace {
unsigned int v[4];
unsigned int mid;
@ -101,21 +105,13 @@ typedef struct MultiresEdge {
unsigned int mid;
} MultiresEdge;
typedef struct MultiresTexColFace {
/* vertex colors and texfaces */
struct Image *tex_page;
MultiresCol col[4];
short tex_mode, tex_tile, tex_unwrap;
char tex_flag, tex_transp;
} MultiresTexColFace;
struct MultiresMapNode;
typedef struct MultiresLevel {
struct MultiresLevel *next, *prev;
MVert *verts;
MultiresFace *faces;
MultiresTexColFace *texcolfaces;
MultiresColFace *colfaces;
MultiresEdge *edges;
struct ListBase *vert_edge_map;
struct ListBase *vert_face_map;
@ -130,7 +126,8 @@ typedef struct Multires {
unsigned char use_col, use_tex;
/* Special level 1 data that cannot be modified from other levels */
struct CustomData vdata;
CustomData vdata;
CustomData fdata;
short *edge_flags;
} Multires;

View File

@ -0,0 +1,330 @@
#include "DNA_customdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "BIF_editmesh.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BLI_editVert.h"
#include "MEM_guardedalloc.h"
#include "multires.h"
#include <string.h>
MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl);
MTFace *subdivide_mtfaces(MTFace *src, MultiresLevel *lvl);
/*********** Generic ***********/
int cdtype(const FirstLevelType type)
{
if(type == FirstLevelType_Vert)
return CD_MDEFORMVERT;
else if(type == FirstLevelType_Face)
return CD_MTFACE;
return -1;
}
CustomDataMask cdmask(const FirstLevelType type)
{
if(type == FirstLevelType_Vert)
return CD_MASK_MDEFORMVERT;
else if(type == FirstLevelType_Face)
return CD_MASK_MTFACE;
return -1;
}
char type_ok(const FirstLevelType type)
{
return (type == FirstLevelType_Vert) || (type == FirstLevelType_Face);
}
/* Copy vdata or fdata from Mesh or EditMesh to Multires. */
void multires_update_customdata(MultiresLevel *lvl1, CustomData *src,
CustomData *dst, const FirstLevelType type)
{
if(lvl1 && src && dst && type_ok(type)) {
const int tot= (type == FirstLevelType_Vert ? lvl1->totvert : lvl1->totface);
int i;
CustomData_free(dst, tot);
if(CustomData_has_layer(src, cdtype(type))) {
if(G.obedit) {
EditVert *eve= G.editMesh->verts.first;
EditFace *efa= G.editMesh->faces.first;
CustomData_copy(src, dst, cdmask(type), CD_CALLOC, tot);
for(i=0; i<tot; ++i) {
if(type == FirstLevelType_Vert) {
CustomData_from_em_block(&G.editMesh->vdata, dst, eve->data, i);
eve= eve->next;
}
else if(type == FirstLevelType_Face) {
CustomData_from_em_block(&G.editMesh->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 FirstLevelType 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 == FirstLevelType_Vert)
cr_data= subdivide_dverts(pr_data, lvl);
else if(type == FirstLevelType_Face)
cr_data= subdivide_mtfaces(pr_data, lvl);
/* Free previous subdivision level's data */
if(lvl != lvl_start) {
if(type == FirstLevelType_Vert)
free_dverts(pr_data, lvl->totvert);
else if(type == FirstLevelType_Face)
MEM_freeN(pr_data);
}
pr_data= cr_data;
cr_data= NULL;
}
return pr_data;
}
return NULL;
}
/* Copy vdata or fdata from Multires to either Mesh or EditMesh. */
void multires_customdata_to_mesh(Mesh *me, EditMesh *em, MultiresLevel *lvl, CustomData *src,
CustomData *dst, const FirstLevelType type)
{
if(me->mr && lvl && src && dst && type_ok(type) &&
CustomData_has_layer(src, cdtype(type))) {
const int tot= (type == FirstLevelType_Vert ? lvl->totvert : lvl->totface);
int i;
if(lvl == me->mr->levels.first) {
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 == FirstLevelType_Vert) {
CustomData_to_em_block(&em->vdata, dst, i, &eve->data);
eve= eve->next;
}
else if(type == FirstLevelType_Face) {
CustomData_to_em_block(&em->fdata, dst, i, &efa->data);
efa= efa->next;
}
}
} else {
CustomData_merge(src, dst, cdmask(type), CD_DUPLICATE, tot);
}
}
else {
if(type == FirstLevelType_Vert) {
MDeformVert *dverts= subdivide_customdata_to_level(CustomData_get(src, 0, cdtype(type)),
me->mr->levels.first, lvl, type);
if(dverts) {
if(em) {
EditVert *eve;
EM_add_data_layer(&em->vdata, cdtype(type));
for(i=0, eve= em->verts.first; eve; ++i, eve= eve->next)
CustomData_em_set(&em->vdata, eve->data, cdtype(type), &dverts[i]);
free_dverts(dverts, lvl->totvert);
} else
CustomData_add_layer(&me->vdata, cdtype(type),
CD_ASSIGN, dverts, me->totvert);
}
}
else if(type == FirstLevelType_Face) {
const int count = CustomData_number_of_layers(src, CD_MTFACE);
int i, j;
CustomData_merge(src, dst, CD_MASK_MTFACE, CD_ASSIGN, lvl->totface);
for(i=0; i<count; ++i) {
void *layer = CustomData_get_layer_n(src, CD_MTFACE, i);
MTFace *mtfaces= subdivide_customdata_to_level(layer, me->mr->levels.first, lvl, type);
if(mtfaces) {
if(em) {
EditFace *efa;
for(j=0, efa= em->faces.first; efa; ++j, efa= efa->next)
CustomData_em_set_n(&em->fdata, efa->data, cdtype(type), i, &mtfaces[j]);
MEM_freeN(mtfaces);
} else
CustomData_set_layer_n(dst, CD_MTFACE, i, mtfaces);
}
}
}
}
}
}
/* 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, FirstLevelType_Vert);
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, FirstLevelType_Face);
if(mtfaces)
CustomData_set_layer_n(&cdf, CD_MTFACE, i, mtfaces);
}
CustomData_free(&mr->fdata, lvl1->totface);
mr->fdata= cdf;
}
/*********** 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;
}

View File

@ -76,10 +76,8 @@
#include "parametrizer.h"
#include <math.h>
#include <string.h>
/* Only do deformverts */
CustomDataMask vdata_mask= CD_MASK_MDEFORMVERT;
const CustomDataMask vdata_mask= CD_MASK_MDEFORMVERT;
/* editmesh.h */
int multires_test()
@ -335,8 +333,8 @@ void boundary_edges_average(MultiApplyData *data, MultiresLevel *lvl,
for(j=0; j<3; ++j) out[j]/= count;
}
/* For manipulating MultiresTexColFace */
void mcol_to_multires(MultiresTexColFace *mrf, MCol *mcol)
/* For manipulating vertex colors / uvs */
void mcol_to_multires(MultiresColFace *mrf, MCol *mcol)
{
char i;
for(i=0; i<4; ++i) {
@ -346,19 +344,7 @@ void mcol_to_multires(MultiresTexColFace *mrf, MCol *mcol)
mrf->col[i].b= mcol[i].b;
}
}
void tface_to_multires(MultiresTexColFace *mrf, MTFace *t)
{
char i;
mrf->tex_page= t->tpage;
mrf->tex_transp= t->transp;
mrf->tex_mode= t->mode;
mrf->tex_tile= t->tile;
mrf->tex_unwrap= t->unwrap;
for(i=0; i<4; ++i) {
mrf->col[i].u= t->uv[i][0];
mrf->col[i].v= t->uv[i][1];
}
}
float clamp_component(const float c)
{
if(c<0) return 0;
@ -366,7 +352,7 @@ float clamp_component(const float c)
else return c;
}
void multires_to_mcol(MultiresTexColFace *f, MCol mcol[4])
void multires_to_mcol(MultiresColFace *f, MCol mcol[4])
{
unsigned char j;
for(j=0; j<4; ++j) {
@ -378,40 +364,25 @@ void multires_to_mcol(MultiresTexColFace *f, MCol mcol[4])
}
}
void multires_to_mtface(MultiresTexColFace *f, MTFace *t)
{
unsigned i;
for(i=0; i<4; ++i) {
t->uv[i][0]= f->col[i].u;
t->uv[i][1]= f->col[i].v;
}
t->tpage= f->tex_page;
t->flag= f->tex_flag;
t->transp= f->tex_transp;
t->mode= f->tex_mode;
t->tile= f->tex_tile;
t->unwrap= f->tex_unwrap;
}
/* 1 <= count <= 4 */
void multires_col_avg(MultiresCol *avg, MultiresCol cols[4], char count)
{
unsigned i;
avg->a= avg->r= avg->g= avg->b= avg->u= avg->v= 0;
avg->a= avg->r= avg->g= avg->b= /*avg->u= avg->v=*/ 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->u+= cols[i].u;
avg->v+= cols[i].v;
//avg->u+= cols[i].u;
//avg->v+= cols[i].v;
}
avg->a/= count;
avg->r/= count;
avg->g/= count;
avg->b/= count;
avg->u/= count;
avg->v/= count;
//avg->u/= count;
//avg->v/= count;
}
void multires_col_avg2(MultiresCol *avg, MultiresCol *c1, MultiresCol *c2)
@ -422,89 +393,6 @@ void multires_col_avg2(MultiresCol *avg, MultiresCol *c1, MultiresCol *c2)
multires_col_avg(avg,in,2);
}
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->prev) {
MDeformVert *out = MEM_callocN(sizeof(MDeformVert)*lvl->totvert, "dvert prop array");
int i, j;
/* Copy lower level */
for(i=0; i<lvl->prev->totvert; ++i)
multires_add_dvert(&out[i], &src[i], 1);
/* Edge verts */
for(i=0; i<lvl->prev->totedge; ++i) {
for(j=0; j<2; ++j)
multires_add_dvert(&out[lvl->prev->totvert+i], &src[lvl->prev->edges[i].v[j]],0.5);
}
/* Face verts */
for(i=0; i<lvl->prev->totface; ++i) {
for(j=0; j<(lvl->prev->faces[i].v[3]?4:3); ++j)
multires_add_dvert(&out[lvl->prev->totvert + lvl->prev->totedge + i],
&src[lvl->prev->faces[i].v[j]],
lvl->prev->faces[i].v[3]?0.25:(1.0f/3.0f));
}
return out;
}
return NULL;
}
/* Uses subdivide_dverts to subdivide src to match lvl_end. Does not free src. */
MDeformVert *subdivide_dverts_to_level(MDeformVert *src, MultiresLevel *lvl_start, MultiresLevel *lvl_end)
{
MultiresLevel *lvl;
MDeformVert *cr_dverts= NULL, *pr_dverts= NULL;
pr_dverts= src;
for(lvl= lvl_start->next; lvl && lvl != lvl_end->next; lvl= lvl->next) {
cr_dverts= subdivide_dverts(pr_dverts, lvl);
/* Free previous dvert subdivision level */
if(lvl->prev != lvl_start)
free_dverts(pr_dverts, lvl->prev->totvert);
pr_dverts= cr_dverts;
cr_dverts= NULL;
}
return pr_dverts;
}
void multires_load_cols(Mesh *me)
{
MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1), *cur;
@ -517,20 +405,20 @@ void multires_load_cols(Mesh *me)
/* Add texcol data */
for(cur= me->mr->levels.first; cur; cur= cur->next)
if(!cur->texcolfaces)
cur->texcolfaces= MEM_callocN(sizeof(MultiresTexColFace)*cur->totface,"TexColFaces");
if(!cur->colfaces)
cur->colfaces= MEM_callocN(sizeof(MultiresColFace)*cur->totface,"ColFaces");
me->mr->use_col= CustomData_has_layer(src, CD_MCOL);
me->mr->use_tex= CustomData_has_layer(src, CD_MTFACE);
if(em) efa= em->faces.first;
for(i=0; i<lvl->totface; ++i) {
MultiresTexColFace *f= &lvl->texcolfaces[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(me->mr->use_tex)
tface_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MTFACE) : &me->mtface[i]);
//if(me->mr->use_tex)
// tface_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MTFACE) : &me->mtface[i]);
if(em) efa= efa->next;
}
@ -538,16 +426,16 @@ void multires_load_cols(Mesh *me)
/* Update higher levels */
lvl= lvl->next;
while(lvl) {
MultiresTexColFace *cf= lvl->texcolfaces;
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->texcolfaces[i].col,sides);
multires_col_avg(&cntr,lvl->prev->colfaces[i].col,sides);
for(j=0; j<sides; ++j) {
MultiresTexColFace *pf= &lvl->prev->texcolfaces[i];
MultiresColFace *pf= &lvl->prev->colfaces[i];
multires_col_avg2(&cf->col[0],
&pf->col[j],
@ -558,12 +446,12 @@ void multires_load_cols(Mesh *me)
&pf->col[j==sides-1?0:j+1]);
cf->col[3]= cntr;
cf->tex_page= pf->tex_page;
/*cf->tex_page= pf->tex_page;
cf->tex_flag= pf->tex_flag;
cf->tex_transp= pf->tex_transp;
cf->tex_mode= pf->tex_mode;
cf->tex_tile= pf->tex_tile;
cf->tex_unwrap= pf->tex_unwrap;
cf->tex_unwrap= pf->tex_unwrap;*/
++cf;
}
@ -579,7 +467,7 @@ void multires_load_cols(Mesh *me)
for(i=0; i<lvl->totface; ++i) {
MultiresFace *f= &lvl->faces[i];
for(j=0; j<(f->v[3]?4:3); ++j) {
lvl->texcolfaces[i].col[j]= lvl->next->texcolfaces[curf].col[1];
lvl->colfaces[i].col[j]= lvl->next->colfaces[curf].col[1];
++curf;
}
}
@ -643,29 +531,6 @@ void multires_get_edge(MultiresEdge *e, EditEdge *eed, MEdge *m, short *flag)
}
}
void multires_update_deformverts(Multires *mr, CustomData *src)
{
MultiresLevel *lvl= mr->levels.first;
if(lvl) {
int i;
CustomData_free(&mr->vdata, lvl->totvert);
if(CustomData_has_layer(src, CD_MDEFORMVERT)) {
if(G.obedit) {
EditVert *eve= G.editMesh->verts.first;
CustomData_add_layer(&mr->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, lvl->totvert);
for(i=0; i<lvl->totvert; ++i) {
CustomData_from_em_block(&G.editMesh->vdata, &mr->vdata, eve->data, i);
eve= eve->next;
}
}
else
CustomData_copy(src, &mr->vdata, vdata_mask, CD_DUPLICATE, lvl->totvert);
}
}
}
void multires_make(void *ob, void *me_v)
{
Mesh *me= me_v;
@ -707,26 +572,29 @@ void multires_make(void *ob, void *me_v)
/* Load mesh (or editmesh) into multires data */
/* Load vertices */
/* Load vertices and vdata (MDeformVerts) */
lvl->totvert= em ? BLI_countlist(&em->verts) : me->totvert;
lvl->verts= MEM_callocN(sizeof(MVert)*lvl->totvert,"multires verts");
multires_update_deformverts(me->mr, em ? &em->vdata : &me->vdata);
multires_update_customdata(me->mr->levels.first, em ? &em->vdata : &me->vdata,
&me->mr->vdata, FirstLevelType_Vert);
if(em) eve= em->verts.first;
for(i=0; i<lvl->totvert; ++i) {
multires_get_vert(&lvl->verts[i], eve, &me->mvert[i], i);
if(em) eve= eve->next;
}
/* Load faces */
/* 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->fdata : &me->fdata,
&me->mr->fdata, FirstLevelType_Face);
if(em) efa= em->faces.first;
for(i=0; i<lvl->totface; ++i) {
multires_get_face(&lvl->faces[i], efa, &me->mface[i]);
if(em) efa= efa->next;
}
/* Load edges */
/* 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");
@ -768,7 +636,7 @@ MultiresLevel *multires_level_copy(MultiresLevel *orig)
lvl->next= lvl->prev= NULL;
lvl->verts= MEM_dupallocN(orig->verts);
lvl->faces= MEM_dupallocN(orig->faces);
lvl->texcolfaces= MEM_dupallocN(orig->texcolfaces);
lvl->colfaces= MEM_dupallocN(orig->colfaces);
lvl->edges= MEM_dupallocN(orig->edges);
lvl->vert_edge_map= lvl->vert_face_map= NULL;
multires_calc_level_maps(lvl);
@ -792,6 +660,7 @@ Multires *multires_copy(Multires *orig)
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);
}
@ -808,6 +677,7 @@ void multires_free(Multires *mr)
/* Free the first-level data */
if(lvl) {
CustomData_free(&mr->vdata, lvl->totvert);
CustomData_free(&mr->fdata, lvl->totface);
MEM_freeN(mr->edge_flags);
}
@ -829,7 +699,7 @@ void multires_free_level(MultiresLevel *lvl)
if(lvl->verts) MEM_freeN(lvl->verts);
if(lvl->faces) MEM_freeN(lvl->faces);
if(lvl->edges) MEM_freeN(lvl->edges);
if(lvl->texcolfaces) MEM_freeN(lvl->texcolfaces);
if(lvl->colfaces) MEM_freeN(lvl->colfaces);
/* Free all vertex maps */
MEM_freeN(lvl->vert_edge_map);
@ -846,7 +716,6 @@ void multires_del_lower(void *ob, void *me)
MultiresLevel *lvl1= mr->levels.first, *cr_lvl= current_level(mr);
MultiresLevel *lvl= NULL, *lvlprev= NULL;
short *edgeflags= NULL;
MDeformVert *dverts= NULL;
int i, last;
if(cr_lvl == lvl1) return;
@ -861,13 +730,7 @@ void multires_del_lower(void *ob, void *me)
MEM_freeN(mr->edge_flags);
mr->edge_flags= edgeflags;
/* Subdivide the dverts to the current level */
dverts= subdivide_dverts_to_level(CustomData_get(&mr->vdata, 0, CD_MDEFORMVERT),
mr->levels.first, cr_lvl);
if(dverts) {
CustomData_free_layers(&mr->vdata, CD_MDEFORMVERT, lvl1->totvert);
CustomData_add_layer(&mr->vdata, CD_MDEFORMVERT, CD_ASSIGN, dverts, cr_lvl->totvert);
}
multires_del_lower_customdata(mr, cr_lvl);
lvl= cr_lvl->prev;
while(lvl) {
@ -1085,31 +948,31 @@ void multires_add_level(void *ob, void *me_v)
============= */
curf= 0;
if(me->mr->use_col || me->mr->use_tex) {
MultiresTexColFace *cf= MEM_callocN(sizeof(MultiresTexColFace)*lvl->totface,"MultiresTexColFaces");
lvl->texcolfaces= cf;
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->texcolfaces[i].col,sides);
multires_col_avg(&cntr,lvl->prev->colfaces[i].col,sides);
for(j=0; j<sides; ++j) {
multires_col_avg2(&cf->col[0],
&lvl->prev->texcolfaces[i].col[j],
&lvl->prev->texcolfaces[i].col[j==0?sides-1:j-1]);
cf->col[1]= lvl->prev->texcolfaces[i].col[j];
&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->texcolfaces[i].col[j],
&lvl->prev->texcolfaces[i].col[j==sides-1?0:j+1]);
&lvl->prev->colfaces[i].col[j],
&lvl->prev->colfaces[i].col[j==sides-1?0:j+1]);
cf->col[3]= cntr;
cf->tex_page= lvl->prev->texcolfaces[i].tex_page;
cf->tex_flag= lvl->prev->texcolfaces[i].tex_flag;
cf->tex_transp= lvl->prev->texcolfaces[i].tex_transp;
cf->tex_mode= lvl->prev->texcolfaces[i].tex_mode;
cf->tex_tile= lvl->prev->texcolfaces[i].tex_tile;
cf->tex_unwrap= lvl->prev->texcolfaces[i].tex_unwrap;
/*cf->tex_page= lvl->prev->colfaces[i].tex_page;
cf->tex_flag= lvl->prev->colfaces[i].tex_flag;
cf->tex_transp= lvl->prev->colfaces[i].tex_transp;
cf->tex_mode= lvl->prev->colfaces[i].tex_mode;
cf->tex_tile= lvl->prev->colfaces[i].tex_tile;
cf->tex_unwrap= lvl->prev->colfaces[i].tex_unwrap;*/
++cf;
}
@ -1261,8 +1124,9 @@ void multires_level_to_mesh(Object *ob, Mesh *me)
}
}
/* Vertex groups */
if(lvl==me->mr->levels.first && CustomData_has_layer(&me->mr->vdata, CD_MDEFORMVERT)) {
multires_customdata_to_mesh(me, em, lvl, &me->mr->vdata, em ? &em->vdata : &me->vdata, FirstLevelType_Vert);
multires_customdata_to_mesh(me, em, lvl, &me->mr->fdata, em ? &em->fdata : &me->fdata, FirstLevelType_Face);
/*if(lvl==me->mr->levels.first && CustomData_has_layer(&me->mr->vdata, CD_MDEFORMVERT)) {
if(em) {
EM_add_data_layer(&em->vdata, CD_MDEFORMVERT);
for(i=0, eve= em->verts.first; eve; ++i, eve= eve->next)
@ -1286,7 +1150,7 @@ void multires_level_to_mesh(Object *ob, Mesh *me)
CustomData_add_layer(&me->vdata, CD_MDEFORMVERT,
CD_ASSIGN, dverts, me->totvert);
}
}
}*/
/* Colors and UVs */
if(me->mr->use_col || me->mr->use_tex) {
@ -1296,29 +1160,29 @@ void multires_level_to_mesh(Object *ob, Mesh *me)
CustomData *src= em ? &em->fdata : &me->fdata;
if(em) {
if(me->mr->use_col) EM_add_data_layer(src, CD_MCOL);
if(me->mr->use_tex) EM_add_data_layer(src, CD_MTFACE);
//if(me->mr->use_tex) EM_add_data_layer(src, CD_MTFACE);
efa= em->faces.first;
}
else {
if(me->mr->use_col) me->mcol= CustomData_add_layer(src, CD_MCOL, CD_CALLOC, NULL, me->totface);
if(me->mr->use_tex) me->mtface= CustomData_add_layer(src, CD_MTFACE, CD_CALLOC, NULL, me->totface);
//if(me->mr->use_tex) me->mtface= CustomData_add_layer(src, CD_MTFACE, CD_CALLOC, NULL, me->totface);
}
for(i=0; i<lvl->totface; ++i) {
if(em) {
if(me->mr->use_col) {
multires_to_mcol(&lvl->texcolfaces[i], c);
multires_to_mcol(&lvl->colfaces[i], c);
CustomData_em_set(src, efa->data, CD_MCOL, c);
}
if(me->mr->use_tex) {
multires_to_mtface(&lvl->texcolfaces[i], &f);
CustomData_em_set(src, efa->data, CD_MTFACE, &f);
}
//if(me->mr->use_tex) {
// multires_to_mtface(&lvl->colfaces[i], &f);
// CustomData_em_set(src, efa->data, CD_MTFACE, &f);
//}
efa= efa->next;
}
else {
if(me->mr->use_col) multires_to_mcol(&lvl->texcolfaces[i], &me->mcol[i*4]);
if(me->mr->use_tex) multires_to_mtface(&lvl->texcolfaces[i], &me->mtface[i]);
if(me->mr->use_col) multires_to_mcol(&lvl->colfaces[i], &me->mcol[i*4]);
//if(me->mr->use_tex) multires_to_mtface(&lvl->colfaces[i], &me->mtface[i]);
}
}
@ -1341,6 +1205,7 @@ void multires_level_to_mesh(Object *ob, Mesh *me)
if(G.vd->depths) G.vd->depths->damaged= 1;
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWIMAGE, 0);
}
void multires_update_colors(Mesh *me)
@ -1361,15 +1226,15 @@ void multires_update_colors(Mesh *me)
MTFace *mtf= em ? CustomData_em_get(src, efa->data, CD_MTFACE) : &me->mtface[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_tex) {
cr_deltas[i*4+j].u= mtf->uv[j][0] - lvl->texcolfaces[i].col[j].u;
cr_deltas[i*4+j].v= mtf->uv[j][1] - lvl->texcolfaces[i].col[j].v;
}
//if(me->mr->use_tex) {
// cr_deltas[i*4+j].u= mtf->uv[j][0] - lvl->colfaces[i].col[j].u;
// cr_deltas[i*4+j].v= mtf->uv[j][1] - lvl->colfaces[i].col[j].v;
//}
if(me->mr->use_col) {
cr_deltas[i*4+j].a= col[j].a - lvl->texcolfaces[i].col[j].a;
cr_deltas[i*4+j].r= col[j].r - lvl->texcolfaces[i].col[j].r;
cr_deltas[i*4+j].g= col[j].g - lvl->texcolfaces[i].col[j].g;
cr_deltas[i*4+j].b= col[j].b - lvl->texcolfaces[i].col[j].b;
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;
@ -1378,12 +1243,12 @@ void multires_update_colors(Mesh *me)
/* Update current level */
if(em) efa= em->faces.first;
for(i=0; i<lvl->totface; ++i) {
MultiresTexColFace *f= &lvl->texcolfaces[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(me->mr->use_tex)
tface_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MTFACE) : &me->mtface[i]);
//if(me->mr->use_tex)
// tface_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MTFACE) : &me->mtface[i]);
if(em) efa= efa->next;
}
@ -1419,12 +1284,12 @@ void multires_update_colors(Mesh *me)
for(i=0; i<lvl->totface; ++i) {
for(j=0; j<4; ++j) {
lvl->texcolfaces[i].col[j].a+= cr_deltas[i*4+j].a;
lvl->texcolfaces[i].col[j].r+= cr_deltas[i*4+j].r;
lvl->texcolfaces[i].col[j].g+= cr_deltas[i*4+j].g;
lvl->texcolfaces[i].col[j].b+= cr_deltas[i*4+j].b;
lvl->texcolfaces[i].col[j].u+= cr_deltas[i*4+j].u;
lvl->texcolfaces[i].col[j].v+= cr_deltas[i*4+j].v;
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;
//lvl->colfaces[i].col[j].u+= cr_deltas[i*4+j].u;
//lvl->colfaces[i].col[j].v+= cr_deltas[i*4+j].v;
}
}
@ -1437,11 +1302,11 @@ void multires_update_colors(Mesh *me)
lvl= me->mr->levels.last;
lvl= lvl->prev;
while(lvl) {
MultiresTexColFace *nf= lvl->next->texcolfaces;
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->texcolfaces[i].col[j]= nf->col[1];
lvl->colfaces[i].col[j]= nf->col[1];
++nf;
}
}
@ -1485,7 +1350,10 @@ void multires_update_levels(Mesh *me)
/* Update special first-level data */
if(cr_lvl==me->mr->levels.first) {
multires_update_deformverts(me->mr, (em ? &em->vdata : &me->vdata));
multires_update_customdata(me->mr->levels.first, em ? &em->vdata : &me->vdata,
&me->mr->vdata, FirstLevelType_Vert);
multires_update_customdata(me->mr->levels.first, em ? &em->fdata : &me->fdata,
&me->mr->fdata, FirstLevelType_Face);
multires_update_edge_flags(me->mr, me, em);
}