Fix T40712: Duplicators don't generate orco and UV coordinates in Cycles viewport preview.

Fix T39286: Display percentage ignored in Cycles viewport.

The threaded depsgraph update changes included a cleanup of the global
is_rendering flag, which was replaced by a general EvalContext being
passed to dupli functions.

Problem is that the global flag was true for viewport duplis before
(ugly hack), which was used as a check for generating dupli orco/UV from
mesh data layers. The new flag is stricter and only true for actual
renders, which disables these attributes and breaks the Cycles
Texture Coordinates and UVMap nodes.

The solution is to extend the simple for_render boolean to an enum:
* VIEWPORT: OpenGL viewport drawing (dupli tex coords omitted)
* PREVIEW: Viewport preview render (simplified modifiers)
* RENDER: Full render with all details and attributes

There are still some areas that need to be examined, in particular
modifiers seem to totally ignore the EvaluationContext!
Instead they generally execute without render params from the depsgraph
(BKE_object_handle_update_ex) and are built with render settings
explicitly.

Differential Revision: https://developer.blender.org/D613
This commit is contained in:
Lukas Tönne 2014-07-07 10:50:43 +02:00
parent 7481d2aad1
commit 2fe0cf54a5
Notes: blender-bot 2023-02-14 11:18:07 +01:00
Referenced by issue #40712, "From Dupli" in Cycles Texture Coordinates not working
8 changed files with 49 additions and 29 deletions

View File

@ -457,10 +457,10 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
BL::Scene::object_bases_iterator b_base;
BL::Scene b_sce = b_scene;
/* modifier result type (not exposed as enum in C++ API)
* 1 : eModifierMode_Realtime
* 2 : eModifierMode_Render
*/
int dupli_settings = preview ? 1 : 2;
* 1 : DAG_EVAL_PREVIEW
* 2 : DAG_EVAL_RENDER
*/
int dupli_settings = preview ? 1 : 2;
bool cancel = false;

View File

