forked from bartvdbraak/blender
Patch [#29035] Vertex colour baking
There is a new option in the Bake panel to enable baking to vertex colors. Unlike regular baking, this mode does not require a UV map or image to bake to, however the object must have a vertex color layer. Thanks to: - AutoCRC for funding - Brech van Lommel and Dalai Felinto for their initial advice on how to implement it - Campbell Barton for helping to make this feature work with modifiers and bmesh
This commit is contained in:
parent
7085387def
commit
5e0e62f040
@ -609,9 +609,12 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
|
|||||||
split = layout.split()
|
split = layout.split()
|
||||||
|
|
||||||
col = split.column()
|
col = split.column()
|
||||||
col.prop(rd, "use_bake_clear")
|
col.prop(rd, "use_bake_to_vertex_color")
|
||||||
col.prop(rd, "bake_margin")
|
sub = col.column()
|
||||||
col.prop(rd, "bake_quad_split", text="Split")
|
sub.active = not rd.use_bake_to_vertex_color
|
||||||
|
sub.prop(rd, "use_bake_clear")
|
||||||
|
sub.prop(rd, "bake_margin")
|
||||||
|
sub.prop(rd, "bake_quad_split", text="Split")
|
||||||
|
|
||||||
col = split.column()
|
col = split.column()
|
||||||
col.prop(rd, "use_bake_selected_to_active")
|
col.prop(rd, "use_bake_selected_to_active")
|
||||||
|
@ -1319,6 +1319,7 @@ typedef struct Scene {
|
|||||||
#define R_BAKE_NORMALIZE 8
|
#define R_BAKE_NORMALIZE 8
|
||||||
#define R_BAKE_MULTIRES 16
|
#define R_BAKE_MULTIRES 16
|
||||||
#define R_BAKE_LORES_MESH 32
|
#define R_BAKE_LORES_MESH 32
|
||||||
|
#define R_BAKE_VCOL 64
|
||||||
|
|
||||||
/* bake_normal_space */
|
/* bake_normal_space */
|
||||||
#define R_BAKE_SPACE_CAMERA 0
|
#define R_BAKE_SPACE_CAMERA 0
|
||||||
|
@ -3918,6 +3918,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
|
|||||||
RNA_def_property_ui_text(prop, "Samples", "Number of samples used for ambient occlusion baking from multires");
|
RNA_def_property_ui_text(prop, "Samples", "Number of samples used for ambient occlusion baking from multires");
|
||||||
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
|
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "use_bake_to_vertex_color", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_VCOL);
|
||||||
|
RNA_def_property_ui_text(prop, "Bake to Vertex Colour",
|
||||||
|
"Bake to vertex colors instead of to a UV-mapped image.");
|
||||||
|
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
|
||||||
|
|
||||||
/* stamp */
|
/* stamp */
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_stamp_time", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_stamp_time", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
@ -59,12 +59,16 @@ typedef struct VertTableNode {
|
|||||||
float *tangent;
|
float *tangent;
|
||||||
float *stress;
|
float *stress;
|
||||||
float *winspeed;
|
float *winspeed;
|
||||||
|
/* Index of vertex in source mesh (before modifiers). */
|
||||||
|
int *origindex;
|
||||||
} VertTableNode;
|
} VertTableNode;
|
||||||
|
|
||||||
typedef struct VlakTableNode {
|
typedef struct VlakTableNode {
|
||||||
struct VlakRen *vlak;
|
struct VlakRen *vlak;
|
||||||
struct MTFace *mtface;
|
struct MTFace *mtface;
|
||||||
struct MCol *mcol;
|
struct MCol *mcol;
|
||||||
|
/* Index of mpoly in source mesh (before tessellation). */
|
||||||
|
int *origindex;
|
||||||
int totmtface, totmcol;
|
int totmtface, totmcol;
|
||||||
float *surfnor;
|
float *surfnor;
|
||||||
float *tangent;
|
float *tangent;
|
||||||
@ -114,9 +118,11 @@ float *RE_vertren_get_rad(struct ObjectRen *obr, struct VertRen *ver, int verify
|
|||||||
float *RE_vertren_get_strand(struct ObjectRen *obr, struct VertRen *ver, int verify);
|
float *RE_vertren_get_strand(struct ObjectRen *obr, struct VertRen *ver, int verify);
|
||||||
float *RE_vertren_get_tangent(struct ObjectRen *obr, struct VertRen *ver, int verify);
|
float *RE_vertren_get_tangent(struct ObjectRen *obr, struct VertRen *ver, int verify);
|
||||||
float *RE_vertren_get_winspeed(struct ObjectInstanceRen *obi, struct VertRen *ver, int verify);
|
float *RE_vertren_get_winspeed(struct ObjectInstanceRen *obi, struct VertRen *ver, int verify);
|
||||||
|
int *RE_vertren_get_origindex(struct ObjectRen *obr, VertRen *ver, int verify);
|
||||||
|
|
||||||
struct MTFace *RE_vlakren_get_tface(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
|
struct MTFace *RE_vlakren_get_tface(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
|
||||||
struct MCol *RE_vlakren_get_mcol(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
|
struct MCol *RE_vlakren_get_mcol(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
|
||||||
|
int *RE_vlakren_get_origindex(struct ObjectRen *obr, VlakRen *vlak, int verify);
|
||||||
float *RE_vlakren_get_surfnor(struct ObjectRen *obr, VlakRen *ren, int verify);
|
float *RE_vlakren_get_surfnor(struct ObjectRen *obr, VlakRen *ren, int verify);
|
||||||
float *RE_vlakren_get_nmap_tangent(struct ObjectRen *obr, VlakRen *ren, int verify);
|
float *RE_vlakren_get_nmap_tangent(struct ObjectRen *obr, VlakRen *ren, int verify);
|
||||||
RadFace **RE_vlakren_get_radface(struct ObjectRen *obr, VlakRen *ren, int verify);
|
RadFace **RE_vlakren_get_radface(struct ObjectRen *obr, VlakRen *ren, int verify);
|
||||||
|
@ -3231,7 +3231,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
|
|||||||
CustomDataMask mask;
|
CustomDataMask mask;
|
||||||
float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3],
|
float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3],
|
||||||
float *orco=0;
|
float *orco=0;
|
||||||
int need_orco=0, need_stress=0, need_nmap_tangent=0, need_tangent=0;
|
int need_orco=0, need_stress=0, need_nmap_tangent=0, need_tangent=0, need_origindex=0;
|
||||||
int a, a1, ok, vertofs;
|
int a, a1, ok, vertofs;
|
||||||
int end, do_autosmooth = FALSE, totvert = 0;
|
int end, do_autosmooth = FALSE, totvert = 0;
|
||||||
int use_original_normals = FALSE;
|
int use_original_normals = FALSE;
|
||||||
@ -3281,6 +3281,10 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
|
|||||||
need_nmap_tangent= 1;
|
need_nmap_tangent= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* origindex currently only used when baking to vertex colors */
|
||||||
|
if(re->flag & R_BAKING && re->r.bake_flag & R_BAKE_VCOL)
|
||||||
|
need_origindex= 1;
|
||||||
|
|
||||||
/* check autosmooth and displacement, we then have to skip only-verts optimize */
|
/* check autosmooth and displacement, we then have to skip only-verts optimize */
|
||||||
do_autosmooth |= (me->flag & ME_AUTOSMOOTH);
|
do_autosmooth |= (me->flag & ME_AUTOSMOOTH);
|
||||||
if (do_autosmooth)
|
if (do_autosmooth)
|
||||||
@ -3318,6 +3322,15 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
|
|||||||
make_render_halos(re, obr, me, totvert, mvert, ma, orco);
|
make_render_halos(re, obr, me, totvert, mvert, ma, orco);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
const int *index_vert_orig = NULL;
|
||||||
|
const int *index_mf_to_mpoly = NULL;
|
||||||
|
const int *index_mp_to_orig = NULL;
|
||||||
|
if (need_origindex) {
|
||||||
|
index_vert_orig = dm->getVertDataArray(dm, CD_ORIGINDEX);
|
||||||
|
/* double lookup for faces -> polys */
|
||||||
|
index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
|
||||||
|
index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
|
||||||
|
}
|
||||||
|
|
||||||
for (a=0; a<totvert; a++, mvert++) {
|
for (a=0; a<totvert; a++, mvert++) {
|
||||||
ver= RE_findOrAddVert(obr, obr->totvert++);
|
ver= RE_findOrAddVert(obr, obr->totvert++);
|
||||||
@ -3334,6 +3347,18 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
|
|||||||
ver->orco= orco;
|
ver->orco= orco;
|
||||||
orco+=3;
|
orco+=3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (need_origindex) {
|
||||||
|
int *origindex;
|
||||||
|
origindex = RE_vertren_get_origindex(obr, ver, 1);
|
||||||
|
|
||||||
|
/* Use orig index array if it's available (e.g. in the presence
|
||||||
|
* of modifiers). */
|
||||||
|
if (index_vert_orig)
|
||||||
|
*origindex = index_vert_orig[a];
|
||||||
|
else
|
||||||
|
*origindex = a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!timeoffset) {
|
if (!timeoffset) {
|
||||||
@ -3455,6 +3480,21 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (need_origindex) {
|
||||||
|
/* Find original index of mpoly for this tessface. Options:
|
||||||
|
- Modified mesh; two-step look up from tessface -> modified mpoly -> original mpoly
|
||||||
|
- OR Tesselated mesh; look up from tessface -> mpoly
|
||||||
|
- OR Failsafe; tessface == mpoly. Could probably assert(false) in this case? */
|
||||||
|
int *origindex;
|
||||||
|
origindex = RE_vlakren_get_origindex(obr, vlr, 1);
|
||||||
|
if (index_mf_to_mpoly && index_mp_to_orig)
|
||||||
|
*origindex = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a);
|
||||||
|
else if (index_mf_to_mpoly)
|
||||||
|
*origindex = index_mf_to_mpoly[a];
|
||||||
|
else
|
||||||
|
*origindex = a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*
|
*
|
||||||
* Contributors: Hos, Robert Wenzlaff.
|
* Contributors: Hos, Robert Wenzlaff.
|
||||||
* Contributors: 2004/2005/2006 Blender Foundation, full recode
|
* Contributors: 2004/2005/2006 Blender Foundation, full recode
|
||||||
|
* Contributors: Vertex color baking, Copyright 2011 AutoCRC
|
||||||
*
|
*
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
*/
|
*/
|
||||||
@ -51,9 +52,12 @@
|
|||||||
#include "DNA_image_types.h"
|
#include "DNA_image_types.h"
|
||||||
#include "DNA_lamp_types.h"
|
#include "DNA_lamp_types.h"
|
||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
#include "DNA_meshdata_types.h"
|
#include "DNA_meshdata_types.h"
|
||||||
#include "DNA_group_types.h"
|
#include "DNA_group_types.h"
|
||||||
|
|
||||||
|
#include "BKE_customdata.h"
|
||||||
|
#include "BKE_depsgraph.h"
|
||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
#include "BKE_image.h"
|
#include "BKE_image.h"
|
||||||
#include "BKE_main.h"
|
#include "BKE_main.h"
|
||||||
@ -2004,6 +2008,12 @@ typedef struct BakeShade {
|
|||||||
float dir[3];
|
float dir[3];
|
||||||
Object *actob;
|
Object *actob;
|
||||||
|
|
||||||
|
/* Output: vertex color or image data. If vcol is not NULL, rect and
|
||||||
|
* rect_float should be NULL. */
|
||||||
|
MPoly *mpoly;
|
||||||
|
MLoop *mloop;
|
||||||
|
MLoopCol *vcol;
|
||||||
|
|
||||||
unsigned int *rect;
|
unsigned int *rect;
|
||||||
float *rect_float;
|
float *rect_float;
|
||||||
|
|
||||||
@ -2179,7 +2189,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bs->rect_float) {
|
if (bs->rect_float && !bs->vcol) {
|
||||||
float *col= bs->rect_float + 4*(bs->rectx*y + x);
|
float *col= bs->rect_float + 4*(bs->rectx*y + x);
|
||||||
copy_v3_v3(col, shr.combined);
|
copy_v3_v3(col, shr.combined);
|
||||||
if (bs->type==RE_BAKE_ALL || bs->type==RE_BAKE_TEXTURE) {
|
if (bs->type==RE_BAKE_ALL || bs->type==RE_BAKE_TEXTURE) {
|
||||||
@ -2190,7 +2200,8 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unsigned char *col= (unsigned char *)(bs->rect + bs->rectx*y + x);
|
/* Target is char (LDR). */
|
||||||
|
unsigned char col[4];
|
||||||
|
|
||||||
if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
|
if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
|
||||||
float rgb[3];
|
float rgb[3];
|
||||||
@ -2210,6 +2221,19 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
|
|||||||
else {
|
else {
|
||||||
col[3]= 255;
|
col[3]= 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bs->vcol) {
|
||||||
|
/* Vertex colour baking. Vcol has no useful alpha channel (it exists
|
||||||
|
* but is used only for vertex painting). */
|
||||||
|
bs->vcol->r = col[0];
|
||||||
|
bs->vcol->g = col[1];
|
||||||
|
bs->vcol->b = col[2];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unsigned char *imcol= (unsigned char *)(bs->rect + bs->rectx*y + x);
|
||||||
|
copy_v4_v4_char((char *)imcol, (char *)col);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bs->rect_mask) {
|
if (bs->rect_mask) {
|
||||||
@ -2229,15 +2253,28 @@ static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist,
|
|||||||
disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/
|
disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bs->rect_float) {
|
if (bs->rect_float && !bs->vcol) {
|
||||||
float *col= bs->rect_float + 4*(bs->rectx*y + x);
|
float *col= bs->rect_float + 4*(bs->rectx*y + x);
|
||||||
col[0] = col[1] = col[2] = disp;
|
col[0] = col[1] = col[2] = disp;
|
||||||
col[3]= 1.0f;
|
col[3]= 1.0f;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char *col= (char *)(bs->rect + bs->rectx*y + x);
|
/* Target is char (LDR). */
|
||||||
|
unsigned char col[4];
|
||||||
col[0] = col[1] = col[2] = FTOCHAR(disp);
|
col[0] = col[1] = col[2] = FTOCHAR(disp);
|
||||||
col[3]= 255;
|
col[3] = 255;
|
||||||
|
|
||||||
|
if(bs->vcol) {
|
||||||
|
/* Vertex colour baking. Vcol has no useful alpha channel (it exists
|
||||||
|
* but is used only for vertex painting). */
|
||||||
|
bs->vcol->r = col[0];
|
||||||
|
bs->vcol->g = col[1];
|
||||||
|
bs->vcol->b = col[2];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char *imcol= (char *)(bs->rect + bs->rectx*y + x);
|
||||||
|
copy_v4_v4_char((char *)imcol, (char *)col);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (bs->rect_mask) {
|
if (bs->rect_mask) {
|
||||||
bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED;
|
bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED;
|
||||||
@ -2473,14 +2510,56 @@ static int get_next_bake_face(BakeShade *bs)
|
|||||||
vlr= RE_findOrAddVlak(obr, v);
|
vlr= RE_findOrAddVlak(obr, v);
|
||||||
|
|
||||||
if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) {
|
if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) {
|
||||||
tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
|
if(R.r.bake_flag & R_BAKE_VCOL) {
|
||||||
|
/* Gather face data for vertex colour bake */
|
||||||
|
Mesh *me;
|
||||||
|
int *origindex, vcollayer;
|
||||||
|
CustomDataLayer *cdl;
|
||||||
|
|
||||||
if (tface && tface->tpage) {
|
if(obr->ob->type != OB_MESH)
|
||||||
Image *ima= tface->tpage;
|
continue;
|
||||||
ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
|
me = obr->ob->data;
|
||||||
|
|
||||||
|
origindex = RE_vlakren_get_origindex(obr, vlr, 0);
|
||||||
|
if(origindex == NULL)
|
||||||
|
continue;
|
||||||
|
if (*origindex >= me->totpoly) {
|
||||||
|
/* Small hack for Array modifier, which gives false
|
||||||
|
original indices - z0r */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
/* Only shade selected faces. */
|
||||||
|
if((me->mface[*origindex].flag & ME_FACE_SEL) == 0)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vcollayer = CustomData_get_render_layer_index(&me->ldata, CD_MLOOPCOL);
|
||||||
|
if(vcollayer == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cdl = &me->ldata.layers[vcollayer];
|
||||||
|
bs->mpoly = me->mpoly + *origindex;
|
||||||
|
bs->vcol = ((MLoopCol*)cdl->data) + bs->mpoly->loopstart;
|
||||||
|
bs->mloop = me->mloop + bs->mpoly->loopstart;
|
||||||
|
|
||||||
|
/* Tag mesh for reevaluation. */
|
||||||
|
DAG_id_tag_update(&me->id, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Image *ima = NULL;
|
||||||
|
ImBuf *ibuf = NULL;
|
||||||
const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f};
|
const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f};
|
||||||
const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f};
|
const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
|
||||||
|
tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
|
||||||
|
|
||||||
|
if (!tface || !tface->tpage)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ima = tface->tpage;
|
||||||
|
ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
|
||||||
|
|
||||||
if (ibuf==NULL)
|
if (ibuf==NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -2515,28 +2594,91 @@ static int get_next_bake_face(BakeShade *bs)
|
|||||||
R.bakebuf= ima;
|
R.bakebuf= ima;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Tag image for redraw. */
|
||||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||||
|
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
bs->obi= obi;
|
bs->obi = obi;
|
||||||
bs->vlr= vlr;
|
bs->vlr = vlr;
|
||||||
|
|
||||||
bs->vdone++; /* only for error message if nothing was rendered */
|
bs->vdone++; /* only for error message if nothing was rendered */
|
||||||
v++;
|
v++;
|
||||||
|
|
||||||
BLI_unlock_thread(LOCK_CUSTOM1);
|
BLI_unlock_thread(LOCK_CUSTOM1);
|
||||||
|
|
||||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
BLI_unlock_thread(LOCK_CUSTOM1);
|
BLI_unlock_thread(LOCK_CUSTOM1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v) {
|
||||||
|
int *origindex, i;
|
||||||
|
MLoopCol *basevcol;
|
||||||
|
MLoop *mloop;
|
||||||
|
|
||||||
|
origindex = RE_vertren_get_origindex(bs->obi->obr, vert, 0);
|
||||||
|
if (!origindex || *origindex == ORIGINDEX_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Search for matching vertex index and apply shading. */
|
||||||
|
for (i = 0; i < bs->mpoly->totloop; i++) {
|
||||||
|
mloop = bs->mloop + i;
|
||||||
|
if (mloop->v != *origindex)
|
||||||
|
continue;
|
||||||
|
basevcol = bs->vcol;
|
||||||
|
bs->vcol = basevcol + i;
|
||||||
|
do_bake_shade(bs, 0, 0, u, v);
|
||||||
|
bs->vcol = basevcol;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bake all vertices of a face. Actually, this still works on a face-by-face
|
||||||
|
basis, and each vertex on each face is shaded. Vertex colors are a property
|
||||||
|
of loops, not vertices. */
|
||||||
|
static void shade_verts(BakeShade *bs)
|
||||||
|
{
|
||||||
|
VlakRen *vlr = bs->vlr;
|
||||||
|
|
||||||
|
/* Disable baking to image; write to vcol instead. vcol pointer is set in
|
||||||
|
* bake_single_vertex. */
|
||||||
|
bs->ima = NULL;
|
||||||
|
bs->rect = NULL;
|
||||||
|
bs->rect_float = NULL;
|
||||||
|
|
||||||
|
bs->quad = 0;
|
||||||
|
|
||||||
|
/* No anti-aliasing for vertices. */
|
||||||
|
zero_v3(bs->dxco);
|
||||||
|
zero_v3(bs->dyco);
|
||||||
|
|
||||||
|
/* Shade each vertex of the face. u and v are barycentric coordinates; since
|
||||||
|
we're only interested in vertices, these will be 0 or 1. */
|
||||||
|
if ((vlr->flag & R_FACE_SPLIT) == 0) {
|
||||||
|
/* Processing triangle face, whole quad, or first half of split quad. */
|
||||||
|
|
||||||
|
bake_single_vertex(bs, bs->vlr->v1, 1.0f, 0.0f);
|
||||||
|
bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f);
|
||||||
|
bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
if (vlr->v4) {
|
||||||
|
bs->quad = 1;
|
||||||
|
bake_single_vertex(bs, bs->vlr->v4, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Processing second half of split quad. Only one vertex to go. */
|
||||||
|
if (vlr->flag & R_DIVIDE_24) {
|
||||||
|
bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* already have tested for tface and ima and zspan */
|
/* already have tested for tface and ima and zspan */
|
||||||
static void shade_tface(BakeShade *bs)
|
static void shade_tface(BakeShade *bs)
|
||||||
{
|
{
|
||||||
@ -2564,6 +2706,7 @@ static void shade_tface(BakeShade *bs)
|
|||||||
bs->rect= bs->ibuf->rect;
|
bs->rect= bs->ibuf->rect;
|
||||||
bs->rect_colorspace= bs->ibuf->rect_colorspace;
|
bs->rect_colorspace= bs->ibuf->rect_colorspace;
|
||||||
bs->rect_float= bs->ibuf->rect_float;
|
bs->rect_float= bs->ibuf->rect_float;
|
||||||
|
bs->vcol = NULL;
|
||||||
bs->quad= 0;
|
bs->quad= 0;
|
||||||
|
|
||||||
if (bs->use_mask) {
|
if (bs->use_mask) {
|
||||||
@ -2607,6 +2750,9 @@ static void *do_bake_thread(void *bs_v)
|
|||||||
BakeShade *bs= bs_v;
|
BakeShade *bs= bs_v;
|
||||||
|
|
||||||
while (get_next_bake_face(bs)) {
|
while (get_next_bake_face(bs)) {
|
||||||
|
if (R.r.bake_flag & R_BAKE_VCOL)
|
||||||
|
shade_verts(bs);
|
||||||
|
else
|
||||||
shade_tface(bs);
|
shade_tface(bs);
|
||||||
|
|
||||||
/* fast threadsafe break test */
|
/* fast threadsafe break test */
|
||||||
@ -2671,15 +2817,17 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
|
|||||||
use_mask = TRUE;
|
use_mask = TRUE;
|
||||||
|
|
||||||
/* baker uses this flag to detect if image was initialized */
|
/* baker uses this flag to detect if image was initialized */
|
||||||
for (ima= G.main->image.first; ima; ima= ima->id.next) {
|
if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
|
||||||
ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
|
for (ima = G.main->image.first; ima; ima = ima->id.next) {
|
||||||
|
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
|
||||||
ima->id.flag |= LIB_DOIT;
|
ima->id.flag |= LIB_DOIT;
|
||||||
ima->flag&= ~IMA_USED_FOR_RENDER;
|
ima->flag &= ~IMA_USED_FOR_RENDER;
|
||||||
if (ibuf) {
|
if (ibuf) {
|
||||||
ibuf->userdata = NULL; /* use for masking if needed */
|
ibuf->userdata = NULL; /* use for masking if needed */
|
||||||
}
|
}
|
||||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BLI_init_threads(&threads, do_bake_thread, re->r.threads);
|
BLI_init_threads(&threads, do_bake_thread, re->r.threads);
|
||||||
|
|
||||||
@ -2702,7 +2850,10 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
|
|||||||
|
|
||||||
handles[a].type= type;
|
handles[a].type= type;
|
||||||
handles[a].actob= actob;
|
handles[a].actob= actob;
|
||||||
handles[a].zspan= MEM_callocN(sizeof(ZSpan), "zspan for bake");
|
if (R.r.bake_flag & R_BAKE_VCOL)
|
||||||
|
handles[a].zspan = NULL;
|
||||||
|
else
|
||||||
|
handles[a].zspan = MEM_callocN(sizeof(ZSpan), "zspan for bake");
|
||||||
|
|
||||||
handles[a].use_mask = use_mask;
|
handles[a].use_mask = use_mask;
|
||||||
|
|
||||||
@ -2729,12 +2880,13 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* filter and refresh images */
|
/* filter and refresh images */
|
||||||
for (ima= G.main->image.first; ima; ima= ima->id.next) {
|
if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
|
||||||
|
for (ima = G.main->image.first; ima; ima = ima->id.next) {
|
||||||
if ((ima->id.flag & LIB_DOIT)==0) {
|
if ((ima->id.flag & LIB_DOIT)==0) {
|
||||||
ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
|
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
|
||||||
|
|
||||||
if (ima->flag & IMA_USED_FOR_RENDER)
|
if (ima->flag & IMA_USED_FOR_RENDER)
|
||||||
result= BAKE_RESULT_FEEDBACK_LOOP;
|
result = BAKE_RESULT_FEEDBACK_LOOP;
|
||||||
|
|
||||||
if (!ibuf)
|
if (!ibuf)
|
||||||
continue;
|
continue;
|
||||||
@ -2747,10 +2899,11 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* calculate return value */
|
/* calculate return value */
|
||||||
for (a=0; a<re->r.threads; a++) {
|
for (a = 0; a < re->r.threads; a++) {
|
||||||
zbuf_free_span(handles[a].zspan);
|
zbuf_free_span(handles[a].zspan);
|
||||||
MEM_freeN(handles[a].zspan);
|
MEM_freeN(handles[a].zspan);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MEM_freeN(handles);
|
MEM_freeN(handles);
|
||||||
|
|
||||||
|
@ -105,6 +105,8 @@
|
|||||||
#define RE_MTFACE_ELEMS 1
|
#define RE_MTFACE_ELEMS 1
|
||||||
#define RE_MCOL_ELEMS 4
|
#define RE_MCOL_ELEMS 4
|
||||||
#define RE_UV_ELEMS 2
|
#define RE_UV_ELEMS 2
|
||||||
|
#define RE_VLAK_ORIGINDEX_ELEMS 1
|
||||||
|
#define RE_VERT_ORIGINDEX_ELEMS 1
|
||||||
#define RE_SURFNOR_ELEMS 3
|
#define RE_SURFNOR_ELEMS 3
|
||||||
#define RE_RADFACE_ELEMS 1
|
#define RE_RADFACE_ELEMS 1
|
||||||
#define RE_SIMPLIFY_ELEMS 2
|
#define RE_SIMPLIFY_ELEMS 2
|
||||||
@ -192,10 +194,26 @@ float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify)
|
|||||||
return winspeed + ver->index*RE_WINSPEED_ELEMS;
|
return winspeed + ver->index*RE_WINSPEED_ELEMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int *RE_vertren_get_origindex(ObjectRen *obr, VertRen *ver, int verify)
|
||||||
|
{
|
||||||
|
int *origindex;
|
||||||
|
int nr= ver->index>>8;
|
||||||
|
|
||||||
|
origindex= obr->vertnodes[nr].origindex;
|
||||||
|
if (origindex==NULL) {
|
||||||
|
if (verify)
|
||||||
|
origindex= obr->vertnodes[nr].origindex= MEM_mallocN(256*RE_VERT_ORIGINDEX_ELEMS*sizeof(int), "origindex table");
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return origindex + (ver->index & 255)*RE_VERT_ORIGINDEX_ELEMS;
|
||||||
|
}
|
||||||
|
|
||||||
VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
|
VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
|
||||||
{
|
{
|
||||||
VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
|
VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
|
||||||
float *fp1, *fp2;
|
float *fp1, *fp2;
|
||||||
|
int *int1, *int2;
|
||||||
int index= v1->index;
|
int index= v1->index;
|
||||||
|
|
||||||
*v1= *ver;
|
*v1= *ver;
|
||||||
@ -221,6 +239,11 @@ VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
|
|||||||
fp2= RE_vertren_get_tangent(obr, v1, 1);
|
fp2= RE_vertren_get_tangent(obr, v1, 1);
|
||||||
memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
|
memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
|
||||||
}
|
}
|
||||||
|
int1= RE_vertren_get_origindex(obr, ver, 0);
|
||||||
|
if (int1) {
|
||||||
|
int2= RE_vertren_get_origindex(obr, v1, 1);
|
||||||
|
memcpy(int2, int1, RE_VERT_ORIGINDEX_ELEMS*sizeof(int));
|
||||||
|
}
|
||||||
return v1;
|
return v1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,6 +355,21 @@ MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int
|
|||||||
return node->mcol + index*RE_MCOL_ELEMS;
|
return node->mcol + index*RE_MCOL_ELEMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int *RE_vlakren_get_origindex(ObjectRen *obr, VlakRen *vlak, int verify)
|
||||||
|
{
|
||||||
|
int *origindex;
|
||||||
|
int nr= vlak->index>>8;
|
||||||
|
|
||||||
|
origindex= obr->vlaknodes[nr].origindex;
|
||||||
|
if(origindex==NULL) {
|
||||||
|
if(verify)
|
||||||
|
origindex= obr->vlaknodes[nr].origindex= MEM_callocN(256*RE_VLAK_ORIGINDEX_ELEMS*sizeof(int), "origindex table");
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return origindex + (vlak->index & 255)*RE_VLAK_ORIGINDEX_ELEMS;
|
||||||
|
}
|
||||||
|
|
||||||
float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
|
float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
|
||||||
{
|
{
|
||||||
float *surfnor;
|
float *surfnor;
|
||||||
@ -383,6 +421,7 @@ VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
|
|||||||
MTFace *mtface, *mtface1;
|
MTFace *mtface, *mtface1;
|
||||||
MCol *mcol, *mcol1;
|
MCol *mcol, *mcol1;
|
||||||
float *surfnor, *surfnor1, *tangent, *tangent1;
|
float *surfnor, *surfnor1, *tangent, *tangent1;
|
||||||
|
int *origindex, *origindex1;
|
||||||
RadFace **radface, **radface1;
|
RadFace **radface, **radface1;
|
||||||
int i, index = vlr1->index;
|
int i, index = vlr1->index;
|
||||||
char *name;
|
char *name;
|
||||||
@ -400,6 +439,13 @@ VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
|
|||||||
memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
|
memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
origindex= RE_vlakren_get_origindex(obr, vlr, 0);
|
||||||
|
if(origindex) {
|
||||||
|
origindex1= RE_vlakren_get_origindex(obr, vlr1, 1);
|
||||||
|
/* Just an int, but memcpy for consistency. */
|
||||||
|
memcpy(origindex1, origindex, sizeof(int)*RE_VLAK_ORIGINDEX_ELEMS);
|
||||||
|
}
|
||||||
|
|
||||||
surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
|
surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
|
||||||
if (surfnor) {
|
if (surfnor) {
|
||||||
surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
|
surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
|
||||||
@ -725,6 +771,8 @@ void free_renderdata_vertnodes(VertTableNode *vertnodes)
|
|||||||
MEM_freeN(vertnodes[a].stress);
|
MEM_freeN(vertnodes[a].stress);
|
||||||
if (vertnodes[a].winspeed)
|
if (vertnodes[a].winspeed)
|
||||||
MEM_freeN(vertnodes[a].winspeed);
|
MEM_freeN(vertnodes[a].winspeed);
|
||||||
|
if (vertnodes[a].origindex)
|
||||||
|
MEM_freeN(vertnodes[a].origindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_freeN(vertnodes);
|
MEM_freeN(vertnodes);
|
||||||
@ -743,6 +791,8 @@ void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
|
|||||||
MEM_freeN(vlaknodes[a].mtface);
|
MEM_freeN(vlaknodes[a].mtface);
|
||||||
if (vlaknodes[a].mcol)
|
if (vlaknodes[a].mcol)
|
||||||
MEM_freeN(vlaknodes[a].mcol);
|
MEM_freeN(vlaknodes[a].mcol);
|
||||||
|
if(vlaknodes[a].origindex)
|
||||||
|
MEM_freeN(vlaknodes[a].origindex);
|
||||||
if (vlaknodes[a].surfnor)
|
if (vlaknodes[a].surfnor)
|
||||||
MEM_freeN(vlaknodes[a].surfnor);
|
MEM_freeN(vlaknodes[a].surfnor);
|
||||||
if (vlaknodes[a].tangent)
|
if (vlaknodes[a].tangent)
|
||||||
|
Loading…
Reference in New Issue
Block a user