This module allow tracking of object and geometry data accross time. This commit adds no user visible changes. It work in both viewport (*) and render mode, gives correct motion for any camera projection type and is compatible with displacement (**). It is a huge improvement upon the old EEVEE velocity which was only used for motion blur and only available in render. It is also an improvement for speed as the animated objects do not need to be rendered a 3rd time. The code is also much cleaner: no GPUVertBuf duplication, no GPUBatch amendment, no special cases for different geometry types, no DRWShadingGroup per object, no double buffering of velocity. The module is still work in progress as the final output may still be flawed. (*): Viewport support is already working but there might be some cases where mapping will fail. For instance if topology changes but not vertex count. (**): Displacement does not contribute to motion vectors. Surfaces using displacement will have the same motion vectors as if they were not displaced.
161 lines
3.6 KiB
C++
161 lines
3.6 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Copyright 2021 Blender Foundation.
|
|
*/
|
|
|
|
/** \file
|
|
* \ingroup eevee
|
|
*
|
|
* Structures to identify unique data blocks. The keys are unique so we are able to
|
|
* match ids across frame updates.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "BKE_duplilist.h"
|
|
#include "BLI_ghash.h"
|
|
#include "BLI_map.hh"
|
|
#include "DNA_object_types.h"
|
|
#include "DRW_render.h"
|
|
#include "GPU_material.h"
|
|
|
|
#include "eevee_shader_shared.hh"
|
|
|
|
namespace blender::eevee {
|
|
|
|
class Instance;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name ObjectKey
|
|
*
|
|
* Unique key to identify each object in the hash-map.
|
|
* Note that we get a unique key for each object component.
|
|
* \{ */
|
|
|
|
struct ObjectKey {
|
|
/** Hash value of the key. */
|
|
uint64_t hash_value;
|
|
/** Original Object or source object for duplis. */
|
|
Object *ob;
|
|
/** Original Parent object for duplis. */
|
|
Object *parent;
|
|
/** Dupli objects recursive unique identifier */
|
|
int id[MAX_DUPLI_RECUR];
|
|
/** If object uses particle system hair. */
|
|
bool use_particle_hair;
|
|
#ifdef DEBUG
|
|
char name[64];
|
|
#endif
|
|
ObjectKey() : ob(nullptr), parent(nullptr){};
|
|
|
|
ObjectKey(Object *ob_, Object *parent_, int id_[MAX_DUPLI_RECUR], bool use_particle_hair_)
|
|
: ob(ob_), parent(parent_), use_particle_hair(use_particle_hair_)
|
|
{
|
|
if (id_) {
|
|
memcpy(id, id_, sizeof(id));
|
|
}
|
|
else {
|
|
memset(id, 0, sizeof(id));
|
|
}
|
|
/* Compute hash on creation so we avoid the cost of it for every sync. */
|
|
hash_value = BLI_ghashutil_ptrhash(ob);
|
|
hash_value = BLI_ghashutil_combine_hash(hash_value, BLI_ghashutil_ptrhash(parent));
|
|
for (int i = 0; i < MAX_DUPLI_RECUR; i++) {
|
|
if (id[i] != 0) {
|
|
hash_value = BLI_ghashutil_combine_hash(hash_value, BLI_ghashutil_inthash(id[i]));
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
#ifdef DEBUG
|
|
STRNCPY(name, ob->id.name);
|
|
#endif
|
|
}
|
|
|
|
ObjectKey(Object *ob, DupliObject *dupli, Object *parent)
|
|
: ObjectKey(ob, parent, dupli ? dupli->persistent_id : nullptr, false){};
|
|
|
|
ObjectKey(Object *ob)
|
|
: ObjectKey(ob, DRW_object_get_dupli(ob), DRW_object_get_dupli_parent(ob)){};
|
|
|
|
uint64_t hash() const
|
|
{
|
|
return hash_value;
|
|
}
|
|
|
|
bool operator<(const ObjectKey &k) const
|
|
{
|
|
if (ob != k.ob) {
|
|
return (ob < k.ob);
|
|
}
|
|
if (parent != k.parent) {
|
|
return (parent < k.parent);
|
|
}
|
|
if (use_particle_hair != k.use_particle_hair) {
|
|
return (use_particle_hair < k.use_particle_hair);
|
|
}
|
|
return memcmp(id, k.id, sizeof(id)) < 0;
|
|
}
|
|
|
|
bool operator==(const ObjectKey &k) const
|
|
{
|
|
if (ob != k.ob) {
|
|
return false;
|
|
}
|
|
if (parent != k.parent) {
|
|
return false;
|
|
}
|
|
if (use_particle_hair != k.use_particle_hair) {
|
|
return false;
|
|
}
|
|
return memcmp(id, k.id, sizeof(id)) == 0;
|
|
}
|
|
};
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Sync Module
|
|
*
|
|
* \{ */
|
|
|
|
struct ObjectHandle : public DrawData {
|
|
ObjectKey object_key;
|
|
|
|
void reset_recalc_flag()
|
|
{
|
|
if (recalc != 0) {
|
|
recalc = 0;
|
|
}
|
|
}
|
|
};
|
|
|
|
struct WorldHandle : public DrawData {
|
|
void reset_recalc_flag()
|
|
{
|
|
if (recalc != 0) {
|
|
recalc = 0;
|
|
}
|
|
}
|
|
};
|
|
|
|
class SyncModule {
|
|
private:
|
|
Instance &inst_;
|
|
|
|
public:
|
|
SyncModule(Instance &inst) : inst_(inst){};
|
|
~SyncModule(){};
|
|
|
|
ObjectHandle &sync_object(Object *ob);
|
|
WorldHandle &sync_world(::World *world);
|
|
|
|
void sync_mesh(Object *ob, ObjectHandle &ob_handle);
|
|
void sync_gpencil(Object *ob, ObjectHandle &ob_handle);
|
|
void sync_curves(Object *ob, ObjectHandle &ob_handle, ModifierData *modifier_data = nullptr);
|
|
};
|
|
|
|
/** \} */
|
|
|
|
} // namespace blender::eevee
|