@ -56,10 +56,15 @@ struct ListBase;
* which is needed for it's evaluation,
*/
typedef struct EvaluationContext {
bool for_render; /* Set to true if evaluation shall be performed for render purposes,
* keep at false if update shall happen for the viewport. */
int mode; /* evaluation mode */
} EvaluationContext;
typedef enum eEvaluationMode {
DAG_EVAL_VIEWPORT = 0, /* evaluate for OpenGL viewport */
DAG_EVAL_PREVIEW = 1, /* evaluate for render with preview settings */
DAG_EVAL_RENDER = 2, /* evaluate for render purposes */
} eEvaluationMode;
/* DagNode->eval_flags */
enum {
/* Regardless to curve->path animation flag path is to be evaluated anyway,

View File

@ -2280,7 +2280,7 @@ void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob,
mball_count(eval_ctx, &process, scene, ob);
if (process.totelem == 0) return;
if ((eval_ctx->for_render == false) && (mb->flag == MB_UPDATE_NEVER)) return;
if ((eval_ctx->mode != DAG_EVAL_RENDER) && (mb->flag == MB_UPDATE_NEVER)) return;
if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return;
process.thresh = mb->thresh;
@ -2318,7 +2318,7 @@ void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob,
}
/* width is size per polygonize cube */
if (eval_ctx->for_render) {
if (eval_ctx->mode == DAG_EVAL_RENDER) {
width = mb->rendersize;
}
else {

View File

@ -2179,7 +2179,7 @@ Mesh *BKE_mesh_new_from_object(
* implemented, this is to be rethinked.
*/
EvaluationContext eval_ctx = {0};
eval_ctx.for_render = render;
eval_ctx.mode = DAG_EVAL_RENDER;
BKE_displist_make_mball_forRender(&eval_ctx, sce, ob, &disp);
BKE_mesh_from_metaball(&disp, tmpmesh);
BKE_displist_free(&disp);

View File

@ -2989,7 +2989,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
if (psys_check_enabled(ob, psys)) {
/* check use of dupli objects here */
if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->for_render) &&
if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->mode == DAG_EVAL_RENDER) &&
((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) ||
(psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group)))
{
@ -3009,7 +3009,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
psys = psys->next;
}
if (eval_ctx->for_render && ob->transflag & OB_DUPLIPARTS) {
if (eval_ctx->mode == DAG_EVAL_RENDER && ob->transflag & OB_DUPLIPARTS) {
/* this is to make sure we get render level duplis in groups:
* the derivedmesh must be created before init_render_mesh,
* since object_duplilist does dupliparticles before that */

View File

@ -101,7 +101,7 @@ static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene
r_ctx->eval_ctx = eval_ctx;
r_ctx->scene = scene;
/* don't allow BKE_object_handle_update for viewport during render, can crash */
r_ctx->do_update = update && !(G.is_rendering && !eval_ctx->for_render);
r_ctx->do_update = update && !(G.is_rendering && eval_ctx->mode != DAG_EVAL_RENDER);
r_ctx->animated = false;
r_ctx->group = NULL;
@ -268,7 +268,7 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
/* OB_DUPLIGROUP */
static void make_duplis_group(const DupliContext *ctx)
{
bool for_render = ctx->eval_ctx->for_render;
bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER);
Object *ob = ctx->object;
Group *group;
GroupObject *go;
@ -524,7 +524,7 @@ static void make_duplis_verts(const DupliContext *ctx)
{
Scene *scene = ctx->scene;
Object *parent = ctx->object;
bool for_render = ctx->eval_ctx->for_render;
bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
VertexDupliData vdd;
vdd.ctx = ctx;
@ -534,7 +534,7 @@ static void make_duplis_verts(const DupliContext *ctx)
{
Mesh *me = parent->data;
BMEditMesh *em = BKE_editmesh_from_object(parent);
CustomDataMask dm_mask = (for_render ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH);
CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH);
if (em)
vdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask);
@ -542,7 +542,7 @@ static void make_duplis_verts(const DupliContext *ctx)
vdd.dm = mesh_get_derived_final(scene, parent, dm_mask);
vdd.edit_btmesh = me->edit_btmesh;
if (for_render)
if (use_texcoords)
vdd.orco = vdd.dm->getVertDataArray(vdd.dm, CD_ORCO);
else
vdd.orco = NULL;
@ -724,6 +724,7 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj
float (*orco)[3] = fdd->orco;
MLoopUV *mloopuv = fdd->mloopuv;
int a, totface = fdd->totface;
bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
float child_imat[4][4];
DupliObject *dob;
@ -762,7 +763,7 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj
mul_m4_m4m4(space_mat, obmat, inst_ob->imat);
dob = make_dupli(ctx, inst_ob, obmat, a, false, false);
if (ctx->eval_ctx->for_render) {
if (use_texcoords) {
float w = 1.0f / (float)mp->totloop;
if (orco) {
@ -789,7 +790,7 @@ static void make_duplis_faces(const DupliContext *ctx)
{
Scene *scene = ctx->scene;
Object *parent = ctx->object;
bool for_render = ctx->eval_ctx->for_render;
bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
FaceDupliData fdd;
fdd.use_scale = ((parent->transflag & OB_DUPLIFACES_SCALE) != 0);
@ -797,14 +798,14 @@ static void make_duplis_faces(const DupliContext *ctx)
/* gather mesh info */
{
BMEditMesh *em = BKE_editmesh_from_object(parent);
CustomDataMask dm_mask = (for_render ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH);
CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH);
if (em)
fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask);
else
fdd.dm = mesh_get_derived_final(scene, parent, dm_mask);
if (for_render) {
if (use_texcoords) {
fdd.orco = fdd.dm->getVertDataArray(fdd.dm, CD_ORCO);
fdd.mloopuv = fdd.dm->getLoopDataArray(fdd.dm, CD_MLOOPUV);
}
@ -834,7 +835,8 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
{
Scene *scene = ctx->scene;
Object *par = ctx->object;
bool for_render = ctx->eval_ctx->for_render;
bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER;
bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
GroupObject *go;
Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL;
@ -1051,7 +1053,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
dob = make_dupli(ctx, go->ob, mat, a, false, false);
dob->particle_system = psys;
if (for_render)
if (use_texcoords)
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
}
}
@ -1100,7 +1102,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
dob = make_dupli(ctx, ob, mat, a, false, false);
dob->particle_system = psys;
if (for_render)
if (use_texcoords)
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
/* XXX blender internal needs this to be set to dupligroup to render
* groups correctly, but we don't want this hack for cycles */
@ -1161,7 +1163,7 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
return NULL;
/* Should the dupli's be generated for this object? - Respect restrict flags */
if (ctx->eval_ctx->for_render ? (restrictflag & OB_RESTRICT_RENDER) : (restrictflag & OB_RESTRICT_VIEW))
if (ctx->eval_ctx->mode == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) : (restrictflag & OB_RESTRICT_VIEW))
return NULL;
if (transflag & OB_DUPLIPARTS) {

View File

@ -42,6 +42,8 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "BKE_depsgraph.h"
#include "rna_internal.h" /* own include */
static EnumPropertyItem space_items[] = {
@ -66,7 +68,6 @@ static EnumPropertyItem space_items[] = {
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_depsgraph.h"
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_main.h"
@ -167,9 +168,9 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e
/* When no longer needed, duplilist should be freed with Object.free_duplilist */
static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce, int settings)
{
int for_render = settings == eModifierMode_Render;
bool for_render = (settings == DAG_EVAL_RENDER);
EvaluationContext eval_ctx = {0};
eval_ctx.for_render = for_render;
eval_ctx.mode = settings;
if (!(ob->transflag & OB_DUPLI)) {
BKE_report(reports, RPT_ERROR, "Object does not have duplis");
@ -432,6 +433,13 @@ void RNA_api_object(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem dupli_eval_mode_items[] = {
{DAG_EVAL_VIEWPORT, "VIEWPORT", 0, "Viewport", "Generate duplis using viewport settings"},
{DAG_EVAL_PREVIEW, "PREVIEW", 0, "Preview", "Generate duplis using preview settings"},
{DAG_EVAL_RENDER, "RENDER", 0, "Render", "Generate duplis using render settings"},
{0, NULL, 0, NULL, NULL}
};
#ifndef NDEBUG
static EnumPropertyItem mesh_dm_info_items[] = {
{0, "SOURCE", 0, "Source", "Source mesh"},
@ -483,7 +491,7 @@ void RNA_api_object(StructRNA *srna)
"objects real matrix and layers");
parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate duplis");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Generate texture coordinates for rendering");
RNA_def_enum(func, "settings", dupli_eval_mode_items, 0, "", "Generate texture coordinates for rendering");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
func = RNA_def_function(srna, "dupli_list_clear", "rna_Object_free_duplilist");

View File

@ -387,7 +387,7 @@ Render *RE_NewRender(const char *name)
BLI_strncpy(re->name, name, RE_MAXNAME);
BLI_rw_mutex_init(&re->resultmutex);
re->eval_ctx = MEM_callocN(sizeof(EvaluationContext), "re->eval_ctx");
re->eval_ctx->for_render = true;
re->eval_ctx->mode = DAG_EVAL_RENDER;
}
RE_InitRenderCB(re);
@ -661,6 +661,11 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
re->result->recty = re->recty;
}
if (re->r.scemode & R_VIEWPORT_PREVIEW)
re->eval_ctx->mode = DAG_EVAL_PREVIEW;
else
re->eval_ctx->mode = DAG_EVAL_RENDER;
/* ensure renderdatabase can use part settings correct */
RE_parts_clamp(re);