Merge branch 'master' into sculpt-dev
This commit is contained in:
commit
3ccc160682
|
@ -472,8 +472,7 @@ if(NOT GFLAGS_FOUND)
|
|||
gflags_report_not_found(
|
||||
"Could not find gflags include directory, set GFLAGS_INCLUDE_DIR "
|
||||
"to directory containing gflags/gflags.h")
|
||||
endif(NOT GFLAGS_INCLUDE_DIR OR
|
||||
NOT EXISTS ${GFLAGS_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
find_library(GFLAGS_LIBRARY NAMES gflags
|
||||
PATHS ${GFLAGS_LIBRARY_DIR_HINTS}
|
||||
|
@ -484,8 +483,7 @@ if(NOT GFLAGS_FOUND)
|
|||
gflags_report_not_found(
|
||||
"Could not find gflags library, set GFLAGS_LIBRARY "
|
||||
"to full path to libgflags.")
|
||||
endif(NOT GFLAGS_LIBRARY OR
|
||||
NOT EXISTS ${GFLAGS_LIBRARY})
|
||||
endif()
|
||||
|
||||
# gflags typically requires a threading library (which is OS dependent), note
|
||||
# that this defines the CMAKE_THREAD_LIBS_INIT variable. If we are able to
|
||||
|
@ -560,8 +558,7 @@ if(NOT GFLAGS_FOUND)
|
|||
gflags_report_not_found(
|
||||
"Caller defined GFLAGS_INCLUDE_DIR:"
|
||||
" ${GFLAGS_INCLUDE_DIR} does not contain gflags/gflags.h header.")
|
||||
endif(GFLAGS_INCLUDE_DIR AND
|
||||
NOT EXISTS ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
|
||||
endif()
|
||||
# TODO: This regex for gflags library is pretty primitive, we use lowercase
|
||||
# for comparison to handle Windows using CamelCase library names, could
|
||||
# this check be better?
|
||||
|
@ -571,8 +568,7 @@ if(NOT GFLAGS_FOUND)
|
|||
gflags_report_not_found(
|
||||
"Caller defined GFLAGS_LIBRARY: "
|
||||
"${GFLAGS_LIBRARY} does not match gflags.")
|
||||
endif(GFLAGS_LIBRARY AND
|
||||
NOT "${LOWERCASE_GFLAGS_LIBRARY}" MATCHES ".*gflags[^/]*")
|
||||
endif()
|
||||
|
||||
gflags_reset_find_library_prefix()
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(NanoVDB DEFAULT_MSG
|
|||
|
||||
IF(NANOVDB_FOUND)
|
||||
SET(NANOVDB_INCLUDE_DIRS ${NANOVDB_INCLUDE_DIR})
|
||||
ENDIF(NANOVDB_FOUND)
|
||||
ENDIF()
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
NANOVDB_INCLUDE_DIR
|
||||
|
|
|
@ -40,7 +40,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(sse2neon DEFAULT_MSG
|
|||
|
||||
IF(SSE2NEON_FOUND)
|
||||
SET(SSE2NEON_INCLUDE_DIRS ${SSE2NEON_INCLUDE_DIR})
|
||||
ENDIF(SSE2NEON_FOUND)
|
||||
ENDIF()
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
SSE2NEON_INCLUDE_DIR
|
||||
|
|
|
@ -274,13 +274,6 @@ void BKE_mesh_vert_normals_apply(struct Mesh *mesh, const short (*vert_normals)[
|
|||
|
||||
/* *** mesh_tessellate.c *** */
|
||||
|
||||
void BKE_mesh_loops_to_tessdata(struct CustomData *fdata,
|
||||
struct CustomData *ldata,
|
||||
struct MFace *mface,
|
||||
const int *polyindices,
|
||||
unsigned int (*loopindices)[4],
|
||||
const int num_faces);
|
||||
|
||||
int BKE_mesh_tessface_calc_ex(struct CustomData *fdata,
|
||||
struct CustomData *ldata,
|
||||
struct CustomData *pdata,
|
||||
|
@ -297,6 +290,13 @@ void BKE_mesh_recalc_looptri(const struct MLoop *mloop,
|
|||
int totloop,
|
||||
int totpoly,
|
||||
struct MLoopTri *mlooptri);
|
||||
void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop,
|
||||
const struct MPoly *mpoly,
|
||||
const struct MVert *mvert,
|
||||
int totloop,
|
||||
int totpoly,
|
||||
struct MLoopTri *mlooptri,
|
||||
const float (*poly_normals)[3]);
|
||||
|
||||
/* *** mesh_evaluate.c *** */
|
||||
|
||||
|
|
|
@ -1970,7 +1970,7 @@ const CustomData_MeshMasks CD_MASK_BMESH = {
|
|||
CD_MASK_SCULPT_FACE_SETS),
|
||||
};
|
||||
/**
|
||||
* cover values copied by #BKE_mesh_loops_to_tessdata
|
||||
* cover values copied by #mesh_loops_to_tessdata
|
||||
*/
|
||||
const CustomData_MeshMasks CD_MASK_FACECORNERS = {
|
||||
.vmask = 0,
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "BLI_math.h"
|
||||
#include "BLI_memarena.h"
|
||||
#include "BLI_polyfill_2d.h"
|
||||
#include "BLI_task.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
|
@ -43,8 +44,13 @@
|
|||
|
||||
#include "BLI_strict_flags.h"
|
||||
|
||||
/** Compared against total loops. */
|
||||
#define MESH_FACE_TESSELLATE_THREADED_LIMIT 4096
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name MFace Tessellation
|
||||
*
|
||||
* #MFace is a legacy data-structure that should be avoided, use #MLoopTri instead.
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
|
@ -56,18 +62,17 @@
|
|||
* \note when mface is not NULL, mface[face_index].v4
|
||||
* is used to test quads, else, loopindices[face_index][3] is used.
|
||||
*/
|
||||
void BKE_mesh_loops_to_tessdata(CustomData *fdata,
|
||||
CustomData *ldata,
|
||||
MFace *mface,
|
||||
const int *polyindices,
|
||||
uint (*loopindices)[4],
|
||||
const int num_faces)
|
||||
static void mesh_loops_to_tessdata(CustomData *fdata,
|
||||
CustomData *ldata,
|
||||
MFace *mface,
|
||||
const int *polyindices,
|
||||
uint (*loopindices)[4],
|
||||
const int num_faces)
|
||||
{
|
||||
/* Note: performances are sub-optimal when we get a NULL mface,
|
||||
* we could be ~25% quicker with dedicated code...
|
||||
* Issue is, unless having two different functions with nearly the same code,
|
||||
* there's not much ways to solve this. Better imho to live with it for now. :/ --mont29
|
||||
*/
|
||||
/* NOTE(mont29): performances are sub-optimal when we get a NULL #MFace,
|
||||
* we could be ~25% quicker with dedicated code.
|
||||
* The issue is, unless having two different functions with nearly the same code,
|
||||
* there's not much ways to solve this. Better IMHO to live with it for now (sigh). */
|
||||
const int numUV = CustomData_number_of_layers(ldata, CD_MLOOPUV);
|
||||
const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
|
||||
const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
|
||||
|
@ -135,7 +140,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata,
|
|||
}
|
||||
|
||||
if (hasLoopTangent) {
|
||||
/* need to do for all uv maps at some point */
|
||||
/* Need to do for all UV maps at some point. */
|
||||
float(*ftangents)[4] = CustomData_get_layer(fdata, CD_TANGENT);
|
||||
float(*ltangents)[4] = CustomData_get_layer(ldata, CD_TANGENT);
|
||||
|
||||
|
@ -150,12 +155,15 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata,
|
|||
}
|
||||
|
||||
/**
|
||||
* Recreate tessellation.
|
||||
* Recreate #MFace Tessellation.
|
||||
*
|
||||
* \param do_face_nor_copy: Controls whether the normals from the poly
|
||||
* are copied to the tessellated faces.
|
||||
*
|
||||
* \return number of tessellation faces.
|
||||
*
|
||||
* \note This doesn't use multi-threading like #BKE_mesh_recalc_looptri since
|
||||
* it's not used in many places and #MFace should be phased out.
|
||||
*/
|
||||
int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
||||
CustomData *ldata,
|
||||
|
@ -166,13 +174,10 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
int totpoly,
|
||||
const bool do_face_nor_copy)
|
||||
{
|
||||
/* use this to avoid locking pthread for _every_ polygon
|
||||
* and calling the fill function */
|
||||
|
||||
#define USE_TESSFACE_SPEEDUP
|
||||
#define USE_TESSFACE_QUADS /* NEEDS FURTHER TESTING */
|
||||
#define USE_TESSFACE_QUADS
|
||||
|
||||
/* We abuse MFace->edcode to tag quad faces. See below for details. */
|
||||
/* We abuse #MFace.edcode to tag quad faces. See below for details. */
|
||||
#define TESSFACE_IS_QUAD 1
|
||||
|
||||
const int looptri_num = poly_to_tri_count(totpoly, totloop);
|
||||
|
@ -189,9 +194,9 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
mpoly = CustomData_get_layer(pdata, CD_MPOLY);
|
||||
mloop = CustomData_get_layer(ldata, CD_MLOOP);
|
||||
|
||||
/* allocate the length of totfaces, avoid many small reallocs,
|
||||
* if all faces are tri's it will be correct, quads == 2x allocs */
|
||||
/* take care. we are _not_ calloc'ing so be sure to initialize each field */
|
||||
/* Allocate the length of `totfaces`, avoid many small reallocation's,
|
||||
* if all faces are triangles it will be correct, `quads == 2x` allocations. */
|
||||
/* Take care since memory is _not_ zeroed so be sure to initialize each field. */
|
||||
mface_to_poly_map = MEM_malloc_arrayN((size_t)looptri_num, sizeof(*mface_to_poly_map), __func__);
|
||||
mface = MEM_malloc_arrayN((size_t)looptri_num, sizeof(*mface), __func__);
|
||||
lindices = MEM_malloc_arrayN((size_t)looptri_num, sizeof(*lindices), __func__);
|
||||
|
@ -204,7 +209,7 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
uint l1, l2, l3, l4;
|
||||
uint *lidx;
|
||||
if (mp_totloop < 3) {
|
||||
/* do nothing */
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
#ifdef USE_TESSFACE_SPEEDUP
|
||||
|
@ -213,7 +218,7 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
mface_to_poly_map[mface_index] = poly_index; \
|
||||
mf = &mface[mface_index]; \
|
||||
lidx = lindices[mface_index]; \
|
||||
/* set loop indices, transformed to vert indices later */ \
|
||||
/* Set loop indices, transformed to vert indices later. */ \
|
||||
l1 = mp_loopstart + i1; \
|
||||
l2 = mp_loopstart + i2; \
|
||||
l3 = mp_loopstart + i3; \
|
||||
|
@ -235,7 +240,7 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
mface_to_poly_map[mface_index] = poly_index; \
|
||||
mf = &mface[mface_index]; \
|
||||
lidx = lindices[mface_index]; \
|
||||
/* set loop indices, transformed to vert indices later */ \
|
||||
/* Set loop indices, transformed to vert indices later. */ \
|
||||
l1 = mp_loopstart + 0; /* EXCEPTION */ \
|
||||
l2 = mp_loopstart + 1; /* EXCEPTION */ \
|
||||
l3 = mp_loopstart + 2; /* EXCEPTION */ \
|
||||
|
@ -289,7 +294,7 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
|
||||
zero_v3(normal);
|
||||
|
||||
/* calc normal, flipped: to get a positive 2d cross product */
|
||||
/* Calculate the normal, flipped: to get a positive 2D cross product. */
|
||||
ml = mloop + mp_loopstart;
|
||||
co_prev = mvert[ml[mp_totloop - 1].v].co;
|
||||
for (j = 0; j < mp_totloop; j++, ml++) {
|
||||
|
@ -301,7 +306,7 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
normal[2] = 1.0f;
|
||||
}
|
||||
|
||||
/* project verts to 2d */
|
||||
/* Project verts to 2D. */
|
||||
axis_dominant_v3_to_m3_negate(axis_mat, normal);
|
||||
|
||||
ml = mloop + mp_loopstart;
|
||||
|
@ -311,7 +316,7 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
|
||||
BLI_polyfill_calc_arena(projverts, mp_totloop, 1, tris, arena);
|
||||
|
||||
/* apply fill */
|
||||
/* Apply fill. */
|
||||
for (j = 0; j < totfilltri; j++) {
|
||||
uint *tri = tris[j];
|
||||
lidx = lindices[mface_index];
|
||||
|
@ -319,7 +324,7 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
mface_to_poly_map[mface_index] = poly_index;
|
||||
mf = &mface[mface_index];
|
||||
|
||||
/* set loop indices, transformed to vert indices later */
|
||||
/* Set loop indices, transformed to vert indices later. */
|
||||
l1 = mp_loopstart + tri[0];
|
||||
l2 = mp_loopstart + tri[1];
|
||||
l3 = mp_loopstart + tri[2];
|
||||
|
@ -355,7 +360,7 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
|
||||
BLI_assert(totface <= looptri_num);
|
||||
|
||||
/* not essential but without this we store over-alloc'd memory in the CustomData layers */
|
||||
/* Not essential but without this we store over-allocated memory in the #CustomData layers. */
|
||||
if (LIKELY(looptri_num != totface)) {
|
||||
mface = MEM_reallocN(mface, sizeof(*mface) * (size_t)totface);
|
||||
mface_to_poly_map = MEM_reallocN(mface_to_poly_map,
|
||||
|
@ -364,14 +369,14 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
|
||||
CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface);
|
||||
|
||||
/* CD_ORIGINDEX will contain an array of indices from tessfaces to the polygons
|
||||
* they are directly tessellated from */
|
||||
/* #CD_ORIGINDEX will contain an array of indices from tessellation-faces to the polygons
|
||||
* they are directly tessellated from. */
|
||||
CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface);
|
||||
CustomData_from_bmeshpoly(fdata, ldata, totface);
|
||||
|
||||
if (do_face_nor_copy) {
|
||||
/* If polys have a normals layer, copying that to faces can help
|
||||
* avoid the need to recalculate normals later */
|
||||
* avoid the need to recalculate normals later. */
|
||||
if (CustomData_has_layer(pdata, CD_NORMAL)) {
|
||||
float(*pnors)[3] = CustomData_get_layer(pdata, CD_NORMAL);
|
||||
float(*fnors)[3] = CustomData_add_layer(fdata, CD_NORMAL, CD_CALLOC, NULL, totface);
|
||||
|
@ -383,14 +388,12 @@ int BKE_mesh_tessface_calc_ex(CustomData *fdata,
|
|||
|
||||
/* NOTE: quad detection issue - fourth vertidx vs fourth loopidx:
|
||||
* Polygons take care of their loops ordering, hence not of their vertices ordering.
|
||||
* Currently, our tfaces' fourth vertex index might be 0 even for a quad. However,
|
||||
* we know our fourth loop index is never 0 for quads (because they are sorted for polygons,
|
||||
* and our quads are still mere copies of their polygons).
|
||||
* So we pass NULL as MFace pointer, and BKE_mesh_loops_to_tessdata
|
||||
* will use the fourth loop index as quad test.
|
||||
* ...
|
||||
*/
|
||||
BKE_mesh_loops_to_tessdata(fdata, ldata, NULL, mface_to_poly_map, lindices, totface);
|
||||
* Currently, our tfaces' fourth vertex index might be 0 even for a quad.
|
||||
* However, we know our fourth loop index is never 0 for quads
|
||||
* (because they are sorted for polygons, and our quads are still mere copies of their polygons).
|
||||
* So we pass NULL as MFace pointer, and #mesh_loops_to_tessdata
|
||||
* will use the fourth loop index as quad test. */
|
||||
mesh_loops_to_tessdata(fdata, ldata, NULL, mface_to_poly_map, lindices, totface);
|
||||
|
||||
/* NOTE: quad detection issue - fourth vertidx vs fourth loopidx:
|
||||
* ...However, most TFace code uses 'MFace->v4 == 0' test to check whether it is a tri or quad.
|
||||
|
@ -427,7 +430,7 @@ void BKE_mesh_tessface_calc(Mesh *mesh)
|
|||
mesh->totface,
|
||||
mesh->totloop,
|
||||
mesh->totpoly,
|
||||
/* calc normals right after, don't copy from polys here */
|
||||
/* Calculate normals right after, don't copy from polys here. */
|
||||
false);
|
||||
|
||||
BKE_mesh_update_customdata_pointers(mesh, true);
|
||||
|
@ -437,8 +440,278 @@ void BKE_mesh_tessface_calc(Mesh *mesh)
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Loop Tessellation
|
||||
*
|
||||
* Fill in #MLoopTri data-structure.
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* \param face_normal: This will be optimized out as a constant.
|
||||
*/
|
||||
BLI_INLINE void mesh_calc_tessellation_for_face_impl(const MLoop *mloop,
|
||||
const MPoly *mpoly,
|
||||
const MVert *mvert,
|
||||
uint poly_index,
|
||||
MLoopTri *mlt,
|
||||
MemArena **pf_arena_p,
|
||||
const bool face_normal,
|
||||
const float normal_precalc[3])
|
||||
{
|
||||
const uint mp_loopstart = (uint)mpoly[poly_index].loopstart;
|
||||
const uint mp_totloop = (uint)mpoly[poly_index].totloop;
|
||||
|
||||
#define ML_TO_MLT(i1, i2, i3) \
|
||||
{ \
|
||||
ARRAY_SET_ITEMS(mlt->tri, mp_loopstart + i1, mp_loopstart + i2, mp_loopstart + i3); \
|
||||
mlt->poly = poly_index; \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
switch (mp_totloop) {
|
||||
case 3: {
|
||||
ML_TO_MLT(0, 1, 2);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
ML_TO_MLT(0, 1, 2);
|
||||
MLoopTri *mlt_a = mlt++;
|
||||
ML_TO_MLT(0, 2, 3);
|
||||
MLoopTri *mlt_b = mlt;
|
||||
|
||||
if (UNLIKELY(face_normal ? is_quad_flip_v3_first_third_fast_with_normal(
|
||||
/* Simpler calculation (using the normal). */
|
||||
mvert[mloop[mlt_a->tri[0]].v].co,
|
||||
mvert[mloop[mlt_a->tri[1]].v].co,
|
||||
mvert[mloop[mlt_a->tri[2]].v].co,
|
||||
mvert[mloop[mlt_b->tri[2]].v].co,
|
||||
normal_precalc) :
|
||||
is_quad_flip_v3_first_third_fast(
|
||||
/* Expensive calculation (no normal). */
|
||||
mvert[mloop[mlt_a->tri[0]].v].co,
|
||||
mvert[mloop[mlt_a->tri[1]].v].co,
|
||||
mvert[mloop[mlt_a->tri[2]].v].co,
|
||||
mvert[mloop[mlt_b->tri[2]].v].co))) {
|
||||
/* Flip out of degenerate 0-2 state. */
|
||||
mlt_a->tri[2] = mlt_b->tri[2];
|
||||
mlt_b->tri[0] = mlt_a->tri[1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
const MLoop *ml;
|
||||
float axis_mat[3][3];
|
||||
|
||||
/* Calculate `axis_mat` to project verts to 2D. */
|
||||
if (face_normal == false) {
|
||||
float normal[3];
|
||||
const float *co_curr, *co_prev;
|
||||
|
||||
zero_v3(normal);
|
||||
|
||||
/* Calc normal, flipped: to get a positive 2D cross product. */
|
||||
ml = mloop + mp_loopstart;
|
||||
co_prev = mvert[ml[mp_totloop - 1].v].co;
|
||||
for (uint j = 0; j < mp_totloop; j++, ml++) {
|
||||
co_curr = mvert[ml->v].co;
|
||||
add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
|
||||
co_prev = co_curr;
|
||||
}
|
||||
if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
|
||||
normal[2] = 1.0f;
|
||||
}
|
||||
axis_dominant_v3_to_m3_negate(axis_mat, normal);
|
||||
}
|
||||
else {
|
||||
axis_dominant_v3_to_m3_negate(axis_mat, normal_precalc);
|
||||
}
|
||||
|
||||
const uint totfilltri = mp_totloop - 2;
|
||||
|
||||
MemArena *pf_arena = *pf_arena_p;
|
||||
if (UNLIKELY(pf_arena == NULL)) {
|
||||
pf_arena = *pf_arena_p = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
|
||||
}
|
||||
|
||||
uint(*tris)[3] = tris = BLI_memarena_alloc(pf_arena, sizeof(*tris) * (size_t)totfilltri);
|
||||
float(*projverts)[2] = projverts = BLI_memarena_alloc(
|
||||
pf_arena, sizeof(*projverts) * (size_t)mp_totloop);
|
||||
|
||||
ml = mloop + mp_loopstart;
|
||||
for (uint j = 0; j < mp_totloop; j++, ml++) {
|
||||
mul_v2_m3v3(projverts[j], axis_mat, mvert[ml->v].co);
|
||||
}
|
||||
|
||||
BLI_polyfill_calc_arena(projverts, mp_totloop, 1, tris, pf_arena);
|
||||
|
||||
/* Apply fill. */
|
||||
for (uint j = 0; j < totfilltri; j++, mlt++) {
|
||||
const uint *tri = tris[j];
|
||||
ML_TO_MLT(tri[0], tri[1], tri[2]);
|
||||
}
|
||||
|
||||
BLI_memarena_clear(pf_arena);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
#undef ML_TO_MLT
|
||||
}
|
||||
|
||||
static void mesh_calc_tessellation_for_face(const MLoop *mloop,
|
||||
const MPoly *mpoly,
|
||||
const MVert *mvert,
|
||||
uint poly_index,
|
||||
MLoopTri *mlt,
|
||||
MemArena **pf_arena_p)
|
||||
{
|
||||
mesh_calc_tessellation_for_face_impl(
|
||||
mloop, mpoly, mvert, poly_index, mlt, pf_arena_p, false, NULL);
|
||||
}
|
||||
|
||||
static void mesh_calc_tessellation_for_face_with_normal(const MLoop *mloop,
|
||||
const MPoly *mpoly,
|
||||
const MVert *mvert,
|
||||
uint poly_index,
|
||||
MLoopTri *mlt,
|
||||
MemArena **pf_arena_p,
|
||||
const float normal_precalc[3])
|
||||
{
|
||||
mesh_calc_tessellation_for_face_impl(
|
||||
mloop, mpoly, mvert, poly_index, mlt, pf_arena_p, true, normal_precalc);
|
||||
}
|
||||
|
||||
static void mesh_recalc_looptri__single_threaded(const MLoop *mloop,
|
||||
const MPoly *mpoly,
|
||||
const MVert *mvert,
|
||||
int totloop,
|
||||
int totpoly,
|
||||
MLoopTri *mlooptri,
|
||||
const float (*poly_normals)[3])
|
||||
{
|
||||
MemArena *pf_arena = NULL;
|
||||
const MPoly *mp = mpoly;
|
||||
uint tri_index = 0;
|
||||
|
||||
if (poly_normals != NULL) {
|
||||
for (uint poly_index = 0; poly_index < (uint)totpoly; poly_index++, mp++) {
|
||||
mesh_calc_tessellation_for_face_with_normal(mloop,
|
||||
mpoly,
|
||||
mvert,
|
||||
poly_index,
|
||||
&mlooptri[tri_index],
|
||||
&pf_arena,
|
||||
poly_normals[poly_index]);
|
||||
tri_index += (uint)(mp->totloop - 2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (uint poly_index = 0; poly_index < (uint)totpoly; poly_index++, mp++) {
|
||||
mesh_calc_tessellation_for_face(
|
||||
mloop, mpoly, mvert, poly_index, &mlooptri[tri_index], &pf_arena);
|
||||
tri_index += (uint)(mp->totloop - 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (pf_arena) {
|
||||
BLI_memarena_free(pf_arena);
|
||||
pf_arena = NULL;
|
||||
}
|
||||
BLI_assert(tri_index == (uint)poly_to_tri_count(totpoly, totloop));
|
||||
UNUSED_VARS_NDEBUG(totloop);
|
||||
}
|
||||
|
||||
struct TessellationUserData {
|
||||
const MLoop *mloop;
|
||||
const MPoly *mpoly;
|
||||
const MVert *mvert;
|
||||
|
||||
/** Output array. */
|
||||
MLoopTri *mlooptri;
|
||||
|
||||
/** Optional pre-calculated polygon normals array. */
|
||||
const float (*poly_normals)[3];
|
||||
};
|
||||
|
||||
struct TessellationUserTLS {
|
||||
MemArena *pf_arena;
|
||||
};
|
||||
|
||||
static void mesh_calc_tessellation_for_face_fn(void *__restrict userdata,
|
||||
const int index,
|
||||
const TaskParallelTLS *__restrict tls)
|
||||
{
|
||||
const struct TessellationUserData *data = userdata;
|
||||
struct TessellationUserTLS *tls_data = tls->userdata_chunk;
|
||||
const int tri_index = poly_to_tri_count(index, data->mpoly[index].loopstart);
|
||||
mesh_calc_tessellation_for_face_impl(data->mloop,
|
||||
data->mpoly,
|
||||
data->mvert,
|
||||
(uint)index,
|
||||
&data->mlooptri[tri_index],
|
||||
&tls_data->pf_arena,
|
||||
false,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void mesh_calc_tessellation_for_face_with_normal_fn(void *__restrict userdata,
|
||||
const int index,
|
||||
const TaskParallelTLS *__restrict tls)
|
||||
{
|
||||
const struct TessellationUserData *data = userdata;
|
||||
struct TessellationUserTLS *tls_data = tls->userdata_chunk;
|
||||
const int tri_index = poly_to_tri_count(index, data->mpoly[index].loopstart);
|
||||
mesh_calc_tessellation_for_face_impl(data->mloop,
|
||||
data->mpoly,
|
||||
data->mvert,
|
||||
(uint)index,
|
||||
&data->mlooptri[tri_index],
|
||||
&tls_data->pf_arena,
|
||||
true,
|
||||
data->poly_normals[index]);
|
||||
}
|
||||
|
||||
static void mesh_calc_tessellation_for_face_free_fn(const void *__restrict UNUSED(userdata),
|
||||
void *__restrict tls_v)
|
||||
{
|
||||
struct TessellationUserTLS *tls_data = tls_v;
|
||||
if (tls_data->pf_arena) {
|
||||
BLI_memarena_free(tls_data->pf_arena);
|
||||
}
|
||||
}
|
||||
|
||||
static void mesh_recalc_looptri__multi_threaded(const MLoop *mloop,
|
||||
const MPoly *mpoly,
|
||||
const MVert *mvert,
|
||||
int UNUSED(totloop),
|
||||
int totpoly,
|
||||
MLoopTri *mlooptri,
|
||||
const float (*poly_normals)[3])
|
||||
{
|
||||
struct TessellationUserTLS tls_data_dummy = {NULL};
|
||||
|
||||
struct TessellationUserData data = {
|
||||
.mloop = mloop,
|
||||
.mpoly = mpoly,
|
||||
.mvert = mvert,
|
||||
.mlooptri = mlooptri,
|
||||
.poly_normals = poly_normals,
|
||||
};
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
|
||||
settings.userdata_chunk = &tls_data_dummy;
|
||||
settings.userdata_chunk_size = sizeof(tls_data_dummy);
|
||||
|
||||
settings.func_free = mesh_calc_tessellation_for_face_free_fn;
|
||||
|
||||
BLI_task_parallel_range(0,
|
||||
totpoly,
|
||||
&data,
|
||||
poly_normals ? mesh_calc_tessellation_for_face_with_normal_fn :
|
||||
mesh_calc_tessellation_for_face_fn,
|
||||
&settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate tessellation into #MLoopTri which exist only for this purpose.
|
||||
*/
|
||||
|
@ -449,136 +722,39 @@ void BKE_mesh_recalc_looptri(const MLoop *mloop,
|
|||
int totpoly,
|
||||
MLoopTri *mlooptri)
|
||||
{
|
||||
/* use this to avoid locking pthread for _every_ polygon
|
||||
* and calling the fill function */
|
||||
|
||||
#define USE_TESSFACE_SPEEDUP
|
||||
|
||||
const MPoly *mp;
|
||||
const MLoop *ml;
|
||||
MLoopTri *mlt;
|
||||
MemArena *arena = NULL;
|
||||
int poly_index, mlooptri_index;
|
||||
uint j;
|
||||
|
||||
mlooptri_index = 0;
|
||||
mp = mpoly;
|
||||
for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) {
|
||||
const uint mp_loopstart = (uint)mp->loopstart;
|
||||
const uint mp_totloop = (uint)mp->totloop;
|
||||
uint l1, l2, l3;
|
||||
if (mp_totloop < 3) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
#ifdef USE_TESSFACE_SPEEDUP
|
||||
|
||||
# define ML_TO_MLT(i1, i2, i3) \
|
||||
{ \
|
||||
mlt = &mlooptri[mlooptri_index]; \
|
||||
l1 = mp_loopstart + i1; \
|
||||
l2 = mp_loopstart + i2; \
|
||||
l3 = mp_loopstart + i3; \
|
||||
ARRAY_SET_ITEMS(mlt->tri, l1, l2, l3); \
|
||||
mlt->poly = (uint)poly_index; \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
else if (mp_totloop == 3) {
|
||||
ML_TO_MLT(0, 1, 2);
|
||||
mlooptri_index++;
|
||||
}
|
||||
else if (mp_totloop == 4) {
|
||||
ML_TO_MLT(0, 1, 2);
|
||||
MLoopTri *mlt_a = mlt;
|
||||
mlooptri_index++;
|
||||
ML_TO_MLT(0, 2, 3);
|
||||
MLoopTri *mlt_b = mlt;
|
||||
mlooptri_index++;
|
||||
|
||||
if (UNLIKELY(is_quad_flip_v3_first_third_fast(mvert[mloop[mlt_a->tri[0]].v].co,
|
||||
mvert[mloop[mlt_a->tri[1]].v].co,
|
||||
mvert[mloop[mlt_a->tri[2]].v].co,
|
||||
mvert[mloop[mlt_b->tri[2]].v].co))) {
|
||||
/* flip out of degenerate 0-2 state. */
|
||||
mlt_a->tri[2] = mlt_b->tri[2];
|
||||
mlt_b->tri[0] = mlt_a->tri[1];
|
||||
}
|
||||
}
|
||||
#endif /* USE_TESSFACE_SPEEDUP */
|
||||
else {
|
||||
const float *co_curr, *co_prev;
|
||||
|
||||
float normal[3];
|
||||
|
||||
float axis_mat[3][3];
|
||||
float(*projverts)[2];
|
||||
uint(*tris)[3];
|
||||
|
||||
const uint totfilltri = mp_totloop - 2;
|
||||
|
||||
if (UNLIKELY(arena == NULL)) {
|
||||
arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
|
||||
}
|
||||
|
||||
tris = BLI_memarena_alloc(arena, sizeof(*tris) * (size_t)totfilltri);
|
||||
projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * (size_t)mp_totloop);
|
||||
|
||||
zero_v3(normal);
|
||||
|
||||
/* calc normal, flipped: to get a positive 2d cross product */
|
||||
ml = mloop + mp_loopstart;
|
||||
co_prev = mvert[ml[mp_totloop - 1].v].co;
|
||||
for (j = 0; j < mp_totloop; j++, ml++) {
|
||||
co_curr = mvert[ml->v].co;
|
||||
add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
|
||||
co_prev = co_curr;
|
||||
}
|
||||
if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
|
||||
normal[2] = 1.0f;
|
||||
}
|
||||
|
||||
/* project verts to 2d */
|
||||
axis_dominant_v3_to_m3_negate(axis_mat, normal);
|
||||
|
||||
ml = mloop + mp_loopstart;
|
||||
for (j = 0; j < mp_totloop; j++, ml++) {
|
||||
mul_v2_m3v3(projverts[j], axis_mat, mvert[ml->v].co);
|
||||
}
|
||||
|
||||
BLI_polyfill_calc_arena(projverts, mp_totloop, 1, tris, arena);
|
||||
|
||||
/* apply fill */
|
||||
for (j = 0; j < totfilltri; j++) {
|
||||
uint *tri = tris[j];
|
||||
|
||||
mlt = &mlooptri[mlooptri_index];
|
||||
|
||||
/* set loop indices, transformed to vert indices later */
|
||||
l1 = mp_loopstart + tri[0];
|
||||
l2 = mp_loopstart + tri[1];
|
||||
l3 = mp_loopstart + tri[2];
|
||||
|
||||
ARRAY_SET_ITEMS(mlt->tri, l1, l2, l3);
|
||||
mlt->poly = (uint)poly_index;
|
||||
|
||||
mlooptri_index++;
|
||||
}
|
||||
|
||||
BLI_memarena_clear(arena);
|
||||
}
|
||||
if (totloop < MESH_FACE_TESSELLATE_THREADED_LIMIT) {
|
||||
mesh_recalc_looptri__single_threaded(mloop, mpoly, mvert, totloop, totpoly, mlooptri, NULL);
|
||||
}
|
||||
|
||||
if (arena) {
|
||||
BLI_memarena_free(arena);
|
||||
arena = NULL;
|
||||
else {
|
||||
mesh_recalc_looptri__multi_threaded(mloop, mpoly, mvert, totloop, totpoly, mlooptri, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
BLI_assert(mlooptri_index == poly_to_tri_count(totpoly, totloop));
|
||||
UNUSED_VARS_NDEBUG(totloop);
|
||||
|
||||
#undef USE_TESSFACE_SPEEDUP
|
||||
#undef ML_TO_MLT
|
||||
/**
|
||||
* A version of #BKE_mesh_recalc_looptri which takes pre-calculated polygon normals
|
||||
* (used to avoid having to calculate the face normal for NGON tessellation).
|
||||
*
|
||||
* \note Only use this function if normals have already been calculated, there is no need
|
||||
* to calculate normals just to use this function as it will cause the normals for triangles
|
||||
* to be calculated which aren't needed for tessellation.
|
||||
*/
|
||||
void BKE_mesh_recalc_looptri_with_normals(const MLoop *mloop,
|
||||
const MPoly *mpoly,
|
||||
const MVert *mvert,
|
||||
int totloop,
|
||||
int totpoly,
|
||||
MLoopTri *mlooptri,
|
||||
const float (*poly_normals)[3])
|
||||
{
|
||||
BLI_assert(poly_normals != NULL);
|
||||
if (totloop < MESH_FACE_TESSELLATE_THREADED_LIMIT) {
|
||||
mesh_recalc_looptri__single_threaded(
|
||||
mloop, mpoly, mvert, totloop, totpoly, mlooptri, poly_normals);
|
||||
}
|
||||
else {
|
||||
mesh_recalc_looptri__multi_threaded(
|
||||
mloop, mpoly, mvert, totloop, totpoly, mlooptri, poly_normals);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -105,6 +105,11 @@ bool is_quad_flip_v3_first_third_fast(const float v1[3],
|
|||
const float v2[3],
|
||||
const float v3[3],
|
||||
const float v4[3]);
|
||||
bool is_quad_flip_v3_first_third_fast_with_normal(const float v1[3],
|
||||
const float v2[3],
|
||||
const float v3[3],
|
||||
const float v4[3],
|
||||
const float normal[3]);
|
||||
|
||||
/********************************* Distance **********************************/
|
||||
|
||||
|
|
|
@ -6218,6 +6218,19 @@ bool is_quad_flip_v3_first_third_fast(const float v1[3],
|
|||
return dot_v3v3(cross_a, cross_b) > 0.0f;
|
||||
}
|
||||
|
||||
bool is_quad_flip_v3_first_third_fast_with_normal(const float v1[3],
|
||||
const float v2[3],
|
||||
const float v3[3],
|
||||
const float v4[3],
|
||||
const float normal[3])
|
||||
{
|
||||
float dir_v3v1[3], tangent[3];
|
||||
sub_v3_v3v3(dir_v3v1, v3, v1);
|
||||
cross_v3_v3v3(tangent, dir_v3v1, normal);
|
||||
const float dot = dot_v3v3(v1, tangent);
|
||||
return (dot_v3v3(v4, tangent) >= dot) || (dot_v3v3(v2, tangent) <= dot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value which the distance between points will need to be scaled by,
|
||||
* to define a handle, given both points are on a perfect circle.
|
||||
|
|
|
@ -244,10 +244,13 @@ MINLINE int min_axis_v3(const float vec[3])
|
|||
}
|
||||
|
||||
/**
|
||||
* Simple method to find how many tri's we need when we already know the corner+poly count.
|
||||
* Simple function to either:
|
||||
* - Calculate how many triangles needed from the total number of polygons + loops.
|
||||
* - Calculate the first triangle index from the polygon index & that polygons loop-start.
|
||||
*
|
||||
* \param poly_count: The number of ngon's/tris (1-2 sided faces will give incorrect results)
|
||||
* \param corner_count: also known as loops in BMesh/DNA
|
||||
* \param poly_count: The number of polygons or polygon-index
|
||||
* (3+ sided faces, 1-2 sided give incorrect results).
|
||||
* \param corner_count: The number of corners (also called loop-index).
|
||||
*/
|
||||
MINLINE int poly_to_tri_count(const int poly_count, const int corner_count)
|
||||
{
|
||||
|
|
|
@ -95,8 +95,11 @@ BLI_INLINE void bmesh_calc_tessellation_for_face_impl(BMLoop *(*looptris)[3],
|
|||
efa->no, l_ptr_a[0]->v->co, l_ptr_a[1]->v->co, l_ptr_a[2]->v->co, l_ptr_b[2]->v->co);
|
||||
}
|
||||
|
||||
if (UNLIKELY(is_quad_flip_v3_first_third_fast(
|
||||
l_ptr_a[0]->v->co, l_ptr_a[1]->v->co, l_ptr_a[2]->v->co, l_ptr_b[2]->v->co))) {
|
||||
if (UNLIKELY(is_quad_flip_v3_first_third_fast_with_normal(l_ptr_a[0]->v->co,
|
||||
l_ptr_a[1]->v->co,
|
||||
l_ptr_a[2]->v->co,
|
||||
l_ptr_b[2]->v->co,
|
||||
efa->no))) {
|
||||
/* Flip out of degenerate 0-2 state. */
|
||||
l_ptr_a[2] = l_ptr_b[2];
|
||||
l_ptr_b[0] = l_ptr_a[1];
|
||||
|
|
|
@ -67,8 +67,8 @@ static void mesh_render_data_loose_geom_load(MeshRenderData *mr, MeshBufferExtra
|
|||
static void mesh_render_data_loose_geom_ensure(const MeshRenderData *mr,
|
||||
MeshBufferExtractionCache *cache)
|
||||
{
|
||||
/* Early exit: Are loose geometry already available. Only checking for loose verts as loose edges
|
||||
* and verts are calculated at the same time.*/
|
||||
/* Early exit: Are loose geometry already available.
|
||||
* Only checking for loose verts as loose edges and verts are calculated at the same time. */
|
||||
if (cache->loose_geom.verts) {
|
||||
return;
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ static void mesh_render_data_mat_offset_build(MeshRenderData *mr, MeshBufferExtr
|
|||
|
||||
typedef struct MatOffsetUserData {
|
||||
MeshRenderData *mr;
|
||||
/* struct is extended during allocation to hold mat_tri_len for each material. */
|
||||
/** This struct is extended during allocation to hold mat_tri_len for each material. */
|
||||
int mat_tri_len[0];
|
||||
} MatOffsetUserData;
|
||||
|
||||
|
@ -252,7 +252,7 @@ static void mesh_render_data_mat_offset_build_threaded(MeshRenderData *mr,
|
|||
int face_len,
|
||||
TaskParallelRangeFunc range_func)
|
||||
{
|
||||
/* Extending the MatOffsetUserData with an int per material slot. */
|
||||
/* Extending the #MatOffsetUserData with an int per material slot. */
|
||||
size_t userdata_size = sizeof(MatOffsetUserData) +
|
||||
(mr->mat_len) * sizeof(*cache->mat_offsets.tri);
|
||||
MatOffsetUserData *userdata = MEM_callocN(userdata_size, __func__);
|
||||
|
@ -348,9 +348,23 @@ void mesh_render_data_update_looptris(MeshRenderData *mr,
|
|||
if (mr->extract_type != MR_EXTRACT_BMESH) {
|
||||
/* Mesh */
|
||||
if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
|
||||
/* NOTE(campbell): It's possible to skip allocating tessellation,
|
||||
* the tessellation can be calculated as part of the iterator, see: P2188.
|
||||
* The overall advantage is small (around 1%), so keep this as-is. */
|
||||
mr->mlooptri = MEM_mallocN(sizeof(*mr->mlooptri) * mr->tri_len, "MR_DATATYPE_LOOPTRI");
|
||||
BKE_mesh_recalc_looptri(
|
||||
me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mr->mlooptri);
|
||||
if (mr->poly_normals != NULL) {
|
||||
BKE_mesh_recalc_looptri_with_normals(me->mloop,
|
||||
me->mpoly,
|
||||
me->mvert,
|
||||
me->totloop,
|
||||
me->totpoly,
|
||||
mr->mlooptri,
|
||||
mr->poly_normals);
|
||||
}
|
||||
else {
|
||||
BKE_mesh_recalc_looptri(
|
||||
me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mr->mlooptri);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -564,7 +578,7 @@ void mesh_render_data_free(MeshRenderData *mr)
|
|||
MEM_SAFE_FREE(mr->mlooptri);
|
||||
MEM_SAFE_FREE(mr->loop_normals);
|
||||
|
||||
/* Loose geometry are owned by MeshBufferExtractionCache. */
|
||||
/* Loose geometry are owned by #MeshBufferExtractionCache. */
|
||||
mr->ledges = NULL;
|
||||
mr->lverts = NULL;
|
||||
|
||||
|
|
|
@ -760,15 +760,15 @@ static void annotation_draw_data_all(Scene *scene,
|
|||
int winy,
|
||||
int cfra,
|
||||
int dflag,
|
||||
const char spacetype)
|
||||
const eSpace_Type space_type)
|
||||
{
|
||||
bGPdata *gpd_source = NULL;
|
||||
|
||||
if (scene) {
|
||||
if (spacetype == SPACE_VIEW3D) {
|
||||
if (space_type == SPACE_VIEW3D) {
|
||||
gpd_source = (scene->gpd ? scene->gpd : NULL);
|
||||
}
|
||||
else if (spacetype == SPACE_CLIP && scene->clip) {
|
||||
else if (space_type == SPACE_CLIP && scene->clip) {
|
||||
/* currently drawing only gpencil data from either clip or track,
|
||||
* but not both - XXX fix logic behind */
|
||||
gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL);
|
||||
|
|
|
@ -68,7 +68,7 @@ static ScrArea *screen_addarea_ex(ScrAreaMap *area_map,
|
|||
ScrVert *top_left,
|
||||
ScrVert *top_right,
|
||||
ScrVert *bottom_right,
|
||||
short spacetype)
|
||||
const eSpace_Type space_type)
|
||||
{
|
||||
ScrArea *area = MEM_callocN(sizeof(ScrArea), "addscrarea");
|
||||
|
||||
|
@ -76,7 +76,7 @@ static ScrArea *screen_addarea_ex(ScrAreaMap *area_map,
|
|||
area->v2 = top_left;
|
||||
area->v3 = top_right;
|
||||
area->v4 = bottom_right;
|
||||
area->spacetype = spacetype;
|
||||
area->spacetype = space_type;
|
||||
|
||||
BLI_addtail(&area_map->areabase, area);
|
||||
|
||||
|
@ -87,10 +87,10 @@ static ScrArea *screen_addarea(bScreen *screen,
|
|||
ScrVert *left_top,
|
||||
ScrVert *right_top,
|
||||
ScrVert *right_bottom,
|
||||
short spacetype)
|
||||
const eSpace_Type space_type)
|
||||
{
|
||||
return screen_addarea_ex(
|
||||
AREAMAP_FROM_SCREEN(screen), left_bottom, left_top, right_top, right_bottom, spacetype);
|
||||
AREAMAP_FROM_SCREEN(screen), left_bottom, left_top, right_top, right_bottom, space_type);
|
||||
}
|
||||
|
||||
static void screen_delarea(bContext *C, bScreen *screen, ScrArea *area)
|
||||
|
@ -972,7 +972,7 @@ int ED_screen_area_active(const bContext *C)
|
|||
*/
|
||||
static ScrArea *screen_area_create_with_geometry(ScrAreaMap *area_map,
|
||||
const rcti *rect,
|
||||
short spacetype)
|
||||
eSpace_Type space_type)
|
||||
{
|
||||
ScrVert *bottom_left = screen_geom_vertex_add_ex(area_map, rect->xmin, rect->ymin);
|
||||
ScrVert *top_left = screen_geom_vertex_add_ex(area_map, rect->xmin, rect->ymax);
|
||||
|
@ -984,7 +984,7 @@ static ScrArea *screen_area_create_with_geometry(ScrAreaMap *area_map,
|
|||
screen_geom_edge_add_ex(area_map, top_right, bottom_right);
|
||||
screen_geom_edge_add_ex(area_map, bottom_right, bottom_left);
|
||||
|
||||
return screen_addarea_ex(area_map, bottom_left, top_left, top_right, bottom_right, spacetype);
|
||||
return screen_addarea_ex(area_map, bottom_left, top_left, top_right, bottom_right, space_type);
|
||||
}
|
||||
|
||||
static void screen_area_set_geometry_rect(ScrArea *area, const rcti *rect)
|
||||
|
@ -1001,7 +1001,7 @@ static void screen_area_set_geometry_rect(ScrArea *area, const rcti *rect)
|
|||
|
||||
static void screen_global_area_refresh(wmWindow *win,
|
||||
bScreen *screen,
|
||||
eSpace_Type space_type,
|
||||
const eSpace_Type space_type,
|
||||
GlobalAreaAlign align,
|
||||
const rcti *rect,
|
||||
const short height_cur,
|
||||
|
|
|
@ -355,7 +355,7 @@ static void seq_transform_update_effects(TransInfo *t, SeqCollection *collection
|
|||
Sequence *seq;
|
||||
SEQ_ITERATOR_FOREACH (seq, collection) {
|
||||
if ((seq->type & SEQ_TYPE_EFFECT) && (seq->seq1 || seq->seq2 || seq->seq3)) {
|
||||
SEQ_time_update_sequence(t->scene, seq);
|
||||
SEQ_time_update_sequence(t->scene, seq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,7 +177,11 @@ const EnumPropertyItem rna_enum_space_graph_mode_items[] = {
|
|||
const EnumPropertyItem rna_enum_space_sequencer_view_type_items[] = {
|
||||
{SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""},
|
||||
{SEQ_VIEW_PREVIEW, "PREVIEW", ICON_SEQ_PREVIEW, "Preview", ""},
|
||||
{SEQ_VIEW_SEQUENCE_PREVIEW, "SEQUENCER_PREVIEW", ICON_SEQ_SPLITVIEW, "Sequencer & Preview", ""},
|
||||
{SEQ_VIEW_SEQUENCE_PREVIEW,
|
||||
"SEQUENCER_PREVIEW",
|
||||
ICON_SEQ_SPLITVIEW,
|
||||
"Sequencer & Preview",
|
||||
""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
|
|
|
@ -466,7 +466,16 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
|
|||
looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
|
||||
triangles = MEM_callocN(sizeof(TriTessFace) * tottri, __func__);
|
||||
|
||||
BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
|
||||
const float(*precomputed_normals)[3] = CustomData_get_layer(&me->pdata, CD_NORMAL);
|
||||
const bool calculate_normal = precomputed_normals ? false : true;
|
||||
|
||||
if (precomputed_normals != NULL) {
|
||||
BKE_mesh_recalc_looptri_with_normals(
|
||||
me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri, precomputed_normals);
|
||||
}
|
||||
else {
|
||||
BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
|
||||
}
|
||||
|
||||
if (tangent) {
|
||||
BKE_mesh_ensure_normals_for_display(me_eval);
|
||||
|
@ -479,9 +488,6 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
|
|||
loop_normals = CustomData_get_layer(&me_eval->ldata, CD_NORMAL);
|
||||
}
|
||||
|
||||
const float(*precomputed_normals)[3] = CustomData_get_layer(&me->pdata, CD_NORMAL);
|
||||
const bool calculate_normal = precomputed_normals ? false : true;
|
||||
|
||||
for (i = 0; i < tottri; i++) {
|
||||
const MLoopTri *lt = &looptri[i];
|
||||
const MPoly *mp = &me->mpoly[lt->poly];
|
||||
|
|
Loading…
Reference in New Issue