Files
test2/source/blender/modifiers/intern/lineart/lineart_util.cc
YimingWu 9cb4d3bbff Fix #128887: LineArt: Prevent iterating over not evaluated objects
Line art uses `DEG_OBJECT_ITER_BEGIN` to load all objects that has a
geometry in the scene, which is kind of a hack since the beginning. This
left potential problem where the iterator could go through some objects
that line art didn't have a dependency on (e.g. other grease pencil
objects):

- Since those "other" objects often evaluates fast enough, so
line art always end up having valid data from everywhere after lengthy
mesh evaluation prior to itself, so this problem was not prominent.
- However, in rare cases, there are other objects that takes a lot of
time to evaluate, this causes line art to potentially iterate to objects
that are still invalid.

This fix will build a `Vector<Object *>` during `update_depsgraph`, and
use such list inside `DEGObjectIterSettings` to filter out objects that
the modifier isn't dependent on, thus remove the possibility of reading
objects that hasn't been evaluated.

Since Line art will not add grease pencil objects as potential geometry
inputs, all mesh/curve types of geometries generated by geometry nodes
modifier directly inside other grease pencil objects won't be loaded.
This can be mitigated by having a third mesh object that reads the
result from the grease pencil object that generates geometries, then
directly output them for line art to read.

This also fixes #128888.

Pull Request: https://projects.blender.org/blender/blender/pulls/128890
2024-10-16 15:15:11 +02:00

246 lines
6.6 KiB
C++

