Object Engine: Fix multi user lamp data display bug.

Objects that were using the same lamp data were having the same display matrices.
This is fixed by allowing engine to store a memory block inside the object itself.
This commit is contained in:
Clément Foucault 2017-04-03 19:01:10 +02:00
parent 682c4dcd1e
commit ccd8353d58
8 changed files with 69 additions and 15 deletions

View File

@ -119,6 +119,8 @@
#include "BKE_camera.h"
#include "BKE_image.h"
#include "DRW_engine.h"
#ifdef WITH_MOD_FLUID
#include "LBM_fluidsim.h"
#endif
@ -443,6 +445,8 @@ void BKE_object_free(Object *ob)
}
GPU_lamp_free(ob);
DRW_object_engine_data_free(ob);
BKE_sculptsession_free(ob);
BLI_freelistN(&ob->pc_ids);
@ -1177,6 +1181,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
BLI_listbase_clear(&obn->gpulamp);
BLI_listbase_clear(&obn->pc_ids);
BLI_listbase_clear(&obn->drawdata);
obn->mpath = NULL;

View File

@ -5587,6 +5587,7 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->derivedDeform = NULL;
ob->derivedFinal = NULL;
BLI_listbase_clear(&ob->gpulamp);
BLI_listbase_clear(&ob->drawdata);
link_list(fd, &ob->pc_ids);
/* Runtime curve data */

View File

@ -52,6 +52,8 @@ void DRW_engine_register(struct DrawEngineType *draw_engine_type);
void DRW_draw_view(const struct bContext *C);
void DRW_object_engine_data_free(struct Object *ob);
/* This is here because GPUViewport needs it */
void DRW_pass_free(struct DRWPass *pass);

View File

@ -247,6 +247,9 @@ bool DRW_viewport_cache_is_dirty(void);
struct DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void);
struct DefaultTextureList *DRW_viewport_texture_list_get(void);
/* Objects */
void **DRW_object_engine_data_get(Object *ob, DrawEngineType *det);
/* Settings */
bool DRW_is_object_renderable(struct Object *ob);

View File

@ -1377,6 +1377,42 @@ DefaultTextureList *DRW_viewport_texture_list_get(void)
return GPU_viewport_texture_list_get(DST.viewport);
}
/* **************************************** OBJECTS *************************************** */
typedef struct ObjectEngineData {
struct ObjectEngineData *next, *prev;
DrawEngineType *engine_type;
void *storage;
} ObjectEngineData;
void **DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type)
{
ObjectEngineData *oed;
for (oed = ob->drawdata.first; oed; oed = oed->next) {
if (oed->engine_type == engine_type) {
return &oed->storage;
}
}
oed = MEM_callocN(sizeof(ObjectEngineData), "ObjectEngineData");
BLI_addtail(&ob->drawdata, oed);
return &oed->storage;
}
void DRW_object_engine_data_free(Object *ob)
{
for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) {
if (oed->storage) {
MEM_freeN(oed->storage);
}
}
BLI_freelistN(&ob->drawdata);
}
/* **************************************** RENDERING ************************************** */
#define TIMER_FALLOFF 0.1f

View File

@ -683,6 +683,16 @@ static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, SceneLayer *sl
int theme_id = DRW_object_wire_theme_get(ob, sl, &color);
static float zero = 0.0f;
float **la_mats = (float **)DRW_object_engine_data_get(ob, &draw_engine_object_type);
if (*la_mats == NULL) {
/* we need 2 matrices */
*la_mats = MEM_mallocN(sizeof(float) * 16 * 2, "Lamp Object Mode Matrices");
}
float (*shapemat)[4], (*spotblendmat)[4];
shapemat = (float (*)[4])*la_mats;
spotblendmat = (float (*)[4])*la_mats + 16;
/* Don't draw the center if it's selected or active */
if (theme_id == TH_GROUP)
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_center_group, ob->obmat[3]);
@ -704,7 +714,7 @@ static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, SceneLayer *sl
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_distance, color, &zero, &la->dist, ob->obmat);
}
copy_m4_m4(la->shapemat, ob->obmat);
copy_m4_m4(shapemat, ob->obmat);
if (la->type == LA_SUN) {
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_sunrays, ob->obmat[3], color);
@ -718,42 +728,41 @@ static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, SceneLayer *sl
size[2] = cosf(la->spotsize * 0.5f) * la->dist;
size_to_mat4(sizemat, size);
mul_m4_m4m4(la->spotconemat, ob->obmat, sizemat);
mul_m4_m4m4(shapemat, ob->obmat, sizemat);
size[0] = size[1] = blend; size[2] = 1.0f;
size_to_mat4(sizemat, size);
translate_m4(sizemat, 0.0f, 0.0f, -1.0f);
rotate_m4(sizemat, 'X', M_PI / 2.0f);
mul_m4_m4m4(la->spotblendmat, la->spotconemat, sizemat);
mul_m4_m4m4(spotblendmat, shapemat, sizemat);
if (la->mode & LA_SQUARE) {
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_pyramid, color, &one, la->spotconemat);
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_pyramid, color, &one, shapemat);
/* hide line if it is zero size or overlaps with outer border,
* previously it adjusted to always to show it but that seems
* confusing because it doesn't show the actual blend size */
if (blend != 0.0f && blend != 1.0f) {
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_blend_rect, color, &one, la->spotblendmat);
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_blend_rect, color, &one, spotblendmat);
}
}
else {
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_cone, color, la->spotconemat);
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_cone, color, shapemat);
/* hide line if it is zero size or overlaps with outer border,
* previously it adjusted to always to show it but that seems
* confusing because it doesn't show the actual blend size */
if (blend != 0.0f && blend != 1.0f) {
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_blend, color, &one, la->spotblendmat);
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_blend, color, &one, spotblendmat);
}
}
normalize_m4(la->shapemat);
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_buflimit, color, &la->clipsta, &la->clipend, ob->obmat);
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat);
}
else if (la->type == LA_HEMI) {
static float hemisize = 2.0f;
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_hemi, color, &hemisize, la->shapemat);
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_hemi, color, &hemisize, shapemat);
}
else if (la->type == LA_AREA) {
float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4];
@ -761,10 +770,10 @@ static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, SceneLayer *sl
if (la->area_shape == LA_AREA_RECT) {
size[1] = la->area_sizey / la->area_size;
size_to_mat4(sizemat, size);
mul_m4_m4m4(la->shapemat, la->shapemat, sizemat);
mul_m4_m4m4(shapemat, shapemat, sizemat);
}
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_area, color, &la->area_size, la->shapemat);
DRW_shgroup_dynamic_call_add(stl->g_data->lamp_area, color, &la->area_size, shapemat);
}
/* Line and point going to the ground */

View File

@ -106,10 +106,6 @@ typedef struct Lamp {
short pr_texture, use_nodes;
char pad6[4];
float shapemat[4][4]; /* runtime, for display only */
float spotconemat[4][4]; /* runtime, for display only */
float spotblendmat[4][4]; /* runtime, for display only */
/* preview */
struct PreviewImage *preview;

View File

@ -304,6 +304,8 @@ typedef struct Object {
struct PreviewImage *preview;
struct IDProperty *base_collection_properties; /* used by depsgraph, flushed from base */
ListBase drawdata; /* runtime, for draw engine datas */
} Object;
/* Warning, this is not used anymore because hooks are now modifiers */