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
246 lines
6.6 KiB
C++
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. */
|
|
}
|