/* SPDX-FileCopyrightText: 2019 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#include <cstdio>
#include <cstdlib>
/* #include <time.h> */
#include <cmath>
#include "MEM_guardedalloc.h"
#include "BLI_math_matrix.h"
#include "MOD_lineart.hh"
#include "lineart_intern.hh"
/* Line art memory and list helper */
void *lineart_list_append_pointer_pool(ListBase *h, LineartStaticMemPool *smp, void *data)
{
LinkData *lip;
if (h == nullptr) {
return nullptr;
}
lip = static_cast<LinkData *>(lineart_mem_acquire(smp, sizeof(LinkData)));
lip->data = data;
BLI_addtail(h, lip);
return lip;
}
void *lineart_list_append_pointer_pool_sized(ListBase *h,
LineartStaticMemPool *smp,
void *data,
int size)
{
LinkData *lip;
if (h == nullptr) {
return nullptr;
}
lip = static_cast<LinkData *>(lineart_mem_acquire(smp, size));
lip->data = data;
BLI_addtail(h, lip);
return lip;
}
void *lineart_list_append_pointer_pool_thread(ListBase *h, LineartStaticMemPool *smp, void *data)
{
LinkData *lip;
if (h == nullptr) {
return nullptr;
}
lip = static_cast<LinkData *>(lineart_mem_acquire_thread(smp, sizeof(LinkData)));
lip->data = data;
BLI_addtail(h, lip);
return lip;
}
void *lineart_list_append_pointer_pool_sized_thread(ListBase *h,
LineartStaticMemPool *smp,
void *data,
int size)
{
LinkData *lip;
if (h == nullptr) {
return nullptr;
}
lip = static_cast<LinkData *>(lineart_mem_acquire_thread(smp, size));
lip->data = data;
BLI_addtail(h, lip);
return lip;
}
void *lineart_list_pop_pointer_no_free(ListBase *h)
{
LinkData *lip;
void *rev = nullptr;
if (h == nullptr) {
return nullptr;
}
lip = static_cast<LinkData *>(BLI_pophead(h));
rev = lip ? lip->data : nullptr;
return rev;
}
void lineart_list_remove_pointer_item_no_free(ListBase *h, LinkData *lip)
{
BLI_remlink(h, (void *)lip);
}
LineartStaticMemPoolNode *lineart_mem_new_static_pool(LineartStaticMemPool *smp, size_t size)
{
size_t set_size = size;
if (set_size < LRT_MEMORY_POOL_1MB) {
set_size = LRT_MEMORY_POOL_1MB; /* Prevent too many small allocations. */
}
size_t total_size = set_size + sizeof(LineartStaticMemPoolNode);
LineartStaticMemPoolNode *smpn = static_cast<LineartStaticMemPoolNode *>(
MEM_callocN(total_size, "mempool"));
smpn->size = total_size;
smpn->used_byte = sizeof(LineartStaticMemPoolNode);
BLI_addhead(&smp->pools, smpn);
return smpn;
}
void *lineart_mem_acquire(LineartStaticMemPool *smp, size_t size)
{
LineartStaticMemPoolNode *smpn = static_cast<LineartStaticMemPoolNode *>(smp->pools.first);
void *ret;
if (!smpn || (smpn->used_byte + size) > smpn->size) {
smpn = lineart_mem_new_static_pool(smp, size);
}
ret = ((uchar *)smpn) + smpn->used_byte;
smpn->used_byte += size;
return ret;
}
void *lineart_mem_acquire_thread(LineartStaticMemPool *smp, size_t size)
{
void *ret;
BLI_spin_lock(&smp->lock_mem);
LineartStaticMemPoolNode *smpn = static_cast<LineartStaticMemPoolNode *>(smp->pools.first);
if (!smpn || (smpn->used_byte + size) > smpn->size) {
smpn = lineart_mem_new_static_pool(smp, size);
}
ret = ((uchar *)smpn) + smpn->used_byte;
smpn->used_byte += size;
BLI_spin_unlock(&smp->lock_mem);
return ret;
}
void lineart_mem_destroy(LineartStaticMemPool *smp)
{
while (LineartStaticMemPoolNode *smpn = static_cast<LineartStaticMemPoolNode *>(
BLI_pophead(&smp->pools)))
{
MEM_freeN(smpn);
}
}
void lineart_prepend_pool(LinkNode **first, LineartStaticMemPool *smp, void *link)
{
LinkNode *ln = static_cast<LinkNode *>(lineart_mem_acquire_thread(smp, sizeof(LinkNode)));
ln->next = (*first);
ln->link = link;
(*first) = ln;
}
/* =======================================================================[str] */
void lineart_matrix_perspective_44d(
double (*mProjection)[4], double fFov_rad, double fAspect, double zMin, double zMax)
{
double yMax;
double yMin;
double xMin;
double xMax;
if (fAspect < 1) {
yMax = zMin * tan(fFov_rad * 0.5f);
yMin = -yMax;
xMin = yMin * fAspect;
xMax = -xMin;
}
else {
xMax = zMin * tan(fFov_rad * 0.5f);
xMin = -xMax;
yMin = xMin / fAspect;
yMax = -yMin;
}
unit_m4_db(mProjection);
mProjection[0][0] = (2.0f * zMin) / (xMax - xMin);
mProjection[1][1] = (2.0f * zMin) / (yMax - yMin);
mProjection[2][0] = (xMax + xMin) / (xMax - xMin);
mProjection[2][1] = (yMax + yMin) / (yMax - yMin);
mProjection[2][2] = -((zMax + zMin) / (zMax - zMin));
mProjection[2][3] = -1.0f;
mProjection[3][2] = -((2.0f * (zMax * zMin)) / (zMax - zMin));
mProjection[3][3] = 0.0f;
}
void lineart_matrix_ortho_44d(double (*mProjection)[4],
double xMin,
double xMax,
double yMin,
double yMax,
double zMin,
double zMax)
{
unit_m4_db(mProjection);
mProjection[0][0] = 2.0f / (xMax - xMin);
mProjection[1][1] = 2.0f / (yMax - yMin);
mProjection[2][2] = -2.0f / (zMax - zMin);
mProjection[3][0] = -((xMax + xMin) / (xMax - xMin));
mProjection[3][1] = -((yMax + yMin) / (yMax - yMin));
mProjection[3][2] = -((zMax + zMin) / (zMax - zMin));
mProjection[3][3] = 1.0f;
}
void lineart_count_and_print_render_buffer_memory(LineartData *ld)
{
size_t total = 0;
size_t sum_this = 0;
size_t count_this = 0;
LISTBASE_FOREACH (LineartStaticMemPoolNode *, smpn, &ld->render_data_pool.pools) {
count_this++;
sum_this += LRT_MEMORY_POOL_1MB;
}
printf("LANPR Memory allocated %zu Standalone nodes, total %zu Bytes.\n", count_this, sum_this);
total += sum_this;
sum_this = 0;
count_this = 0;
LISTBASE_FOREACH (LineartElementLinkNode *, reln, &ld->geom.line_buffer_pointers) {
count_this++;
sum_this += reln->element_count * sizeof(LineartEdge);
}
printf(" allocated %zu edge blocks, total %zu Bytes.\n", count_this, sum_this);
total += sum_this;
sum_this = 0;
count_this = 0;
LISTBASE_FOREACH (LineartElementLinkNode *, reln, &ld->geom.triangle_buffer_pointers) {
count_this++;
sum_this += reln->element_count * ld->sizeof_triangle;
}
printf(" allocated %zu triangle blocks, total %zu Bytes.\n", count_this, sum_this);
total += sum_this;
sum_this = 0;
count_this = 0;
(void)total; /* Ignored. */
}