diff options
39 files changed, 972 insertions, 475 deletions
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 3f133adc68a..b20e60c9442 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -166,6 +166,7 @@ void *CustomData_em_get(const struct CustomData *data, void *block, int type); void *CustomData_get_layer(const struct CustomData *data, int type); void *CustomData_get_layer_n(const struct CustomData *data, int type, int n); +int CustomData_get_layer_index(const struct CustomData *data, int type); int CustomData_get_active_layer_index(const struct CustomData *data, int type); /* copies the data from source to the data element at index in the first @@ -206,4 +207,7 @@ int CustomData_sizeof(int type); /* get the name of a layer type */ const char *CustomData_layertype_name(int type); +/* make sure the name of layer at index is unique */ +void CustomData_set_layer_unique_name(struct CustomData *data, int index); + #endif diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 586c6db972b..2567595171c 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -34,6 +34,7 @@ #include "BKE_customdata.h" +#include "BLI_blenlib.h" #include "BLI_linklist.h" #include "DNA_customdata_types.h" @@ -52,6 +53,7 @@ typedef struct LayerTypeInfo { int size; /* the memory size of one element of this layer's data */ char *structname; /* name of the struct used, for file writing */ int structnum; /* number of structs per element, for file writing */ + char *defaultname; /* default layer name */ /* a function to copy count elements of this layer's data * (deep copy if appropriate) @@ -351,22 +353,22 @@ static void layerDefault_mcol(void *data, int count) } const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { - {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL}, - {sizeof(MSticky), "MSticky", 1, NULL, NULL, layerInterp_msticky, NULL, + {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(MSticky), "MSticky", 1, NULL, NULL, NULL, layerInterp_msticky, NULL, NULL}, - {sizeof(MDeformVert), "MDeformVert", 1, layerCopy_mdeformvert, + {sizeof(MDeformVert), "MDeformVert", 1, NULL, layerCopy_mdeformvert, layerFree_mdeformvert, layerInterp_mdeformvert, NULL, NULL}, - {sizeof(MEdge), "MEdge", 1, NULL, NULL, NULL, NULL, NULL}, - {sizeof(MFace), "MFace", 1, NULL, NULL, NULL, NULL, NULL}, - {sizeof(MTFace), "MTFace", 1, layerCopy_tface, NULL, + {sizeof(MEdge), "MEdge", 1, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(MFace), "MFace", 1, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(MTFace), "MTFace", 1, "UVTex", layerCopy_tface, NULL, layerInterp_tface, layerSwap_tface, layerDefault_tface}, /* 4 MCol structs per face */ - {sizeof(MCol)*4, "MCol", 4, NULL, NULL, layerInterp_mcol, + {sizeof(MCol)*4, "MCol", 4, "Col", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, - {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL}, + {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 3 floats per normal vector */ - {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL}, - {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL}, + {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, }; const char *LAYERTYPENAMES[CD_NUMTYPES] = { @@ -403,7 +405,7 @@ static const char *layerType_getName(int type) static void customData_update_offsets(CustomData *data); static CustomDataLayer *customData_add_layer__internal(CustomData *data, - int type, int alloctype, void *layerdata, int totelem); + int type, int alloctype, void *layerdata, int totelem, const char *name); void CustomData_merge(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, int totelem) @@ -432,10 +434,10 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, if((alloctype == CD_ASSIGN) && (layer->flag & CD_FLAG_NOFREE)) newlayer = customData_add_layer__internal(dest, type, CD_REFERENCE, - layer->data, totelem); + layer->data, totelem, layer->name); else newlayer = customData_add_layer__internal(dest, type, alloctype, - layer->data, totelem); + layer->data, totelem, layer->name); if(newlayer) newlayer->active = lastactive; @@ -493,7 +495,7 @@ static void customData_update_offsets(CustomData *data) data->totsize = offset; } -static int CustomData_get_layer_index(const struct CustomData *data, int type) +int CustomData_get_layer_index(const CustomData *data, int type) { int i; @@ -550,7 +552,7 @@ static int customData_resize(CustomData *data, int amount) } static CustomDataLayer *customData_add_layer__internal(CustomData *data, - int type, int alloctype, void *layerdata, int totelem) + int type, int alloctype, void *layerdata, int totelem, const char *name) { const LayerTypeInfo *typeInfo= layerType_getInfo(type); int size = typeInfo->size * totelem, flag = 0, index = data->totlayer; @@ -586,6 +588,8 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, } } + data->totlayer++; + /* keep layers ordered by type */ for( ; index > 0 && data->layers[index - 1].type > type; --index) data->layers[index] = data->layers[index - 1]; @@ -594,13 +598,18 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, data->layers[index].flag = flag; data->layers[index].data = newlayerdata; + if(name) { + strcpy(data->layers[index].name, name); + CustomData_set_layer_unique_name(data, index); + } + else + data->layers[index].name[0] = '\0'; + if(index > 0 && data->layers[index-1].type == type) data->layers[index].active = data->layers[index-1].active; else data->layers[index].active = 0; - data->totlayer++; - customData_update_offsets(data); return &data->layers[index]; @@ -610,9 +619,10 @@ void *CustomData_add_layer(CustomData *data, int type, int alloctype, void *layerdata, int totelem) { CustomDataLayer *layer; + const LayerTypeInfo *typeInfo= layerType_getInfo(type); layer = customData_add_layer__internal(data, type, alloctype, layerdata, - totelem); + totelem, typeInfo->defaultname); if(layer) return layer->data; @@ -1195,3 +1205,53 @@ const char *CustomData_layertype_name(int type) { return layerType_getName(type); } + +void CustomData_set_layer_unique_name(CustomData *data, int index) +{ + char tempname[64]; + int number, i, type; + char *dot, *name; + CustomDataLayer *layer, *nlayer= &data->layers[index]; + const LayerTypeInfo *typeInfo= layerType_getInfo(nlayer->type); + + if (!typeInfo->defaultname) + return; + + type = nlayer->type; + name = nlayer->name; + + if (name[0] == '\0') + BLI_strncpy(nlayer->name, typeInfo->defaultname, sizeof(nlayer->name)); + + /* see if there is a duplicate */ + for(i=0; i<data->totlayer; i++) { + layer = &data->layers[i]; + + if(i!=index && layer->type==type && strcmp(layer->name, name)==0) + break; + } + + if(i == data->totlayer) + return; + + /* strip off the suffix */ + dot = strchr(nlayer->name, '.'); + if(dot) *dot=0; + + for(number=1; number <=999; number++) { + sprintf(tempname, "%s.%03d", nlayer->name, number); + + for(i=0; i<data->totlayer; i++) { + layer = &data->layers[i]; + + if(i!=index && layer->type==type && strcmp(layer->name, tempname)==0) + break; + } + + if(i == data->totlayer) { + BLI_strncpy(nlayer->name, tempname, sizeof(nlayer->name)); + return; + } + } +} + diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 62c8d53d15a..0e69607d1bb 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -282,7 +282,6 @@ void count_displist(ListBase *lb, int *totvert, int *totface) static ShadeInput shi; static void init_fastshade_shadeinput(void) { - memset(&shi, 0, sizeof(ShadeInput)); shi.lay= G.scene->lay; shi.view[2]= -1.0f; @@ -311,15 +310,19 @@ void fastshade_free_render(void) } } -static void fastshade(float *co, float *nor, float *orco, float *uv, Material *ma, char *col1, char *col2, char *vertcol) +static void fastshade(float *co, float *nor, float *orco, float *uv, char *uvname, Material *ma, char *col1, char *col2, char *vertcol, char *colname) { ShadeResult shr; int a; if(vertcol) { - shi.vcol[0]= ((float)vertcol[3])/255.0f; - shi.vcol[1]= ((float)vertcol[2])/255.0f; - shi.vcol[2]= ((float)vertcol[1])/255.0f; + shi.col[0].col[0]= ((float)vertcol[3])/255.0f; + shi.col[0].col[1]= ((float)vertcol[2])/255.0f; + shi.col[0].col[2]= ((float)vertcol[1])/255.0f; + shi.col[0].name= colname; + shi.totcol= 1; + + VECCOPY(shi.vcol, shi.col[0].col); } VECCOPY(shi.co, co); @@ -343,12 +346,15 @@ static void fastshade(float *co, float *nor, float *orco, float *uv, Material *m } if(ma->texco & TEXCO_UV) { if(uv) { - shi.uv[0]= 2.0f*uv[0]-1.0f; - shi.uv[1]= 2.0f*uv[1]-1.0f; + shi.uv[0].uv[0]= 2.0f*uv[0]-1.0f; + shi.uv[0].uv[1]= 2.0f*uv[1]-1.0f; + shi.uv[0].uv[2]= 1.0f; } else { - VECCOPY(shi.uv, shi.lo); + VECCOPY(shi.uv[0].uv, shi.lo); } + shi.uv[0].name = uvname; + shi.totuv= 1; } if(ma->texco & TEXCO_OBJECT) { VECCOPY(shi.co, shi.lo); @@ -449,7 +455,8 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un MTFace *mtface; unsigned int *col1, *col2; float *orco, *vnors, *nors, imat[3][3], mat[4][4], vec[3]; - int a, i, need_orco, totface, totvert; + int a, i, need_orco, totface, totvert, layerindex; + char *uvname= "", *colname= ""; CustomDataMask dataMask = CD_MASK_BAREMESH | CD_MASK_MCOL | CD_MASK_MTFACE | CD_MASK_NORMAL; @@ -470,6 +477,15 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un totvert = dm->getNumVerts(dm); totface = dm->getNumFaces(dm); + if (mcol) { + layerindex= CustomData_get_active_layer_index(&dm->faceData, CD_MCOL); + colname= dm->faceData.layers[layerindex].name; + } + if (mtface) { + layerindex= CustomData_get_active_layer_index(&dm->faceData, CD_MTFACE); + uvname= dm->faceData.layers[layerindex].name; + } + if (onlyForMesh) { col1 = *col1_r; col2 = NULL; @@ -546,7 +562,7 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un vec[0]+= 0.001*vn[0]; vec[1]+= 0.001*vn[1]; vec[2]+= 0.001*vn[2]; - fastshade(vec, vn, orco?&orco[vidx[j]*3]:mv->co, uv, ma, col1, col2, mcol); + fastshade(vec, vn, orco?&orco[vidx[j]*3]:mv->co, uv, uvname, ma, col1, col2, mcol, colname); } } MEM_freeN(vnors); @@ -566,7 +582,7 @@ void shadeMeshMCol(Object *ob, Mesh *me) Render *re= fastshade_get_render(); mesh_create_shadedColors(re, ob, 1, (unsigned int **)&me->mcol, NULL); - + /* swap bytes */ for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) { SWAP(char, cp[0], cp[3]); @@ -646,7 +662,7 @@ void shadeDispList(Base *base) VECCOPY(vec, fp); Mat4MulVecfl(mat, vec); - fastshade(vec, n1, fp, NULL, ma, (char *)col1, NULL, NULL); + fastshade(vec, n1, fp, NULL, "", ma, (char *)col1, NULL, NULL, ""); fp+= 3; col1++; } @@ -667,7 +683,7 @@ void shadeDispList(Base *base) n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2]; Normalise(n1); - fastshade(vec, n1, fp, NULL, ma, (char *)col1, NULL, NULL); + fastshade(vec, n1, fp, NULL, "", ma, (char *)col1, NULL, NULL, ""); fp+= 3; nor+= 3; col1++; } @@ -705,7 +721,7 @@ void shadeDispList(Base *base) n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2]; Normalise(n1); - fastshade(vec, n1, fp, NULL, ma, (char *)col1, NULL, NULL); + fastshade(vec, n1, fp, NULL, "", ma, (char *)col1, NULL, NULL, ""); fp+= 3; col1++; nor+= 3; } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index d10ff6c6d33..59dcccc1f8d 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -785,6 +785,8 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup) node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f); else if(type==SH_NODE_CURVE_RGB) node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); + else if(type==SH_NODE_GEOMETRY) + node->storage= MEM_callocN(sizeof(NodeGeometry), "NodeGeometry"); } else if(ntree->type==NTREE_COMPOSIT) { if(type==CMP_NODE_VALTORGB) diff --git a/source/blender/blenkernel/intern/node_shaders.c b/source/blender/blenkernel/intern/node_shaders.c index dbdca2edcb6..f332873de49 100644 --- a/source/blender/blenkernel/intern/node_shaders.c +++ b/source/blender/blenkernel/intern/node_shaders.c @@ -188,13 +188,25 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **in, bNod { if(data) { ShadeInput *shi= ((ShaderCallData *)data)->shi; + ShadeInputUV *suv= &shi->uv[0]; + NodeGeometry *ngeo= (NodeGeometry*)node->storage; + int i; + + if(ngeo->uvname[0]) { + for(i = 0; i < shi->totuv; i++) { + if(strcmp(shi->uv[i].name, ngeo->uvname)==0) { + suv= &shi->uv[i]; + break; + } + } + } /* out: global, local, view, orco, uv, normal */ VECCOPY(out[GEOM_OUT_GLOB]->vec, shi->gl); VECCOPY(out[GEOM_OUT_LOCAL]->vec, shi->co); VECCOPY(out[GEOM_OUT_VIEW]->vec, shi->view); VECCOPY(out[GEOM_OUT_ORCO]->vec, shi->lo); - VECCOPY(out[GEOM_OUT_UV]->vec, shi->uv); + VECCOPY(out[GEOM_OUT_UV]->vec, suv->uv); VECCOPY(out[GEOM_OUT_NORMAL]->vec, shi->vno); if(shi->osatex) { @@ -206,7 +218,7 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **in, bNod out[GEOM_OUT_VIEW]->datatype= NS_OSA_VALUES; out[GEOM_OUT_ORCO]->data= shi->dxlo; out[GEOM_OUT_ORCO]->datatype= NS_OSA_VECTORS; - out[GEOM_OUT_UV]->data= shi->dxuv; + out[GEOM_OUT_UV]->data= suv->dxuv; out[GEOM_OUT_UV]->datatype= NS_OSA_VECTORS; out[GEOM_OUT_NORMAL]->data= shi->dxno; out[GEOM_OUT_NORMAL]->datatype= NS_OSA_VECTORS; @@ -218,11 +230,11 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **in, bNod static bNodeType sh_node_geom= { /* type code */ SH_NODE_GEOMETRY, /* name */ "Geometry", - /* width+range */ 90, 40, 100, - /* class+opts */ NODE_CLASS_INPUT, 0, + /* width+range */ 120, 80, 160, + /* class+opts */ NODE_CLASS_INPUT, NODE_OPTIONS, /* input sock */ NULL, /* output sock */ sh_node_geom_out, - /* storage */ "", + /* storage */ "NodeGeometry", /* execfunc */ node_shader_exec_geom }; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 48eb6ae8e55..0330883b2f9 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4203,10 +4203,11 @@ static void sort_shape_fix(Main *main) static void customdata_version_242(Mesh *me) { + CustomDataLayer *layer; MTFace *mtf; MCol *mcol; TFace *tf; - int a; + int a, mtfacen, mcoln; if (!me->vdata.totlayer) { CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, me->mvert, me->totvert); @@ -4256,6 +4257,25 @@ static void customdata_version_242(Mesh *me) me->tface= NULL; } + for (a=0, mtfacen=0, mcoln=0; a < me->fdata.totlayer; a++) { + layer= &me->fdata.layers[a]; + + if (layer->type == CD_MTFACE) { + if (layer->name[0] == 0) { + if (mtfacen == 0) strcpy(layer->name, "UVTex"); + else sprintf(layer->name, "UVTex.%.3d", mtfacen); + } + mtfacen++; + } + else if (layer->type == CD_MCOL) { + if (layer->name[0] == 0) { + if (mcoln == 0) strcpy(layer->name, "Col"); + else sprintf(layer->name, "Col.%.3d", mcoln); + } + mcoln++; + } + } + mesh_update_customdata_pointers(me); } diff --git a/source/blender/include/BDR_editface.h b/source/blender/include/BDR_editface.h index edb54325ff4..84c1e09d058 100644 --- a/source/blender/include/BDR_editface.h +++ b/source/blender/include/BDR_editface.h @@ -57,5 +57,8 @@ void set_texturepaint(void); void get_same_uv(void); void seam_mark_clear_tface(short mode); +void select_mface_from_tface(struct Mesh *me); +void select_tface_from_mface(struct Mesh *me); + #endif /* BDR_EDITFACE_H */ diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 83111f58c67..d8930f8a098 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -38,6 +38,7 @@ typedef struct CustomDataLayer { int offset; /* in editmode, offset of layer in block */ int flag; /* general purpose flag */ int active; /* number of the active layer of this type */ + char name[32]; /* layer name */ void *data; /* layer data */ } CustomDataLayer; @@ -85,4 +86,8 @@ typedef struct CustomData { /* indicates the layer is only temporary, also implies no copy */ #define CD_FLAG_TEMPORARY ((1<<2)|CD_FLAG_NOCOPY) +/* Limits */ +#define MAX_MTFACE 4 +#define MAX_MCOL 4 + #endif diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 5e899dce0f6..db7db374dcc 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -213,5 +213,9 @@ typedef struct NodeChroma { float key[4]; } NodeChroma; +typedef struct NodeGeometry { + char uvname[32]; +} NodeGeometry; + #endif diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index eae2a07ec6e..3fbe85818c2 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -51,6 +51,7 @@ typedef struct MTex { short texco, mapto, maptoneg, blendtype; struct Object *object; struct Tex *tex; + char uvname[32]; char projx, projy, projz, mapping; float ofs[3], size[3]; diff --git a/source/blender/radiosity/intern/source/radrender.c b/source/blender/radiosity/intern/source/radrender.c index d75b2536c1e..d0472a834af 100644 --- a/source/blender/radiosity/intern/source/radrender.c +++ b/source/blender/radiosity/intern/source/radrender.c @@ -95,7 +95,7 @@ static VlakRen *findshoot_rr(Render *re) maxenergy= 0.0; for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; else vlr++; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; if(vlr->radface) { rf= vlr->radface; rf->flag &= ~RAD_SHOOT; @@ -129,7 +129,7 @@ static void backface_test_rr(Render *re, VlakRen *shoot) /* backface testing */ for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; else vlr++; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; if(vlr->radface) { if(vlr!=shoot) { rf= vlr->radface; @@ -151,7 +151,7 @@ static void clear_backface_test_rr(Render *re) /* backface flag clear */ for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; else vlr++; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; if(vlr->radface) { rf= vlr->radface; @@ -208,7 +208,7 @@ static void makeformfactors_rr(Render *re, VlakRen *shoot) fp= RG.formfactors; for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; else vlr++; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; if(vlr->radface) { rf= vlr->radface; @@ -236,7 +236,7 @@ static void applyformfactors_rr(Render *re, VlakRen *shoot) fp= RG.formfactors; for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; else vlr++; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; if(vlr->radface) { rf= vlr->radface; @@ -327,7 +327,7 @@ static void initradfaces(Render *re) /* count first for fast malloc */ for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; else vlr++; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; if(vlr->mat->mode & MA_RADIO) { if(vlr->mat->emit > 0.0) { @@ -343,7 +343,7 @@ printf(" Rad elems: %d emittors %d\n", RG.totelem, RG.totpatch); /* make/init radfaces */ rf=radfaces= MEM_callocN(RG.totelem*sizeof(RadFace), "radfaces"); for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; else vlr++; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; if(vlr->mat->mode & MA_RADIO) { @@ -419,7 +419,7 @@ static void make_vertex_rad_values(Render *re) /* accumulate vertexcolors */ for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; else vlr++; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; if(vlr->radface) { rf= vlr->radface; diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 398e85a60e2..81660d23656 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -74,6 +74,16 @@ struct ShadeInputCopy { int mode; /* base material mode (OR-ed result of entire node tree) */ }; +typedef struct ShadeInputUV { + float dxuv[3], dyuv[3], uv[3]; + char *name; +} ShadeInputUV; + +typedef struct ShadeInputCol { + float col[3]; + char *name; +} ShadeInputCol; + /* localized renderloop data */ typedef struct ShadeInput { @@ -112,13 +122,17 @@ typedef struct ShadeInput float layerfac; /* texture coordinates */ - float lo[3], gl[3], uv[3], ref[3], orn[3], winco[3], sticky[3], vcol[3], rad[3]; + float lo[3], gl[3], ref[3], orn[3], winco[3], sticky[3], vcol[3], rad[3]; float refcol[4], displace[3]; float strand, tang[3], stress, winspeed[4]; + + ShadeInputUV uv[4]; /* 4 = MAX_MTFACE */ + ShadeInputCol col[4]; /* 4 = MAX_MCOL */ + int totuv, totcol; /* dx/dy OSA coordinates */ float dxco[3], dyco[3]; - float dxlo[3], dylo[3], dxgl[3], dygl[3], dxuv[3], dyuv[3]; + float dxlo[3], dylo[3], dxgl[3], dygl[3]; float dxref[3], dyref[3], dxorn[3], dyorn[3]; float dxno[3], dyno[3], dxview, dyview; float dxlv[3], dylv[3]; diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 4a3b0324143..609c391d599 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -45,6 +45,7 @@ struct Object; struct MemArena; struct VertTableNode; +struct VlakTableNode; struct Octree; struct GHash; @@ -158,16 +159,18 @@ struct Render int vertnodeslen; struct VertTableNode *vertnodes; + int vlaknodeslen; + struct VlakTableNode *vlaknodes; int blohalen; struct HaloRen **bloha; - int blovllen; - struct VlakRen **blovl; ListBase objecttable; - + struct Image *backbuf, *bakebuf; struct GHash *orco_hash; + ListBase customdata_names; + /* arena for allocating data for use during render, for * example dynamic TFaces to go in the VlakRen structure. */ @@ -259,12 +262,11 @@ typedef struct VlakRen { unsigned int lay; float n[3]; struct Material *mat; - struct MTFace *tface; - unsigned int *vcol; char snproj, puno; char flag, ec; RadFace *radface; Object *ob; + int index; } VlakRen; typedef struct HaloRen diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h index 6f52a13f6e6..75aea05fee2 100644 --- a/source/blender/render/intern/include/renderdatabase.h +++ b/source/blender/render/intern/include/renderdatabase.h @@ -36,6 +36,9 @@ struct VertRen; struct HaloRen; struct Material; struct Render; +struct MCol; +struct MTFace; +struct CustomData; #define RE_QUAD_MASK 0x7FFFFFF #define RE_QUAD_OFFS 0x8000000 @@ -51,9 +54,25 @@ typedef struct VertTableNode { float *winspeed; } VertTableNode; +typedef struct VlakTableNode { + struct VlakRen *vlak; + struct MTFace **mtface; + struct MCol **mcol; + int totmtface, totmcol; + struct CustomDataNames **names; +} VlakTableNode; + +typedef struct CustomDataNames{ + struct CustomDataNames *next, *prev; + + char (*mtface)[32]; + char (*mcol)[32]; +} CustomDataNames; + /* renderdatabase.c */ void free_renderdata_tables(struct Render *re); void free_renderdata_vertnodes(struct VertTableNode *vertnodes); +void free_renderdata_vlaknodes(struct VlakTableNode *vlaknodes); void set_normalflags(Render *re); void project_renderdata(struct Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs); @@ -74,7 +93,13 @@ float *RE_vertren_get_strand(struct Render *re, struct VertRen *ver, int verify) float *RE_vertren_get_tangent(struct Render *re, struct VertRen *ver, int verify); float *RE_vertren_get_winspeed(struct Render *re, struct VertRen *ver, int verify); -VertRen *RE_vertren_copy(struct Render *re, struct VertRen *ver); +struct MTFace *RE_vlakren_get_tface(struct Render *re, VlakRen *ren, int n, char **name, int verify); +struct MCol *RE_vlakren_get_mcol(struct Render *re, VlakRen *ren, int n, char **name, int verify); + +struct VertRen *RE_vertren_copy(struct Render *re, struct VertRen *ver); +struct VlakRen *RE_vlakren_copy(struct Render *re, struct VlakRen *vlr); + +void RE_vlakren_set_customdata_names(struct Render *re, struct CustomData *data); /* haloren->type: flags */ #define HA_ONLYSKY 1 diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h index 6c8f20673ed..902899bce94 100644 --- a/source/blender/render/intern/include/shading.h +++ b/source/blender/render/intern/include/shading.h @@ -32,14 +32,15 @@ struct LampRen; /* shadeinput.c */ +#define RE_MAX_OSA 16 /* needed to calculate shadow and AO for an entire pixel */ typedef struct ShadeSample { int tot; /* amount of shi in use, can be 1 for not FULL_OSA */ /* could be malloced once */ - ShadeInput shi[16]; /* RE_MAX_OSA */ - ShadeResult shr[16]; /* RE_MAX_OSA */ + ShadeInput shi[RE_MAX_OSA]; + ShadeResult shr[RE_MAX_OSA]; int samplenr; /* counter, detect shadow-reuse for shaders */ } ShadeSample; diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h index 6c7d12c4c8c..9175145869c 100644 --- a/source/blender/render/intern/include/texture.h +++ b/source/blender/render/intern/include/texture.h @@ -62,7 +62,7 @@ void do_lamp_tex(LampRen *la, float *lavec, struct ShadeInput *shi, float *colf) void init_render_textures(Render *re); -void render_realtime_texture(struct ShadeInput *shi); +void render_realtime_texture(struct ShadeInput *shi, struct Image *ima); /* imagetexture.h */ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 650eba5fef0..6b431fbecff 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -434,7 +434,7 @@ static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak) /* gets tangent from tface or orco */ static void calc_tangent_vector(Render *re, VlakRen *vlr) { - MTFace *tface= vlr->tface; + MTFace *tface= RE_vlakren_get_tface(re, vlr, 0, NULL, 0); VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4; float tang[3], tangv[3], ct[3], e1[3], e2[3], *tav; float *uv1, *uv2, *uv3, *uv4; @@ -1627,37 +1627,33 @@ static void init_render_mball(Render *re, Object *ob) /* ------------------------------------------------------------------------- */ /* convert */ +static int vlakren_customdata_layer_num(int n, int active) +{ + /* make the active layer the first */ + if (n == active) return 0; + else if (n < active) return n+1; + else return n; +} + struct edgesort { int v1, v2; - int has_mcol; - MTFace *tface; - float uv1[2], uv2[2]; - unsigned int mcol1, mcol2; + int f; + int i1, i2; }; /* edges have to be added with lowest index first for sorting */ -static void to_edgesort(struct edgesort *ed, int i1, int i2, int v1, int v2, unsigned int *mcol, MTFace *tface) +static void to_edgesort(struct edgesort *ed, int i1, int i2, int v1, int v2, int f) { - if(v1<v2) { - ed->v1= v1; ed->v2= v2; - } - else { - ed->v1= v2; ed->v2= v1; + if(v1>v2) { + SWAP(int, v1, v2); SWAP(int, i1, i2); } - /* copy color and tface, edges use different ordering */ - ed->tface= tface; - if(tface) { - ed->uv1[0]= tface->uv[i1][0]; - ed->uv1[1]= tface->uv[i1][1]; - ed->uv2[0]= tface->uv[i2][0]; - ed->uv2[1]= tface->uv[i2][1]; - } - ed->has_mcol= mcol!=NULL; - if(mcol) { - ed->mcol1= mcol[i1]; - ed->mcol2= mcol[i2]; - } + + ed->v1= v1; + ed->v2= v2; + ed->i1= i1; + ed->i2= i2; + ed->f = f; } static int vergedgesort(const void *v1, const void *v2) @@ -1687,72 +1683,83 @@ static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort) if(mcol==NULL && tface==NULL) return NULL; - /* make sorted table with edges and and tface/mcol pointers in it */ + /* make sorted table with edges and face indices in it */ for(a= totface, mf= mface; a>0; a--, mf++) { if(mf->v4) totedge+=4; else if(mf->v3) totedge+=3; } - if(totedge==0) return NULL; + + if(totedge==0) + return NULL; ed= edsort= MEM_callocN(totedge*sizeof(struct edgesort), "edgesort"); - for(a= totface, mf= mface; a>0; a--, mf++) { - if(mface->v4 || mface->v3) { - to_edgesort(ed++, 0, 1, mf->v1, mf->v2, mcol, tface); - to_edgesort(ed++, 1, 2, mf->v2, mf->v3, mcol, tface); - if(mf->v4) { - to_edgesort(ed++, 2, 3, mf->v3, mf->v4, mcol, tface); - to_edgesort(ed++, 3, 0, mf->v4, mf->v1, mcol, tface); - } - else if(mf->v3) { - to_edgesort(ed++, 2, 3, mf->v3, mf->v1, mcol, tface); - } + for(a=0, mf=mface; a<totface; a++, mf++) { + to_edgesort(ed++, 0, 1, mf->v1, mf->v2, a); + to_edgesort(ed++, 1, 2, mf->v2, mf->v3, a); + if(mf->v4) { + to_edgesort(ed++, 2, 3, mf->v3, mf->v4, a); + to_edgesort(ed++, 3, 0, mf->v4, mf->v1, a); } - if(mcol) mcol+=4; - if(tface) tface++; + else if(mf->v3) + to_edgesort(ed++, 2, 3, mf->v3, mf->v1, a); } qsort(edsort, totedge, sizeof(struct edgesort), vergedgesort); *totedgesort= totedge; + return edsort; } -static void use_mesh_edge_lookup(Render *re, MEdge *medge, VlakRen *vlr, struct edgesort *edgetable, int totedge) +static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, VlakRen *vlr, struct edgesort *edgetable, int totedge) { struct edgesort ed, *edp; + CustomDataLayer *layer; + MTFace *mtface, *mtf; + MCol *mcol, *mc; + int index, mtfn, mcn, n; + char *name; if(medge->v1 < medge->v2) { - ed.v1= medge->v1; ed.v2= medge->v2; + ed.v1= medge->v1; + ed.v2= medge->v2; } else { - ed.v1= medge->v2; ed.v2= medge->v1; + ed.v1= medge->v2; + ed.v2= medge->v1; } edp= bsearch(&ed, edgetable, totedge, sizeof(struct edgesort), vergedgesort); + + /* since edges have different index ordering, we have to duplicate mcol and tface */ if(edp) { - /* since edges have different index ordering, we have to duplicate mcol and tface */ - if(edp->tface) { - vlr->tface= BLI_memarena_alloc(re->memArena, sizeof(MTFace)); - memcpy(vlr->tface, edp->tface, sizeof(MTFace)); - - if(edp->v1==medge->v1) { - memcpy(vlr->tface->uv[0], edp->uv1, 2*sizeof(float)); - memcpy(vlr->tface->uv[1], edp->uv2, 2*sizeof(float)); + mtfn= mcn= 0; + + for(index=0; index<dm->faceData.totlayer; index++) { + layer= &dm->faceData.layers[index]; + name= layer->name; + + if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) { + mtface= &((MTFace*)layer->data)[edp->f]; + n= vlakren_customdata_layer_num(mtfn++, layer->active); + mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1); + + *mtf= *mtface; + + memcpy(mtf->uv[0], mtface->uv[edp->i1], sizeof(float)*2); + memcpy(mtf->uv[1], mtface->uv[edp->i2], sizeof(float)*2); + memcpy(mtf->uv[2], mtface->uv[1], sizeof(float)*2); + memcpy(mtf->uv[3], mtface->uv[1], sizeof(float)*2); } - else { - memcpy(vlr->tface->uv[0], edp->uv2, 2*sizeof(float)); - memcpy(vlr->tface->uv[1], edp->uv1, 2*sizeof(float)); + else if(layer->type == CD_MCOL && mcn < MAX_MCOL) { + mcol= &((MCol*)layer->data)[edp->f*4]; + n= vlakren_customdata_layer_num(mcn++, layer->active); + mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1); + + mc[0]= mcol[edp->i1]; + mc[1]= mc[2]= mc[3]= mcol[edp->i2]; } - memcpy(vlr->tface->uv[2], vlr->tface->uv[1], 2*sizeof(float)); - memcpy(vlr->tface->uv[3], vlr->tface->uv[1], 2*sizeof(float)); - } - if(edp->has_mcol) { - vlr->vcol= BLI_memarena_alloc(re->memArena, sizeof(MCol)*4); - vlr->vcol[0]= edp->mcol1; - vlr->vcol[1]= edp->mcol2; - vlr->vcol[2]= vlr->vcol[1]; - vlr->vcol[3]= vlr->vcol[1]; } } } @@ -1768,7 +1775,6 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts MSticky *ms = NULL; PartEff *paf; DerivedMesh *dm; - unsigned int *vertcol; float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3], float *orco=0; int a, a1, ok, need_orco=0, need_stress=0, need_tangent=0, totvlako, totverto, vertofs; @@ -1899,6 +1905,8 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts } if(!only_verts) { + /* store customdata names, because DerivedMesh is freed */ + RE_vlakren_set_customdata_names(re, &dm->faceData); /* still to do for keys: the correct local texture coordinate */ @@ -1927,14 +1935,10 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts } if(ok) { - MTFace *tface= NULL; - end= dm->getNumFaces(dm); mface= dm->getFaceArray(dm); - tface= dm->getFaceDataArray(dm, CD_MTFACE); - vertcol= dm->getFaceDataArray(dm, CD_MCOL); - for(a=0; a<end; a++) { + for(a=0; a<end; a++, mface++) { int v1, v2, v3, v4, flag; if( mface->mat_nr==a1 ) { @@ -1981,19 +1985,31 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts if(len==0) re->totvlak--; else { - if(tface) { - vlr->tface= BLI_memarena_alloc(re->memArena, sizeof(MTFace)); - memcpy(vlr->tface, tface, sizeof(MTFace)); - } - if (vertcol) { - vlr->vcol= BLI_memarena_alloc(re->memArena, sizeof(int)*4); - memcpy(vlr->vcol, vertcol+4*a, sizeof(int)*4); + CustomDataLayer *layer; + MTFace *mtface, *mtf; + MCol *mcol, *mc; + int index, mtfn= 0, mcn= 0, n; + char *name; + + for(index=0; index<dm->faceData.totlayer; index++) { + layer= &dm->faceData.layers[index]; + name= layer->name; + + if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) { + n= vlakren_customdata_layer_num(mtfn++, layer->active); + mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1); + mtface= (MTFace*)layer->data; + *mtf= mtface[a]; + } + else if(layer->type == CD_MCOL && mcn < MAX_MCOL) { + n= vlakren_customdata_layer_num(mcn++, layer->active); + mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1); + mcol= (MCol*)layer->data; + memcpy(mc, &mcol[a*4], sizeof(MCol)*4); + } } } } - - mface++; - if(tface) tface++; } } } @@ -2025,7 +2041,7 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts vlr->v4= NULL; if(edgetable) { - use_mesh_edge_lookup(re, medge, vlr, edgetable, totedge); + use_mesh_edge_lookup(re, dm, medge, vlr, edgetable, totedge); } xn= -(v0->no[0]+v1->no[0]); @@ -2935,11 +2951,6 @@ void RE_Database_Free(Render *re) /* FREE */ - if(re->memArena) { - BLI_memarena_free(re->memArena); - re->memArena = NULL; - } - for(lar= re->lampren.first; lar; lar= lar->next) { freeshadowbuf(lar); if(lar->jitter) MEM_freeN(lar->jitter); @@ -2991,6 +3002,10 @@ void RE_Database_Free(Render *re) if((re->r.scemode & R_PREVIEWBUTS)==0) BKE_image_free_all_textures(); + if(re->memArena) { + BLI_memarena_free(re->memArena); + re->memArena = NULL; + } } /* per face check if all samples should be taken. @@ -3081,8 +3096,7 @@ static void check_non_flat_quads(Render *re) if(ABS(xn) < 0.999995 ) { // checked on noisy fractal grid float d1, d2; - vlr1= RE_findOrAddVlak(re, re->totvlak++); - *vlr1= *vlr; + vlr1= RE_vlakren_copy(re, vlr); vlr1->flag |= R_FACE_SPLIT; /* split direction based on vnorms */ @@ -3117,10 +3131,6 @@ static void check_non_flat_quads(Render *re) /* new normals */ CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); CalcNormFloat(vlr1->v3->co, vlr1->v2->co, vlr1->v1->co, vlr1->n); - - /* so later UV can be pulled from original tface, look for R_DIVIDE_24 for direction */ - vlr1->tface=vlr->tface; - } /* clear the flag when not divided */ else vlr->flag &= ~R_DIVIDE_24; @@ -3914,7 +3924,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type) unsigned int lay; re->scene= scene; - + /* renderdata setup and exceptions */ re->r= scene->r; re->r.mode &= ~R_OSA; @@ -4110,15 +4120,34 @@ static short test_for_displace(Render *re, Object *ob) return 0; } -static void displace_render_vert(Render *re, ShadeInput *shi, VertRen *vr, float *scale) +static void displace_render_vert(Render *re, ShadeInput *shi, VertRen *vr, int vindex, float *scale) { + MTFace *tface; short texco= shi->mat->texco; float sample=0; + char *name; + int i; + /* shi->co is current render coord, just make sure at least some vector is here */ VECCOPY(shi->co, vr->co); /* vertex normal is used for textures type 'col' and 'var' */ VECCOPY(shi->vn, vr->n); - + + if (texco & TEXCO_UV) { + shi->totuv= 0; + + for (i=0; (tface=RE_vlakren_get_tface(re, shi->vlr, i, &name, 0)); i++) { + ShadeInputUV *suv= &shi->uv[i]; + + /* shi.uv needs scale correction from tface uv */ + suv->uv[0]= 2*tface->uv[vindex][0]-1.0f; + suv->uv[1]= 2*tface->uv[vindex][1]-1.0f; + suv->uv[2]= 0.0f; + suv->name= name; + shi->totuv++; + } + } + /* set all rendercoords, 'texco' is an ORed value for all textures needed */ if ((texco & TEXCO_ORCO) && (vr->orco)) { VECCOPY(shi->lo, vr->orco); @@ -4173,55 +4202,26 @@ static void displace_render_vert(Render *re, ShadeInput *shi, VertRen *vr, float static void displace_render_face(Render *re, VlakRen *vlr, float *scale) { ShadeInput shi; - // VertRen vr; - // float samp1,samp2, samp3, samp4, xn; - short hasuv=0; + /* set up shadeinput struct for multitex() */ - shi.osatex= 0; /* signal not to use dx[] and dy[] texture AA vectors */ shi.vlr= vlr; /* current render face */ shi.mat= vlr->mat; /* current input material */ - - /* UV coords must come from face */ - hasuv = vlr->tface && (shi.mat->texco & TEXCO_UV); - if (hasuv) shi.uv[2]=0.0f; - /* I don't think this is used, but seting it just in case */ - /* Displace the verts, flag is set when done */ - if (! (vlr->v1->flag)){ - if (hasuv) { - shi.uv[0] = 2*vlr->tface->uv[0][0]-1.0f; /* shi.uv and tface->uv are */ - shi.uv[1]= 2*vlr->tface->uv[0][1]-1.0f; /* scalled differently */ - } - displace_render_vert(re, &shi, vlr->v1, scale); - } - - if (! (vlr->v2->flag)) { - if (hasuv) { - shi.uv[0] = 2*vlr->tface->uv[1][0]-1.0f; - shi.uv[1]= 2*vlr->tface->uv[1][1]-1.0f; - } - displace_render_vert(re, &shi, vlr->v2, scale); - } - - if (! (vlr->v3->flag)) { - if (hasuv) { - shi.uv[0] = 2*vlr->tface->uv[2][0]-1.0f; - shi.uv[1]= 2*vlr->tface->uv[2][1]-1.0f; - } - displace_render_vert(re, &shi, vlr->v3, scale); - } + if (!vlr->v1->flag) + displace_render_vert(re, &shi, vlr->v1,0, scale); + if (!vlr->v2->flag) + displace_render_vert(re, &shi, vlr->v2, 1, scale); + + if (!vlr->v3->flag) + displace_render_vert(re, &shi, vlr->v3, 2, scale); + if (vlr->v4) { - if (! (vlr->v4->flag)) { - if (hasuv) { - shi.uv[0] = 2*vlr->tface->uv[3][0]-1.0f; - shi.uv[1]= 2*vlr->tface->uv[3][1]-1.0f; - } - displace_render_vert(re, &shi, vlr->v4, scale); - } - /* We want to split the quad along the opposite verts that are */ + if (!vlr->v4->flag) + displace_render_vert(re, &shi, vlr->v4, 3, scale); + /* closest in displace value. This will help smooth edges. */ if ( fabs(vlr->v1->accum - vlr->v3->accum) > fabs(vlr->v2->accum - vlr->v4->accum)) vlr->flag |= R_DIVIDE_24; @@ -4235,7 +4235,6 @@ static void displace_render_face(Render *re, VlakRen *vlr, float *scale) else { CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); } - } @@ -4261,7 +4260,7 @@ static void do_displacement(Render *re, Object *ob, int startface, int numface, vr= RE_findOrAddVert(re, i); vr->flag= 0; } - + for(i=startface; i<startface+numface; i++){ vlr=RE_findOrAddVlak(re, i); displace_render_face(re, vlr, scale); diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 782308a65ec..684651ca97b 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -154,8 +154,9 @@ static Render *envmap_render_copy(Render *re, EnvMap *env) envre->vertnodes= re->vertnodes; envre->blohalen= re->blohalen; envre->bloha= re->bloha; - envre->blovllen= re->blovllen; - envre->blovl= re->blovl; + envre->vlaknodeslen= re->vlaknodeslen; + envre->vlaknodes= re->vlaknodes; + envre->customdata_names= re->customdata_names; envre->oc= re->oc; return envre; @@ -173,8 +174,9 @@ static void envmap_free_render_copy(Render *envre) envre->vertnodes= NULL; envre->blohalen= 0; envre->bloha= NULL; - envre->blovllen= 0; - envre->blovl= NULL; + envre->vlaknodeslen= 0; + envre->vlaknodes= NULL; + envre->customdata_names.first= envre->customdata_names.last= NULL; envre->oc.adrbranch= NULL; envre->oc.adrnode= NULL; @@ -258,7 +260,7 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode) } for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; xn= vlr->n[0]; @@ -321,7 +323,7 @@ static void env_layerflags(Render *re, unsigned int notlay) notlay= ~notlay; for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; if((vlr->lay & notlay)==0) vlr->flag &= ~R_VISIBLE; @@ -334,7 +336,7 @@ static void env_hideobject(Render *re, Object *ob) int a; for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; if(vlr->ob == ob) vlr->flag &= ~R_VISIBLE; } diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c index 41fa2dbbf16..d6090cad4de 100644 --- a/source/blender/render/intern/source/ray.c +++ b/source/blender/render/intern/source/ray.c @@ -49,6 +49,7 @@ #include "render_types.h" #include "renderpipeline.h" #include "rendercore.h" +#include "renderdatabase.h" #include "pixelblending.h" #include "pixelshading.h" #include "shading.h" @@ -490,7 +491,7 @@ void makeoctree(Render *re) /* first min max octree space */ for(v=0;v<re->totvlak;v++) { - if((v & 255)==0) vlr= re->blovl[v>>8]; + if((v & 255)==0) vlr= re->vlaknodes[v>>8].vlak; else vlr++; if(vlr->mat->mode & MA_TRACEBLE) { if((vlr->mat->mode & MA_WIRE)==0) { @@ -533,7 +534,7 @@ void makeoctree(Render *re) if((v & 255)==0) { double time= PIL_check_seconds_timer(); - vlr= re->blovl[v>>8]; + vlr= re->vlaknodes[v>>8].vlak; if(re->test_break()) break; if(time-lasttime>1.0f) { diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 0ebd778754e..e6ace571156 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -404,11 +404,11 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, break; case SCE_PASS_UV: /* box filter only, gauss will screwup UV too much */ - if(shi->uv[2]!=0.0f) { + if(shi->uv[0].uv[2]!=0.0f) { float mult= (float)count_mask(curmask)/(float)R.osa; fp= rpass->rect + 3*offset; - fp[0]+= mult*(0.5f + 0.5f*shi->uv[0]); - fp[1]+= mult*(0.5f + 0.5f*shi->uv[1]); + fp[0]+= mult*(0.5f + 0.5f*shi->uv[0].uv[0]); + fp[1]+= mult*(0.5f + 0.5f*shi->uv[0].uv[1]); fp[2]+= mult; } break; @@ -481,8 +481,8 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult col= shr->nor; break; case SCE_PASS_UV: - uvcol[0]= 0.5f + 0.5f*shi->uv[0]; - uvcol[1]= 0.5f + 0.5f*shi->uv[1]; + uvcol[0]= 0.5f + 0.5f*shi->uv[0].uv[0]; + uvcol[1]= 0.5f + 0.5f*shi->uv[0].uv[1]; uvcol[2]= 1.0f; col= uvcol; break; @@ -1443,6 +1443,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) static int get_next_bake_face(BakeShade *bs) { VlakRen *vlr; + MTFace *tface; static int v= 0, vdone= 0; if(bs==NULL) { @@ -1457,8 +1458,10 @@ static int get_next_bake_face(BakeShade *bs) vlr= RE_findOrAddVlak(&R, v); if(vlr->ob->flag & SELECT) { - if(vlr->tface && vlr->tface->tpage) { - Image *ima= vlr->tface->tpage; + tface= RE_vlakren_get_tface(&R, vlr, 0, NULL, 0); + + if(tface && tface->tpage) { + Image *ima= tface->tpage; ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f}; @@ -1509,7 +1512,7 @@ static int get_next_bake_face(BakeShade *bs) static void shade_tface(BakeShade *bs) { VlakRen *vlr= bs->vlr; - MTFace *tface= vlr->tface; + MTFace *tface= RE_vlakren_get_tface(&R, vlr, 0, NULL, 0); Image *ima= tface->tpage; float vec[4][2]; int a, i1, i2, i3; diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index e5c7d8c60a4..cf4e2a1b006 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -28,7 +28,7 @@ /* * Storage, retrieval and query of render specific data. * - * All data from a Blender scene is converter by the renderconverter/ + * All data from a Blender scene is converted by the renderconverter/ * into a special format that is used by the render module to make * images out of. These functions interface to the render-specific * database. @@ -40,7 +40,7 @@ * offset in a 256-entry block. * * - If the 256-entry block entry has an entry in the - * vertnodes/bloha/blovl array of the current block, the i-th entry in + * vertnodes/vlaknodes/bloha array of the current block, the i-th entry in * that block is allocated to this entry. * * - If the entry has no block allocated for it yet, memory is @@ -62,12 +62,14 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" +#include "BLI_memarena.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_texture_types.h" +#include "BKE_customdata.h" #include "BKE_texture.h" #include "RE_render_ext.h" /* externtex */ @@ -80,10 +82,11 @@ /* ------------------------------------------------------------------------- */ -/* More dynamic allocation of options for render vertices, so we dont +/* More dynamic allocation of options for render vertices and faces, so we dont have to reserve this space inside vertices. - Important; vertices should have been created already (to get tables checked) - that's a reason why the calls demand VertRen * as arg, not the index */ + Important; vertices and faces, should have been created already (to get tables + checked) that's a reason why the calls demand VertRen/VlakRen * as arg, not + the index */ /* NOTE! the hardcoded table size 256 is used still in code for going quickly over vertices/faces */ @@ -94,6 +97,8 @@ #define RE_TANGENT_ELEMS 3 #define RE_STRESS_ELEMS 1 #define RE_WINSPEED_ELEMS 4 +#define RE_MTFACE_ELEMS 1 +#define RE_MCOL_ELEMS 4 float *RE_vertren_get_sticky(Render *re, VertRen *ver, int verify) { @@ -268,6 +273,207 @@ VertRen *RE_findOrAddVert(Render *re, int nr) return v; } +/* ------------------------------------------------------------------------ */ + +MTFace *RE_vlakren_get_tface(Render *re, VlakRen *vlr, int n, char **name, int verify) +{ + VlakTableNode *node; + int nr= vlr->index>>8, vlakindex= (vlr->index&255); + int index= (n<<8) + vlakindex; + + node= &re->vlaknodes[nr]; + + if(verify) { + if(n>=node->totmtface) { + MTFace **mtface= node->mtface; + int size= size= (n+1)*256; + + node->mtface= MEM_callocN(size*sizeof(MTFace*), "Vlak mtface"); + + if(mtface) { + size= node->totmtface*256; + memcpy(node->mtface, mtface, size*sizeof(MTFace*)); + MEM_freeN(mtface); + } + + node->totmtface= n+1; + + if (!node->names) { + size= sizeof(*node->names)*256; + node->names= MEM_callocN(size, "Vlak names"); + } + } + + if(node->mtface[index]==NULL) { + node->mtface[index]= BLI_memarena_alloc(re->memArena, + sizeof(MTFace)*RE_MTFACE_ELEMS); + + node->names[vlakindex]= re->customdata_names.last; + } + } + else { + if(n>=node->totmtface || node->mtface[index]==NULL) + return NULL; + + if(name) *name= node->names[vlakindex]->mtface[n]; + } + + return node->mtface[index]; +} + +MCol *RE_vlakren_get_mcol(Render *re, VlakRen *vlr, int n, char **name, int verify) +{ + VlakTableNode *node; + int nr= vlr->index>>8, vlakindex= (vlr->index&255); + int index= (n<<8) + vlakindex; + + node= &re->vlaknodes[nr]; + + if(verify) { + if(n>=node->totmcol) { + MCol **mcol= node->mcol; + int size= (n+1)*256; + + node->mcol= MEM_callocN(size*sizeof(MCol*), "Vlak mcol"); + + if(mcol) { + size= node->totmcol*256; + memcpy(node->mcol, mcol, size*sizeof(MCol*)); + MEM_freeN(mcol); + } + + node->totmcol= n+1; + + if (!node->names) { + size= sizeof(*node->names)*256; + node->names= MEM_callocN(size, "Vlak names"); + } + } + + if(node->mcol[index]==NULL) { + node->mcol[index]= BLI_memarena_alloc(re->memArena, + sizeof(MCol)*RE_MCOL_ELEMS); + + node->names[vlakindex]= re->customdata_names.last; + } + } + else { + if(n>=node->totmcol || node->mcol[index]==NULL) + return NULL; + + if(name) *name= node->names[vlakindex]->mcol[n]; + } + + return node->mcol[index]; +} + +VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr) +{ + VlakRen *vlr1 = RE_findOrAddVlak(re, re->totvlak++); + MTFace *mtface, *mtface1; + MCol *mcol, *mcol1; + int i, index = vlr1->index; + char *name; + + *vlr1= *vlr; + vlr1->index= index; + + for (i=0; (mtface=RE_vlakren_get_tface(re, vlr, i, &name, 0)) != NULL; i++) { + mtface1= RE_vlakren_get_tface(re, vlr1, i, &name, 1); + memcpy(mtface1, mtface, sizeof(MTFace)*RE_MTFACE_ELEMS); + } + + for (i=0; (mcol=RE_vlakren_get_mcol(re, vlr, i, &name, 0)) != NULL; i++) { + mcol1= RE_vlakren_get_mcol(re, vlr1, i, &name, 1); + memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS); + } + + return vlr1; +} + +static int vlakren_remap_layer_num(int n, int active) +{ + /* make the active layer the first */ + if (n == active) return 0; + else if (n < active) return n+1; + else return n; +} + +void RE_vlakren_set_customdata_names(Render *re, CustomData *data) +{ + /* CustomData layer names are stored per object here, because the + DerivedMesh which stores the layers is freed */ + + CustomDataNames *cdn= MEM_callocN(sizeof(*cdn), "CustomDataNames"); + CustomDataLayer *layer; + int numlayers, i, mtfn, mcn, n; + + BLI_addtail(&re->customdata_names, cdn); + + if (CustomData_has_layer(data, CD_MTFACE)) { + numlayers= CustomData_number_of_layers(data, CD_MTFACE); + cdn->mtface= MEM_callocN(sizeof(*cdn->mtface)*numlayers, "mtfacenames"); + } + + if (CustomData_has_layer(data, CD_MCOL)) { + numlayers= CustomData_number_of_layers(data, CD_MCOL); + cdn->mcol= MEM_callocN(sizeof(*cdn->mcol)*numlayers, "mcolnames"); + } + + for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) { + layer= &data->layers[i]; + + if (layer->type == CD_MTFACE) { + n= vlakren_remap_layer_num(mtfn++, layer->active); + strcpy(cdn->mtface[n], layer->name); + } + else if (layer->type == CD_MCOL) { + n= vlakren_remap_layer_num(mcn++, layer->active); + strcpy(cdn->mcol[n], layer->name); + } + } +} + +VlakRen *RE_findOrAddVlak(Render *re, int nr) +{ + VlakTableNode *temp; + VlakRen *v; + int a; + + if(nr<0) { + printf("error in findOrAddVlak: %d\n",nr); + return re->vlaknodes[0].vlak; + } + a= nr>>8; + + if (a>=re->vlaknodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */ + temp= re->vlaknodes; + + re->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(re->vlaknodeslen+TABLEINITSIZE) , "vlaknodes"); + if(temp) memcpy(re->vlaknodes, temp, re->vlaknodeslen*sizeof(VlakTableNode)); + memset(re->vlaknodes+re->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode)); + + re->vlaknodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ + if(temp) MEM_freeN(temp); + } + + v= re->vlaknodes[a].vlak; + + if(v==NULL) { + int i; + + v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak"); + re->vlaknodes[a].vlak= v; + + for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) + v[a].index= i; + } + v+= (nr & 255); + return v; +} + +/* ------------------------------------------------------------------------ */ + void RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int sve, int eve, int sfa, int efa) { ObjectRen *obr= MEM_mallocN(sizeof(ObjectRen), "object render struct"); @@ -306,22 +512,33 @@ void free_renderdata_vertnodes(VertTableNode *vertnodes) } MEM_freeN(vertnodes); - } -void free_renderdata_tables(Render *re) +void free_renderdata_vlaknodes(VlakTableNode *vlaknodes) { - int a=0; + int a; - if(re->blovl) { - for(a=0; re->blovl[a]; a++) - MEM_freeN(re->blovl[a]); + if(vlaknodes==NULL) return; + + for(a=0; vlaknodes[a].vlak; a++) { + MEM_freeN(vlaknodes[a].vlak); - MEM_freeN(re->blovl); - re->blovl= NULL; - re->blovllen= 0; + if(vlaknodes[a].mtface) + MEM_freeN(vlaknodes[a].mtface); + if(vlaknodes[a].mcol) + MEM_freeN(vlaknodes[a].mcol); + if(vlaknodes[a].names) + MEM_freeN(vlaknodes[a].names); } + MEM_freeN(vlaknodes); +} + +void free_renderdata_tables(Render *re) +{ + int a=0; + CustomDataNames *cdn; + if(re->bloha) { for(a=0; re->bloha[a]; a++) MEM_freeN(re->bloha[a]); @@ -336,7 +553,21 @@ void free_renderdata_tables(Render *re) re->vertnodes= NULL; re->vertnodeslen= 0; } - + + if(re->vlaknodes) { + free_renderdata_vlaknodes(re->vlaknodes); + re->vlaknodes= NULL; + re->vlaknodeslen= 0; + } + + for(cdn=re->customdata_names.first; cdn; cdn=cdn->next) { + if(cdn->mtface) + MEM_freeN(cdn->mtface); + if(cdn->mcol) + MEM_freeN(cdn->mcol); + } + + BLI_freelistN(&re->customdata_names); BLI_freelistN(&re->objecttable); } @@ -375,41 +606,6 @@ HaloRen *RE_findOrAddHalo(Render *re, int nr) return h; } -/* ------------------------------------------------------------------------ */ - -VlakRen *RE_findOrAddVlak(Render *re, int nr) -{ - VlakRen *v, **temp; - int a; - - if(nr<0) { - printf("error in findOrAddVlak: %d\n",nr); - return re->blovl[0]; - } - a= nr>>8; - - if (a>=re->blovllen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */ - // printf("Allocating %i more face groups. %i total.\n", - // TABLEINITSIZE, re->blovllen+TABLEINITSIZE ); - temp= re->blovl; - - re->blovl=(VlakRen**)MEM_callocN(sizeof(void*)*(re->blovllen+TABLEINITSIZE) , "Blovl"); - if(temp) memcpy(re->blovl, temp, re->blovllen*sizeof(void*)); - memset(&(re->blovl[re->blovllen]), 0, TABLEINITSIZE*sizeof(void*)); - re->blovllen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ - if(temp) MEM_freeN(temp); - } - - v= re->blovl[a]; - - if(v==NULL) { - v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak"); - re->blovl[a]= v; - } - v+= (nr & 255); - return v; -} - /* ------------------------------------------------------------------------- */ HaloRen *RE_inithalo(Render *re, Material *ma, float *vec, float *vec1, @@ -667,7 +863,7 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], /* set flags at 0 if clipped away */ for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; vlr->flag |= R_VISIBLE; @@ -690,7 +886,7 @@ void set_normalflags(Render *re) /* switch normal 'snproj' values (define which axis is the optimal one for calculations) */ for(a1=0; a1<re->totvlak; a1++) { - if((a1 & 255)==0) vlr= re->blovl[a1>>8]; + if((a1 & 255)==0) vlr= re->vlaknodes[a1>>8].vlak; else vlr++; /* abuse of this flag... this is code that just sets face normal in direction of camera */ diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index b4653f5b3d2..3c6975c2a67 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -302,7 +302,7 @@ static void shadowbuf_autoclip(Render *re, LampRen *lar) /* set clip in vertices when face visible */ for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; /* note; these conditions are copied from zbuffer_shadow() */ @@ -317,7 +317,7 @@ static void shadowbuf_autoclip(Render *re, LampRen *lar) vlr->v2->clip= 1; vlr->v3->clip= 1; if(vlr->v4) vlr->v4->clip= 1; - } + } } /* calculate min and max */ @@ -1424,7 +1424,7 @@ static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root) for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; /* note, these conditions are copied in shadowbuf_autoclip() */ diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 9bf5f5a5207..c1bc3108eb4 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -638,23 +638,38 @@ void shade_input_set_shade_texco(ShadeInput *shi) if((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE))) { VlakRen *vlr= shi->vlr; - int j1=shi->i1, j2=shi->i2, j3=shi->i3; - + MTFace *tface; + MCol *mcol; + char *name; + int i, j1=shi->i1, j2=shi->i2, j3=shi->i3; + /* uv and vcols are not copied on split, so set them according vlr divide flag */ vlr_set_uv_indices(vlr, &j1, &j2, &j3); - + + shi->totuv= 0; + shi->totcol= 0; + if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) { - - if(vlr->vcol) { + for (i=0; (mcol=RE_vlakren_get_mcol(&R, vlr, i, &name, 0)); i++) { + ShadeInputCol *scol= &shi->col[i]; char *cp1, *cp2, *cp3; - cp1= (char *)(vlr->vcol+j1); - cp2= (char *)(vlr->vcol+j2); - cp3= (char *)(vlr->vcol+j3); + shi->totcol++; + scol->name= name; + + cp1= (char *)(mcol+j1); + cp2= (char *)(mcol+j2); + cp3= (char *)(mcol+j3); - shi->vcol[0]= (l*((float)cp3[3]) - u*((float)cp1[3]) - v*((float)cp2[3]))/255.0f; - shi->vcol[1]= (l*((float)cp3[2]) - u*((float)cp1[2]) - v*((float)cp2[2]))/255.0f; - shi->vcol[2]= (l*((float)cp3[1]) - u*((float)cp1[1]) - v*((float)cp2[1]))/255.0f; + scol->col[0]= (l*((float)cp3[3]) - u*((float)cp1[3]) - v*((float)cp2[3]))/255.0f; + scol->col[1]= (l*((float)cp3[2]) - u*((float)cp1[2]) - v*((float)cp2[2]))/255.0f; + scol->col[2]= (l*((float)cp3[1]) - u*((float)cp1[1]) - v*((float)cp2[1]))/255.0f; + } + + if(shi->totcol) { + shi->vcol[0]= shi->col[0].col[0]; + shi->vcol[1]= shi->col[0].col[1]; + shi->vcol[2]= shi->col[0].col[2]; } else { shi->vcol[0]= 0.0f; @@ -662,17 +677,22 @@ void shade_input_set_shade_texco(ShadeInput *shi) shi->vcol[2]= 0.0f; } } - if(vlr->tface) { + + for (i=0; (tface=RE_vlakren_get_tface(&R, vlr, i, &name, 0)); i++) { + ShadeInputUV *suv= &shi->uv[i]; float *uv1, *uv2, *uv3; + + shi->totuv++; + suv->name= name; - uv1= vlr->tface->uv[j1]; - uv2= vlr->tface->uv[j2]; - uv3= vlr->tface->uv[j3]; - - shi->uv[0]= -1.0f + 2.0f*(l*uv3[0]-u*uv1[0]-v*uv2[0]); - shi->uv[1]= -1.0f + 2.0f*(l*uv3[1]-u*uv1[1]-v*uv2[1]); - shi->uv[2]= 1.0f; /* texture.c assumes there are 3 coords, also to indicate it is real UV for passes */ + uv1= tface->uv[j1]; + uv2= tface->uv[j2]; + uv3= tface->uv[j3]; + suv->uv[0]= -1.0f + 2.0f*(l*uv3[0]-u*uv1[0]-v*uv2[0]); + suv->uv[1]= -1.0f + 2.0f*(l*uv3[1]-u*uv1[1]-v*uv2[1]); + suv->uv[2]= 1.0f; /* texture.c assumes there are 3 coords, also to indicate it is real UV for passes */ + if(shi->osatex) { float duv[2]; @@ -680,29 +700,34 @@ void shade_input_set_shade_texco(ShadeInput *shi) duv[0]= shi->dx_u; duv[1]= shi->dx_v; - shi->dxuv[0]= 2.0f*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]); - shi->dxuv[1]= 2.0f*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]); + suv->dxuv[0]= 2.0f*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]); + suv->dxuv[1]= 2.0f*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]); dl= shi->dy_u+shi->dy_v; duv[0]= shi->dy_u; duv[1]= shi->dy_v; - shi->dyuv[0]= 2.0f*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]); - shi->dyuv[1]= 2.0f*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]); + suv->dyuv[0]= 2.0f*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]); + suv->dyuv[1]= 2.0f*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]); } - if(mode & MA_FACETEXTURE) { + + if((mode & MA_FACETEXTURE) && i==0) { if((mode & (MA_VERTEXCOL|MA_VERTEXCOLP))==0) { shi->vcol[0]= 1.0f; shi->vcol[1]= 1.0f; shi->vcol[2]= 1.0f; } - if(vlr->tface) render_realtime_texture(shi); + if(tface && tface->tpage) + render_realtime_texture(shi, tface->tpage); } } - else { - shi->uv[0]= 2.0f*(u+.5f); - shi->uv[1]= 2.0f*(v+.5f); - shi->uv[2]= 0.0f; /* texture.c assumes there are 3 coords, also to indicate it is no real UV for passes */ + + if(shi->totuv == 0) { + ShadeInputUV *suv= &shi->uv[0]; + + suv->uv[0]= 2.0f*(u+.5f); + suv->uv[1]= 2.0f*(v+.5f); + suv->uv[2]= 0.0f; /* texture.c assumes there are 3 coords, also to indicate it is no real UV for passes */ if(mode & MA_FACETEXTURE) { /* no tface? set at 1.0f */ @@ -842,7 +867,6 @@ void shade_input_set_shade_texco(ShadeInput *shi) /* ****************** ShadeSample ************************************** */ - /* initialize per part, not per pixel! */ void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, int sample) { @@ -877,7 +901,6 @@ void shade_sample_initialize(ShadeSample *ssamp, RenderPart *pa, RenderLayer *rl ssamp->samplenr= 0; /* counter, detect shadow-reuse for shaders */ } - /* Do AO or (future) GI */ void shade_samples_do_AO(ShadeSample *ssamp) { diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index b53954c8ace..8837b933fa3 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -822,14 +822,8 @@ void shade_color(ShadeInput *shi, ShadeResult *shr) shi->b= shi->vcol[2]; } - if(ma->texco) { - if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) { - shi->r= shi->vcol[0]; - shi->g= shi->vcol[1]; - shi->b= shi->vcol[2]; - } + if(ma->texco) do_material_tex(shi); - } if(ma->fresnel_tra!=0.0f) shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra); diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 3860ca1f4c4..643b4c9338f 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -1416,7 +1416,21 @@ void do_material_tex(ShadeInput *shi) co= shi->gl; dx= shi->dxco; dy= shi->dyco; } else if(mtex->texco==TEXCO_UV) { - co= shi->uv; dx= shi->dxuv; dy= shi->dyuv; + ShadeInputUV *suv= &shi->uv[0]; + int i; + + if(mtex->uvname[0] != 0) { + for(i = 0; i < shi->totuv; i++) { + if(strcmp(shi->uv[i].name, mtex->uvname)==0) { + suv= &shi->uv[i]; + break; + } + } + } + + co= suv->uv; + dx= suv->dxuv; + dy= suv->dyuv; } else if(mtex->texco==TEXCO_WINDOW) { co= shi->winco; dx= shi->dxwin; dy= shi->dywin; @@ -2366,15 +2380,14 @@ int externtex(MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *t /* ------------------------------------------------------------------------- */ -void render_realtime_texture(ShadeInput *shi) +void render_realtime_texture(ShadeInput *shi, Image *ima) { TexResult texr; - Image *ima; static Tex tex1, tex2; // threadsafe static int firsttime= 1; Tex *tex; float texvec[3], dx[2], dy[2]; - + if(firsttime) { firsttime= 0; default_tex(&tex1); @@ -2385,27 +2398,23 @@ void render_realtime_texture(ShadeInput *shi) if(shi->ys & 1) tex= &tex1; else tex= &tex2; // threadsafe - ima = shi->vlr->tface->tpage; - if(ima) { - - texvec[0]= 0.5+0.5*shi->uv[0]; - texvec[1]= 0.5+0.5*shi->uv[1]; - if(shi->osatex) { - dx[0]= 0.5*shi->dxuv[0]; - dx[1]= 0.5*shi->dxuv[1]; - dy[0]= 0.5*shi->dyuv[0]; - dy[1]= 0.5*shi->dyuv[1]; - } - - texr.nor= NULL; - - if(shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr); - else imagewrap(tex, ima, NULL, texvec, &texr); - - shi->vcol[0]*= texr.tr; - shi->vcol[1]*= texr.tg; - shi->vcol[2]*= texr.tb; + texvec[0]= 0.5+0.5*shi->uv[0].uv[0]; + texvec[1]= 0.5+0.5*shi->uv[0].uv[1]; + if(shi->osatex) { + dx[0]= 0.5*shi->uv[0].dxuv[0]; + dx[1]= 0.5*shi->uv[0].dxuv[1]; + dy[0]= 0.5*shi->uv[0].dyuv[0]; + dy[1]= 0.5*shi->uv[0].dyuv[1]; } + + texr.nor= NULL; + + if(shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr); + else imagewrap(tex, ima, NULL, texvec, &texr); + + shi->vcol[0]*= texr.tr; + shi->vcol[1]*= texr.tg; + shi->vcol[2]*= texr.tb; } /* eof */ diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 44fbd782214..e934fcf2c29 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -1756,7 +1756,7 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag) for(v=0; v<R.totvlak; v++) { - if((v & 255)==0) vlr= R.blovl[v>>8]; + if((v & 255)==0) vlr= R.vlaknodes[v>>8].vlak; else vlr++; if((vlr->flag & R_VISIBLE)) { @@ -1919,7 +1919,7 @@ void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem, Re int totface=0; for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; else vlr++; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; if(vlr->radface) { rf= vlr->radface; @@ -1979,7 +1979,7 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx, for(a=0; a<re->totvlak; a++) { - if((a & 255)==0) vlr= re->blovl[a>>8]; + if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; /* note, these conditions are copied in shadowbuf_autoclip() */ @@ -2588,7 +2588,7 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, un for(v=0; v<R.totvlak; v++) { if((v & 255)==0) - vlr= R.blovl[v>>8]; + vlr= R.vlaknodes[v>>8].vlak; else vlr++; if(vlr->mat!=ma) { diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 537ae7d6a68..75c44e9b399 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -671,32 +671,90 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an /* *************************** MESH ******************************** */ -static void customdata_buttons(uiBlock *block, CustomData *data, int type, int *activep, int setevt, int newevt, int delevt, char *label, char *shortlabel, char *browsetip, char *newtip, char *deltip, int x, int y) +static void verify_customdata_name_func(void *data1, void *data2) +{ + CustomData *data= (CustomData*)data1; + CustomDataLayer *layer= (CustomDataLayer*)data2; + + CustomData_set_layer_unique_name(data, layer - data->layers); +} + +static void delete_customdata_layer(void *data1, void *data2) +{ + Mesh *me= (Mesh*)data1; + CustomData *data= (G.obedit)? &G.editMesh->fdata: &me->fdata; + CustomDataLayer *layer= (CustomDataLayer*)data2; + int type= layer->type; + int index= CustomData_get_layer_index(data, type); + + CustomData_set_layer_active(data, type, layer - &data->layers[index]); + + if(G.obedit) { + EM_free_data_layer(data, type); + } + else if(me) { + CustomData_free_layer(data, type, me->totface); + mesh_update_customdata_pointers(me); + } + + if(!CustomData_has_layer(data, type)) { + if(type == CD_MCOL && (G.f & G_VERTEXPAINT)) + G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */ + if(type == CD_MTFACE && (G.f & G_FACESELECT)) + set_faceselect(); /* get out of faceselect mode */ + } + + DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); + + if(type == CD_MTFACE) + BIF_undo_push("Delete UV Texture"); + else if(type == CD_MCOL) + BIF_undo_push("Delete Vertex Color"); + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWIMAGE, 0); + allqueue(REDRAWBUTSEDIT, 0); +} + +static int customdata_buttons(uiBlock *block, Mesh *me, CustomData *data, int type, int *activep, int setevt, int newevt, char *label, char *shortlabel, char *browsetip, char *newtip, char *deltip, int x, int y) { CustomDataLayer *layer; - int i, count= 0; + uiBut *but; + int i, count= CustomData_number_of_layers(data, type); + + if(count >= MAX_MTFACE) { + uiDefBut(block, LABEL, 0, label, x,y,220,19, 0, 0.0, 0, 0, 0, ""); + } + else { + uiDefBut(block, LABEL, 0, label, x,y,140,19, 0, 0.0, 0, 0, 0, ""); + uiBlockBeginAlign(block); + uiDefBut(block, BUT, newevt, "New", x+140,y,80,19, 0,0,0,0,0, newtip); + uiBlockEndAlign(block); + } - *activep = 1; + y -= (count)? 24: 19; - for (i=0; i<data->totlayer; i++) { + uiBlockBeginAlign(block); + for (count=1, i=0; i<data->totlayer; i++) { layer= &data->layers[i]; if(layer->type == type) { - if(count == layer->active) - *activep = count+1; + *activep= layer->active + 1; + + uiDefButI(block, ROW, setevt, "", x,y,25,19, activep, 1.0, count, 0, 0, "Set active UV texture layer"); + but=uiDefBut(block, TEX, setevt, "", x+25,y,170,19, layer->name, 0.0, 31.0, 0, 0, "UV texture layer name"); + uiButSetFunc(but, verify_customdata_name_func, data, layer); + but= uiDefIconBut(block, BUT, B_NOP, VICON_X, x+195,y,25,19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete UV texture layer"); + uiButSetFunc(but, delete_customdata_layer, me, layer); + + count++; + y -= 19; } } - - uiBlockBeginAlign(block); - if (count == 0) - uiDefBut(block, LABEL, 0, label, x,y,140,20, 0, 0.0, 0, 0, 0, ""); - else - uiDefButI(block, NUM, setevt, shortlabel, x,y,140,20, activep, 1, count, 0, 0, browsetip); - - uiDefBut(block, BUT, newevt, "New", x+140,y,52,20, 0,0,0,0,0, newtip); - uiDefBut(block, BUT, delevt, "Delete", x+182,y,68,20, 0,0,0,0,0, deltip); uiBlockEndAlign(block); + + return y; } static void editing_panel_mesh_type(Object *ob, Mesh *me) @@ -705,62 +763,65 @@ static void editing_panel_mesh_type(Object *ob, Mesh *me) uiBut *but; float val; CustomData *fdata; + int yco; block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_type", UI_EMBOSS, UI_HELV, curarea->win); if( uiNewPanel(curarea, block, "Mesh", "Editing", 320, 0, 318, 204)==0) return; uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, ME_AUTOSMOOTH, REDRAWVIEW3D, "Auto Smooth",10,180,154,19, &me->flag, 0, 0, 0, 0, "Treats all set-smoothed faces with angles less than Degr: as 'smooth' during render"); - uiDefButS(block, NUM, B_DIFF, "Degr:", 10,160,154,19, &me->smoothresh, 1, 80, 0, 0, "Defines maximum angle between face normals that 'Auto Smooth' will operate on"); + uiDefButBitS(block, TOG, ME_AUTOSMOOTH, REDRAWVIEW3D, "Auto Smooth",10,180,170,19, &me->flag, 0, 0, 0, 0, "Treats all set-smoothed faces with angles less than Degr: as 'smooth' during render"); + uiDefButS(block, NUM, B_DIFF, "Degr:", 10,160,170,19, &me->smoothresh, 1, 80, 0, 0, "Defines maximum angle between face normals that 'Auto Smooth' will operate on"); uiBlockEndAlign(block); /* Retopo */ if(G.obedit) { uiBlockBeginAlign(block); - but= uiDefButBitC(block,TOG,1,B_NOP, "Retopo", 10,130,154,19, &G.editMesh->retopo_mode, 0,0,0,0, "Turn on the re-topology tool"); + but= uiDefButBitC(block,TOG,1,B_NOP, "Retopo", 10,130,170,19, &G.editMesh->retopo_mode, 0,0,0,0, "Turn on the re-topology tool"); uiButSetFunc(but,retopo_toggle,ob,me); if(G.editMesh->retopo_mode) { - but= uiDefButBitC(block,TOG,2,B_NOP,"Paint", 10,110,50,19, &G.editMesh->retopo_mode,0,0,0,0, ""); + but= uiDefButBitC(block,TOG,2,B_NOP,"Paint", 10,110,55,19, &G.editMesh->retopo_mode,0,0,0,0, ""); uiButSetFunc(but,retopo_paint_toggle,ob,me); - but= uiDefBut(block,BUT,B_NOP,"Retopo All", 60,110,104,19, 0,0,0,0,0, "Apply the re-topology tool to all selected vertices"); + but= uiDefBut(block,BUT,B_NOP,"Retopo All", 65,110,115,19, 0,0,0,0,0, "Apply the re-topology tool to all selected vertices"); uiButSetFunc(but,retopo_do_all,ob,me); } uiBlockEndAlign(block); } - uiBlockSetCol(block, TH_AUTO); - - uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, B_REDR, "TexMesh: ", 180,180,230,19, &me->texcomesh, "Derive texture coordinates from another mesh."); + uiBlockBeginAlign(block); + uiDefBut(block, BUT,B_DOCENTRE, "Centre", 10, 80, 65, 19, 0, 0, 0, 0, 0, "Shifts object data to be centered about object's origin"); + uiDefBut(block, BUT,B_DOCENTRENEW, "Centre New", 75, 80, 105, 19, 0, 0, 0, 0, 0, "Shifts object's origin to center of object data"); + uiDefBut(block, BUT,B_DOCENTRECURSOR, "Centre Cursor", 10, 60, 170, 19, 0, 0, 0, 0, 0, "Shifts object's origin to cursor location"); + uiBlockEndAlign(block); - fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata; - customdata_buttons(block, fdata, CD_MCOL, &actmcol, B_SETMCOL, - B_NEWMCOL, B_DELMCOL, "Vert Color", "Vert Color:", - "Sets active vertex color layer", "Creates a new vertex color layer", - "Removes the current vertex color layer", 10, 60); + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, ME_TWOSIDED, REDRAWVIEW3D, "Double Sided", 10,30,170,19, &me->flag, 0, 0, 0, 0, "Render/display the mesh as double or single sided"); + uiDefButBitS(block, TOG, ME_NOPUNOFLIP, REDRAWVIEW3D, "No V.Normal Flip", 10,10,170,19, &me->flag, 0, 0, 0, 0, "Disables flipping of vertexnormals during render"); + uiBlockEndAlign(block); - customdata_buttons(block, fdata, CD_MTFACE, &acttface, B_SETTFACE, - B_NEWTFACE, B_DELTFACE, "UV Texture", "UV Texture:", - "Set active UV texture", "Creates a new UV texture layer", - "Removes the current UV texture layer", 10, 35); + uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, B_REDR, "TexMesh: ", 190,180,220,19, &me->texcomesh, "Derive texture coordinates from another mesh."); - uiBlockBeginAlign(block); if(me->msticky) val= 1.0; else val= 0.0; - uiDefBut(block, LABEL, 0, "Sticky", 10,10,140,20, 0, val, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Sticky", 190,155,140,19, 0, val, 0, 0, 0, ""); + uiBlockBeginAlign(block); if(me->msticky==NULL) { - uiDefBut(block, BUT, B_MAKESTICKY, "Make", 150,10,110,20, 0, 0, 0, 0, 0, "Creates Sticky coordinates from the current camera view background picture"); + uiDefBut(block, BUT, B_MAKESTICKY, "Make", 330,155, 80,19, 0, 0, 0, 0, 0, "Creates Sticky coordinates from the current camera view background picture"); } - else uiDefBut(block, BUT, B_DELSTICKY, "Delete", 150,10,110,20, 0, 0, 0, 0, 0, "Deletes Sticky texture coordinates"); + else uiDefBut(block, BUT, B_DELSTICKY, "Delete", 330,155, 80,19, 0, 0, 0, 0, 0, "Deletes Sticky texture coordinates"); uiBlockEndAlign(block); - uiBlockBeginAlign(block); - uiDefBut(block, BUT,B_DOCENTRE, "Centre", 275, 95, 130, 19, 0, 0, 0, 0, 0, "Shifts object data to be centered about object's origin"); - uiDefBut(block, BUT,B_DOCENTRENEW, "Centre New", 275, 75, 130, 19, 0, 0, 0, 0, 0, "Shifts object's origin to center of object data"); - uiDefBut(block, BUT,B_DOCENTRECURSOR, "Centre Cursor", 275, 55, 130, 19, 0, 0, 0, 0, 0, "Shifts object's origin to cursor location"); + fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata; + yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, + B_SETTFACE, B_NEWTFACE, "UV Texture", "UV Texture:", + "Set active UV texture", "Creates a new UV texture layer", + "Removes the current UV texture layer", 190, 130); - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, ME_TWOSIDED, REDRAWVIEW3D, "Double Sided", 275,30,130,19, &me->flag, 0, 0, 0, 0, "Render/display the mesh as double or single sided"); - uiDefButBitS(block, TOG, ME_NOPUNOFLIP, REDRAWVIEW3D, "No V.Normal Flip",275,10,130,19, &me->flag, 0, 0, 0, 0, "Disables flipping of vertexnormals during render"); - uiBlockEndAlign(block); + yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, + B_SETMCOL, B_NEWMCOL, "Vertex Color", "Vertex Color:", + "Sets active vertex color layer", "Creates a new vertex color layer", + "Removes the current vertex color layer", 190, yco-5); + + if(yco < 0) + uiNewPanelHeight(block, 204 - yco); } /* *************************** MODIFIERS ******************************** */ @@ -3601,11 +3662,13 @@ void do_meshbuts(unsigned short event) if(me->msticky) { CustomData_free_layer(&me->vdata, CD_MSTICKY, me->totvert); me->msticky= NULL; + BIF_undo_push("Delete Sticky"); } allqueue(REDRAWBUTSEDIT, 0); break; case B_MAKESTICKY: RE_make_sticky(); + BIF_undo_push("Make Sticky"); allqueue(REDRAWBUTSEDIT, 0); break; @@ -3634,22 +3697,7 @@ void do_meshbuts(unsigned short event) } DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWBUTSEDIT, 0); - break; - case B_DELMCOL: - if(G.obedit) { - EM_free_data_layer(&em->fdata, CD_MCOL); - } - else if(me) { - CustomData_free_layer(&me->fdata, CD_MCOL, me->totface); - me->mcol= CustomData_get_layer(&me->fdata, CD_MCOL); - } - - if((me && me->mcol == NULL) && (G.f & G_VERTEXPAINT)) - G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */ - - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + BIF_undo_push("New Vertex Color"); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); break; @@ -3660,6 +3708,7 @@ void do_meshbuts(unsigned short event) mesh_update_customdata_pointers(me); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + BIF_undo_push("Set Active Vertex Color"); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); } @@ -3686,34 +3735,28 @@ void do_meshbuts(unsigned short event) } DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + BIF_undo_push("New UV Texture"); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); - break; - case B_DELTFACE: - if(G.obedit) { - EM_free_data_layer(&em->fdata, CD_MTFACE); - } - else if(me) { - CustomData_free_layer(&me->fdata, CD_MTFACE, me->totface); - me->mtface= CustomData_get_layer(&me->fdata, CD_MTFACE); - } - - if((me && me->mtface == NULL) && (G.f & G_FACESELECT)) - set_faceselect(); /* get out of vertexpaint mode */ - - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWIMAGE, 0); break; case B_SETTFACE: if (G.obedit || me) { + if (G.f & G_FACESELECT) + select_mface_from_tface(me); + CustomData *fdata= (G.obedit)? &em->fdata: &me->fdata; CustomData_set_layer_active(fdata, CD_MTFACE, acttface-1); mesh_update_customdata_pointers(me); + if (G.f & G_FACESELECT) + select_tface_from_mface(me); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + BIF_undo_push("Set Active UV Texture"); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWIMAGE, 0); } break; diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 8557cea5468..6998f8ec19b 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -46,6 +46,7 @@ #include "DNA_image_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" +#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_node_types.h" #include "DNA_packedFile_types.h" @@ -3025,7 +3026,10 @@ static void material_panel_map_input(Object *ob, Material *ma) uiBlockBeginAlign(block); uiDefButS(block, ROW, B_MATPRV, "Glob", 630,180,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates"); uiDefButS(block, ROW, B_MATPRV, "Object", 675,180,75,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates"); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "",750,180,158,18, &(mtex->object), ""); + if(mtex->texco == TEXCO_UV) + uiDefBut(block, TEX, B_MATPRV, "UV:", 750,180,158,18, mtex->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer"); + else + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "Ob:",750,180,158,18, &(mtex->object), ""); uiDefButS(block, ROW, B_MATPRV, "UV", 630,160,40,18, &(mtex->texco), 4.0, (float)TEXCO_UV, 0, 0, "Uses UV coordinates for texture coordinates"); uiDefButS(block, ROW, B_MATPRV, "Orco", 670,160,55,18, &(mtex->texco), 4.0, (float)TEXCO_ORCO, 0, 0, "Uses the original undeformed coordinates of the object"); diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c index 94255384108..c8c07748d6a 100644 --- a/source/blender/src/drawmesh.c +++ b/source/blender/src/drawmesh.c @@ -926,16 +926,19 @@ static int draw_tface__set_draw(MTFace *tface, MCol *mcol, int matnr) { if (tface && ((tface->flag&TF_HIDE) || (tface->mode&TF_INVISIBLE))) return 0; - if (set_draw_settings_cached(0, g_draw_tface_mesh_istex, tface, g_draw_tface_mesh_islight, g_draw_tface_mesh_ob, matnr, TF_TWOSIDE)) { + if (tface && set_draw_settings_cached(0, g_draw_tface_mesh_istex, tface, g_draw_tface_mesh_islight, g_draw_tface_mesh_ob, matnr, TF_TWOSIDE)) { glColor3ub(0xFF, 0x00, 0xFF); return 2; /* Don't set color */ } else if (tface && tface->mode&TF_OBCOL) { glColor3ubv(g_draw_tface_mesh_obcol); return 2; /* Don't set color */ } else if (!mcol) { - Material *ma= give_current_material(g_draw_tface_mesh_ob, matnr+1); - if(ma) glColor3f(ma->r, ma->g, ma->b); - else glColor3f(1.0, 1.0, 1.0); + if (tface) glColor3f(1.0, 1.0, 1.0); + else { + Material *ma= give_current_material(g_draw_tface_mesh_ob, matnr+1); + if(ma) glColor3f(ma->r, ma->g, ma->b); + else glColor3f(1.0, 1.0, 1.0); + } return 2; /* Don't set color */ } else { return 1; /* Set color from mcol */ diff --git a/source/blender/src/drawnode.c b/source/blender/src/drawnode.c index 831387de931..b6af394b9f4 100644 --- a/source/blender/src/drawnode.c +++ b/source/blender/src/drawnode.c @@ -599,6 +599,18 @@ static int node_shader_buts_vect_math(uiBlock *block, bNodeTree *ntree, bNode *n return 20; } +static int node_shader_buts_geometry(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +{ + if(block) { + NodeGeometry *ngeo= (NodeGeometry*)node->storage; + + uiDefBut(block, TEX, B_NODE_EXEC+node->nr, "UV:", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, ngeo->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer"); + } + + return 20; +} + + /* only once called */ static void node_shader_set_butfunc(bNodeType *ntype) { @@ -642,6 +654,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_VECT_MATH: ntype->butfunc= node_shader_buts_vect_math; break; + case SH_NODE_GEOMETRY: + ntype->butfunc= node_shader_buts_geometry; + break; default: ntype->butfunc= NULL; } diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 538e7e6fef2..567e4a7bab2 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -2002,7 +2002,7 @@ static void draw_mesh_fancy(Base *base, DerivedMesh *baseDM, DerivedMesh *dm, in else if(dt==OB_WIRE || totface==0) { draw_wire = 1; } - else if( (ob==OBACT && (G.f & G_FACESELECT)) || (G.vd->drawtype==OB_TEXTURE && dt>OB_SOLID)) { + else if( (ob==OBACT && (G.f & (G_FACESELECT|G_TEXTUREPAINT))) || (G.vd->drawtype==OB_TEXTURE && dt>OB_SOLID)) { if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&(G_FACESELECT|G_PICKSEL)) && !draw_wire) { draw_mesh_object_outline(ob, dm); @@ -2059,7 +2059,8 @@ static void draw_mesh_fancy(Base *base, DerivedMesh *baseDM, DerivedMesh *dm, in dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1); } else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mtface) { - dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1); + glColor3f(1.0f, 1.0f, 1.0f); + dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0); } else do_draw= 1; } @@ -2177,7 +2178,7 @@ static int draw_mesh_object(Base *base, int dt, int flag) if(baseDM && realDM) draw_mesh_fancy(base, baseDM, realDM, dt, flag); if(me->totvert==0) retval= 1; - + baseDM->release(baseDM); realDM->release(realDM); } diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c index 81c77adfdde..68fcc200622 100644 --- a/source/blender/src/editface.c +++ b/source/blender/src/editface.c @@ -1434,11 +1434,15 @@ void set_faceselect() /* toggle */ setcursor_space(SPACE_VIEW3D, CURSOR_STD); BIF_undo_push("End UV Faceselect"); } + + if(me) + select_mface_from_tface(me); } else if (me && (ob->lay & G.vd->lay)) { G.f |= G_FACESELECT; if(me->mtface==NULL) make_tfaces(me); + select_tface_from_mface(me); setcursor_space(SPACE_VIEW3D, CURSOR_FACESEL); BIF_undo_push("Set UV Faceselect"); @@ -1451,6 +1455,44 @@ void set_faceselect() /* toggle */ allqueue(REDRAWIMAGE, 0); } +void select_tface_from_mface(Mesh *me) +{ + MFace *mf; + MTFace *tf; + int a; + + if(!me->mtface) return; + + mf= me->mface; + tf= me->mtface; + for(a=0; a<me->totface; a++, mf++, tf++) { + if(mf->flag & ME_FACE_SEL) tf->flag |= TF_SELECT; + else tf->flag &= ~TF_SELECT; + + if(mf->flag & ME_HIDE) tf->flag |= TF_HIDE; + else tf->flag &= ~TF_HIDE; + } +} + +void select_mface_from_tface(Mesh *me) +{ + MFace *mf; + MTFace *tf; + int a; + + if(!me->mtface) return; + + mf= me->mface; + tf= me->mtface; + for(a=0; a<me->totface; a++, mf++, tf++) { + if(tf->flag & TF_SELECT) mf->flag |= ME_FACE_SEL; + else mf->flag &= ~ME_FACE_SEL; + + if(tf->flag & TF_HIDE) mf->flag |= ME_HIDE; + else mf->flag &= ~ME_HIDE; + } +} + /* Texture Paint */ void set_texturepaint() /* toggle */ @@ -1480,6 +1522,10 @@ void set_texturepaint() /* toggle */ } else if (me) { G.f |= G_TEXTUREPAINT; + + if(me->mtface==NULL) + make_tfaces(me); + brush_check_exists(&G.scene->toolsettings->imapaint.brush); texpaint_disable_mipmap(); } diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index b4f1bddc716..f5b0c432b3a 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -784,7 +784,6 @@ void make_editMesh() Mesh *me= G.obedit->data; EditMesh *em= G.editMesh; MFace *mface; - MTFace *tface; MVert *mvert; MSelect *mselect; KeyBlock *actkey; @@ -872,10 +871,11 @@ void make_editMesh() } CustomData_copy(&me->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0); + if (G.f & G_FACESELECT) + select_mface_from_tface(me); /* make faces */ mface= me->mface; - tface= me->mtface; for(a=0; a<me->totface; a++, mface++) { eve1= evlist[mface->v1]; @@ -892,22 +892,15 @@ void make_editMesh() efa->mat_nr= mface->mat_nr; efa->flag= mface->flag & ~ME_HIDE; - if((G.f & G_FACESELECT)==0) { - /* select face flag, if no edges we flush down */ - if(mface->flag & ME_FACE_SEL) { - efa->f |= SELECT; - } - if(mface->flag & ME_HIDE) efa->h= 1; - } - else if((tface = CustomData_get(&me->fdata, a, CD_MTFACE))) { - if(tface->flag & TF_HIDE) - efa->h= 1; - else if(tface->flag & TF_SELECT) - EM_select_face(efa, 1); + /* select and hide face flag */ + if(mface->flag & ME_FACE_SEL) { + efa->f |= SELECT; } - } + if(mface->flag & ME_HIDE) efa->h= 1; - if(me->mtface) tface++; + if((G.f & G_FACESELECT) && (efa->f & SELECT)) + EM_select_face(efa, 1); /* flush down */ + } } } @@ -956,7 +949,6 @@ void load_editMesh(void) MEdge *medge; MFace *mface; MSelect *mselect; - MTFace *tf; EditVert *eve; EditFace *efa; EditEdge *eed; @@ -1148,20 +1140,8 @@ void load_editMesh(void) } /* sync hide and select flags with faceselect mode */ - if(G.f & G_FACESELECT) { - if(me->mtface && (me->totface > 0)) { - efa= em->faces.first; - for(a=0, efa=em->faces.first; efa; a++, efa=efa->next) { - tf = &me->mtface[a]; - - if(efa->h) tf->flag |= TF_HIDE; - else tf->flag &= ~TF_HIDE; - if(efa->f & SELECT) tf->flag |= TF_SELECT; - else tf->flag &= ~TF_SELECT; - } - } - } - + if (G.f & G_FACESELECT) + select_tface_from_mface(me); /* patch hook indices and vertex parents */ { diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c index 3724aaf43a0..e2bcc122df1 100644 --- a/source/blender/src/imagepaint.c +++ b/source/blender/src/imagepaint.c @@ -250,7 +250,7 @@ static void imapaint_redraw(int final, int texpaint, Image *image) imagepaint_composite_tags(G.scene->nodetree, image, &G.sima->iuser); } /* signal composite (hurmf, need an allqueue?) */ - if(G.sima->lock) { + if(!texpaint && G.sima->lock) { ScrArea *sa; for(sa=G.curscreen->areabase.first; sa; sa= sa->next) { if(sa->spacetype==SPACE_NODE) { diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c index 95d4ae4dd55..8ba30f778c3 100644 --- a/source/blender/src/vpaint.c +++ b/source/blender/src/vpaint.c @@ -247,7 +247,7 @@ void make_vertexcol(int shade) /* single ob */ if(shade) shadeMeshMCol(ob, me); else - memset(me->mcol, 0, 4*sizeof(MCol)*me->totface); + memset(me->mcol, 255, 4*sizeof(MCol)*me->totface); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); diff --git a/source/blender/yafray/intern/export_File.cpp b/source/blender/yafray/intern/export_File.cpp index 7d9f23a4e4c..c8c0b3c6bb1 100755 --- a/source/blender/yafray/intern/export_File.cpp +++ b/source/blender/yafray/intern/export_File.cpp @@ -1230,7 +1230,7 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_li string matname(face0mat->id.name); // use name in imgtex_shader list if 'TexFace' enabled for this material if (face0mat->mode & MA_FACETEXTURE) { - MTFace* tface = face0->tface; + MTFace* tface = RE_vlakren_get_tface(re, face0, 0, NULL, 0); if (tface) { Image* fimg = (Image*)tface->tpage; if (fimg) matname = imgtex_shader[string(face0mat->id.name) + string(fimg->id.name)]; @@ -1412,7 +1412,7 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_li string fmatname(fmat->id.name); // use name in imgtex_shader list if 'TexFace' enabled for this face material if (fmat->mode & MA_FACETEXTURE) { - MTFace* tface = vlr->tface; + MTFace* tface = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); if (tface) { Image* fimg = (Image*)tface->tpage; if (fimg) fmatname = imgtex_shader[fmatname + string(fimg->id.name)]; @@ -1437,23 +1437,25 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_li } else if (vlr->flag & R_FACE_SPLIT) { ui2++; ui3++; } - MTFace* uvc = vlr->tface; // possible uvcoords (v upside down) + MTFace* uvc = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); // possible uvcoords (v upside down) if (uvc) { ostr << " u_a=\"" << uvc->uv[ui1][0] << "\" v_a=\"" << 1-uvc->uv[ui1][1] << "\"" << " u_b=\"" << uvc->uv[ui2][0] << "\" v_b=\"" << 1-uvc->uv[ui2][1] << "\"" << " u_c=\"" << uvc->uv[ui3][0] << "\" v_c=\"" << 1-uvc->uv[ui3][1] << "\""; } + MCol *mcol= RE_vlakren_get_mcol(re, vlr, 0, NULL, 0); + // since Blender seems to need vcols when uvs are used, for yafray only export when the material actually uses vcols - if ((EXPORT_VCOL) && (vlr->vcol)) { + if ((EXPORT_VCOL) && mcol) { // vertex colors - unsigned char* pt = reinterpret_cast<unsigned char*>(&vlr->vcol[ui1]); + unsigned char* pt = reinterpret_cast<unsigned char*>(&mcol[ui1]); ostr << " vcol_a_r=\"" << (float)pt[3]/255.f << "\" vcol_a_g=\"" << (float)pt[2]/255.f << "\" vcol_a_b=\"" << (float)pt[1]/255.f << "\""; - pt = reinterpret_cast<unsigned char*>(&vlr->vcol[ui2]); + pt = reinterpret_cast<unsigned char*>(&mcol[ui2]); ostr << " vcol_b_r=\"" << (float)pt[3]/255.f << "\" vcol_b_g=\"" << (float)pt[2]/255.f << "\" vcol_b_b=\"" << (float)pt[1]/255.f << "\""; - pt = reinterpret_cast<unsigned char*>(&vlr->vcol[ui3]); + pt = reinterpret_cast<unsigned char*>(&mcol[ui3]); ostr << " vcol_c_r=\"" << (float)pt[3]/255.f << "\" vcol_c_g=\"" << (float)pt[2]/255.f << "\" vcol_c_b=\"" << (float)pt[1]/255.f << "\""; } @@ -1480,15 +1482,15 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_li << " u_b=\"" << uvc->uv[ui2][0] << "\" v_b=\"" << 1-uvc->uv[ui2][1] << "\"" << " u_c=\"" << uvc->uv[ui3][0] << "\" v_c=\"" << 1-uvc->uv[ui3][1] << "\""; } - if ((EXPORT_VCOL) && (vlr->vcol)) { + if ((EXPORT_VCOL) && mcol) { // vertex colors - unsigned char* pt = reinterpret_cast<unsigned char*>(&vlr->vcol[ui1]); + unsigned char* pt = reinterpret_cast<unsigned char*>(&mcol[ui1]); ostr << " vcol_a_r=\"" << (float)pt[3]/255.f << "\" vcol_a_g=\"" << (float)pt[2]/255.f << "\" vcol_a_b=\"" << (float)pt[1]/255.f << "\""; - pt = reinterpret_cast<unsigned char*>(&vlr->vcol[ui2]); + pt = reinterpret_cast<unsigned char*>(&mcol[ui2]); ostr << " vcol_b_r=\"" << (float)pt[3]/255.f << "\" vcol_b_g=\"" << (float)pt[2]/255.f << "\" vcol_b_b=\"" << (float)pt[1]/255.f << "\""; - pt = reinterpret_cast<unsigned char*>(&vlr->vcol[ui3]); + pt = reinterpret_cast<unsigned char*>(&mcol[ui3]); ostr << " vcol_c_r=\"" << (float)pt[3]/255.f << "\" vcol_c_g=\"" << (float)pt[2]/255.f << "\" vcol_c_b=\"" << (float)pt[1]/255.f << "\""; } diff --git a/source/blender/yafray/intern/export_Plugin.cpp b/source/blender/yafray/intern/export_Plugin.cpp index d2ed7f66f32..6a6137fefe9 100644 --- a/source/blender/yafray/intern/export_Plugin.cpp +++ b/source/blender/yafray/intern/export_Plugin.cpp @@ -1109,7 +1109,9 @@ void yafrayPluginRender_t::genUVcoords(vector<yafray::GFLOAT> &uvcoords, VlakRen void yafrayPluginRender_t::genVcol(vector<yafray::CFLOAT> &vcol, VlakRen *vlr, bool comple) { - if (vlr->vcol) + MCol *mcol= RE_vlakren_get_mcol(re, vlr, 0, NULL, 0); + + if (mcol) { // tri vcol split indices int ui1=0, ui2=1, ui3=2; @@ -1123,11 +1125,11 @@ void yafrayPluginRender_t::genVcol(vector<yafray::CFLOAT> &vcol, VlakRen *vlr, b ui2 = (ui2+2) & 3; ui3 = (ui3+2) & 3; } - unsigned char* pt = reinterpret_cast<unsigned char*>(&vlr->vcol[ui1]); + unsigned char* pt = reinterpret_cast<unsigned char*>(&mcol[ui1]); vcol.push_back((float)pt[3]/255.f); vcol.push_back((float)pt[2]/255.f); vcol.push_back((float)pt[1]/255.f); - pt = reinterpret_cast<unsigned char*>(&vlr->vcol[ui2]); + pt = reinterpret_cast<unsigned char*>(&mcol[ui2]); vcol.push_back((float)pt[3]/255.f); vcol.push_back((float)pt[2]/255.f); vcol.push_back((float)pt[1]/255.f); - pt = reinterpret_cast<unsigned char*>(&vlr->vcol[ui3]); + pt = reinterpret_cast<unsigned char*>(&mcol[ui3]); vcol.push_back((float)pt[3]/255.f); vcol.push_back((float)pt[2]/255.f); vcol.push_back((float)pt[1]/255.f); } else @@ -1148,7 +1150,7 @@ void yafrayPluginRender_t::genFace(vector<int> &faces,vector<string> &shaders,ve string fmatname(fmat->id.name); // use name in imgtex_shader list if 'TexFace' enabled for this face material if (fmat->mode & MA_FACETEXTURE) { - MTFace* tface = vlr->tface; + MTFace* tface = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); if (tface) { Image* fimg = (Image*)tface->tpage; if (fimg) fmatname = imgtex_shader[fmatname + string(fimg->id.name)]; @@ -1168,7 +1170,8 @@ void yafrayPluginRender_t::genFace(vector<int> &faces,vector<string> &shaders,ve shaders.push_back(fmatname); faceshader.push_back(shaders.size()-1); } - MTFace* uvc = vlr->tface; // possible uvcoords (v upside down) + + MTFace* uvc = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); // possible uvcoords (v upside down) int idx1, idx2, idx3; idx1 = vert_idx.find(vlr->v1)->second; @@ -1193,7 +1196,7 @@ void yafrayPluginRender_t::genCompleFace(vector<int> &faces,/*vector<string> &sh bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0); faceshader.push_back(faceshader.back()); - MTFace* uvc = vlr->tface; // possible uvcoords (v upside down) + MTFace* uvc = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); // possible uvcoords (v upside down) int idx1, idx2, idx3; idx1 = vert_idx.find(vlr->v3)->second; idx2 = vert_idx.find(vlr->v4)->second; @@ -1336,7 +1339,7 @@ void yafrayPluginRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_ { VlakRen* vlr = *fci; genVertices(verts, vidx, vert_idx, vlr, has_orco, obj); - if(vlr->tface) has_uv=true; + if(RE_vlakren_get_tface(re, vlr, 0, NULL, 0)) has_uv=true; } // all faces using the index list created above vector<int> faces; diff --git a/source/blender/yafray/intern/yafray_Render.cpp b/source/blender/yafray/intern/yafray_Render.cpp index 0d9757b19ad..01ab49c001b 100644 --- a/source/blender/yafray/intern/yafray_Render.cpp +++ b/source/blender/yafray/intern/yafray_Render.cpp @@ -86,7 +86,7 @@ bool yafrayRender_t::getAllMatTexObs() for (int i=0; i < re->totvlak; i++) { - if ((i & 255)==0) vlr = re->blovl[i>>8]; else vlr++; + if ((i & 255)==0) vlr=re->vlaknodes[i>>8].vlak; else vlr++; // ---- The materials & textures // in this case, probably every face has a material assigned, which can be the default material, @@ -129,17 +129,20 @@ bool yafrayRender_t::getAllMatTexObs() // Also make list of facetexture images (material 'TexFace'). if (vlr->ob) { int nv = 0; // number of vertices + MTFace *tface; + if (vlr->v4) nv=4; else if (vlr->v3) nv=3; if (nv) { renderobs[vlr->ob->id.name] = vlr->ob; all_objects[vlr->ob].push_back(vlr); - if (vlr->tface) { - Image* fc_img = vlr->tface->tpage; - if (fc_img) { - Material* fmat = vlr->mat; - // only save if TexFace enabled - if (fmat && (fmat->mode & MA_FACETEXTURE)) imagetex[fc_img].insert(fmat); - } + + tface= RE_vlakren_get_tface(re, vlr, 0, NULL, 0); + if (tface && tface->tpage) { + Material* fmat = vlr->mat; + + // only save if TexFace enabled + if(fmat && (fmat->mode & MA_FACETEXTURE)) + imagetex[tface->tpage].insert(fmat); } } } diff --git a/source/blender/yafray/intern/yafray_Render.h b/source/blender/yafray/intern/yafray_Render.h index 0d794b6755d..4002f514a6e 100644 --- a/source/blender/yafray/intern/yafray_Render.h +++ b/source/blender/yafray/intern/yafray_Render.h @@ -24,6 +24,7 @@ extern "C" { #include "BKE_global.h" #include "render_types.h" +#include "renderdatabase.h" /* display_draw() needs render layer info */ #include "renderpipeline.h" |