Geometry Nodes: Avoid index lookup from index mask #109174
|
@ -79,6 +79,7 @@ typedef hiprtError(thiprtSetFuncTable)(hiprtContext context,
|
|||
hiprtFuncDataSet set);
|
||||
typedef hiprtError(thiprtDestroyFuncTable)(hiprtContext context,
|
||||
hiprtFuncTable funcTable);
|
||||
typedef void(thiprtSetLogLevel)( hiprtLogLevel level );
|
||||
|
||||
/* Function declarations. */
|
||||
extern thiprtCreateContext *hiprtCreateContext;
|
||||
|
@ -94,6 +95,7 @@ extern thiprtGetSceneBuildTemporaryBufferSize *hiprtGetSceneBuildTemporaryBuffer
|
|||
extern thiprtCreateFuncTable *hiprtCreateFuncTable;
|
||||
extern thiprtSetFuncTable *hiprtSetFuncTable;
|
||||
extern thiprtDestroyFuncTable *hiprtDestroyFuncTable;
|
||||
extern thiprtSetLogLevel *hiprtSetLogLevel;
|
||||
|
||||
/* HIPEW API. */
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ thiprtGetSceneBuildTemporaryBufferSize *hiprtGetSceneBuildTemporaryBufferSize;
|
|||
thiprtCreateFuncTable *hiprtCreateFuncTable;
|
||||
thiprtSetFuncTable *hiprtSetFuncTable;
|
||||
thiprtDestroyFuncTable *hiprtDestroyFuncTable;
|
||||
thiprtSetLogLevel *hiprtSetLogLevel;
|
||||
|
||||
static void hipewHipRtExit(void)
|
||||
{
|
||||
|
@ -89,6 +90,7 @@ bool hiprtewInit()
|
|||
HIPRT_LIBRARY_FIND(hiprtCreateFuncTable)
|
||||
HIPRT_LIBRARY_FIND(hiprtSetFuncTable)
|
||||
HIPRT_LIBRARY_FIND(hiprtDestroyFuncTable)
|
||||
HIPRT_LIBRARY_FIND(hiprtSetLogLevel)
|
||||
|
||||
result = true;
|
||||
#endif
|
||||
|
|
|
@ -96,6 +96,8 @@ HIPRTDevice::HIPRTDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
|
|||
set_error(string_printf("Failed to create HIPRT Function Table"));
|
||||
return;
|
||||
}
|
||||
|
||||
hiprtSetLogLevel(hiprtLogLevelNone);
|
||||
}
|
||||
|
||||
HIPRTDevice::~HIPRTDevice()
|
||||
|
@ -261,8 +263,7 @@ string HIPRTDevice::compile_kernel(const uint kernel_features, const char *name,
|
|||
linker_options.append(" --offload-arch=").append(arch);
|
||||
linker_options.append(" -fgpu-rdc --hip-link --cuda-device-only ");
|
||||
string hiprt_ver(HIPRT_VERSION_STR);
|
||||
string hiprt_bc;
|
||||
hiprt_bc = hiprt_path + "\\hiprt" + hiprt_ver + "_amd_lib_win.bc";
|
||||
string hiprt_bc = hiprt_path + "\\dist\\bin\\Release\\hiprt" + hiprt_ver + "_amd_lib_win.bc";
|
||||
|
||||
string linker_command = string_printf("clang++ %s \"%s\" %s -o \"%s\"",
|
||||
linker_options.c_str(),
|
||||
|
|
|
@ -61,6 +61,8 @@ bool HIPRTDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
0),
|
||||
"enqueue");
|
||||
|
||||
debug_enqueue_end();
|
||||
|
||||
return !(hiprt_device_->have_error());
|
||||
}
|
||||
|
||||
|
|
|
@ -46,11 +46,11 @@ ccl_device_intersect bool scene_intersect(KernelGlobals kg,
|
|||
GET_TRAVERSAL_STACK()
|
||||
|
||||
if (visibility & PATH_RAY_SHADOW_OPAQUE) {
|
||||
GET_TRAVERSAL_ANY_HIT(table_closest_intersect, 0)
|
||||
GET_TRAVERSAL_ANY_HIT(table_closest_intersect, 0, ray->time)
|
||||
hit = traversal.getNextHit();
|
||||
}
|
||||
else {
|
||||
GET_TRAVERSAL_CLOSEST_HIT(table_closest_intersect, 0)
|
||||
GET_TRAVERSAL_CLOSEST_HIT(table_closest_intersect, 0, ray->time)
|
||||
hit = traversal.getNextHit();
|
||||
}
|
||||
if (hit.hasHit()) {
|
||||
|
@ -157,13 +157,13 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals kg,
|
|||
payload.in_state = state;
|
||||
payload.max_hits = max_hits;
|
||||
payload.visibility = visibility;
|
||||
payload.prim_type = PRIMITIVE_TRIANGLE;
|
||||
payload.prim_type = PRIMITIVE_NONE;
|
||||
payload.ray_time = ray->time;
|
||||
payload.num_hits = 0;
|
||||
payload.r_num_recorded_hits = num_recorded_hits;
|
||||
payload.r_throughput = throughput;
|
||||
GET_TRAVERSAL_STACK()
|
||||
GET_TRAVERSAL_ANY_HIT(table_shadow_intersect, 1)
|
||||
GET_TRAVERSAL_ANY_HIT(table_shadow_intersect, 1, ray->time)
|
||||
hiprtHit hit = traversal.getNextHit();
|
||||
num_recorded_hits = payload.r_num_recorded_hits;
|
||||
throughput = payload.r_throughput;
|
||||
|
@ -201,7 +201,7 @@ ccl_device_intersect bool scene_intersect_volume(KernelGlobals kg,
|
|||
|
||||
GET_TRAVERSAL_STACK()
|
||||
|
||||
GET_TRAVERSAL_CLOSEST_HIT(table_volume_intersect, 3)
|
||||
GET_TRAVERSAL_CLOSEST_HIT(table_volume_intersect, 3, ray->time)
|
||||
hiprtHit hit = traversal.getNextHit();
|
||||
// return hit.hasHit();
|
||||
if (hit.hasHit()) {
|
||||
|
|
|
@ -53,7 +53,7 @@ struct LocalPayload {
|
|||
# endif
|
||||
|
||||
# ifdef HIPRT_SHARED_STACK
|
||||
# define GET_TRAVERSAL_ANY_HIT(FUNCTION_TABLE, RAY_TYPE) \
|
||||
# define GET_TRAVERSAL_ANY_HIT(FUNCTION_TABLE, RAY_TYPE, RAY_TIME) \
|
||||
hiprtSceneTraversalAnyHitCustomStack<Stack> traversal(kernel_data.device_bvh, \
|
||||
ray_hip, \
|
||||
stack, \
|
||||
|
@ -61,10 +61,10 @@ struct LocalPayload {
|
|||
hiprtTraversalHintDefault, \
|
||||
&payload, \
|
||||
kernel_params.FUNCTION_TABLE, \
|
||||
RAY_TYPE); \
|
||||
hiprtSceneTraversalAnyHitCustomStack<Stack> traversal_simple( \
|
||||
kernel_data.device_bvh, ray_hip, stack, visibility);
|
||||
# define GET_TRAVERSAL_CLOSEST_HIT(FUNCTION_TABLE, RAY_TYPE) \
|
||||
RAY_TYPE, \
|
||||
RAY_TIME);
|
||||
|
||||
# define GET_TRAVERSAL_CLOSEST_HIT(FUNCTION_TABLE, RAY_TYPE, RAY_TIME) \
|
||||
hiprtSceneTraversalClosestCustomStack<Stack> traversal(kernel_data.device_bvh, \
|
||||
ray_hip, \
|
||||
stack, \
|
||||
|
@ -72,9 +72,8 @@ struct LocalPayload {
|
|||
hiprtTraversalHintDefault, \
|
||||
&payload, \
|
||||
kernel_params.FUNCTION_TABLE, \
|
||||
RAY_TYPE); \
|
||||
hiprtSceneTraversalClosestCustomStack<Stack> traversal_simple( \
|
||||
kernel_data.device_bvh, ray_hip, stack, visibility);
|
||||
RAY_TYPE, \
|
||||
RAY_TIME);
|
||||
# else
|
||||
# define GET_TRAVERSAL_ANY_HIT(FUNCTION_TABLE) \
|
||||
hiprtSceneTraversalAnyHit traversal(kernel_data.device_bvh, \
|
||||
|
@ -82,16 +81,14 @@ struct LocalPayload {
|
|||
visibility, \
|
||||
FUNCTION_TABLE, \
|
||||
hiprtTraversalHintDefault, \
|
||||
&payload); \
|
||||
hiprtSceneTraversalAnyHit traversal_simple(kernel_data.device_bvh, ray_hip, visibility);
|
||||
&payload);
|
||||
# define GET_TRAVERSAL_CLOSEST_HIT(FUNCTION_TABLE) \
|
||||
hiprtSceneTraversalClosest traversal(kernel_data.device_bvh, \
|
||||
ray_hip, \
|
||||
visibility, \
|
||||
FUNCTION_TABLE, \
|
||||
hiprtTraversalHintDefault, \
|
||||
&payload); \
|
||||
hiprtSceneTraversalClosest traversal_simple(kernel_data.device_bvh, ray_hip, visibility);
|
||||
&payload);
|
||||
# endif
|
||||
|
||||
ccl_device_inline void set_intersect_point(KernelGlobals kg,
|
||||
|
|
|
@ -2217,7 +2217,9 @@ def km_animation_channels(params):
|
|||
items.extend([
|
||||
# Click select.
|
||||
("anim.channels_click", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
|
||||
("anim.channels_click", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
("anim.channels_click", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True},
|
||||
{"properties": [("extend_range", True)]}),
|
||||
("anim.channels_click", {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True},
|
||||
{"properties": [("extend", True)]}),
|
||||
("anim.channels_click", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
|
||||
{"properties": [("children_only", True)]}),
|
||||
|
|
|
@ -206,7 +206,7 @@ typedef struct GlyphBLF {
|
|||
|
||||
/**
|
||||
* X and Y bearing of the glyph.
|
||||
* The X bearing is from the origin to the glyph left bbox edge.
|
||||
* The X bearing is from the origin to the glyph left bounding-box edge.
|
||||
* The Y bearing is from the baseline to the top of the glyph edge.
|
||||
*/
|
||||
int pos[2];
|
||||
|
|
|
@ -930,7 +930,7 @@ void gather_attributes(AttributeAccessor src_attributes,
|
|||
MutableAttributeAccessor dst_attributes);
|
||||
|
||||
/**
|
||||
* Copy attribute values from groups groups defined by \a src_offsets to groups defined by \a
|
||||
* Copy attribute values from groups defined by \a src_offsets to groups defined by \a
|
||||
* dst_offsets. The group indices are gathered to the result by \a selection. The size of each
|
||||
* source and result group must be the same.
|
||||
*/
|
||||
|
|
|
@ -71,8 +71,7 @@ class Layer;
|
|||
/**
|
||||
* A TreeNode represents one node in the layer tree.
|
||||
* It can either be a layer or a group. The node has zero children if it is a layer or zero or
|
||||
more
|
||||
* children if it is a group.
|
||||
* more children if it is a group.
|
||||
*/
|
||||
class TreeNode : public ::GreasePencilLayerTreeNode {
|
||||
public:
|
||||
|
|
|
@ -93,13 +93,15 @@ void normals_calc_poly_vert(Span<float3> vert_positions,
|
|||
* a regular #float3 format.
|
||||
*/
|
||||
struct CornerNormalSpace {
|
||||
/** Reference vector, orthogonal to corner normal. */
|
||||
/** The automatically computed face corner normal, not including influence of custom normals. */
|
||||
float3 vec_lnor;
|
||||
/** Reference vector, orthogonal to #vec_lnor. */
|
||||
float3 vec_ref;
|
||||
/** Third vector, orthogonal to corner normal and #vec_ref. */
|
||||
/** Third vector, orthogonal to #vec_lnor and #vec_ref. */
|
||||
float3 vec_ortho;
|
||||
/** Reference angle around #vec_ortho, in [0, pi] range (0.0 marks space as invalid). */
|
||||
float ref_alpha;
|
||||
/** Reference angle around corner normal, in [0, 2pi] range (0.0 marks space as invalid). */
|
||||
/** Reference angle around #vec_lnor, in [0, 2pi] range (0.0 marks space as invalid). */
|
||||
float ref_beta;
|
||||
};
|
||||
|
||||
|
@ -131,7 +133,6 @@ struct CornerNormalSpaceArray {
|
|||
};
|
||||
|
||||
void lnor_space_custom_normal_to_data(const CornerNormalSpace *lnor_space,
|
||||
float3 lnor_no_custom,
|
||||
const float custom_lnor[3],
|
||||
short r_clnor_data[2]);
|
||||
|
||||
|
|
|
@ -219,11 +219,13 @@ static void setup_app_userdef(BlendFileData *bfd)
|
|||
}
|
||||
}
|
||||
|
||||
/** Helper struct to manage IDs that are re-used across blendfile loading (i.e. moved from the old
|
||||
* Main the the new one).
|
||||
/**
|
||||
* Helper struct to manage IDs that are re-used across blend-file loading (i.e. moved from the old
|
||||
* Main the new one).
|
||||
*
|
||||
* NOTE: this is only used when actually loading a real .blend file, loading of memfile undo steps
|
||||
* does not need it. */
|
||||
* NOTE: this is only used when actually loading a real `.blend` file,
|
||||
* loading of memfile undo steps does not need it.
|
||||
*/
|
||||
typedef struct ReuseOldBMainData {
|
||||
Main *new_bmain;
|
||||
Main *old_bmain;
|
||||
|
|
|
@ -432,15 +432,12 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
|||
mirrorj += result_polys[mirror_i].size() - (j - src_poly.start());
|
||||
}
|
||||
|
||||
const blender::float3 orig_normal = loop_normals[mirrorj];
|
||||
copy_v3_v3(loop_normals[mirrorj], loop_normals[j]);
|
||||
mul_m4_v3(mtx_nor, loop_normals[mirrorj]);
|
||||
|
||||
const int space_index = lnors_spacearr.corner_space_indices[mirrorj];
|
||||
blender::bke::mesh::lnor_space_custom_normal_to_data(&lnors_spacearr.spaces[space_index],
|
||||
orig_normal,
|
||||
loop_normals[mirrorj],
|
||||
clnors[mirrorj]);
|
||||
blender::bke::mesh::lnor_space_custom_normal_to_data(
|
||||
&lnors_spacearr.spaces[space_index], loop_normals[mirrorj], clnors[mirrorj]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -472,6 +472,8 @@ static void lnor_space_define(CornerNormalSpace *lnor_space,
|
|||
return;
|
||||
}
|
||||
|
||||
lnor_space->vec_lnor = lnor;
|
||||
|
||||
/* Compute ref alpha, average angle of all available edge vectors to lnor. */
|
||||
if (!edge_vectors.is_empty()) {
|
||||
float alpha = 0.0f;
|
||||
|
@ -526,7 +528,7 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
|
|||
using namespace blender::bke::mesh;
|
||||
CornerNormalSpace space{};
|
||||
lnor_space_define(&space, lnor, vec_ref, vec_other, edge_vectors);
|
||||
copy_v3_v3(lnor_space->vec_lnor, lnor);
|
||||
copy_v3_v3(lnor_space->vec_lnor, space.vec_lnor);
|
||||
copy_v3_v3(lnor_space->vec_ref, space.vec_ref);
|
||||
copy_v3_v3(lnor_space->vec_ortho, space.vec_ortho);
|
||||
lnor_space->ref_alpha = space.ref_alpha;
|
||||
|
@ -570,13 +572,12 @@ MINLINE short unit_float_to_short(const float val)
|
|||
|
||||
namespace blender::bke::mesh {
|
||||
static void lnor_space_custom_data_to_normal(const CornerNormalSpace *lnor_space,
|
||||
const float3 lnor_no_custom,
|
||||
const short clnor_data[2],
|
||||
float r_custom_lnor[3])
|
||||
{
|
||||
/* NOP custom normal data or invalid lnor space, return. */
|
||||
if (clnor_data[0] == 0 || lnor_space->ref_alpha == 0.0f || lnor_space->ref_beta == 0.0f) {
|
||||
copy_v3_v3(r_custom_lnor, lnor_no_custom);
|
||||
copy_v3_v3(r_custom_lnor, lnor_space->vec_lnor);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -589,7 +590,7 @@ static void lnor_space_custom_data_to_normal(const CornerNormalSpace *lnor_space
|
|||
alphafac;
|
||||
const float betafac = unit_short_to_float(clnor_data[1]);
|
||||
|
||||
mul_v3_v3fl(r_custom_lnor, lnor_no_custom, cosf(alpha));
|
||||
mul_v3_v3fl(r_custom_lnor, lnor_space->vec_lnor, cosf(alpha));
|
||||
|
||||
if (betafac == 0.0f) {
|
||||
madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinf(alpha));
|
||||
|
@ -611,29 +612,29 @@ void BKE_lnor_space_custom_data_to_normal(const MLoopNorSpace *lnor_space,
|
|||
{
|
||||
using namespace blender::bke::mesh;
|
||||
CornerNormalSpace space;
|
||||
space.vec_lnor = lnor_space->vec_lnor;
|
||||
space.vec_ref = lnor_space->vec_ref;
|
||||
space.vec_ortho = lnor_space->vec_ortho;
|
||||
space.ref_alpha = lnor_space->ref_alpha;
|
||||
space.ref_beta = lnor_space->ref_beta;
|
||||
lnor_space_custom_data_to_normal(&space, lnor_space->vec_lnor, clnor_data, r_custom_lnor);
|
||||
lnor_space_custom_data_to_normal(&space, clnor_data, r_custom_lnor);
|
||||
}
|
||||
|
||||
namespace blender::bke::mesh {
|
||||
void lnor_space_custom_normal_to_data(const CornerNormalSpace *lnor_space,
|
||||
const float3 lnor_no_custom,
|
||||
const float custom_lnor[3],
|
||||
short r_clnor_data[2])
|
||||
{
|
||||
/* We use nullptr vector as NOP custom normal (can be simpler than giving auto-computed `lnor`).
|
||||
*/
|
||||
if (is_zero_v3(custom_lnor) || compare_v3v3(lnor_no_custom, custom_lnor, 1e-4f)) {
|
||||
if (is_zero_v3(custom_lnor) || compare_v3v3(lnor_space->vec_lnor, custom_lnor, 1e-4f)) {
|
||||
r_clnor_data[0] = r_clnor_data[1] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
const float pi2 = float(M_PI * 2.0);
|
||||
const float cos_alpha = dot_v3v3(lnor_no_custom, custom_lnor);
|
||||
const float cos_alpha = dot_v3v3(lnor_space->vec_lnor, custom_lnor);
|
||||
float vec[3], cos_beta;
|
||||
float alpha;
|
||||
|
||||
|
@ -648,7 +649,7 @@ void lnor_space_custom_normal_to_data(const CornerNormalSpace *lnor_space,
|
|||
}
|
||||
|
||||
/* Project custom lnor on (vec_ref, vec_ortho) plane. */
|
||||
mul_v3_v3fl(vec, lnor_no_custom, -cos_alpha);
|
||||
mul_v3_v3fl(vec, lnor_space->vec_lnor, -cos_alpha);
|
||||
add_v3_v3(vec, custom_lnor);
|
||||
normalize_v3(vec);
|
||||
|
||||
|
@ -680,11 +681,12 @@ void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space,
|
|||
{
|
||||
using namespace blender::bke::mesh;
|
||||
CornerNormalSpace space;
|
||||
space.vec_lnor = lnor_space->vec_lnor;
|
||||
space.vec_ref = lnor_space->vec_ref;
|
||||
space.vec_ortho = lnor_space->vec_ortho;
|
||||
space.ref_alpha = lnor_space->ref_alpha;
|
||||
space.ref_beta = lnor_space->ref_beta;
|
||||
lnor_space_custom_normal_to_data(&space, lnor_space->vec_lnor, custom_lnor, r_clnor_data);
|
||||
lnor_space_custom_normal_to_data(&space, custom_lnor, r_clnor_data);
|
||||
}
|
||||
|
||||
namespace blender::bke::mesh {
|
||||
|
@ -901,10 +903,8 @@ static void lnor_space_for_single_fan(LoopSplitTaskDataCommon *common_data,
|
|||
lnors_spacearr->corner_space_indices[ml_curr_index] = space_index;
|
||||
|
||||
if (!clnors_data.is_empty()) {
|
||||
lnor_space_custom_data_to_normal(lnor_space,
|
||||
loop_normals[ml_curr_index],
|
||||
clnors_data[ml_curr_index],
|
||||
loop_normals[ml_curr_index]);
|
||||
lnor_space_custom_data_to_normal(
|
||||
lnor_space, clnors_data[ml_curr_index], loop_normals[ml_curr_index]);
|
||||
}
|
||||
|
||||
if (!lnors_spacearr->corners_by_space.is_empty()) {
|
||||
|
@ -1084,7 +1084,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
|||
/* Extra bonus: since small-stack is local to this function,
|
||||
* no more need to empty it at all cost! */
|
||||
|
||||
lnor_space_custom_data_to_normal(lnor_space, lnor, *clnor_ref, lnor);
|
||||
lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1600,8 +1600,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
float *nor = r_custom_loop_normals[nidx];
|
||||
|
||||
const int space_index = lnors_spacearr.corner_space_indices[i];
|
||||
lnor_space_custom_normal_to_data(
|
||||
&lnors_spacearr.spaces[space_index], loop_normals[i], nor, r_clnors_data[i]);
|
||||
lnor_space_custom_normal_to_data(&lnors_spacearr.spaces[space_index], nor, r_clnors_data[i]);
|
||||
done_loops[i].reset();
|
||||
}
|
||||
else {
|
||||
|
@ -1618,7 +1617,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
mul_v3_fl(avg_nor, 1.0f / float(fan_corners.size()));
|
||||
short2 clnor_data_tmp;
|
||||
lnor_space_custom_normal_to_data(
|
||||
&lnors_spacearr.spaces[space_index], loop_normals[i], avg_nor, clnor_data_tmp);
|
||||
&lnors_spacearr.spaces[space_index], avg_nor, clnor_data_tmp);
|
||||
|
||||
r_clnors_data.fill_indices(fan_corners, clnor_data_tmp);
|
||||
}
|
||||
|
|
|
@ -746,6 +746,15 @@ template<typename T> class MutableSpan {
|
|||
return counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a constant time check to see if the pointer points to a value in the referenced array.
|
||||
* Return true if it is, otherwise false.
|
||||
*/
|
||||
constexpr bool contains_ptr(const T *ptr) const
|
||||
{
|
||||
return (this->begin() <= ptr) && (ptr < this->end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all values from another span into this span. This invokes undefined behavior when the
|
||||
* destination contains uninitialized data and T is not trivially copy constructible.
|
||||
|
|
|
@ -1086,9 +1086,8 @@ uint BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float n
|
|||
for (a = 0; a < poly; a++, pf++) {
|
||||
for (c = (ushort)(a + 1); c < poly; c++) {
|
||||
|
||||
/* if 'a' inside 'c': join (bbox too)
|
||||
* Careful: 'a' can also be inside another poly.
|
||||
*/
|
||||
/* If 'a' inside 'c': join (bounding-box too)
|
||||
* Careful: 'a' can also be inside another poly. */
|
||||
if (boundisect(pf, pflist + c)) {
|
||||
*pc = c;
|
||||
pc++;
|
||||
|
|
|
@ -519,13 +519,13 @@ static void do_versions_nodetree_customnodes(bNodeTree *ntree, int UNUSED(is_gro
|
|||
/* tree type idname */
|
||||
switch (ntree->type) {
|
||||
case NTREE_COMPOSIT:
|
||||
strcpy(ntree->idname, "CompositorNodeTree");
|
||||
STRNCPY(ntree->idname, "CompositorNodeTree");
|
||||
break;
|
||||
case NTREE_SHADER:
|
||||
strcpy(ntree->idname, "ShaderNodeTree");
|
||||
STRNCPY(ntree->idname, "ShaderNodeTree");
|
||||
break;
|
||||
case NTREE_TEXTURE:
|
||||
strcpy(ntree->idname, "TextureNodeTree");
|
||||
STRNCPY(ntree->idname, "TextureNodeTree");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1732,13 +1732,13 @@ if (!MAIN_VERSION_ATLEAST(bmain, 266, 2)) {
|
|||
/* convert deprecated treetype setting to tree_idname */
|
||||
switch (snode->treetype) {
|
||||
case NTREE_COMPOSIT:
|
||||
strcpy(snode->tree_idname, "CompositorNodeTree");
|
||||
STRNCPY(snode->tree_idname, "CompositorNodeTree");
|
||||
break;
|
||||
case NTREE_SHADER:
|
||||
strcpy(snode->tree_idname, "ShaderNodeTree");
|
||||
STRNCPY(snode->tree_idname, "ShaderNodeTree");
|
||||
break;
|
||||
case NTREE_TEXTURE:
|
||||
strcpy(snode->tree_idname, "TextureNodeTree");
|
||||
STRNCPY(snode->tree_idname, "TextureNodeTree");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,8 +54,8 @@
|
|||
* - write #BLO_CODE_GLOB (#FileGlobal struct) (some global vars).
|
||||
* - write #BLO_CODE_DNA1 (#SDNA struct)
|
||||
* - write #BLO_CODE_USER (#UserDef struct) for file paths:
|
||||
- #BLENDER_STARTUP_FILE (on UNIX `~/.config/blender/X.X/config/startup.blend`).
|
||||
- #BLENDER_USERPREF_FILE (on UNIX `~/.config/blender/X.X/config/userpref.blend`).
|
||||
* - #BLENDER_STARTUP_FILE (on UNIX `~/.config/blender/X.X/config/startup.blend`).
|
||||
* - #BLENDER_USERPREF_FILE (on UNIX `~/.config/blender/X.X/config/userpref.blend`).
|
||||
*/
|
||||
|
||||
#include <cerrno>
|
||||
|
|
|
@ -440,7 +440,7 @@ BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l)
|
|||
{
|
||||
BMLoop *l_other;
|
||||
|
||||
// BLI_assert(BM_edge_is_manifold(e)); // TOO strict, just check if we have another radial face
|
||||
// BLI_assert(BM_edge_is_manifold(e)); /* Too strict, just check there is another radial face. */
|
||||
BLI_assert(e->l && e->l->radial_next != e->l);
|
||||
BLI_assert(BM_vert_in_edge(e, l->v));
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ set(GLSL_SRC
|
|||
shaders/compositor_blur_variable_size.glsl
|
||||
shaders/compositor_bokeh_image.glsl
|
||||
shaders/compositor_box_mask.glsl
|
||||
shaders/compositor_compute_preview.glsl
|
||||
shaders/compositor_convert.glsl
|
||||
shaders/compositor_despeckle.glsl
|
||||
shaders/compositor_directional_blur.glsl
|
||||
|
@ -226,6 +227,7 @@ set(SRC_SHADER_CREATE_INFOS
|
|||
shaders/infos/compositor_blur_variable_size_info.hh
|
||||
shaders/infos/compositor_bokeh_image_info.hh
|
||||
shaders/infos/compositor_box_mask_info.hh
|
||||
shaders/infos/compositor_compute_preview_info.hh
|
||||
shaders/infos/compositor_convert_info.hh
|
||||
shaders/infos/compositor_despeckle_info.hh
|
||||
shaders/infos/compositor_directional_blur_info.hh
|
||||
|
|
|
@ -42,6 +42,9 @@ class Context {
|
|||
public:
|
||||
Context(TexturePool &texture_pool);
|
||||
|
||||
/* Get the compositing scene. */
|
||||
virtual const Scene &get_scene() const = 0;
|
||||
|
||||
/* Get the node tree used for compositing. */
|
||||
virtual const bNodeTree &get_node_tree() const = 0;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "COM_context.hh"
|
||||
#include "COM_operation.hh"
|
||||
#include "COM_result.hh"
|
||||
#include "COM_scheduler.hh"
|
||||
|
||||
namespace blender::realtime_compositor {
|
||||
|
@ -44,6 +45,12 @@ class NodeOperation : public Operation {
|
|||
void compute_results_reference_counts(const Schedule &schedule);
|
||||
|
||||
protected:
|
||||
/* Compute a preview for the operation and set to the bNodePreview of the node. This is only done
|
||||
* for nodes which enables previews, are not hidden, and are part of the active node context. The
|
||||
* preview is computed as a lower resolution version of the output of the get_preview_result
|
||||
* method. */
|
||||
void compute_preview() override;
|
||||
|
||||
/* Returns a reference to the derived node that this operation represents. */
|
||||
const DNode &node() const;
|
||||
|
||||
|
@ -53,6 +60,17 @@ class NodeOperation : public Operation {
|
|||
/* Returns true if the output identified by the given identifier is needed and should be
|
||||
* computed, otherwise returns false. */
|
||||
bool should_compute_output(StringRef identifier);
|
||||
|
||||
private:
|
||||
/* Get the result which will be previewed in the node, this is chosen as the first linked output
|
||||
* of the node, if no outputs exist, then the first allocated input will be chosen. Nullptr is
|
||||
* guaranteed not to be returned, since the node will always either have a linked output or an
|
||||
* allocated input. */
|
||||
Result *get_preview_result();
|
||||
|
||||
/* Resize the give input result to the given preview size and set it to the preview buffer after
|
||||
* applying the necessary color management processor.*/
|
||||
void write_preview_from_result(bNodePreview &preview, Result &input_result);
|
||||
};
|
||||
|
||||
} // namespace blender::realtime_compositor
|
||||
|
|
|
@ -130,6 +130,10 @@ class Operation {
|
|||
* output results. */
|
||||
virtual void execute() = 0;
|
||||
|
||||
/* Compute and set a preview of the operation if needed. This method defaults to an empty
|
||||
* implementation and should be implemented by operations which can have previews. */
|
||||
virtual void compute_preview();
|
||||
|
||||
/* Get a reference to the result connected to the input identified by the given identifier. */
|
||||
Result &get_input(StringRef identifier) const;
|
||||
|
||||
|
|
|
@ -4,15 +4,29 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
#include "BLI_assert.h"
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_math_base.hh"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "IMB_colormanagement.h"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
#include "NOD_derived_node_tree.hh"
|
||||
#include "NOD_node_declaration.hh"
|
||||
|
||||
#include "BKE_node.h"
|
||||
|
||||
#include "COM_context.hh"
|
||||
#include "COM_input_descriptor.hh"
|
||||
#include "COM_node_operation.hh"
|
||||
|
@ -39,6 +53,126 @@ NodeOperation::NodeOperation(Context &context, DNode node) : Operation(context),
|
|||
}
|
||||
}
|
||||
|
||||
/* Given the size of a result, compute a lower resolution size for a preview. The greater dimension
|
||||
* will be assigned an arbitrarily chosen size of 128, while the other dimension will get the size
|
||||
* that maintains the same aspect ratio. */
|
||||
static int2 compute_preview_size(int2 size)
|
||||
{
|
||||
const int greater_dimension_size = 128;
|
||||
if (size.x > size.y) {
|
||||
return int2(greater_dimension_size, int(greater_dimension_size * (float(size.y) / size.x)));
|
||||
}
|
||||
else {
|
||||
return int2(int(greater_dimension_size * (float(size.x) / size.y)), greater_dimension_size);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeOperation::compute_preview()
|
||||
{
|
||||
if (!(node()->flag & NODE_PREVIEW)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node()->flag & NODE_HIDDEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only compute previews for nodes in the active context. */
|
||||
if (node().context()->instance_key().value !=
|
||||
node().context()->derived_tree().active_context().instance_key().value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize node tree previews if not already initialized. */
|
||||
bNodeTree *root_tree = const_cast<bNodeTree *>(
|
||||
&node().context()->derived_tree().root_context().btree());
|
||||
if (!root_tree->previews) {
|
||||
root_tree->previews = BKE_node_instance_hash_new("node previews");
|
||||
}
|
||||
|
||||
Result *preview_result = get_preview_result();
|
||||
const int2 preview_size = compute_preview_size(preview_result->domain().size);
|
||||
node()->runtime->preview_xsize = preview_size.x;
|
||||
node()->runtime->preview_ysize = preview_size.y;
|
||||
|
||||
bNodePreview *preview = bke::node_preview_verify(
|
||||
root_tree->previews, node().instance_key(), preview_size.x, preview_size.y, true);
|
||||
|
||||
write_preview_from_result(*preview, *preview_result);
|
||||
}
|
||||
|
||||
Result *NodeOperation::get_preview_result()
|
||||
{
|
||||
/* Find the first linked output. */
|
||||
for (const bNodeSocket *output : node()->output_sockets()) {
|
||||
Result &output_result = get_result(output->identifier);
|
||||
if (output_result.should_compute()) {
|
||||
return &output_result;
|
||||
}
|
||||
}
|
||||
|
||||
/* No linked outputs, find the first allocated input. */
|
||||
for (const bNodeSocket *input : node()->input_sockets()) {
|
||||
Result &input_result = get_input(input->identifier);
|
||||
if (input_result.is_allocated()) {
|
||||
return &input_result;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NodeOperation::write_preview_from_result(bNodePreview &preview, Result &input_result)
|
||||
{
|
||||
GPUShader *shader = shader_manager().get("compositor_compute_preview");
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
if (input_result.type() == ResultType::Float) {
|
||||
GPU_texture_swizzle_set(input_result.texture(), "rrr1");
|
||||
}
|
||||
|
||||
input_result.bind_as_texture(shader, "input_tx");
|
||||
|
||||
const int2 preview_size = int2(preview.xsize, preview.ysize);
|
||||
Result preview_result = Result::Temporary(ResultType::Color, texture_pool());
|
||||
preview_result.allocate_texture(Domain(preview_size));
|
||||
preview_result.bind_as_image(shader, "preview_img");
|
||||
|
||||
compute_dispatch_threads_at_least(shader, preview_size);
|
||||
|
||||
input_result.unbind_as_texture();
|
||||
preview_result.unbind_as_image();
|
||||
GPU_shader_unbind();
|
||||
|
||||
GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
|
||||
float *preview_pixels = static_cast<float *>(
|
||||
GPU_texture_read(preview_result.texture(), GPU_DATA_FLOAT, 0));
|
||||
preview_result.release();
|
||||
|
||||
ColormanageProcessor *color_processor = IMB_colormanagement_display_processor_new(
|
||||
&context().get_scene().view_settings, &context().get_scene().display_settings);
|
||||
|
||||
threading::parallel_for(IndexRange(preview_size.y), 1, [&](const IndexRange sub_y_range) {
|
||||
for (const int64_t y : sub_y_range) {
|
||||
for (const int64_t x : IndexRange(preview_size.x)) {
|
||||
const int index = (y * preview_size.x + x) * 4;
|
||||
IMB_colormanagement_processor_apply_v4(color_processor, preview_pixels + index);
|
||||
rgba_float_to_uchar(preview.rect + index, preview_pixels + index);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* Restore original swizzle mask set above. */
|
||||
if (input_result.type() == ResultType::Float) {
|
||||
GPU_texture_swizzle_set(input_result.texture(), "rgba");
|
||||
}
|
||||
|
||||
IMB_colormanagement_processor_free(color_processor);
|
||||
MEM_freeN(preview_pixels);
|
||||
}
|
||||
|
||||
void NodeOperation::compute_results_reference_counts(const Schedule &schedule)
|
||||
{
|
||||
for (const bNodeSocket *output : this->node()->output_sockets()) {
|
||||
|
|
|
@ -35,6 +35,8 @@ void Operation::evaluate()
|
|||
|
||||
execute();
|
||||
|
||||
compute_preview();
|
||||
|
||||
release_inputs();
|
||||
|
||||
release_unneeded_results();
|
||||
|
@ -136,6 +138,8 @@ void Operation::add_and_evaluate_input_processor(StringRef identifier, SimpleOpe
|
|||
processor->evaluate();
|
||||
}
|
||||
|
||||
void Operation::compute_preview(){};
|
||||
|
||||
Result &Operation::get_input(StringRef identifier) const
|
||||
{
|
||||
return *results_mapped_to_inputs_.lookup(identifier);
|
||||
|
|
|
@ -21,58 +21,6 @@ namespace blender::realtime_compositor {
|
|||
|
||||
using namespace nodes::derived_node_tree_types;
|
||||
|
||||
/* Find the active context from the given context and its descendants contexts. The active context
|
||||
* is the one whose node instance key matches the active_viewer_key stored in the root node tree.
|
||||
* The instance key of each context is computed by calling BKE_node_instance_key given the key of
|
||||
* the parent as well as the group node making the context. */
|
||||
static const DTreeContext *find_active_context_recursive(const DTreeContext *context,
|
||||
bNodeInstanceKey key)
|
||||
{
|
||||
/* The instance key of the given context matches the active viewer instance key, so this is the
|
||||
* active context, return it. */
|
||||
if (key.value == context->derived_tree().root_context().btree().active_viewer_key.value) {
|
||||
return context;
|
||||
}
|
||||
|
||||
/* For each of the group nodes, compute their instance key and contexts and call this function
|
||||
* recursively. */
|
||||
for (const bNode *group_node : context->btree().group_nodes()) {
|
||||
const bNodeInstanceKey child_key = BKE_node_instance_key(key, &context->btree(), group_node);
|
||||
const DTreeContext *child_context = context->child_context(*group_node);
|
||||
const DTreeContext *found_context = find_active_context_recursive(child_context, child_key);
|
||||
|
||||
/* If the found context is null, that means neither the child context nor one of its descendant
|
||||
* contexts is active. */
|
||||
if (!found_context) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise, we have found our active context, return it. */
|
||||
return found_context;
|
||||
}
|
||||
|
||||
/* Neither the given context nor one of its descendant contexts is active, so return null. */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Find the active context for the given node tree. The active context represents the node tree
|
||||
* currently being edited. In most cases, that would be the top level node tree itself, but in the
|
||||
* case where the user is editing the node tree of a node group, the active context would be a
|
||||
* representation of the node tree of that node group. Note that the context also stores the group
|
||||
* node that the user selected to edit the node tree, so the context fully represents a particular
|
||||
* instance of the node group. */
|
||||
static const DTreeContext *find_active_context(const DerivedNodeTree &tree)
|
||||
{
|
||||
/* If the active viewer key is NODE_INSTANCE_KEY_NONE, that means it is not yet initialized and
|
||||
* we return the root context in that case. See the find_active_context_recursive function. */
|
||||
if (tree.root_context().btree().active_viewer_key.value == NODE_INSTANCE_KEY_NONE.value) {
|
||||
return &tree.root_context();
|
||||
}
|
||||
|
||||
/* The root context has an instance key of NODE_INSTANCE_KEY_BASE by definition. */
|
||||
return find_active_context_recursive(&tree.root_context(), NODE_INSTANCE_KEY_BASE);
|
||||
}
|
||||
|
||||
/* Add the viewer node which is marked as NODE_DO_OUTPUT in the given context to the given stack.
|
||||
* If multiple types of viewer nodes are marked, then the preference will be CMP_NODE_VIEWER >
|
||||
* CMP_NODE_SPLITVIEWER. If no viewer nodes were found, composite nodes can be added as a fallback
|
||||
|
@ -114,7 +62,8 @@ static bool add_viewer_nodes_in_context(const DTreeContext *context, Stack<DNode
|
|||
* Output, Composite, and Viewer nodes. Viewer nodes are a special case, as only the nodes that
|
||||
* satisfies the requirements in the add_viewer_nodes_in_context function are added. First, the
|
||||
* active context is searched for viewer nodes, if non were found, the root context is searched.
|
||||
* For more information on what contexts mean here, see the find_active_context function. */
|
||||
* For more information on what contexts mean here, see the DerivedNodeTree::active_context()
|
||||
* function. */
|
||||
static void add_output_nodes(const Context &context,
|
||||
const DerivedNodeTree &tree,
|
||||
Stack<DNode> &node_stack)
|
||||
|
@ -139,8 +88,8 @@ static void add_output_nodes(const Context &context,
|
|||
}
|
||||
}
|
||||
|
||||
const DTreeContext *active_context = find_active_context(tree);
|
||||
const bool viewer_was_added = add_viewer_nodes_in_context(active_context, node_stack);
|
||||
const DTreeContext &active_context = tree.active_context();
|
||||
const bool viewer_was_added = add_viewer_nodes_in_context(&active_context, node_stack);
|
||||
|
||||
/* An active viewer was added, no need to search further. */
|
||||
if (viewer_was_added) {
|
||||
|
@ -149,7 +98,7 @@ static void add_output_nodes(const Context &context,
|
|||
|
||||
/* If the active context is the root one and no viewer nodes were found, we consider this node
|
||||
* tree to have no viewer nodes, even if one of the non-active descendants have viewer nodes. */
|
||||
if (active_context->is_root()) {
|
||||
if (active_context.is_root()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -394,7 +343,8 @@ Schedule compute_schedule(const Context &context, const DerivedNodeTree &tree)
|
|||
int insertion_position = 0;
|
||||
for (int i = 0; i < sorted_dependency_nodes.size(); i++) {
|
||||
if (needed_buffers.lookup(doutput.node()) >
|
||||
needed_buffers.lookup(sorted_dependency_nodes[i])) {
|
||||
needed_buffers.lookup(sorted_dependency_nodes[i]))
|
||||
{
|
||||
insertion_position++;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(imageSize(preview_img));
|
||||
imageStore(preview_img, texel, texture(input_tx, coordinates));
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_compute_preview)
|
||||
.local_group_size(16, 16)
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img")
|
||||
.compute_source("compositor_compute_preview.glsl")
|
||||
.do_static_compilation(true);
|
|
@ -34,7 +34,7 @@ void ObjectRuntimeBackup::init_from_object(Object *object)
|
|||
light_linking_runtime = object->light_linking->runtime;
|
||||
}
|
||||
BKE_object_runtime_reset(object);
|
||||
/* Keep bbox (for now at least). */
|
||||
/* Keep bounding-box (for now at least). */
|
||||
object->runtime.bb = runtime.bb;
|
||||
/* Object update will override actual object->data to an evaluated version.
|
||||
* Need to make sure we don't have data set to evaluated one before free
|
||||
|
|
|
@ -58,6 +58,11 @@ class Context : public realtime_compositor::Context {
|
|||
{
|
||||
}
|
||||
|
||||
const Scene &get_scene() const override
|
||||
{
|
||||
return *DRW_context_state_get()->scene;
|
||||
}
|
||||
|
||||
const bNodeTree &get_node_tree() const override
|
||||
{
|
||||
return *DRW_context_state_get()->scene->nodetree;
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
//#define DEBUG_SNAP_TIME
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -194,6 +196,12 @@ bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx,
|
|||
bool sort,
|
||||
ListBase *r_hit_list);
|
||||
|
||||
#ifdef DEBUG_SNAP_TIME
|
||||
void ED_transform_snap_object_time_average_print(void);
|
||||
#else
|
||||
# define ED_transform_snap_object_time_average_print() void(0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -3291,7 +3291,7 @@ static void do_vpaint_brush_smear(bContext *C,
|
|||
|
||||
/* if the vertex is selected for painting. */
|
||||
if (!use_vert_sel || select_vert[v_index]) {
|
||||
/* Calc the dot prod. between ray norm on surf and current vert
|
||||
/* Calculate the dot prod. between ray norm on surf and current vert
|
||||
* (ie splash prevention factor), and only paint front facing verts. */
|
||||
float brush_strength = cache->bstrength;
|
||||
const float angle_cos = (use_normal && vd.no) ?
|
||||
|
|
|
@ -6402,7 +6402,7 @@ void SCULPT_topology_islands_ensure(Object *ob)
|
|||
*static_cast<uint8_t *>(
|
||||
SCULPT_vertex_attr_get(vertex2, ss->attrs.topology_island_key)) = island_nr;
|
||||
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex2, ni) {
|
||||
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, vertex2, ni) {
|
||||
if (visit.add(ni.vertex) && SCULPT_vertex_any_face_visible_get(ss, ni.vertex)) {
|
||||
stack.append(ni.vertex);
|
||||
}
|
||||
|
|
|
@ -988,34 +988,39 @@ void fsmenu_read_system(FSMenu *fsmenu, int read_bookmarks)
|
|||
fprintf(stderr, "could not close the list of mounted file-systems\n");
|
||||
}
|
||||
}
|
||||
/* Check gvfs shares. */
|
||||
/* Check `gvfs` shares. */
|
||||
const char *const xdg_runtime_dir = BLI_getenv("XDG_RUNTIME_DIR");
|
||||
if (xdg_runtime_dir != NULL) {
|
||||
struct direntry *dirs;
|
||||
char filepath[FILE_MAX];
|
||||
BLI_path_join(filepath, sizeof(filepath), xdg_runtime_dir, "gvfs/");
|
||||
const uint dirs_num = BLI_filelist_dir_contents(filepath, &dirs);
|
||||
for (uint i = 0; i < dirs_num; i++) {
|
||||
if (dirs[i].type & S_IFDIR) {
|
||||
const char *dirname = dirs[i].relname;
|
||||
if (dirname[0] != '.') {
|
||||
/* Dir names contain a lot of unwanted text.
|
||||
* Assuming every entry ends with the share name */
|
||||
const char *label = strstr(dirname, "share=");
|
||||
if (label != NULL) {
|
||||
/* Move pointer so "share=" is trimmed off
|
||||
* or use full dirname as label. */
|
||||
const char *label_test = label + 6;
|
||||
label = *label_test ? label_test : dirname;
|
||||
}
|
||||
SNPRINTF(line, "%s%s", filepath, dirname);
|
||||
fsmenu_insert_entry(
|
||||
fsmenu, FS_CATEGORY_SYSTEM, line, label, ICON_NETWORK_DRIVE, FS_INSERT_SORTED);
|
||||
found = 1;
|
||||
/* Avoid error message if the directory doesn't exist as this isn't a requirement. */
|
||||
if (BLI_is_dir(filepath)) {
|
||||
const uint dirs_num = BLI_filelist_dir_contents(filepath, &dirs);
|
||||
for (uint i = 0; i < dirs_num; i++) {
|
||||
if ((dirs[i].type & S_IFDIR) == 0) {
|
||||
continue;
|
||||
}
|
||||
const char *dirname = dirs[i].relname;
|
||||
if (dirname[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Directory names contain a lot of unwanted text.
|
||||
* Assuming every entry ends with the share name. */
|
||||
const char *label = strstr(dirname, "share=");
|
||||
if (label != NULL) {
|
||||
/* Move pointer so `share=` is trimmed off or use full `dirname` as label. */
|
||||
const char *label_test = label + 6;
|
||||
label = *label_test ? label_test : dirname;
|
||||
}
|
||||
SNPRINTF(line, "%s%s", filepath, dirname);
|
||||
fsmenu_insert_entry(
|
||||
fsmenu, FS_CATEGORY_SYSTEM, line, label, ICON_NETWORK_DRIVE, FS_INSERT_SORTED);
|
||||
found = 1;
|
||||
}
|
||||
BLI_filelist_free(dirs, dirs_num);
|
||||
}
|
||||
BLI_filelist_free(dirs, dirs_num);
|
||||
}
|
||||
# endif
|
||||
|
||||
|
|
|
@ -688,9 +688,9 @@ static void nla_draw_strip_frames_text(
|
|||
/* Always draw times above the strip, whereas sequencer drew below + above.
|
||||
* However, we should be fine having everything on top, since these tend to be
|
||||
* quite spaced out.
|
||||
* - 1 dp is compromise between lack of precision (ints only, as per sequencer)
|
||||
* while also preserving some accuracy, since we do use floats
|
||||
*/
|
||||
* NOTE: 1 decimal point is a compromise between lack of precision (ints only, as per sequencer)
|
||||
* while also preserving some accuracy, since we do use floats. */
|
||||
|
||||
/* start frame */
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "%.1f", strip->start);
|
||||
UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col);
|
||||
|
|
|
@ -56,8 +56,10 @@ typedef struct TransDataNla {
|
|||
/** index of track that strip is currently in. */
|
||||
int trackIndex;
|
||||
|
||||
/** NOTE: This index is relative to the initial first track at the start of transforming and
|
||||
* thus can be negative when the tracks list grows downward. */
|
||||
/**
|
||||
* \note This index is relative to the initial first track at the start of transforming and
|
||||
* thus can be negative when the tracks list grows downward.
|
||||
*/
|
||||
int signed_track_index;
|
||||
|
||||
/** handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends. */
|
||||
|
@ -125,8 +127,8 @@ static float transdata_get_time_shuffle_offset_side(ListBase *trans_datas, const
|
|||
|
||||
total_offset += offset;
|
||||
} while (!IS_EQT(offset, 0.0f, 1e-4));
|
||||
/* Needs a eps greater than FLT_EPS because strip->start/end could be non-integral, and after
|
||||
* those calculations, `offset` could fall outside of FLT_EPS. */
|
||||
/* Needs a epsilon greater than FLT_EPS because strip->start/end could be non-integral,
|
||||
* and after those calculations, `offset` could fall outside of FLT_EPS. */
|
||||
|
||||
return total_offset;
|
||||
}
|
||||
|
@ -148,8 +150,8 @@ static float transdata_get_time_shuffle_offset(ListBase *trans_datas)
|
|||
return -offset_left < offset_right ? offset_left : offset_right;
|
||||
}
|
||||
|
||||
/** Assumes all of given trans_datas are part of the same ID.
|
||||
*
|
||||
/**
|
||||
* Assumes all of given trans_datas are part of the same ID.
|
||||
*
|
||||
* \param shuffle_direction: the direction the strip is traveling. 1 is towards the bottom
|
||||
* of the stack, -1 is away from it.
|
||||
|
@ -205,7 +207,8 @@ static bool transdata_get_track_shuffle_offset_side(ListBase *trans_datas,
|
|||
return true;
|
||||
}
|
||||
|
||||
/** Assumes all of given trans_datas are part of the same ID.
|
||||
/**
|
||||
* Assumes all of given trans_datas are part of the same ID.
|
||||
*
|
||||
* \param r_track_offset: The minimal total signed offset that results in valid strip track-moves
|
||||
* for all strips from \a trans_datas.
|
||||
|
@ -243,7 +246,6 @@ static bool transdata_get_track_shuffle_offset(ListBase *trans_datas, int *r_tra
|
|||
/** \name Transform application to NLA strips
|
||||
* \{ */
|
||||
|
||||
/** \} */
|
||||
static void nlatrack_truncate_temporary_tracks(bAnimContext *ac)
|
||||
{
|
||||
short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
|
||||
|
@ -288,6 +290,9 @@ static void nlatrack_truncate_temporary_tracks(bAnimContext *ac)
|
|||
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Transform application to NLA strips
|
||||
* \{ */
|
||||
|
@ -744,8 +749,7 @@ static void recalcData_nla(TransInfo *t)
|
|||
*
|
||||
* Determine dst_track, which will end up being NULL, the last library override
|
||||
* track, or a normal local track. The first two cases lead to delta_new_tracks!=0.
|
||||
* The last case leads to delta_new_tracks==0.
|
||||
*/
|
||||
* The last case leads to `delta_new_tracks == 0`. */
|
||||
int delta_new_tracks = delta;
|
||||
|
||||
/* it's possible to drag a strip fast enough to make delta > |1|. We only want to process
|
||||
|
@ -760,14 +764,13 @@ static void recalcData_nla(TransInfo *t)
|
|||
}
|
||||
|
||||
/* We assume all library tracks are grouped at the bottom of the nla stack.
|
||||
* Thus, no need to check for them when moving tracks upward.
|
||||
*/
|
||||
* Thus, no need to check for them when moving tracks upward. */
|
||||
while (delta_new_tracks > 0) {
|
||||
dst_track = dst_track->next;
|
||||
delta_new_tracks--;
|
||||
}
|
||||
|
||||
for (int i = 0; i < -delta_new_tracks; i++) {
|
||||
for (int j = 0; j < -delta_new_tracks; j++) {
|
||||
NlaTrack *new_track = BKE_nlatrack_new();
|
||||
new_track->flag |= NLATRACK_TEMPORARILY_ADDED;
|
||||
BKE_nlatrack_insert_before(
|
||||
|
@ -775,7 +778,7 @@ static void recalcData_nla(TransInfo *t)
|
|||
dst_track = new_track;
|
||||
}
|
||||
|
||||
for (int i = 0; i < delta_new_tracks; i++) {
|
||||
for (int j = 0; j < delta_new_tracks; j++) {
|
||||
NlaTrack *new_track = BKE_nlatrack_new();
|
||||
new_track->flag |= NLATRACK_TEMPORARILY_ADDED;
|
||||
|
||||
|
|
|
@ -912,6 +912,8 @@ void freeSnapping(TransInfo *t)
|
|||
else if (t->tsnap.object_context) {
|
||||
ED_transform_snap_object_context_destroy(t->tsnap.object_context);
|
||||
t->tsnap.object_context = nullptr;
|
||||
|
||||
ED_transform_snap_object_time_average_print();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -29,7 +29,7 @@ struct SnapObjectContext {
|
|||
|
||||
struct {
|
||||
Depsgraph *depsgraph;
|
||||
const ARegion *region;
|
||||
const RegionView3D *rv3d;
|
||||
const View3D *v3d;
|
||||
|
||||
eSnapMode snap_to_flag;
|
||||
|
@ -42,7 +42,6 @@ struct SnapObjectContext {
|
|||
float init_co[3];
|
||||
float curr_co[3];
|
||||
|
||||
float pmat[4][4]; /* perspective matrix */
|
||||
float win_size[2]; /* win x and y */
|
||||
float clip_plane[MAX_CLIPPLANE_LEN][4];
|
||||
int clip_plane_len;
|
||||
|
@ -50,7 +49,6 @@ struct SnapObjectContext {
|
|||
/* read/write */
|
||||
uint object_index;
|
||||
|
||||
bool is_persp;
|
||||
bool has_occlusion_plane; /* Ignore plane of occlusion in curves. */
|
||||
bool use_occlusion_test_edit;
|
||||
} runtime;
|
||||
|
@ -116,6 +114,26 @@ using Nearest2DCopyVertNoCallback = void (*)(const int index,
|
|||
float r_no[3]);
|
||||
|
||||
struct Nearest2dUserData {
|
||||
public:
|
||||
/* Constructor. */
|
||||
Nearest2dUserData(SnapObjectContext *sctx,
|
||||
float dist_px_sq,
|
||||
const blender::float4x4 &obmat = blender::float4x4::identity());
|
||||
|
||||
void clip_planes_get(SnapObjectContext *sctx,
|
||||
const blender::float4x4 &obmat,
|
||||
bool skip_occlusion_plane = false);
|
||||
|
||||
bool snap_boundbox(const blender::float3 &min, const blender::float3 &max);
|
||||
|
||||
bool snap_point(const blender::float3 &co, int index = -1);
|
||||
|
||||
bool snap_edge(const blender::float3 &va, const blender::float3 &vb, int edge_index = -1);
|
||||
|
||||
DistProjectedAABBPrecalc nearest_precalc;
|
||||
blender::float4x4 pmat_local;
|
||||
blender::Vector<blender::float4, MAX_CLIPPLANE_LEN> clip_planes;
|
||||
|
||||
Nearest2DGetVertCoCallback get_vert_co;
|
||||
Nearest2DGetEdgeVertsCallback get_edge_verts_index;
|
||||
Nearest2DGetTriVertsCallback get_tri_verts_index;
|
||||
|
@ -138,6 +156,8 @@ struct Nearest2dUserData {
|
|||
|
||||
bool is_persp;
|
||||
bool use_backface_culling;
|
||||
|
||||
BVHTreeNearest nearest_point;
|
||||
};
|
||||
|
||||
/* transform_snap_object.cc */
|
||||
|
@ -147,13 +167,6 @@ void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRay
|
|||
bool raycast_tri_backface_culling_test(
|
||||
const float dir[3], const float v0[3], const float v1[3], const float v2[3], float no[3]);
|
||||
|
||||
bool snap_bound_box_check_dist(const float min[3],
|
||||
const float max[3],
|
||||
const float lpmat[4][4],
|
||||
const float win_size[2],
|
||||
const float mval[2],
|
||||
float dist_px_sq);
|
||||
|
||||
void cb_snap_vert(void *userdata,
|
||||
int index,
|
||||
const DistProjectedAABBPrecalc *precalc,
|
||||
|
@ -172,13 +185,7 @@ bool nearest_world_tree(SnapObjectContext *sctx,
|
|||
BVHTree *tree,
|
||||
BVHTree_NearestPointCallback nearest_cb,
|
||||
void *treedata,
|
||||
const float (*obmat)[4],
|
||||
const float init_co[3],
|
||||
const float curr_co[3],
|
||||
float *r_dist_sq,
|
||||
float *r_loc,
|
||||
float *r_no,
|
||||
int *r_index);
|
||||
const float (*obmat)[4]);
|
||||
|
||||
/* transform_snap_object_editmesh.cc */
|
||||
|
||||
|
@ -217,13 +224,9 @@ eSnapMode snap_polygon_editmesh(SnapObjectContext *sctx,
|
|||
ID *id,
|
||||
const float obmat[4][4],
|
||||
eSnapMode snap_to_flag,
|
||||
int polygon,
|
||||
const float clip_planes_local[MAX_CLIPPLANE_LEN][4]);
|
||||
int polygon);
|
||||
|
||||
void nearest2d_data_init_editmesh(struct BMEditMesh *em,
|
||||
bool is_persp,
|
||||
bool use_backface_culling,
|
||||
struct Nearest2dUserData *r_nearest2d);
|
||||
void nearest2d_data_init_editmesh(struct BMEditMesh *em, struct Nearest2dUserData *r_nearest2d);
|
||||
|
||||
/* transform_snap_object_mesh.cc */
|
||||
|
||||
|
@ -239,10 +242,6 @@ eSnapMode snap_polygon_mesh(SnapObjectContext *sctx,
|
|||
ID *id,
|
||||
const float obmat[4][4],
|
||||
eSnapMode snap_to_flag,
|
||||
int polygon,
|
||||
const float clip_planes_local[MAX_CLIPPLANE_LEN][4]);
|
||||
int polygon);
|
||||
|
||||
void nearest2d_data_init_mesh(const Mesh *mesh,
|
||||
bool is_persp,
|
||||
bool use_backface_culling,
|
||||
Nearest2dUserData *r_nearest2d);
|
||||
void nearest2d_data_init_mesh(const Mesh *mesh, Nearest2dUserData *r_nearest2d);
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include "transform_snap_object.hh"
|
||||
|
||||
using namespace blender;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Snap Object Data
|
||||
* \{ */
|
||||
|
@ -270,14 +272,7 @@ static bool raycastEditMesh(SnapData_EditMesh *sod,
|
|||
SnapObjectContext *sctx,
|
||||
BMEditMesh *em,
|
||||
const float obmat[4][4],
|
||||
const uint ob_index,
|
||||
/* read/write args */
|
||||
float *ray_depth,
|
||||
/* return args */
|
||||
float r_loc[3],
|
||||
float r_no[3],
|
||||
int *r_index,
|
||||
ListBase *r_hit_list)
|
||||
const uint ob_index)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
|
@ -295,7 +290,7 @@ static bool raycastEditMesh(SnapData_EditMesh *sod,
|
|||
|
||||
/* local scale in normal direction */
|
||||
local_scale = normalize_v3(ray_normal_local);
|
||||
local_depth = *ray_depth;
|
||||
local_depth = sctx->ret.ray_depth_max;
|
||||
if (local_depth != BVH_RAYCAST_DIST_MAX) {
|
||||
local_depth *= local_scale;
|
||||
}
|
||||
|
@ -309,11 +304,10 @@ static bool raycastEditMesh(SnapData_EditMesh *sod,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
|
||||
* very far away ray_start values (as returned in case of ortho view3d), see #50486, #38358.
|
||||
*/
|
||||
/* We pass a temp ray_start, set from object's bounding-box, to avoid precision issues with
|
||||
* very far away ray_start values (as returned in case of ortho view3d), see #50486, #38358. */
|
||||
if (len_diff > 400.0f) {
|
||||
len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
|
||||
len_diff -= local_scale; /* make temp start point a bit away from bounding-box hit point. */
|
||||
madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
|
||||
local_depth -= len_diff;
|
||||
}
|
||||
|
@ -326,7 +320,7 @@ static bool raycastEditMesh(SnapData_EditMesh *sod,
|
|||
return retval;
|
||||
}
|
||||
|
||||
if (r_hit_list) {
|
||||
if (sctx->ret.hit_list) {
|
||||
RayCastAll_Data data;
|
||||
|
||||
data.bvhdata = treedata;
|
||||
|
@ -335,14 +329,14 @@ static bool raycastEditMesh(SnapData_EditMesh *sod,
|
|||
data.len_diff = len_diff;
|
||||
data.local_scale = local_scale;
|
||||
data.ob_uuid = ob_index;
|
||||
data.hit_list = r_hit_list;
|
||||
data.hit_list = sctx->ret.hit_list;
|
||||
|
||||
void *hit_last_prev = data.hit_list->last;
|
||||
BLI_bvhtree_ray_cast_all(treedata->tree,
|
||||
ray_start_local,
|
||||
ray_normal_local,
|
||||
0.0f,
|
||||
*ray_depth,
|
||||
sctx->ret.ray_depth_max,
|
||||
raycast_all_cb,
|
||||
&data);
|
||||
|
||||
|
@ -365,26 +359,21 @@ static bool raycastEditMesh(SnapData_EditMesh *sod,
|
|||
{
|
||||
hit.dist += len_diff;
|
||||
hit.dist /= local_scale;
|
||||
if (hit.dist <= *ray_depth) {
|
||||
*ray_depth = hit.dist;
|
||||
copy_v3_v3(r_loc, hit.co);
|
||||
if (hit.dist <= sctx->ret.ray_depth_max) {
|
||||
copy_v3_v3(sctx->ret.loc, hit.co);
|
||||
copy_v3_v3(sctx->ret.no, hit.no);
|
||||
|
||||
/* Back to world-space. */
|
||||
mul_m4_v3(obmat, r_loc);
|
||||
mul_m4_v3(obmat, sctx->ret.loc);
|
||||
|
||||
if (r_no) {
|
||||
copy_v3_v3(r_no, hit.no);
|
||||
mul_transposed_mat3_m4_v3(imat, r_no);
|
||||
normalize_v3(r_no);
|
||||
}
|
||||
mul_transposed_mat3_m4_v3(imat, sctx->ret.no);
|
||||
normalize_v3(sctx->ret.no);
|
||||
|
||||
sctx->ret.ray_depth_max = hit.dist;
|
||||
|
||||
em = sod->treedata_editmesh.em;
|
||||
sctx->ret.index = BM_elem_index_get(em->looptris[hit.index][0]->f);
|
||||
|
||||
retval = true;
|
||||
|
||||
if (r_index) {
|
||||
em = sod->treedata_editmesh.em;
|
||||
|
||||
*r_index = BM_elem_index_get(em->looptris[hit.index][0]->f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -399,30 +388,14 @@ static bool raycastEditMesh(SnapData_EditMesh *sod,
|
|||
static bool nearest_world_editmesh(SnapData_EditMesh *sod,
|
||||
SnapObjectContext *sctx,
|
||||
BMEditMesh *em,
|
||||
const float (*obmat)[4],
|
||||
const float init_co[3],
|
||||
const float curr_co[3],
|
||||
float *r_dist_sq,
|
||||
float *r_loc,
|
||||
float *r_no,
|
||||
int *r_index)
|
||||
const float (*obmat)[4])
|
||||
{
|
||||
BVHTreeFromEditMesh *treedata = snap_object_data_editmesh_treedata_get(sod, sctx, em);
|
||||
if (treedata == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return nearest_world_tree(sctx,
|
||||
treedata->tree,
|
||||
treedata->nearest_callback,
|
||||
treedata,
|
||||
obmat,
|
||||
init_co,
|
||||
curr_co,
|
||||
r_dist_sq,
|
||||
r_loc,
|
||||
r_no,
|
||||
r_index);
|
||||
return nearest_world_tree(sctx, treedata->tree, treedata->nearest_callback, treedata, obmat);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -452,10 +425,7 @@ static void cb_bedge_verts_get(const int index, const Nearest2dUserData *data, i
|
|||
r_v_index[1] = BM_elem_index_get(eed->v2);
|
||||
}
|
||||
|
||||
void nearest2d_data_init_editmesh(BMEditMesh *em,
|
||||
bool is_persp,
|
||||
bool use_backface_culling,
|
||||
Nearest2dUserData *r_nearest2d)
|
||||
void nearest2d_data_init_editmesh(BMEditMesh *em, Nearest2dUserData *r_nearest2d)
|
||||
{
|
||||
r_nearest2d->get_vert_co = cb_bvert_co_get;
|
||||
r_nearest2d->get_edge_verts_index = cb_bedge_verts_get;
|
||||
|
@ -464,9 +434,6 @@ void nearest2d_data_init_editmesh(BMEditMesh *em,
|
|||
r_nearest2d->get_tri_edges_index = nullptr;
|
||||
|
||||
r_nearest2d->bm = em->bm;
|
||||
|
||||
r_nearest2d->is_persp = is_persp;
|
||||
r_nearest2d->use_backface_culling = use_backface_culling;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -480,8 +447,7 @@ eSnapMode snap_polygon_editmesh(SnapObjectContext *sctx,
|
|||
ID * /*id*/,
|
||||
const float obmat[4][4],
|
||||
eSnapMode snap_to_flag,
|
||||
int polygon,
|
||||
const float clip_planes_local[MAX_CLIPPLANE_LEN][4])
|
||||
int polygon)
|
||||
{
|
||||
eSnapMode elem = SCE_SNAP_MODE_NONE;
|
||||
|
||||
|
@ -492,22 +458,14 @@ eSnapMode snap_polygon_editmesh(SnapObjectContext *sctx,
|
|||
|
||||
BMEditMesh *em = sod->treedata_editmesh.em;
|
||||
|
||||
float lpmat[4][4];
|
||||
mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
|
||||
|
||||
DistProjectedAABBPrecalc neasrest_precalc;
|
||||
dist_squared_to_projected_aabb_precalc(
|
||||
&neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval);
|
||||
Nearest2dUserData nearest2d(sctx, sctx->ret.dist_px_sq, float4x4(obmat));
|
||||
nearest2d.clip_planes_get(sctx, float4x4(obmat));
|
||||
nearest2d_data_init_editmesh(em, &nearest2d);
|
||||
|
||||
BVHTreeNearest nearest{};
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = sctx->ret.dist_px_sq;
|
||||
|
||||
Nearest2dUserData nearest2d;
|
||||
|
||||
nearest2d_data_init_editmesh(
|
||||
em, sctx->runtime.is_persp, sctx->runtime.params.use_backface_culling, &nearest2d);
|
||||
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_FACE);
|
||||
BMFace *f = BM_face_at_index(em->bm, polygon);
|
||||
BMLoop *l_iter, *l_first;
|
||||
|
@ -519,9 +477,9 @@ eSnapMode snap_polygon_editmesh(SnapObjectContext *sctx,
|
|||
do {
|
||||
cb_snap_edge(&nearest2d,
|
||||
BM_elem_index_get(l_iter->e),
|
||||
&neasrest_precalc,
|
||||
clip_planes_local,
|
||||
sctx->runtime.clip_plane_len,
|
||||
&nearest2d.nearest_precalc,
|
||||
reinterpret_cast<float(*)[4]>(nearest2d.clip_planes.data()),
|
||||
nearest2d.clip_planes.size(),
|
||||
&nearest);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
@ -532,9 +490,9 @@ eSnapMode snap_polygon_editmesh(SnapObjectContext *sctx,
|
|||
do {
|
||||
cb_snap_vert(&nearest2d,
|
||||
BM_elem_index_get(l_iter->v),
|
||||
&neasrest_precalc,
|
||||
clip_planes_local,
|
||||
sctx->runtime.clip_plane_len,
|
||||
&nearest2d.nearest_precalc,
|
||||
reinterpret_cast<float(*)[4]>(nearest2d.clip_planes.data()),
|
||||
nearest2d.clip_planes.size(),
|
||||
&nearest);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
@ -565,24 +523,14 @@ static eSnapMode snapEditMesh(SnapData_EditMesh *sod,
|
|||
SnapObjectContext *sctx,
|
||||
BMEditMesh *em,
|
||||
const float obmat[4][4],
|
||||
eSnapMode snap_to_flag,
|
||||
/* read/write args */
|
||||
float *dist_px_sq,
|
||||
/* return args */
|
||||
float r_loc[3],
|
||||
float r_no[3],
|
||||
int *r_index)
|
||||
eSnapMode snap_to_flag)
|
||||
{
|
||||
BLI_assert(snap_to_flag != SCE_SNAP_MODE_FACE);
|
||||
float lpmat[4][4];
|
||||
mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
|
||||
|
||||
/* Test BoundBox */
|
||||
Nearest2dUserData nearest2d(sctx, sctx->ret.dist_px_sq, float4x4(obmat));
|
||||
|
||||
/* Was BKE_boundbox_ray_hit_check, see: cf6ca226fa58. */
|
||||
if (!snap_bound_box_check_dist(
|
||||
sod->min, sod->max, lpmat, sctx->runtime.win_size, sctx->runtime.mval, *dist_px_sq))
|
||||
{
|
||||
if (!nearest2d.snap_boundbox(sod->min, sod->max)) {
|
||||
return SCE_SNAP_MODE_NONE;
|
||||
}
|
||||
|
||||
|
@ -646,34 +594,24 @@ static eSnapMode snapEditMesh(SnapData_EditMesh *sod,
|
|||
}
|
||||
}
|
||||
|
||||
Nearest2dUserData nearest2d;
|
||||
nearest2d_data_init_editmesh(sod->treedata_editmesh.em,
|
||||
sctx->runtime.is_persp,
|
||||
sctx->runtime.params.use_backface_culling,
|
||||
&nearest2d);
|
||||
nearest2d.clip_planes_get(sctx, float4x4(obmat));
|
||||
nearest2d_data_init_editmesh(em, &nearest2d);
|
||||
|
||||
BVHTreeNearest nearest{};
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = *dist_px_sq;
|
||||
nearest.dist_sq = sctx->ret.dist_px_sq;
|
||||
|
||||
eSnapMode elem = SCE_SNAP_MODE_VERTEX;
|
||||
|
||||
float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
|
||||
transpose_m4_m4(tobmat, obmat);
|
||||
|
||||
for (int i = sctx->runtime.clip_plane_len; i--;) {
|
||||
mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]);
|
||||
}
|
||||
|
||||
if (sod->bvhtree[0] && (snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
|
||||
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
|
||||
BLI_bvhtree_find_nearest_projected(sod->bvhtree[0],
|
||||
lpmat,
|
||||
nearest2d.pmat_local.ptr(),
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
clip_planes_local,
|
||||
sctx->runtime.clip_plane_len,
|
||||
reinterpret_cast<float(*)[4]>(nearest2d.clip_planes.data()),
|
||||
nearest2d.clip_planes.size(),
|
||||
&nearest,
|
||||
cb_snap_vert,
|
||||
&nearest2d);
|
||||
|
@ -685,11 +623,11 @@ static eSnapMode snapEditMesh(SnapData_EditMesh *sod,
|
|||
BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
|
||||
BM_mesh_elem_index_ensure(em->bm, BM_EDGE | BM_VERT);
|
||||
BLI_bvhtree_find_nearest_projected(sod->bvhtree[1],
|
||||
lpmat,
|
||||
nearest2d.pmat_local.ptr(),
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
clip_planes_local,
|
||||
sctx->runtime.clip_plane_len,
|
||||
reinterpret_cast<float(*)[4]>(nearest2d.clip_planes.data()),
|
||||
nearest2d.clip_planes.size(),
|
||||
&nearest,
|
||||
cb_snap_edge,
|
||||
&nearest2d);
|
||||
|
@ -703,21 +641,18 @@ static eSnapMode snapEditMesh(SnapData_EditMesh *sod,
|
|||
}
|
||||
|
||||
if (nearest.index != -1) {
|
||||
*dist_px_sq = nearest.dist_sq;
|
||||
copy_v3_v3(sctx->ret.loc, nearest.co);
|
||||
copy_v3_v3(sctx->ret.no, nearest.no);
|
||||
|
||||
copy_v3_v3(r_loc, nearest.co);
|
||||
mul_m4_v3(obmat, r_loc);
|
||||
if (r_no) {
|
||||
float imat[4][4];
|
||||
invert_m4_m4(imat, obmat);
|
||||
mul_m4_v3(obmat, sctx->ret.loc);
|
||||
|
||||
copy_v3_v3(r_no, nearest.no);
|
||||
mul_transposed_mat3_m4_v3(imat, r_no);
|
||||
normalize_v3(r_no);
|
||||
}
|
||||
if (r_index) {
|
||||
*r_index = nearest.index;
|
||||
}
|
||||
float imat[4][4];
|
||||
invert_m4_m4(imat, obmat);
|
||||
mul_transposed_mat3_m4_v3(imat, sctx->ret.no);
|
||||
normalize_v3(sctx->ret.no);
|
||||
|
||||
sctx->ret.dist_px_sq = nearest.dist_sq;
|
||||
sctx->ret.index = nearest.index;
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
@ -747,50 +682,20 @@ eSnapMode snap_object_editmesh(SnapObjectContext *sctx,
|
|||
if (snap_mode_used & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT |
|
||||
SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_VERTEX))
|
||||
{
|
||||
elem = snapEditMesh(sod,
|
||||
sctx,
|
||||
em,
|
||||
obmat,
|
||||
snap_to_flag,
|
||||
&sctx->ret.dist_px_sq,
|
||||
sctx->ret.loc,
|
||||
sctx->ret.no,
|
||||
&sctx->ret.index);
|
||||
elem = snapEditMesh(sod, sctx, em, obmat, snap_to_flag);
|
||||
if (elem) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
|
||||
if (snap_mode_used & SCE_SNAP_MODE_FACE) {
|
||||
if (raycastEditMesh(sod,
|
||||
sctx,
|
||||
em,
|
||||
obmat,
|
||||
sctx->runtime.object_index++,
|
||||
/* read/write args */
|
||||
&sctx->ret.ray_depth_max,
|
||||
/* return args */
|
||||
sctx->ret.loc,
|
||||
sctx->ret.no,
|
||||
&sctx->ret.index,
|
||||
sctx->ret.hit_list))
|
||||
{
|
||||
if (raycastEditMesh(sod, sctx, em, obmat, sctx->runtime.object_index++)) {
|
||||
return SCE_SNAP_MODE_FACE;
|
||||
}
|
||||
}
|
||||
|
||||
if (snap_mode_used & SCE_SNAP_MODE_FACE_NEAREST) {
|
||||
if (nearest_world_editmesh(sod,
|
||||
sctx,
|
||||
em,
|
||||
obmat,
|
||||
sctx->runtime.init_co,
|
||||
sctx->runtime.curr_co,
|
||||
&sctx->ret.dist_px_sq,
|
||||
sctx->ret.loc,
|
||||
sctx->ret.no,
|
||||
&sctx->ret.index))
|
||||
{
|
||||
if (nearest_world_editmesh(sod, sctx, em, obmat)) {
|
||||
return SCE_SNAP_MODE_FACE_NEAREST;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
|
||||
#include "transform_snap_object.hh"
|
||||
|
||||
using blender::float3;
|
||||
using blender::Span;
|
||||
using namespace blender;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Snap Object Data
|
||||
|
@ -87,14 +86,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
|
|||
const Mesh *me_eval,
|
||||
const float obmat[4][4],
|
||||
const uint ob_index,
|
||||
bool use_hide,
|
||||
/* read/write args */
|
||||
float *ray_depth,
|
||||
/* return args */
|
||||
float r_loc[3],
|
||||
float r_no[3],
|
||||
int *r_index,
|
||||
ListBase *r_hit_list)
|
||||
bool use_hide)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
|
@ -116,7 +108,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
|
|||
|
||||
/* local scale in normal direction */
|
||||
local_scale = normalize_v3(ray_normal_local);
|
||||
local_depth = *ray_depth;
|
||||
local_depth = sctx->ret.ray_depth_max;
|
||||
if (local_depth != BVH_RAYCAST_DIST_MAX) {
|
||||
local_depth *= local_scale;
|
||||
}
|
||||
|
@ -157,7 +149,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
|
|||
}
|
||||
|
||||
BLI_assert(treedata.raycast_callback != nullptr);
|
||||
if (r_hit_list) {
|
||||
if (sctx->ret.hit_list) {
|
||||
RayCastAll_Data data;
|
||||
|
||||
data.bvhdata = &treedata;
|
||||
|
@ -166,11 +158,16 @@ static bool raycastMesh(SnapObjectContext *sctx,
|
|||
data.len_diff = len_diff;
|
||||
data.local_scale = local_scale;
|
||||
data.ob_uuid = ob_index;
|
||||
data.hit_list = r_hit_list;
|
||||
data.hit_list = sctx->ret.hit_list;
|
||||
|
||||
void *hit_last_prev = data.hit_list->last;
|
||||
BLI_bvhtree_ray_cast_all(
|
||||
treedata.tree, ray_start_local, ray_normal_local, 0.0f, *ray_depth, raycast_all_cb, &data);
|
||||
BLI_bvhtree_ray_cast_all(treedata.tree,
|
||||
ray_start_local,
|
||||
ray_normal_local,
|
||||
0.0f,
|
||||
sctx->ret.ray_depth_max,
|
||||
raycast_all_cb,
|
||||
&data);
|
||||
|
||||
retval = hit_last_prev != data.hit_list->last;
|
||||
}
|
||||
|
@ -191,24 +188,18 @@ static bool raycastMesh(SnapObjectContext *sctx,
|
|||
{
|
||||
hit.dist += len_diff;
|
||||
hit.dist /= local_scale;
|
||||
if (hit.dist <= *ray_depth) {
|
||||
*ray_depth = hit.dist;
|
||||
copy_v3_v3(r_loc, hit.co);
|
||||
if (hit.dist <= sctx->ret.ray_depth_max) {
|
||||
copy_v3_v3(sctx->ret.loc, hit.co);
|
||||
copy_v3_v3(sctx->ret.no, hit.no);
|
||||
|
||||
/* Back to world-space. */
|
||||
mul_m4_v3(obmat, r_loc);
|
||||
mul_m4_v3(obmat, sctx->ret.loc);
|
||||
|
||||
if (r_no) {
|
||||
copy_v3_v3(r_no, hit.no);
|
||||
mul_transposed_mat3_m4_v3(imat, r_no);
|
||||
normalize_v3(r_no);
|
||||
}
|
||||
mul_transposed_mat3_m4_v3(imat, sctx->ret.no);
|
||||
normalize_v3(sctx->ret.no);
|
||||
|
||||
sctx->ret.ray_depth_max = hit.dist;
|
||||
sctx->ret.index = looptri_polys[hit.index];
|
||||
retval = true;
|
||||
|
||||
if (r_index) {
|
||||
*r_index = looptri_polys[hit.index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -225,13 +216,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
|
|||
static bool nearest_world_mesh(SnapObjectContext *sctx,
|
||||
const Mesh *me_eval,
|
||||
const float (*obmat)[4],
|
||||
bool use_hide,
|
||||
const float init_co[3],
|
||||
const float curr_co[3],
|
||||
float *r_dist_sq,
|
||||
float *r_loc,
|
||||
float *r_no,
|
||||
int *r_index)
|
||||
bool use_hide)
|
||||
{
|
||||
BVHTreeFromMesh treedata;
|
||||
snap_object_data_mesh_get(me_eval, use_hide, &treedata);
|
||||
|
@ -239,17 +224,7 @@ static bool nearest_world_mesh(SnapObjectContext *sctx,
|
|||
return false;
|
||||
}
|
||||
|
||||
return nearest_world_tree(sctx,
|
||||
treedata.tree,
|
||||
treedata.nearest_callback,
|
||||
&treedata,
|
||||
obmat,
|
||||
init_co,
|
||||
curr_co,
|
||||
r_dist_sq,
|
||||
r_loc,
|
||||
r_no,
|
||||
r_index);
|
||||
return nearest_world_tree(sctx, treedata.tree, treedata.nearest_callback, &treedata, obmat);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -391,10 +366,7 @@ static void cb_mlooptri_verts_get(const int index, const Nearest2dUserData *data
|
|||
r_v_index[2] = corner_verts[looptri->tri[2]];
|
||||
}
|
||||
|
||||
void nearest2d_data_init_mesh(const Mesh *mesh,
|
||||
bool is_persp,
|
||||
bool use_backface_culling,
|
||||
Nearest2dUserData *r_nearest2d)
|
||||
void nearest2d_data_init_mesh(const Mesh *mesh, Nearest2dUserData *r_nearest2d)
|
||||
{
|
||||
r_nearest2d->get_vert_co = cb_mvert_co_get;
|
||||
r_nearest2d->get_edge_verts_index = cb_medge_verts_get;
|
||||
|
@ -408,9 +380,6 @@ void nearest2d_data_init_mesh(const Mesh *mesh,
|
|||
r_nearest2d->corner_verts = mesh->corner_verts().data();
|
||||
r_nearest2d->corner_edges = mesh->corner_edges().data();
|
||||
r_nearest2d->looptris = mesh->looptris().data();
|
||||
|
||||
r_nearest2d->is_persp = is_persp;
|
||||
r_nearest2d->use_backface_culling = use_backface_culling;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -424,28 +393,20 @@ eSnapMode snap_polygon_mesh(SnapObjectContext *sctx,
|
|||
ID *id,
|
||||
const float obmat[4][4],
|
||||
eSnapMode snap_to_flag,
|
||||
int polygon,
|
||||
const float clip_planes_local[MAX_CLIPPLANE_LEN][4])
|
||||
int polygon)
|
||||
{
|
||||
eSnapMode elem = SCE_SNAP_MODE_NONE;
|
||||
|
||||
Mesh *mesh_eval = reinterpret_cast<Mesh *>(id);
|
||||
|
||||
float lpmat[4][4];
|
||||
mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
|
||||
|
||||
DistProjectedAABBPrecalc neasrest_precalc;
|
||||
dist_squared_to_projected_aabb_precalc(
|
||||
&neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval);
|
||||
Nearest2dUserData nearest2d(sctx, sctx->ret.dist_px_sq, float4x4(obmat));
|
||||
nearest2d.clip_planes_get(sctx, float4x4(obmat));
|
||||
nearest2d_data_init_mesh(mesh_eval, &nearest2d);
|
||||
|
||||
BVHTreeNearest nearest{};
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = sctx->ret.dist_px_sq;
|
||||
|
||||
Nearest2dUserData nearest2d;
|
||||
nearest2d_data_init_mesh(
|
||||
mesh_eval, sctx->runtime.is_persp, sctx->runtime.params.use_backface_culling, &nearest2d);
|
||||
|
||||
const blender::IndexRange poly = mesh_eval->polys()[polygon];
|
||||
|
||||
if (snap_to_flag & SCE_SNAP_MODE_EDGE) {
|
||||
|
@ -455,9 +416,9 @@ eSnapMode snap_polygon_mesh(SnapObjectContext *sctx,
|
|||
for (int i = poly.size(); i--;) {
|
||||
cb_snap_edge(&nearest2d,
|
||||
poly_edges[i],
|
||||
&neasrest_precalc,
|
||||
clip_planes_local,
|
||||
sctx->runtime.clip_plane_len,
|
||||
&nearest2d.nearest_precalc,
|
||||
reinterpret_cast<float(*)[4]>(nearest2d.clip_planes.data()),
|
||||
nearest2d.clip_planes.size(),
|
||||
&nearest);
|
||||
}
|
||||
}
|
||||
|
@ -467,9 +428,9 @@ eSnapMode snap_polygon_mesh(SnapObjectContext *sctx,
|
|||
for (int i = poly.size(); i--;) {
|
||||
cb_snap_vert(&nearest2d,
|
||||
poly_verts[i],
|
||||
&neasrest_precalc,
|
||||
clip_planes_local,
|
||||
sctx->runtime.clip_plane_len,
|
||||
&nearest2d.nearest_precalc,
|
||||
reinterpret_cast<float(*)[4]>(nearest2d.clip_planes.data()),
|
||||
nearest2d.clip_planes.size(),
|
||||
&nearest);
|
||||
}
|
||||
}
|
||||
|
@ -500,13 +461,7 @@ static eSnapMode snapMesh(SnapObjectContext *sctx,
|
|||
Object *ob_eval,
|
||||
const Mesh *me_eval,
|
||||
const float obmat[4][4],
|
||||
bool use_hide,
|
||||
/* read/write args */
|
||||
float *dist_px_sq,
|
||||
/* return args */
|
||||
float r_loc[3],
|
||||
float r_no[3],
|
||||
int *r_index)
|
||||
bool use_hide)
|
||||
{
|
||||
BLI_assert(sctx->runtime.snap_to_flag != SCE_SNAP_MODE_FACE);
|
||||
if (me_eval->totvert == 0) {
|
||||
|
@ -516,19 +471,11 @@ static eSnapMode snapMesh(SnapObjectContext *sctx,
|
|||
return SCE_SNAP_MODE_NONE;
|
||||
}
|
||||
|
||||
float lpmat[4][4];
|
||||
mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
|
||||
Nearest2dUserData nearest2d(sctx, sctx->ret.dist_px_sq, float4x4(obmat));
|
||||
|
||||
/* Test BoundBox */
|
||||
if (ob_eval->data == me_eval) {
|
||||
const BoundBox *bb = BKE_object_boundbox_get(ob_eval);
|
||||
if (!snap_bound_box_check_dist(bb->vec[0],
|
||||
bb->vec[6],
|
||||
lpmat,
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
*dist_px_sq))
|
||||
{
|
||||
const BoundBox *bb = BKE_mesh_boundbox_get(ob_eval);
|
||||
if (!nearest2d.snap_boundbox(bb->vec[0], bb->vec[6])) {
|
||||
return SCE_SNAP_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
@ -544,32 +491,25 @@ static eSnapMode snapMesh(SnapObjectContext *sctx,
|
|||
BLI_assert(treedata_dummy.cached);
|
||||
}
|
||||
|
||||
Nearest2dUserData nearest2d;
|
||||
nearest2d_data_init_mesh(
|
||||
me_eval, sctx->runtime.is_persp, sctx->runtime.params.use_backface_culling, &nearest2d);
|
||||
nearest2d.clip_planes_get(sctx, float4x4(obmat));
|
||||
nearest2d_data_init_mesh(me_eval, &nearest2d);
|
||||
|
||||
BVHTreeNearest nearest{};
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = *dist_px_sq;
|
||||
nearest.dist_sq = sctx->ret.dist_px_sq;
|
||||
|
||||
int last_index = nearest.index;
|
||||
eSnapMode elem = SCE_SNAP_MODE_VERTEX;
|
||||
|
||||
float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
|
||||
transpose_m4_m4(tobmat, obmat);
|
||||
for (int i = sctx->runtime.clip_plane_len; i--;) {
|
||||
mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]);
|
||||
}
|
||||
|
||||
if (bvhtree[1]) {
|
||||
BLI_assert(sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX);
|
||||
/* snap to loose verts */
|
||||
BLI_bvhtree_find_nearest_projected(bvhtree[1],
|
||||
lpmat,
|
||||
nearest2d.pmat_local.ptr(),
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
clip_planes_local,
|
||||
sctx->runtime.clip_plane_len,
|
||||
reinterpret_cast<float(*)[4]>(nearest2d.clip_planes.data()),
|
||||
nearest2d.clip_planes.size(),
|
||||
&nearest,
|
||||
cb_snap_vert,
|
||||
&nearest2d);
|
||||
|
@ -580,28 +520,30 @@ static eSnapMode snapMesh(SnapObjectContext *sctx,
|
|||
if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
|
||||
if (bvhtree[0]) {
|
||||
/* Snap to loose edges. */
|
||||
BLI_bvhtree_find_nearest_projected(bvhtree[0],
|
||||
lpmat,
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
clip_planes_local,
|
||||
sctx->runtime.clip_plane_len,
|
||||
&nearest,
|
||||
cb_snap_edge,
|
||||
&nearest2d);
|
||||
BLI_bvhtree_find_nearest_projected(
|
||||
bvhtree[0],
|
||||
nearest2d.pmat_local.ptr(),
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
reinterpret_cast<float(*)[4]>(nearest2d.clip_planes.data()),
|
||||
nearest2d.clip_planes.size(),
|
||||
&nearest,
|
||||
cb_snap_edge,
|
||||
&nearest2d);
|
||||
}
|
||||
|
||||
if (treedata.tree) {
|
||||
/* Snap to looptris. */
|
||||
BLI_bvhtree_find_nearest_projected(treedata.tree,
|
||||
lpmat,
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
clip_planes_local,
|
||||
sctx->runtime.clip_plane_len,
|
||||
&nearest,
|
||||
cb_snap_tri_edges,
|
||||
&nearest2d);
|
||||
BLI_bvhtree_find_nearest_projected(
|
||||
treedata.tree,
|
||||
nearest2d.pmat_local.ptr(),
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
reinterpret_cast<float(*)[4]>(nearest2d.clip_planes.data()),
|
||||
nearest2d.clip_planes.size(),
|
||||
&nearest,
|
||||
cb_snap_tri_edges,
|
||||
&nearest2d);
|
||||
}
|
||||
|
||||
if (last_index != nearest.index) {
|
||||
|
@ -612,48 +554,47 @@ static eSnapMode snapMesh(SnapObjectContext *sctx,
|
|||
BLI_assert(sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX);
|
||||
if (bvhtree[0]) {
|
||||
/* Snap to loose edge verts. */
|
||||
BLI_bvhtree_find_nearest_projected(bvhtree[0],
|
||||
lpmat,
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
clip_planes_local,
|
||||
sctx->runtime.clip_plane_len,
|
||||
&nearest,
|
||||
cb_snap_edge_verts,
|
||||
&nearest2d);
|
||||
BLI_bvhtree_find_nearest_projected(
|
||||
bvhtree[0],
|
||||
nearest2d.pmat_local.ptr(),
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
reinterpret_cast<float(*)[4]>(nearest2d.clip_planes.data()),
|
||||
nearest2d.clip_planes.size(),
|
||||
&nearest,
|
||||
cb_snap_edge_verts,
|
||||
&nearest2d);
|
||||
}
|
||||
|
||||
if (treedata.tree) {
|
||||
/* Snap to looptri verts. */
|
||||
BLI_bvhtree_find_nearest_projected(treedata.tree,
|
||||
lpmat,
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
clip_planes_local,
|
||||
sctx->runtime.clip_plane_len,
|
||||
&nearest,
|
||||
cb_snap_tri_verts,
|
||||
&nearest2d);
|
||||
BLI_bvhtree_find_nearest_projected(
|
||||
treedata.tree,
|
||||
nearest2d.pmat_local.ptr(),
|
||||
sctx->runtime.win_size,
|
||||
sctx->runtime.mval,
|
||||
reinterpret_cast<float(*)[4]>(nearest2d.clip_planes.data()),
|
||||
nearest2d.clip_planes.size(),
|
||||
&nearest,
|
||||
cb_snap_tri_verts,
|
||||
&nearest2d);
|
||||
}
|
||||
}
|
||||
|
||||
if (nearest.index != -1) {
|
||||
*dist_px_sq = nearest.dist_sq;
|
||||
copy_v3_v3(sctx->ret.loc, nearest.co);
|
||||
copy_v3_v3(sctx->ret.no, nearest.no);
|
||||
|
||||
copy_v3_v3(r_loc, nearest.co);
|
||||
mul_m4_v3(obmat, r_loc);
|
||||
mul_m4_v3(obmat, sctx->ret.loc);
|
||||
|
||||
if (r_no) {
|
||||
float imat[4][4];
|
||||
invert_m4_m4(imat, obmat);
|
||||
float imat[3][3];
|
||||
copy_m3_m4(imat, obmat);
|
||||
invert_m3(imat);
|
||||
mul_transposed_m3_v3(imat, sctx->ret.no);
|
||||
normalize_v3(sctx->ret.no);
|
||||
|
||||
copy_v3_v3(r_no, nearest.no);
|
||||
mul_transposed_mat3_m4_v3(imat, r_no);
|
||||
normalize_v3(r_no);
|
||||
}
|
||||
if (r_index) {
|
||||
*r_index = nearest.index;
|
||||
}
|
||||
sctx->ret.index = nearest.index;
|
||||
sctx->ret.dist_px_sq = nearest.dist_sq;
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
@ -694,51 +635,20 @@ eSnapMode snap_object_mesh(SnapObjectContext *sctx,
|
|||
if (snap_mode_used & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT |
|
||||
SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_VERTEX))
|
||||
{
|
||||
elem = snapMesh(sctx,
|
||||
ob_eval,
|
||||
mesh_eval,
|
||||
obmat,
|
||||
use_hide,
|
||||
&sctx->ret.dist_px_sq,
|
||||
sctx->ret.loc,
|
||||
sctx->ret.no,
|
||||
&sctx->ret.index);
|
||||
elem = snapMesh(sctx, ob_eval, mesh_eval, obmat, use_hide);
|
||||
if (elem) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
|
||||
if (snap_mode_used & SCE_SNAP_MODE_FACE) {
|
||||
if (raycastMesh(sctx,
|
||||
ob_eval,
|
||||
mesh_eval,
|
||||
obmat,
|
||||
sctx->runtime.object_index++,
|
||||
use_hide,
|
||||
/* read/write args */
|
||||
&sctx->ret.ray_depth_max,
|
||||
/* return args */
|
||||
sctx->ret.loc,
|
||||
sctx->ret.no,
|
||||
&sctx->ret.index,
|
||||
sctx->ret.hit_list))
|
||||
{
|
||||
if (raycastMesh(sctx, ob_eval, mesh_eval, obmat, sctx->runtime.object_index++, use_hide)) {
|
||||
return SCE_SNAP_MODE_FACE;
|
||||
}
|
||||
}
|
||||
|
||||
if (snap_mode_used & SCE_SNAP_MODE_FACE_NEAREST) {
|
||||
if (nearest_world_mesh(sctx,
|
||||
mesh_eval,
|
||||
obmat,
|
||||
use_hide,
|
||||
sctx->runtime.init_co,
|
||||
sctx->runtime.curr_co,
|
||||
&sctx->ret.dist_px_sq,
|
||||
sctx->ret.loc,
|
||||
sctx->ret.no,
|
||||
&sctx->ret.index))
|
||||
{
|
||||
if (nearest_world_mesh(sctx, mesh_eval, obmat, use_hide)) {
|
||||
return SCE_SNAP_MODE_FACE_NEAREST;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* SPDX-FileCopyrightText: 2019 Stefano Quer
|
||||
SPDX-FileCopyrightText: 2022 Blender Foundation
|
||||
* SPDX-FileCopyrightText: 2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* SPDX-FileCopyrightText: 2019 Stefano Quer
|
||||
SPDX-FileCopyrightText: 2022 Blender Foundation
|
||||
* SPDX-FileCopyrightText: 2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
|
|
|
@ -1602,7 +1602,7 @@ static const EnumPropertyItem pack_shape_method_items[] = {
|
|||
* \note #ED_UVPACK_PIN_NONE is exposed as a boolean "pin".
|
||||
* \note #ED_UVPACK_PIN_IGNORE is intentionally not exposed as it is confusing from the UI level
|
||||
* (users can simply not select these islands).
|
||||
* The option is kept kept internally because it's used for live unwrap.
|
||||
* The option is kept internally because it's used for live unwrap.
|
||||
*/
|
||||
static const EnumPropertyItem pinned_islands_method_items[] = {
|
||||
{ED_UVPACK_PIN_LOCK_SCALE, "SCALE", 0, "Scale", "Pinned islands won't rescale"},
|
||||
|
|
|
@ -110,7 +110,7 @@ class MTLUniformBuf;
|
|||
class MTLBuffer {
|
||||
|
||||
public:
|
||||
/* NOTE: ListBase API is not used due to cutsom destructor operation required to release
|
||||
/* NOTE: ListBase API is not used due to custom destructor operation required to release
|
||||
* Metal objective C buffer resource. */
|
||||
gpu::MTLBuffer *next, *prev;
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ static void test_framebuffer_scissor_test()
|
|||
}
|
||||
GPU_TEST(framebuffer_scissor_test);
|
||||
|
||||
/* Color each side of a cubemap with a different color. */
|
||||
/* Color each side of a cube-map with a different color. */
|
||||
static void test_framebuffer_cube()
|
||||
{
|
||||
const int SIZE = 32;
|
||||
|
|
|
@ -28,12 +28,12 @@ namespace blender::gpu {
|
|||
*
|
||||
* When using a GPU_TEXTURE_CUBE as an frame buffer attachment it will be used as a
|
||||
* GPU_TEXTURE_2D_ARRAY. eg only a single side of the cube map will be attached. But when bound as
|
||||
* a shader resource the cubemap will be used.
|
||||
* a shader resource the cube-map will be used.
|
||||
*/
|
||||
enum class eImageViewUsage {
|
||||
/** Image View will be used as a bindable shader resource. */
|
||||
ShaderBinding,
|
||||
/** Image View will be used as an framebuffer attachment. */
|
||||
/** Image View will be used as an frame-buffer attachment. */
|
||||
Attachment,
|
||||
};
|
||||
|
||||
|
|
|
@ -188,12 +188,12 @@ using FormatF10 = FloatingPointFormat<false, 5, 5>;
|
|||
*/
|
||||
template<
|
||||
/**
|
||||
* FloatingPointFormat of the the value that is converted to.
|
||||
* FloatingPointFormat of the value that is converted to.
|
||||
*/
|
||||
typename DestinationFormat,
|
||||
|
||||
/**
|
||||
* FloatingPointFormat of the the value that is converted from.
|
||||
* FloatingPointFormat of the value that is converted from.
|
||||
*/
|
||||
typename SourceFormat,
|
||||
|
||||
|
|
|
@ -180,11 +180,12 @@ static ImBuf *get_oiio_ibuf(ImageInput *in, const ReadContext &ctx, char colorsp
|
|||
const ImageSpec &spec = in->spec();
|
||||
const int width = spec.width;
|
||||
const int height = spec.height;
|
||||
const int channels = spec.nchannels;
|
||||
const bool has_alpha = spec.alpha_channel != -1;
|
||||
const bool is_float = spec.format.basesize() > 1;
|
||||
|
||||
if (channels < 1 || channels > 4) {
|
||||
/* Only a maximum of 4 channels are supported by ImBuf. */
|
||||
const int channels = spec.nchannels <= 4 ? spec.nchannels : 4;
|
||||
if (channels < 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ class AbcObjectReader {
|
|||
|
||||
/* XXX - TODO(kevindietrich) : this references stack memory... */
|
||||
ImportSettings *m_settings;
|
||||
/* This is initialised from the ImportSettings above on construction. It will need to be removed
|
||||
/* This is initialized from the ImportSettings above on construction. It will need to be removed
|
||||
* once we fix the stack memory reference situation. */
|
||||
bool m_is_reading_a_file_sequence = false;
|
||||
|
||||
|
|
|
@ -1661,7 +1661,7 @@ typedef struct NodeGeometrySimulationOutput {
|
|||
|
||||
#ifdef __cplusplus
|
||||
blender::Span<NodeSimulationItem> items_span() const;
|
||||
blender::MutableSpan<NodeSimulationItem> items_span_for_write();
|
||||
blender::MutableSpan<NodeSimulationItem> items_span();
|
||||
blender::IndexRange items_range() const;
|
||||
#endif
|
||||
} NodeGeometrySimulationOutput;
|
||||
|
|
|
@ -25,6 +25,10 @@ struct Object;
|
|||
struct PreviewImage;
|
||||
struct Tex;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #MTex
|
||||
* \{ */
|
||||
|
||||
typedef struct MTex {
|
||||
DNA_DEFINE_CXX_METHODS(MTex)
|
||||
|
||||
|
@ -60,6 +64,12 @@ typedef struct MTex {
|
|||
float twistfac;
|
||||
} MTex;
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #ColorBand
|
||||
* \{ */
|
||||
|
||||
#ifndef DNA_USHORT_FIX
|
||||
# define DNA_USHORT_FIX
|
||||
/**
|
||||
|
@ -88,6 +98,12 @@ typedef struct ColorBand {
|
|||
CBData data[32];
|
||||
} ColorBand;
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #PointDensity
|
||||
* \{ */
|
||||
|
||||
typedef struct PointDensity {
|
||||
DNA_DEFINE_CXX_METHODS(PointDensity)
|
||||
|
||||
|
@ -138,6 +154,12 @@ typedef struct PointDensity {
|
|||
struct CurveMapping *falloff_curve;
|
||||
} PointDensity;
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #Tex
|
||||
* \{ */
|
||||
|
||||
typedef struct Tex {
|
||||
DNA_DEFINE_CXX_METHODS(Tex)
|
||||
|
||||
|
@ -235,221 +257,301 @@ typedef struct ColorMapping {
|
|||
char _pad[4];
|
||||
} ColorMapping;
|
||||
|
||||
/* texmap->flag */
|
||||
#define TEXMAP_CLIP_MIN 1
|
||||
#define TEXMAP_CLIP_MAX 2
|
||||
#define TEXMAP_UNIT_MATRIX 4
|
||||
/** \} */
|
||||
|
||||
/* texmap->type */
|
||||
#define TEXMAP_TYPE_POINT 0
|
||||
#define TEXMAP_TYPE_TEXTURE 1
|
||||
#define TEXMAP_TYPE_VECTOR 2
|
||||
#define TEXMAP_TYPE_NORMAL 3
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #TexMapping Types
|
||||
* \{ */
|
||||
|
||||
/* colormap->flag */
|
||||
#define COLORMAP_USE_RAMP 1
|
||||
/** #TexMapping::flag bit-mask. */
|
||||
enum {
|
||||
TEXMAP_CLIP_MIN = 1 << 0,
|
||||
TEXMAP_CLIP_MAX = 1 << 1,
|
||||
TEXMAP_UNIT_MATRIX = 1 << 2,
|
||||
};
|
||||
|
||||
/* **************** TEX ********************* */
|
||||
/** #TexMapping::type. */
|
||||
enum {
|
||||
TEXMAP_TYPE_POINT = 0,
|
||||
TEXMAP_TYPE_TEXTURE = 1,
|
||||
TEXMAP_TYPE_VECTOR = 2,
|
||||
TEXMAP_TYPE_NORMAL = 3,
|
||||
};
|
||||
|
||||
/* type */
|
||||
#define TEX_CLOUDS 1
|
||||
#define TEX_WOOD 2
|
||||
#define TEX_MARBLE 3
|
||||
#define TEX_MAGIC 4
|
||||
#define TEX_BLEND 5
|
||||
#define TEX_STUCCI 6
|
||||
#define TEX_NOISE 7
|
||||
#define TEX_IMAGE 8
|
||||
// #define TEX_PLUGIN 9 /* Deprecated */
|
||||
// #define TEX_ENVMAP 10 /* Deprecated */
|
||||
#define TEX_MUSGRAVE 11
|
||||
#define TEX_VORONOI 12
|
||||
#define TEX_DISTNOISE 13
|
||||
// #define TEX_POINTDENSITY 14 /* Deprecated */
|
||||
// #define TEX_VOXELDATA 15 /* Deprecated */
|
||||
// #define TEX_OCEAN 16 /* Deprecated */
|
||||
/** #ColorMapping::flag bit-mask. */
|
||||
enum {
|
||||
COLORMAP_USE_RAMP = 1,
|
||||
};
|
||||
|
||||
/* musgrave stype */
|
||||
#define TEX_MFRACTAL 0
|
||||
#define TEX_RIDGEDMF 1
|
||||
#define TEX_HYBRIDMF 2
|
||||
#define TEX_FBM 3
|
||||
#define TEX_HTERRAIN 4
|
||||
/** \} */
|
||||
|
||||
/* newnoise: noisebasis 1 & 2 */
|
||||
#define TEX_BLENDER 0
|
||||
#define TEX_STDPERLIN 1
|
||||
#define TEX_NEWPERLIN 2
|
||||
#define TEX_VORONOI_F1 3
|
||||
#define TEX_VORONOI_F2 4
|
||||
#define TEX_VORONOI_F3 5
|
||||
#define TEX_VORONOI_F4 6
|
||||
#define TEX_VORONOI_F2F1 7
|
||||
#define TEX_VORONOI_CRACKLE 8
|
||||
#define TEX_CELLNOISE 14
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #Tex Types
|
||||
* \{ */
|
||||
|
||||
/* newnoise: Voronoi distance metrics, vn_distm */
|
||||
#define TEX_DISTANCE 0
|
||||
#define TEX_DISTANCE_SQUARED 1
|
||||
#define TEX_MANHATTAN 2
|
||||
#define TEX_CHEBYCHEV 3
|
||||
#define TEX_MINKOVSKY_HALF 4
|
||||
#define TEX_MINKOVSKY_FOUR 5
|
||||
#define TEX_MINKOVSKY 6
|
||||
/** #Tex::type. */
|
||||
enum {
|
||||
TEX_CLOUDS = 1,
|
||||
TEX_WOOD = 2,
|
||||
TEX_MARBLE = 3,
|
||||
TEX_MAGIC = 4,
|
||||
TEX_BLEND = 5,
|
||||
TEX_STUCCI = 6,
|
||||
TEX_NOISE = 7,
|
||||
TEX_IMAGE = 8,
|
||||
// TEX_PLUGIN = 9, /* Deprecated */
|
||||
// TEX_ENVMAP = 10, /* Deprecated */
|
||||
TEX_MUSGRAVE = 11,
|
||||
TEX_VORONOI = 12,
|
||||
TEX_DISTNOISE = 13,
|
||||
// TEX_POINTDENSITY = 14, /* Deprecated */
|
||||
// TEX_VOXELDATA = 15, /* Deprecated */
|
||||
// TEX_OCEAN = 16, /* Deprecated */
|
||||
};
|
||||
|
||||
/* imaflag */
|
||||
#define TEX_INTERPOL (1 << 0)
|
||||
#define TEX_USEALPHA (1 << 1)
|
||||
#define TEX_MIPMAP (1 << 2)
|
||||
#define TEX_IMAROT (1 << 4)
|
||||
#define TEX_CALCALPHA (1 << 5)
|
||||
#define TEX_NORMALMAP (1 << 11)
|
||||
#define TEX_GAUSS_MIP (1 << 12)
|
||||
#define TEX_FILTER_MIN (1 << 13)
|
||||
#define TEX_DERIVATIVEMAP (1 << 14)
|
||||
/** #Tex::stype musgrave. */
|
||||
enum {
|
||||
TEX_MFRACTAL = 0,
|
||||
TEX_RIDGEDMF = 1,
|
||||
TEX_HYBRIDMF = 2,
|
||||
TEX_FBM = 3,
|
||||
TEX_HTERRAIN = 4,
|
||||
};
|
||||
|
||||
/* texfilter */
|
||||
#define TXF_BOX 0 /* Blender's old texture filtering method. */
|
||||
#define TXF_EWA 1
|
||||
#define TXF_FELINE 2
|
||||
#define TXF_AREA 3
|
||||
/** #Tex::noisebasis, #Tex::noisebasis2. */
|
||||
enum {
|
||||
TEX_BLENDER = 0,
|
||||
TEX_STDPERLIN = 1,
|
||||
TEX_NEWPERLIN = 2,
|
||||
TEX_VORONOI_F1 = 3,
|
||||
TEX_VORONOI_F2 = 4,
|
||||
TEX_VORONOI_F3 = 5,
|
||||
TEX_VORONOI_F4 = 6,
|
||||
TEX_VORONOI_F2F1 = 7,
|
||||
TEX_VORONOI_CRACKLE = 8,
|
||||
TEX_CELLNOISE = 14,
|
||||
};
|
||||
|
||||
/** #Tex::vn_distm voronoi distance metrics. */
|
||||
enum {
|
||||
TEX_DISTANCE = 0,
|
||||
TEX_DISTANCE_SQUARED = 1,
|
||||
TEX_MANHATTAN = 2,
|
||||
TEX_CHEBYCHEV = 3,
|
||||
TEX_MINKOVSKY_HALF = 4,
|
||||
TEX_MINKOVSKY_FOUR = 5,
|
||||
TEX_MINKOVSKY = 6,
|
||||
};
|
||||
|
||||
/** #Tex::imaflag bit-mask. */
|
||||
enum {
|
||||
TEX_INTERPOL = 1 << 0,
|
||||
TEX_USEALPHA = 1 << 1,
|
||||
TEX_MIPMAP = 1 << 2,
|
||||
TEX_IMAROT = 1 << 4,
|
||||
TEX_CALCALPHA = 1 << 5,
|
||||
TEX_NORMALMAP = 1 << 11,
|
||||
TEX_GAUSS_MIP = 1 << 12,
|
||||
TEX_FILTER_MIN = 1 << 13,
|
||||
TEX_DERIVATIVEMAP = 1 << 14,
|
||||
};
|
||||
|
||||
/** #Tex::texfilter type. */
|
||||
enum {
|
||||
TXF_BOX = 0, /* Blender's old texture filtering method. */
|
||||
TXF_EWA = 1,
|
||||
TXF_FELINE = 2,
|
||||
TXF_AREA = 3,
|
||||
};
|
||||
|
||||
/** #Tex::flag bit-mask. */
|
||||
enum {
|
||||
TEX_COLORBAND = 1 << 0,
|
||||
TEX_FLIPBLEND = 1 << 1,
|
||||
TEX_NEGALPHA = 1 << 2,
|
||||
TEX_CHECKER_ODD = 1 << 3,
|
||||
TEX_CHECKER_EVEN = 1 << 4,
|
||||
TEX_PRV_ALPHA = 1 << 5,
|
||||
TEX_PRV_NOR = 1 << 6,
|
||||
TEX_REPEAT_XMIR = 1 << 7,
|
||||
TEX_REPEAT_YMIR = 1 << 8,
|
||||
TEX_DS_EXPAND = 1 << 9,
|
||||
TEX_NO_CLAMP = 1 << 10,
|
||||
};
|
||||
|
||||
/* flag */
|
||||
#define TEX_COLORBAND (1 << 0)
|
||||
#define TEX_FLIPBLEND (1 << 1)
|
||||
#define TEX_NEGALPHA (1 << 2)
|
||||
#define TEX_CHECKER_ODD (1 << 3)
|
||||
#define TEX_CHECKER_EVEN (1 << 4)
|
||||
#define TEX_PRV_ALPHA (1 << 5)
|
||||
#define TEX_PRV_NOR (1 << 6)
|
||||
#define TEX_REPEAT_XMIR (1 << 7)
|
||||
#define TEX_REPEAT_YMIR (1 << 8)
|
||||
#define TEX_FLAG_MASK \
|
||||
(TEX_COLORBAND | TEX_FLIPBLEND | TEX_NEGALPHA | TEX_CHECKER_ODD | TEX_CHECKER_EVEN | \
|
||||
TEX_PRV_ALPHA | TEX_PRV_NOR | TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)
|
||||
#define TEX_DS_EXPAND (1 << 9)
|
||||
#define TEX_NO_CLAMP (1 << 10)
|
||||
|
||||
/* extend (starts with 1 because of backward comp.) */
|
||||
#define TEX_EXTEND 1
|
||||
#define TEX_CLIP 2
|
||||
#define TEX_REPEAT 3
|
||||
#define TEX_CLIPCUBE 4
|
||||
#define TEX_CHECKER 5
|
||||
/** #Tex::extend (starts with 1 because of backward compatibility). */
|
||||
enum {
|
||||
TEX_EXTEND = 1,
|
||||
TEX_CLIP = 2,
|
||||
TEX_REPEAT = 3,
|
||||
TEX_CLIPCUBE = 4,
|
||||
TEX_CHECKER = 5,
|
||||
};
|
||||
|
||||
/* noisetype */
|
||||
#define TEX_NOISESOFT 0
|
||||
#define TEX_NOISEPERL 1
|
||||
/** #Tex::noisetype type. */
|
||||
enum {
|
||||
TEX_NOISESOFT = 0,
|
||||
TEX_NOISEPERL = 1,
|
||||
};
|
||||
|
||||
/* tex->noisebasis2 in texture.c - wood waveforms */
|
||||
#define TEX_SIN 0
|
||||
#define TEX_SAW 1
|
||||
#define TEX_TRI 2
|
||||
/** #Tex::noisebasis2 wood waveforms. */
|
||||
enum {
|
||||
TEX_SIN = 0,
|
||||
TEX_SAW = 1,
|
||||
TEX_TRI = 2,
|
||||
};
|
||||
|
||||
/* tex->stype in texture.c - wood types */
|
||||
#define TEX_BAND 0
|
||||
#define TEX_RING 1
|
||||
#define TEX_BANDNOISE 2
|
||||
#define TEX_RINGNOISE 3
|
||||
/** #Tex::stype wood types. */
|
||||
enum {
|
||||
TEX_BAND = 0,
|
||||
TEX_RING = 1,
|
||||
TEX_BANDNOISE = 2,
|
||||
TEX_RINGNOISE = 3,
|
||||
};
|
||||
|
||||
/* tex->stype in texture.c - cloud types */
|
||||
#define TEX_DEFAULT 0
|
||||
#define TEX_COLOR 1
|
||||
/** #Tex::stype cloud types. */
|
||||
enum {
|
||||
TEX_DEFAULT = 0,
|
||||
TEX_COLOR = 1,
|
||||
};
|
||||
|
||||
/* tex->stype in texture.c - marble types */
|
||||
#define TEX_SOFT 0
|
||||
#define TEX_SHARP 1
|
||||
#define TEX_SHARPER 2
|
||||
/** #Tex::stype marble types. */
|
||||
enum {
|
||||
TEX_SOFT = 0,
|
||||
TEX_SHARP = 1,
|
||||
TEX_SHARPER = 2,
|
||||
};
|
||||
|
||||
/* tex->stype in texture.c - blend types */
|
||||
#define TEX_LIN 0
|
||||
#define TEX_QUAD 1
|
||||
#define TEX_EASE 2
|
||||
#define TEX_DIAG 3
|
||||
#define TEX_SPHERE 4
|
||||
#define TEX_HALO 5
|
||||
#define TEX_RAD 6
|
||||
/** #Tex::stype blend types. */
|
||||
enum {
|
||||
TEX_LIN = 0,
|
||||
TEX_QUAD = 1,
|
||||
TEX_EASE = 2,
|
||||
TEX_DIAG = 3,
|
||||
TEX_SPHERE = 4,
|
||||
TEX_HALO = 5,
|
||||
TEX_RAD = 6,
|
||||
};
|
||||
|
||||
/* tex->stype in texture.c - stucci types */
|
||||
#define TEX_PLASTIC 0
|
||||
#define TEX_WALLIN 1
|
||||
#define TEX_WALLOUT 2
|
||||
/** #Tex::stype stucci types. */
|
||||
enum {
|
||||
TEX_PLASTIC = 0,
|
||||
TEX_WALLIN = 1,
|
||||
TEX_WALLOUT = 2,
|
||||
};
|
||||
|
||||
/* tex->stype in texture.c - voronoi types */
|
||||
#define TEX_INTENSITY 0
|
||||
#define TEX_COL1 1
|
||||
#define TEX_COL2 2
|
||||
#define TEX_COL3 3
|
||||
/** #Tex::vn_coltype voronoi color types. */
|
||||
enum {
|
||||
TEX_INTENSITY = 0,
|
||||
TEX_COL1 = 1,
|
||||
TEX_COL2 = 2,
|
||||
TEX_COL3 = 3,
|
||||
};
|
||||
|
||||
/* mtex->normapspace */
|
||||
#define MTEX_NSPACE_CAMERA 0
|
||||
#define MTEX_NSPACE_WORLD 1
|
||||
#define MTEX_NSPACE_OBJECT 2
|
||||
#define MTEX_NSPACE_TANGENT 3
|
||||
/** Return value. */
|
||||
enum {
|
||||
TEX_INT = 0,
|
||||
TEX_RGB = 1,
|
||||
};
|
||||
|
||||
/* wrap */
|
||||
#define MTEX_FLAT 0
|
||||
#define MTEX_CUBE 1
|
||||
#define MTEX_TUBE 2
|
||||
#define MTEX_SPHERE 3
|
||||
/**
|
||||
* - #Material::pr_texture
|
||||
* - #Light::pr_texture
|
||||
* - #World::pr_texture
|
||||
* - #FreestyleLineStyle::pr_texture
|
||||
*/
|
||||
enum {
|
||||
TEX_PR_TEXTURE = 0,
|
||||
TEX_PR_OTHER = 1,
|
||||
TEX_PR_BOTH = 2,
|
||||
};
|
||||
|
||||
/* return value */
|
||||
#define TEX_INT 0
|
||||
#define TEX_RGB 1
|
||||
/** \} */
|
||||
|
||||
/* pr_texture in material, world, light. */
|
||||
#define TEX_PR_TEXTURE 0
|
||||
#define TEX_PR_OTHER 1
|
||||
#define TEX_PR_BOTH 2
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #TexMapping Types
|
||||
* \{ */
|
||||
|
||||
/* **************** MTEX ********************* */
|
||||
/**
|
||||
* #TexMapping::projx
|
||||
* #TexMapping::projy
|
||||
* #TexMapping::projz
|
||||
*/
|
||||
enum {
|
||||
PROJ_N = 0,
|
||||
PROJ_X = 1,
|
||||
PROJ_Y = 2,
|
||||
PROJ_Z = 3,
|
||||
};
|
||||
|
||||
/* proj */
|
||||
#define PROJ_N 0
|
||||
#define PROJ_X 1
|
||||
#define PROJ_Y 2
|
||||
#define PROJ_Z 3
|
||||
/** \} */
|
||||
|
||||
/* blendtype */
|
||||
#define MTEX_BLEND 0
|
||||
#define MTEX_MUL 1
|
||||
#define MTEX_ADD 2
|
||||
#define MTEX_SUB 3
|
||||
#define MTEX_DIV 4
|
||||
#define MTEX_DARK 5
|
||||
#define MTEX_DIFF 6
|
||||
#define MTEX_LIGHT 7
|
||||
#define MTEX_SCREEN 8
|
||||
#define MTEX_OVERLAY 9
|
||||
#define MTEX_BLEND_HUE 10
|
||||
#define MTEX_BLEND_SAT 11
|
||||
#define MTEX_BLEND_VAL 12
|
||||
#define MTEX_BLEND_COLOR 13
|
||||
#define MTEX_SOFT_LIGHT 15
|
||||
#define MTEX_LIN_LIGHT 16
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #MTex Types
|
||||
* \{ */
|
||||
|
||||
/* brush_map_mode */
|
||||
#define MTEX_MAP_MODE_VIEW 0
|
||||
#define MTEX_MAP_MODE_TILED 1
|
||||
#define MTEX_MAP_MODE_3D 2
|
||||
#define MTEX_MAP_MODE_AREA 3
|
||||
#define MTEX_MAP_MODE_RANDOM 4
|
||||
#define MTEX_MAP_MODE_STENCIL 5
|
||||
/** #MTex::mapping. */
|
||||
enum {
|
||||
MTEX_FLAT = 0,
|
||||
MTEX_CUBE = 1,
|
||||
MTEX_TUBE = 2,
|
||||
MTEX_SPHERE = 3,
|
||||
};
|
||||
|
||||
/* brush_angle_mode */
|
||||
#define MTEX_ANGLE_RANDOM 1
|
||||
#define MTEX_ANGLE_RAKE 2
|
||||
/** #MTex::blendtype. */
|
||||
enum {
|
||||
MTEX_BLEND = 0,
|
||||
MTEX_MUL = 1,
|
||||
MTEX_ADD = 2,
|
||||
MTEX_SUB = 3,
|
||||
MTEX_DIV = 4,
|
||||
MTEX_DARK = 5,
|
||||
MTEX_DIFF = 6,
|
||||
MTEX_LIGHT = 7,
|
||||
MTEX_SCREEN = 8,
|
||||
MTEX_OVERLAY = 9,
|
||||
MTEX_BLEND_HUE = 10,
|
||||
MTEX_BLEND_SAT = 11,
|
||||
MTEX_BLEND_VAL = 12,
|
||||
MTEX_BLEND_COLOR = 13,
|
||||
MTEX_SOFT_LIGHT = 15,
|
||||
MTEX_LIN_LIGHT = 16,
|
||||
};
|
||||
|
||||
/* **************** ColorBand ********************* */
|
||||
/** #MTex::brush_map_mode. */
|
||||
enum {
|
||||
MTEX_MAP_MODE_VIEW = 0,
|
||||
MTEX_MAP_MODE_TILED = 1,
|
||||
MTEX_MAP_MODE_3D = 2,
|
||||
MTEX_MAP_MODE_AREA = 3,
|
||||
MTEX_MAP_MODE_RANDOM = 4,
|
||||
MTEX_MAP_MODE_STENCIL = 5,
|
||||
};
|
||||
|
||||
/** color-mode. */
|
||||
/** #MTex::brush_angle_mode. */
|
||||
enum {
|
||||
MTEX_ANGLE_RANDOM = 1,
|
||||
MTEX_ANGLE_RAKE = 2,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #ColorBand Types
|
||||
* \{ */
|
||||
|
||||
/** #ColorBand::color_mode. */
|
||||
enum {
|
||||
COLBAND_BLEND_RGB = 0,
|
||||
COLBAND_BLEND_HSV = 1,
|
||||
COLBAND_BLEND_HSL = 2,
|
||||
};
|
||||
|
||||
/** Interpolation. */
|
||||
/** #ColorBand::ipotype (interpolation). */
|
||||
enum {
|
||||
COLBAND_INTERP_LINEAR = 0,
|
||||
COLBAND_INTERP_EASE = 1,
|
||||
|
@ -458,7 +560,7 @@ enum {
|
|||
COLBAND_INTERP_CONSTANT = 4,
|
||||
};
|
||||
|
||||
/** Color interpolation. */
|
||||
/** #ColorBand::ipotype_hue (hue interpolation). */
|
||||
enum {
|
||||
COLBAND_HUE_NEAR = 0,
|
||||
COLBAND_HUE_FAR = 1,
|
||||
|
@ -466,38 +568,52 @@ enum {
|
|||
COLBAND_HUE_CCW = 3,
|
||||
};
|
||||
|
||||
/* **************** PointDensity ********************* */
|
||||
/** \} */
|
||||
|
||||
/* source */
|
||||
#define TEX_PD_PSYS 0
|
||||
#define TEX_PD_OBJECT 1
|
||||
#define TEX_PD_FILE 2
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #PointDensity Types
|
||||
* \{ */
|
||||
|
||||
/* falloff_type */
|
||||
#define TEX_PD_FALLOFF_STD 0
|
||||
#define TEX_PD_FALLOFF_SMOOTH 1
|
||||
#define TEX_PD_FALLOFF_SOFT 2
|
||||
#define TEX_PD_FALLOFF_CONSTANT 3
|
||||
#define TEX_PD_FALLOFF_ROOT 4
|
||||
#define TEX_PD_FALLOFF_PARTICLE_AGE 5
|
||||
#define TEX_PD_FALLOFF_PARTICLE_VEL 6
|
||||
/** #PointDensity::source. */
|
||||
enum {
|
||||
TEX_PD_PSYS = 0,
|
||||
TEX_PD_OBJECT = 1,
|
||||
TEX_PD_FILE = 2,
|
||||
};
|
||||
|
||||
/* psys_cache_space */
|
||||
#define TEX_PD_OBJECTLOC 0
|
||||
#define TEX_PD_OBJECTSPACE 1
|
||||
#define TEX_PD_WORLDSPACE 2
|
||||
/** #PointDensity::falloff_type. */
|
||||
enum {
|
||||
TEX_PD_FALLOFF_STD = 0,
|
||||
TEX_PD_FALLOFF_SMOOTH = 1,
|
||||
TEX_PD_FALLOFF_SOFT = 2,
|
||||
TEX_PD_FALLOFF_CONSTANT = 3,
|
||||
TEX_PD_FALLOFF_ROOT = 4,
|
||||
TEX_PD_FALLOFF_PARTICLE_AGE = 5,
|
||||
TEX_PD_FALLOFF_PARTICLE_VEL = 6,
|
||||
};
|
||||
|
||||
/* flag */
|
||||
#define TEX_PD_TURBULENCE 1
|
||||
#define TEX_PD_FALLOFF_CURVE 2
|
||||
/** #PointDensity::psys_cache_space. */
|
||||
enum {
|
||||
TEX_PD_OBJECTLOC = 0,
|
||||
TEX_PD_OBJECTSPACE = 1,
|
||||
TEX_PD_WORLDSPACE = 2,
|
||||
};
|
||||
|
||||
/* noise_influence */
|
||||
#define TEX_PD_NOISE_STATIC 0
|
||||
/* #define TEX_PD_NOISE_VEL 1 */ /* Deprecated */
|
||||
/* #define TEX_PD_NOISE_AGE 2 */ /* Deprecated */
|
||||
/* #define TEX_PD_NOISE_TIME 3 */ /* Deprecated */
|
||||
/** #PointDensity::flag. */
|
||||
enum {
|
||||
TEX_PD_TURBULENCE = 1 << 0,
|
||||
TEX_PD_FALLOFF_CURVE = 1 << 1,
|
||||
};
|
||||
|
||||
/** color_source. */
|
||||
/** #PointDensity::noise_influence. */
|
||||
enum {
|
||||
TEX_PD_NOISE_STATIC = 0,
|
||||
// TEX_PD_NOISE_VEL = 1, /* Deprecated. */
|
||||
// TEX_PD_NOISE_AGE = 2, /* Deprecated. */
|
||||
// TEX_PD_NOISE_TIME = 3, /* Deprecated. */
|
||||
};
|
||||
|
||||
/** #PointDensity::color_source. */
|
||||
enum {
|
||||
TEX_PD_COLOR_CONSTANT = 0,
|
||||
/* color_source: particles */
|
||||
|
@ -510,9 +626,7 @@ enum {
|
|||
TEX_PD_COLOR_VERTNOR = 3,
|
||||
};
|
||||
|
||||
#define POINT_DATA_VEL 1
|
||||
#define POINT_DATA_LIFE 2
|
||||
#define POINT_DATA_COLOR 4
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1425,8 +1425,9 @@ static char *rna_def_property_set_func(
|
|||
/* C++ may require casting to an enum type. */
|
||||
fprintf(f, "#ifdef __cplusplus\n");
|
||||
fprintf(f,
|
||||
/* If #rna_clamp_value() adds an expression like `CLAMPIS(...)` (instead of an
|
||||
lvalue), #decltype() yields a reference, so that has to be removed.*/
|
||||
/* If #rna_clamp_value() adds an expression like `CLAMPIS(...)`
|
||||
* (instead of an `lvalue`), #decltype() yields a reference,
|
||||
* so that has to be removed. */
|
||||
" data->%s = %s(std::remove_reference_t<decltype(data->%s)>)",
|
||||
dp->dnaname,
|
||||
(dp->booleannegative) ? "!" : "",
|
||||
|
|
|
@ -91,9 +91,9 @@ static void rna_Lattice_update_data(Main * /*bmain*/, Scene * /*scene*/, Pointer
|
|||
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
|
||||
}
|
||||
|
||||
/* copy settings to editlattice,
|
||||
* we could split this up differently (one update call per property)
|
||||
* but for now that's overkill
|
||||
/**
|
||||
* Copy settings to edit-lattice, we could split this up differently
|
||||
* (one update call per property) but for now that's overkill.
|
||||
*/
|
||||
static void rna_Lattice_update_data_editlatt(Main * /*bmain*/, Scene * /*scene*/, PointerRNA *ptr)
|
||||
{
|
||||
|
|
|
@ -2202,7 +2202,7 @@ static void rna_SpaceDopeSheetEditor_action_set(PointerRNA *ptr,
|
|||
}
|
||||
}
|
||||
else if (saction->mode == SACTCONT_SHAPEKEY) {
|
||||
/* as the name says, "shapekey-level" only... */
|
||||
/* As the name says, "shape-key level" only. */
|
||||
if (act->idroot == ID_KE) {
|
||||
saction->action = act;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ class DTreeContext {
|
|||
const bNode *parent_node_;
|
||||
/* The current node tree. */
|
||||
const bNodeTree *btree_;
|
||||
/* The instance key of the parent node. NODE_INSTANCE_KEY_BASE for root contexts. */
|
||||
bNodeInstanceKey instance_key_;
|
||||
/* All the children contexts of this context. */
|
||||
Map<const bNode *, DTreeContext *> children_;
|
||||
DerivedNodeTree *derived_tree_;
|
||||
|
@ -56,6 +58,7 @@ class DTreeContext {
|
|||
const bNodeTree &btree() const;
|
||||
const DTreeContext *parent_context() const;
|
||||
const bNode *parent_node() const;
|
||||
const bNodeInstanceKey instance_key() const;
|
||||
const DTreeContext *child_context(const bNode &node) const;
|
||||
const DerivedNodeTree &derived_tree() const;
|
||||
bool is_root() const;
|
||||
|
@ -76,6 +79,7 @@ class DNode {
|
|||
|
||||
const DTreeContext *context() const;
|
||||
const bNode *bnode() const;
|
||||
const bNodeInstanceKey instance_key() const;
|
||||
const bNode *operator->() const;
|
||||
const bNode &operator*() const;
|
||||
|
||||
|
@ -191,6 +195,14 @@ class DerivedNodeTree {
|
|||
const DTreeContext &root_context() const;
|
||||
Span<const bNodeTree *> used_btrees() const;
|
||||
|
||||
/** Returns the active context for the node tree. The active context represents the node tree
|
||||
* currently being edited. In most cases, that would be the top level node tree itself, but in
|
||||
* the case where the user is editing the node tree of a node group, the active context would be
|
||||
* a representation of the node tree of that node group. Note that the context also stores the
|
||||
* group node that the user selected to edit the node tree, so the context fully represents a
|
||||
* particular instance of the node group. */
|
||||
const DTreeContext &active_context() const;
|
||||
|
||||
/**
|
||||
* \return True when there is a link cycle. Unavailable sockets are ignored.
|
||||
*/
|
||||
|
@ -205,7 +217,8 @@ class DerivedNodeTree {
|
|||
private:
|
||||
DTreeContext &construct_context_recursively(DTreeContext *parent_context,
|
||||
const bNode *parent_node,
|
||||
const bNodeTree &btree);
|
||||
const bNodeTree &btree,
|
||||
const bNodeInstanceKey instance_key);
|
||||
void destruct_context_recursively(DTreeContext *context);
|
||||
|
||||
void foreach_node_in_context_recursive(const DTreeContext &context,
|
||||
|
@ -240,6 +253,11 @@ inline const bNode *DTreeContext::parent_node() const
|
|||
return parent_node_;
|
||||
}
|
||||
|
||||
inline const bNodeInstanceKey DTreeContext::instance_key() const
|
||||
{
|
||||
return instance_key_;
|
||||
}
|
||||
|
||||
inline const DTreeContext *DTreeContext::child_context(const bNode &node) const
|
||||
{
|
||||
return children_.lookup_default(&node, nullptr);
|
||||
|
|
|
@ -325,6 +325,11 @@ static void duplicate_curves(GeometrySet &geometry_set,
|
|||
dst_points_num += count * points_by_curve[index].size();
|
||||
});
|
||||
|
||||
if (dst_points_num == 0) {
|
||||
geometry_set.remove_geometry_during_modify();
|
||||
return;
|
||||
}
|
||||
|
||||
curve_offset_data.last() = dst_curves_num;
|
||||
point_offset_data.last() = dst_points_num;
|
||||
|
||||
|
|
|
@ -995,7 +995,7 @@ blender::Span<NodeSimulationItem> NodeGeometrySimulationOutput::items_span() con
|
|||
return blender::Span<NodeSimulationItem>(items, items_num);
|
||||
}
|
||||
|
||||
blender::MutableSpan<NodeSimulationItem> NodeGeometrySimulationOutput::items_span_for_write()
|
||||
blender::MutableSpan<NodeSimulationItem> NodeGeometrySimulationOutput::items_span()
|
||||
{
|
||||
return blender::MutableSpan<NodeSimulationItem>(items, items_num);
|
||||
}
|
||||
|
@ -1077,7 +1077,7 @@ void NOD_geometry_simulation_output_set_active_item(NodeGeometrySimulationOutput
|
|||
NodeSimulationItem *NOD_geometry_simulation_output_find_item(NodeGeometrySimulationOutput *sim,
|
||||
const char *name)
|
||||
{
|
||||
for (NodeSimulationItem &item : sim->items_span_for_write()) {
|
||||
for (NodeSimulationItem &item : sim->items_span()) {
|
||||
if (STREQ(item.name, name)) {
|
||||
return &item;
|
||||
}
|
||||
|
@ -1164,7 +1164,7 @@ void NOD_geometry_simulation_output_remove_item(NodeGeometrySimulationOutput *si
|
|||
|
||||
void NOD_geometry_simulation_output_clear_items(NodeGeometrySimulationOutput *sim)
|
||||
{
|
||||
for (NodeSimulationItem &item : sim->items_span_for_write()) {
|
||||
for (NodeSimulationItem &item : sim->items_span()) {
|
||||
MEM_SAFE_FREE(item.name);
|
||||
}
|
||||
MEM_SAFE_FREE(sim->items);
|
||||
|
|
|
@ -15,12 +15,14 @@ DerivedNodeTree::DerivedNodeTree(const bNodeTree &btree)
|
|||
/* Construct all possible contexts immediately. This is significantly cheaper than inlining all
|
||||
* node groups. If it still becomes a performance issue in the future, contexts could be
|
||||
* constructed lazily when they are needed. */
|
||||
root_context_ = &this->construct_context_recursively(nullptr, nullptr, btree);
|
||||
root_context_ = &this->construct_context_recursively(
|
||||
nullptr, nullptr, btree, NODE_INSTANCE_KEY_BASE);
|
||||
}
|
||||
|
||||
DTreeContext &DerivedNodeTree::construct_context_recursively(DTreeContext *parent_context,
|
||||
const bNode *parent_node,
|
||||
const bNodeTree &btree)
|
||||
const bNodeTree &btree,
|
||||
const bNodeInstanceKey instance_key)
|
||||
{
|
||||
btree.ensure_topology_cache();
|
||||
DTreeContext &context = *allocator_.construct<DTreeContext>().release();
|
||||
|
@ -28,13 +30,16 @@ DTreeContext &DerivedNodeTree::construct_context_recursively(DTreeContext *paren
|
|||
context.parent_node_ = parent_node;
|
||||
context.derived_tree_ = this;
|
||||
context.btree_ = &btree;
|
||||
context.instance_key_ = instance_key;
|
||||
used_btrees_.add(context.btree_);
|
||||
|
||||
for (const bNode *bnode : context.btree_->all_nodes()) {
|
||||
if (bnode->is_group()) {
|
||||
bNodeTree *child_btree = reinterpret_cast<bNodeTree *>(bnode->id);
|
||||
if (child_btree != nullptr) {
|
||||
DTreeContext &child = this->construct_context_recursively(&context, bnode, *child_btree);
|
||||
const bNodeInstanceKey child_key = BKE_node_instance_key(instance_key, &btree, bnode);
|
||||
DTreeContext &child = this->construct_context_recursively(
|
||||
&context, bnode, *child_btree, child_key);
|
||||
context.children_.add_new(bnode, &child);
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +98,11 @@ void DerivedNodeTree::foreach_node_in_context_recursive(const DTreeContext &cont
|
|||
}
|
||||
}
|
||||
|
||||
const bNodeInstanceKey DNode::instance_key() const
|
||||
{
|
||||
return BKE_node_instance_key(context()->instance_key(), &context()->btree(), bnode());
|
||||
}
|
||||
|
||||
DOutputSocket DInputSocket::get_corresponding_group_node_output() const
|
||||
{
|
||||
BLI_assert(*this);
|
||||
|
@ -299,6 +309,51 @@ void DOutputSocket::foreach_target_socket(ForeachTargetSocketFn target_fn,
|
|||
}
|
||||
}
|
||||
|
||||
/* Find the active context from the given context and its descendants contexts. The active context
|
||||
* is the one whose node instance key matches the active_viewer_key stored in the root node tree.
|
||||
* The instance key of each context is computed by calling BKE_node_instance_key given the key of
|
||||
* the parent as well as the group node making the context. */
|
||||
static const DTreeContext *find_active_context_recursive(const DTreeContext *context)
|
||||
{
|
||||
const bNodeInstanceKey key = context->instance_key();
|
||||
|
||||
/* The instance key of the given context matches the active viewer instance key, so this is the
|
||||
* active context, return it. */
|
||||
if (key.value == context->derived_tree().root_context().btree().active_viewer_key.value) {
|
||||
return context;
|
||||
}
|
||||
|
||||
/* For each of the group nodes, compute their instance key and contexts and call this function
|
||||
* recursively. */
|
||||
for (const bNode *group_node : context->btree().group_nodes()) {
|
||||
const DTreeContext *child_context = context->child_context(*group_node);
|
||||
const DTreeContext *found_context = find_active_context_recursive(child_context);
|
||||
|
||||
/* If the found context is null, that means neither the child context nor one of its descendant
|
||||
* contexts is active. */
|
||||
if (!found_context) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise, we have found our active context, return it. */
|
||||
return found_context;
|
||||
}
|
||||
|
||||
/* Neither the given context nor one of its descendant contexts is active, so return null. */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const DTreeContext &DerivedNodeTree::active_context() const
|
||||
{
|
||||
/* If the active viewer key is NODE_INSTANCE_KEY_NONE, that means it is not yet initialized and
|
||||
* we return the root context in that case. See the find_active_context_recursive function. */
|
||||
if (root_context().btree().active_viewer_key.value == NODE_INSTANCE_KEY_NONE.value) {
|
||||
return root_context();
|
||||
}
|
||||
|
||||
return *find_active_context_recursive(&root_context());
|
||||
}
|
||||
|
||||
/* Each nested node group gets its own cluster. Just as node groups, clusters can be nested. */
|
||||
static dot::Cluster *get_dot_cluster_for_context(
|
||||
dot::DirectedGraph &digraph,
|
||||
|
|
|
@ -182,9 +182,11 @@ bool id_property_type_matches_socket(const bNodeSocket &socket, const IDProperty
|
|||
return property.type == IDP_INT;
|
||||
case SOCK_VECTOR:
|
||||
case SOCK_ROTATION:
|
||||
return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT && property.len == 3;
|
||||
return property.type == IDP_ARRAY && ELEM(property.subtype, IDP_INT, IDP_FLOAT, IDP_FLOAT) &&
|
||||
property.len == 3;
|
||||
case SOCK_RGBA:
|
||||
return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT && property.len == 4;
|
||||
return property.type == IDP_ARRAY &&
|
||||
ELEM(property.subtype, IDP_INT, IDP_FLOAT, IDP_DOUBLE) && property.len == 4;
|
||||
case SOCK_BOOLEAN:
|
||||
return property.type == IDP_BOOLEAN;
|
||||
case SOCK_STRING:
|
||||
|
@ -222,12 +224,35 @@ static void init_socket_cpp_value_from_property(const IDProperty &property,
|
|||
break;
|
||||
}
|
||||
case SOCK_VECTOR: {
|
||||
float3 value = (const float *)IDP_Array(&property);
|
||||
const void *property_array = IDP_Array(&property);
|
||||
float3 value;
|
||||
if (property.subtype == IDP_FLOAT) {
|
||||
value = float3(static_cast<const float *>(property_array));
|
||||
}
|
||||
else if (property.subtype == IDP_INT) {
|
||||
value = float3(int3(static_cast<const int *>(property_array)));
|
||||
}
|
||||
else {
|
||||
BLI_assert(property.subtype == IDP_DOUBLE);
|
||||
value = float3(double3(static_cast<const double *>(property_array)));
|
||||
}
|
||||
new (r_value) fn::ValueOrField<float3>(value);
|
||||
break;
|
||||
}
|
||||
case SOCK_RGBA: {
|
||||
ColorGeometry4f value = (const float *)IDP_Array(&property);
|
||||
const void *property_array = IDP_Array(&property);
|
||||
float4 vec;
|
||||
if (property.subtype == IDP_FLOAT) {
|
||||
vec = float4(static_cast<const float *>(property_array));
|
||||
}
|
||||
else if (property.subtype == IDP_INT) {
|
||||
vec = float4(int4(static_cast<const int *>(property_array)));
|
||||
}
|
||||
else {
|
||||
BLI_assert(property.subtype == IDP_DOUBLE);
|
||||
vec = float4(double4(static_cast<const double *>(property_array)));
|
||||
}
|
||||
ColorGeometry4f value(vec);
|
||||
new (r_value) fn::ValueOrField<ColorGeometry4f>(value);
|
||||
break;
|
||||
}
|
||||
|
@ -237,8 +262,19 @@ static void init_socket_cpp_value_from_property(const IDProperty &property,
|
|||
break;
|
||||
}
|
||||
case SOCK_ROTATION: {
|
||||
const math::EulerXYZ euler_value = math::EulerXYZ(
|
||||
float3(static_cast<const float *>(IDP_Array(&property))));
|
||||
const void *property_array = IDP_Array(&property);
|
||||
float3 vec;
|
||||
if (property.subtype == IDP_FLOAT) {
|
||||
vec = float3(static_cast<const float *>(property_array));
|
||||
}
|
||||
else if (property.subtype == IDP_INT) {
|
||||
vec = float3(int3(static_cast<const int *>(property_array)));
|
||||
}
|
||||
else {
|
||||
BLI_assert(property.subtype == IDP_DOUBLE);
|
||||
vec = float3(double3(static_cast<const double *>(property_array)));
|
||||
}
|
||||
const math::EulerXYZ euler_value = math::EulerXYZ(vec);
|
||||
new (r_value) fn::ValueOrField<math::Quaternion>(math::to_quaternion(euler_value));
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -222,8 +222,8 @@ void RE_FreeAllPersistentData(void);
|
|||
*/
|
||||
void RE_FreePersistentData(const struct Scene *scene);
|
||||
|
||||
/*
|
||||
* Free cached GPU textures to reduce memory usage. Before rendering all are cleard
|
||||
/**
|
||||
* Free cached GPU textures to reduce memory usage. Before rendering all are cleared
|
||||
* and on UI changes when detected they are no longer used.
|
||||
*/
|
||||
void RE_FreeGPUTextureCaches(const bool only_unused);
|
||||
|
|
|
@ -99,6 +99,11 @@ class Context : public realtime_compositor::Context {
|
|||
GPU_TEXTURE_FREE_SAFE(viewer_output_texture_);
|
||||
}
|
||||
|
||||
const Scene &get_scene() const override
|
||||
{
|
||||
return scene_;
|
||||
}
|
||||
|
||||
const bNodeTree &get_node_tree() const override
|
||||
{
|
||||
return node_tree_;
|
||||
|
|
|
@ -2513,7 +2513,7 @@ bool RE_ReadRenderResult(Scene *scene, Scene *scenode)
|
|||
void RE_layer_load_from_file(
|
||||
RenderLayer *layer, ReportList *reports, const char *filepath, int x, int y)
|
||||
{
|
||||
/* First try loading multilayer EXR. */
|
||||
/* First try loading multi-layer EXR. */
|
||||
if (render_result_exr_file_read_path(nullptr, layer, reports, filepath)) {
|
||||
return;
|
||||
}
|
||||
|
@ -2522,7 +2522,7 @@ void RE_layer_load_from_file(
|
|||
ImBuf *ibuf = IMB_loadiffname(filepath, IB_rect, nullptr);
|
||||
RenderPass *rpass = nullptr;
|
||||
|
||||
/* multiview: since the API takes no 'view', we use the first combined pass found */
|
||||
/* multi-view: since the API takes no 'view', we use the first combined pass found */
|
||||
for (rpass = static_cast<RenderPass *>(layer->passes.first); rpass; rpass = rpass->next) {
|
||||
if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
|
||||
break;
|
||||
|
|
|
@ -47,6 +47,12 @@
|
|||
|
||||
static ThreadMutex sample_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
enum {
|
||||
POINT_DATA_VEL = 1 << 0,
|
||||
POINT_DATA_LIFE = 1 << 1,
|
||||
POINT_DATA_COLOR = 1 << 2,
|
||||
};
|
||||
|
||||
static int point_data_used(PointDensity *pd)
|
||||
{
|
||||
int pd_bitflag = 0;
|
||||
|
|
|
@ -517,7 +517,8 @@ static int voronoiTex(const Tex *tex, const float texvec[3], TexResult *texres)
|
|||
BLI_noise_voronoi(texvec[0], texvec[1], texvec[2], da, pa, tex->vn_mexp, tex->vn_distm);
|
||||
texres->tin = sc * fabsf(dot_v4v4(&tex->vn_w1, da));
|
||||
|
||||
if (tex->vn_coltype) {
|
||||
const bool is_color = ELEM(tex->vn_coltype, TEX_COL1, TEX_COL2, TEX_COL3);
|
||||
if (is_color) {
|
||||
float ca[3]; /* cell color */
|
||||
BLI_noise_cell_v3(pa[0], pa[1], pa[2], ca);
|
||||
texres->trgba[0] = aw1 * ca[0];
|
||||
|
@ -535,12 +536,12 @@ static int voronoiTex(const Tex *tex, const float texvec[3], TexResult *texres)
|
|||
texres->trgba[0] += aw4 * ca[0];
|
||||
texres->trgba[1] += aw4 * ca[1];
|
||||
texres->trgba[2] += aw4 * ca[2];
|
||||
if (tex->vn_coltype >= 2) {
|
||||
if (ELEM(tex->vn_coltype, TEX_COL2, TEX_COL3)) {
|
||||
float t1 = (da[1] - da[0]) * 10;
|
||||
if (t1 > 1) {
|
||||
t1 = 1;
|
||||
}
|
||||
if (tex->vn_coltype == 3) {
|
||||
if (tex->vn_coltype == TEX_COL3) {
|
||||
t1 *= texres->tin;
|
||||
}
|
||||
else {
|
||||
|
@ -557,7 +558,7 @@ static int voronoiTex(const Tex *tex, const float texvec[3], TexResult *texres)
|
|||
}
|
||||
}
|
||||
|
||||
if (tex->vn_coltype) {
|
||||
if (is_color) {
|
||||
BRICONTRGB;
|
||||
texres->trgba[3] = 1.0;
|
||||
return (rv | TEX_RGB);
|
||||
|
|
Loading…
Reference in New Issue