Merge branch 'master' into blender2.8
This commit is contained in:
@@ -777,6 +777,15 @@ static void create_mesh(Scene *scene,
|
|||||||
int shader = clamp(f->material_index(), 0, used_shaders.size()-1);
|
int shader = clamp(f->material_index(), 0, used_shaders.size()-1);
|
||||||
bool smooth = f->use_smooth() || use_loop_normals;
|
bool smooth = f->use_smooth() || use_loop_normals;
|
||||||
|
|
||||||
|
if(use_loop_normals) {
|
||||||
|
BL::Array<float, 12> loop_normals = f->split_normals();
|
||||||
|
for(int i = 0; i < n; i++) {
|
||||||
|
N[vi[i]] = make_float3(loop_normals[i * 3],
|
||||||
|
loop_normals[i * 3 + 1],
|
||||||
|
loop_normals[i * 3 + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create triangles.
|
/* Create triangles.
|
||||||
*
|
*
|
||||||
* NOTE: Autosmooth is already taken care about.
|
* NOTE: Autosmooth is already taken care about.
|
||||||
|
|||||||
@@ -79,8 +79,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
|
|||||||
me.calc_normals_split();
|
me.calc_normals_split();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
me.split_faces();
|
me.split_faces(false);
|
||||||
me.calc_normals_split();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(subdivision_type == Mesh::SUBDIVISION_NONE) {
|
if(subdivision_type == Mesh::SUBDIVISION_NONE) {
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ public:
|
|||||||
void mem_free(device_memory& mem)
|
void mem_free(device_memory& mem)
|
||||||
{
|
{
|
||||||
device_ptr tmp = mem.device_pointer;
|
device_ptr tmp = mem.device_pointer;
|
||||||
|
stats.mem_free(mem.device_size);
|
||||||
|
|
||||||
foreach(SubDevice& sub, devices) {
|
foreach(SubDevice& sub, devices) {
|
||||||
mem.device_pointer = sub.ptr_map[tmp];
|
mem.device_pointer = sub.ptr_map[tmp];
|
||||||
@@ -170,7 +171,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
mem.device_pointer = 0;
|
mem.device_pointer = 0;
|
||||||
stats.mem_free(mem.device_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void const_copy_to(const char *name, void *host, size_t size)
|
void const_copy_to(const char *name, void *host, size_t size)
|
||||||
@@ -202,6 +202,7 @@ public:
|
|||||||
void tex_free(device_memory& mem)
|
void tex_free(device_memory& mem)
|
||||||
{
|
{
|
||||||
device_ptr tmp = mem.device_pointer;
|
device_ptr tmp = mem.device_pointer;
|
||||||
|
stats.mem_free(mem.device_size);
|
||||||
|
|
||||||
foreach(SubDevice& sub, devices) {
|
foreach(SubDevice& sub, devices) {
|
||||||
mem.device_pointer = sub.ptr_map[tmp];
|
mem.device_pointer = sub.ptr_map[tmp];
|
||||||
@@ -210,7 +211,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
mem.device_pointer = 0;
|
mem.device_pointer = 0;
|
||||||
stats.mem_free(mem.device_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pixels_alloc(device_memory& mem)
|
void pixels_alloc(device_memory& mem)
|
||||||
|
|||||||
@@ -309,6 +309,8 @@ bool OpenCLDeviceBase::OpenCLProgram::build_kernel(const string *debug_src)
|
|||||||
string build_options;
|
string build_options;
|
||||||
build_options = device->kernel_build_options(debug_src) + kernel_build_options;
|
build_options = device->kernel_build_options(debug_src) + kernel_build_options;
|
||||||
|
|
||||||
|
VLOG(1) << "Build options passed to clBuildProgram: '"
|
||||||
|
<< build_options << "'.";
|
||||||
cl_int ciErr = clBuildProgram(program, 0, NULL, build_options.c_str(), NULL, NULL);
|
cl_int ciErr = clBuildProgram(program, 0, NULL, build_options.c_str(), NULL, NULL);
|
||||||
|
|
||||||
/* show warnings even if build is successful */
|
/* show warnings even if build is successful */
|
||||||
|
|||||||
@@ -18,8 +18,19 @@ CCL_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
/* Noise */
|
/* Noise */
|
||||||
|
|
||||||
ccl_device_inline void svm_noise(float3 p, float detail, float distortion, float *fac, float3 *color)
|
ccl_device void svm_node_tex_noise(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
|
||||||
{
|
{
|
||||||
|
uint co_offset, scale_offset, detail_offset, distortion_offset, fac_offset, color_offset;
|
||||||
|
|
||||||
|
decode_node_uchar4(node.y, &co_offset, &scale_offset, &detail_offset, &distortion_offset);
|
||||||
|
decode_node_uchar4(node.z, &color_offset, &fac_offset, NULL, NULL);
|
||||||
|
|
||||||
|
uint4 node2 = read_node(kg, offset);
|
||||||
|
|
||||||
|
float scale = stack_load_float_default(stack, scale_offset, node2.x);
|
||||||
|
float detail = stack_load_float_default(stack, detail_offset, node2.y);
|
||||||
|
float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
|
||||||
|
float3 p = stack_load_float3(stack, co_offset) * scale;
|
||||||
int hard = 0;
|
int hard = 0;
|
||||||
|
|
||||||
if(distortion != 0.0f) {
|
if(distortion != 0.0f) {
|
||||||
@@ -32,36 +43,17 @@ ccl_device_inline void svm_noise(float3 p, float detail, float distortion, float
|
|||||||
p += r;
|
p += r;
|
||||||
}
|
}
|
||||||
|
|
||||||
*fac = noise_turbulence(p, detail, hard);
|
float f = noise_turbulence(p, detail, hard);
|
||||||
*color = make_float3(*fac,
|
|
||||||
noise_turbulence(make_float3(p.y, p.x, p.z), detail, hard),
|
|
||||||
noise_turbulence(make_float3(p.y, p.z, p.x), detail, hard));
|
|
||||||
}
|
|
||||||
|
|
||||||
ccl_device void svm_node_tex_noise(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
|
if(stack_valid(fac_offset)) {
|
||||||
{
|
|
||||||
uint co_offset, scale_offset, detail_offset, distortion_offset, fac_offset, color_offset;
|
|
||||||
|
|
||||||
decode_node_uchar4(node.y, &co_offset, &scale_offset, &detail_offset, &distortion_offset);
|
|
||||||
|
|
||||||
uint4 node2 = read_node(kg, offset);
|
|
||||||
|
|
||||||
float scale = stack_load_float_default(stack, scale_offset, node2.x);
|
|
||||||
float detail = stack_load_float_default(stack, detail_offset, node2.y);
|
|
||||||
float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
|
|
||||||
float3 co = stack_load_float3(stack, co_offset);
|
|
||||||
|
|
||||||
float3 color;
|
|
||||||
float f;
|
|
||||||
|
|
||||||
svm_noise(co*scale, detail, distortion, &f, &color);
|
|
||||||
|
|
||||||
decode_node_uchar4(node.z, &color_offset, &fac_offset, NULL, NULL);
|
|
||||||
|
|
||||||
if(stack_valid(fac_offset))
|
|
||||||
stack_store_float(stack, fac_offset, f);
|
stack_store_float(stack, fac_offset, f);
|
||||||
if(stack_valid(color_offset))
|
}
|
||||||
|
if(stack_valid(color_offset)) {
|
||||||
|
float3 color = make_float3(f,
|
||||||
|
noise_turbulence(make_float3(p.y, p.x, p.z), detail, hard),
|
||||||
|
noise_turbulence(make_float3(p.y, p.z, p.x), detail, hard));
|
||||||
stack_store_float3(stack, color_offset, color);
|
stack_store_float3(stack, color_offset, color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
#if !defined(__MINGW64__)
|
#if !defined(__MINGW64__)
|
||||||
# if defined(_WIN32) || defined(__APPLE__) || \
|
# if defined(_WIN32) || defined(__APPLE__) || \
|
||||||
defined(__FreeBSD__) || defined(__NetBSD__)
|
defined(__FreeBSD__) || defined(__NetBSD__)
|
||||||
static void sincos(double x, double *sinx, double *cosx) {
|
inline void sincos(double x, double *sinx, double *cosx) {
|
||||||
*sinx = sin(x);
|
*sinx = sin(x);
|
||||||
*cosx = cos(x);
|
*cosx = cos(x);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1008,11 +1008,9 @@ class WM_OT_doc_view(Operator):
|
|||||||
|
|
||||||
doc_id = doc_id
|
doc_id = doc_id
|
||||||
if bpy.app.version_cycle == "release":
|
if bpy.app.version_cycle == "release":
|
||||||
_prefix = ("https://www.blender.org/api/blender_python_api_%s%s_release" %
|
_prefix = ("https://docs.blender.org/api/blender_python_api_current")
|
||||||
("_".join(str(v) for v in bpy.app.version[:2]), bpy.app.version_char))
|
|
||||||
else:
|
else:
|
||||||
_prefix = ("https://www.blender.org/api/blender_python_api_%s" %
|
_prefix = ("https://docs.blender.org/api/blender_python_api_master")
|
||||||
"_".join(str(v) for v in bpy.app.version))
|
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
url = _wm_doc_get_id(self.doc_id, do_url=True, url_prefix=self._prefix)
|
url = _wm_doc_get_id(self.doc_id, do_url=True, url_prefix=self._prefix)
|
||||||
|
|||||||
@@ -1243,7 +1243,7 @@ class USERPREF_MT_addons_online_resources(Menu):
|
|||||||
"wm.url_open", text="API Concepts", icon='URL',
|
"wm.url_open", text="API Concepts", icon='URL',
|
||||||
).url = bpy.types.WM_OT_doc_view._prefix + "/info_quickstart.html"
|
).url = bpy.types.WM_OT_doc_view._prefix + "/info_quickstart.html"
|
||||||
layout.operator("wm.url_open", text="Add-on Tutorial", icon='URL',
|
layout.operator("wm.url_open", text="Add-on Tutorial", icon='URL',
|
||||||
).url = "http://www.blender.org/api/blender_python_api_current/info_tutorial_addon.html"
|
).url = bpy.types.WM_OT_doc_view._prefix + "/info_tutorial_addon.html"
|
||||||
|
|
||||||
|
|
||||||
class USERPREF_PT_addons(Panel):
|
class USERPREF_PT_addons(Panel):
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
struct BezTriple;
|
struct BezTriple;
|
||||||
struct Curve;
|
struct Curve;
|
||||||
struct EditNurb;
|
struct EditNurb;
|
||||||
|
struct GHash;
|
||||||
struct ListBase;
|
struct ListBase;
|
||||||
struct Main;
|
struct Main;
|
||||||
struct Nurb;
|
struct Nurb;
|
||||||
@@ -52,6 +53,13 @@ typedef struct CurveCache {
|
|||||||
struct Path *path;
|
struct Path *path;
|
||||||
} CurveCache;
|
} CurveCache;
|
||||||
|
|
||||||
|
/* Definitions needed for shape keys */
|
||||||
|
typedef struct CVKeyIndex {
|
||||||
|
void *orig_cv;
|
||||||
|
int key_index, nu_index, pt_index, vertex_index;
|
||||||
|
bool switched;
|
||||||
|
} CVKeyIndex;
|
||||||
|
|
||||||
#define KNOTSU(nu) ( (nu)->orderu + (nu)->pntsu + (((nu)->flagu & CU_NURB_CYCLIC) ? ((nu)->orderu - 1) : 0) )
|
#define KNOTSU(nu) ( (nu)->orderu + (nu)->pntsu + (((nu)->flagu & CU_NURB_CYCLIC) ? ((nu)->orderu - 1) : 0) )
|
||||||
#define KNOTSV(nu) ( (nu)->orderv + (nu)->pntsv + (((nu)->flagv & CU_NURB_CYCLIC) ? ((nu)->orderv - 1) : 0) )
|
#define KNOTSV(nu) ( (nu)->orderv + (nu)->pntsv + (((nu)->flagv & CU_NURB_CYCLIC) ? ((nu)->orderv - 1) : 0) )
|
||||||
|
|
||||||
@@ -108,7 +116,8 @@ void BK_curve_nurbs_vertexCos_apply(struct ListBase *lb, float (*vertexCos)[3]);
|
|||||||
float (*BKE_curve_nurbs_keyVertexCos_get(struct ListBase *lb, float *key))[3];
|
float (*BKE_curve_nurbs_keyVertexCos_get(struct ListBase *lb, float *key))[3];
|
||||||
void BKE_curve_nurbs_keyVertexTilts_apply(struct ListBase *lb, float *key);
|
void BKE_curve_nurbs_keyVertexTilts_apply(struct ListBase *lb, float *key);
|
||||||
|
|
||||||
void BKE_curve_editNurb_keyIndex_free(struct EditNurb *editnurb);
|
void BKE_curve_editNurb_keyIndex_delCV(struct GHash *keyindex, const void *cv);
|
||||||
|
void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex);
|
||||||
void BKE_curve_editNurb_free(struct Curve *cu);
|
void BKE_curve_editNurb_free(struct Curve *cu);
|
||||||
struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
|
struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
|
||||||
|
|
||||||
|
|||||||
@@ -131,8 +131,7 @@ bool BKE_mesh_uv_cdlayer_rename(struct Mesh *me, const char *old_name, const cha
|
|||||||
|
|
||||||
float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3];
|
float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3];
|
||||||
|
|
||||||
void BKE_mesh_calc_normals_split(struct Mesh *mesh);
|
void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
|
||||||
void BKE_mesh_split_faces(struct Mesh *mesh);
|
|
||||||
|
|
||||||
struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Scene *sce, struct Object *ob,
|
struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Scene *sce, struct Object *ob,
|
||||||
int apply_modifiers, int settings, int calc_tessface, int calc_undeformed);
|
int apply_modifiers, int settings, int calc_tessface, int calc_undeformed);
|
||||||
@@ -228,6 +227,9 @@ void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space, const float
|
|||||||
|
|
||||||
bool BKE_mesh_has_custom_loop_normals(struct Mesh *me);
|
bool BKE_mesh_has_custom_loop_normals(struct Mesh *me);
|
||||||
|
|
||||||
|
void BKE_mesh_calc_normals_split(struct Mesh *mesh);
|
||||||
|
void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh, struct MLoopNorSpaceArray *r_lnors_spacearr);
|
||||||
|
|
||||||
void BKE_mesh_normals_loop_split(
|
void BKE_mesh_normals_loop_split(
|
||||||
const struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges,
|
const struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges,
|
||||||
struct MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
|
struct MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
|
||||||
|
|||||||
@@ -89,20 +89,33 @@ void BKE_curve_editfont_free(Curve *cu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BKE_curve_editNurb_keyIndex_free(EditNurb *editnurb)
|
static void curve_editNurb_keyIndex_cv_free_cb(void *val)
|
||||||
{
|
{
|
||||||
if (!editnurb->keyindex) {
|
CVKeyIndex *index = val;
|
||||||
|
MEM_freeN(index->orig_cv);
|
||||||
|
MEM_freeN(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_curve_editNurb_keyIndex_delCV(GHash *keyindex, const void *cv)
|
||||||
|
{
|
||||||
|
BLI_assert(keyindex != NULL);
|
||||||
|
BLI_ghash_remove(keyindex, cv, NULL, curve_editNurb_keyIndex_cv_free_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_curve_editNurb_keyIndex_free(GHash **keyindex)
|
||||||
|
{
|
||||||
|
if (!(*keyindex)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BLI_ghash_free(editnurb->keyindex, NULL, MEM_freeN);
|
BLI_ghash_free(*keyindex, NULL, curve_editNurb_keyIndex_cv_free_cb);
|
||||||
editnurb->keyindex = NULL;
|
*keyindex = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BKE_curve_editNurb_free(Curve *cu)
|
void BKE_curve_editNurb_free(Curve *cu)
|
||||||
{
|
{
|
||||||
if (cu->editnurb) {
|
if (cu->editnurb) {
|
||||||
BKE_nurbList_free(&cu->editnurb->nurbs);
|
BKE_nurbList_free(&cu->editnurb->nurbs);
|
||||||
BKE_curve_editNurb_keyIndex_free(cu->editnurb);
|
BKE_curve_editNurb_keyIndex_free(&cu->editnurb->keyindex);
|
||||||
MEM_freeN(cu->editnurb);
|
MEM_freeN(cu->editnurb);
|
||||||
cu->editnurb = NULL;
|
cu->editnurb = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -819,7 +819,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
|
|||||||
if (editmode)
|
if (editmode)
|
||||||
required_mode |= eModifierMode_Editmode;
|
required_mode |= eModifierMode_Editmode;
|
||||||
|
|
||||||
if (cu->editnurb == NULL) {
|
if (!editmode) {
|
||||||
keyVerts = BKE_key_evaluate_object(ob, &numVerts);
|
keyVerts = BKE_key_evaluate_object(ob, &numVerts);
|
||||||
|
|
||||||
if (keyVerts) {
|
if (keyVerts) {
|
||||||
|
|||||||
@@ -39,7 +39,9 @@
|
|||||||
|
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
#include "BLI_math.h"
|
#include "BLI_math.h"
|
||||||
|
#include "BLI_linklist.h"
|
||||||
#include "BLI_listbase.h"
|
#include "BLI_listbase.h"
|
||||||
|
#include "BLI_memarena.h"
|
||||||
#include "BLI_edgehash.h"
|
#include "BLI_edgehash.h"
|
||||||
#include "BLI_string.h"
|
#include "BLI_string.h"
|
||||||
|
|
||||||
@@ -2057,7 +2059,7 @@ void BKE_mesh_mselect_active_set(Mesh *me, int index, int type)
|
|||||||
(me->mselect[me->totselect - 1].type == type));
|
(me->mselect[me->totselect - 1].type == type));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BKE_mesh_calc_normals_split(Mesh *mesh)
|
void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spacearr)
|
||||||
{
|
{
|
||||||
float (*r_loopnors)[3];
|
float (*r_loopnors)[3];
|
||||||
float (*polynors)[3];
|
float (*polynors)[3];
|
||||||
@@ -2092,300 +2094,324 @@ void BKE_mesh_calc_normals_split(Mesh *mesh)
|
|||||||
BKE_mesh_normals_loop_split(
|
BKE_mesh_normals_loop_split(
|
||||||
mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge,
|
mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge,
|
||||||
mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly,
|
mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly,
|
||||||
(mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh, NULL, clnors, NULL);
|
(mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh, r_lnors_spacearr, clnors, NULL);
|
||||||
|
|
||||||
if (free_polynors) {
|
if (free_polynors) {
|
||||||
MEM_freeN(polynors);
|
MEM_freeN(polynors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BKE_mesh_calc_normals_split(Mesh *mesh)
|
||||||
|
{
|
||||||
|
BKE_mesh_calc_normals_split_ex(mesh, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Split faces helper functions. */
|
/* Split faces helper functions. */
|
||||||
|
|
||||||
enum {
|
typedef struct SplitFaceNewVert {
|
||||||
/* Vertex is adjacent to some loop which normal is different,
|
struct SplitFaceNewVert *next;
|
||||||
* hence split of this vertex is required.
|
int new_index;
|
||||||
*/
|
int orig_index;
|
||||||
SPLIT_VERT_NEED_SPLIT = (1 << 0),
|
float *vnor;
|
||||||
/* Original vertex was already re-used by split logic. */
|
} SplitFaceNewVert;
|
||||||
SPLIT_VERT_REUSED = (1 << 1),
|
|
||||||
};
|
|
||||||
enum {
|
|
||||||
/* Edge is adjacent to any of vertex tagged for split.
|
|
||||||
*/
|
|
||||||
SPLIT_EDGE_NEED_SPLIT = (1 << 0),
|
|
||||||
/* Original edge was already re-used by split logic. */
|
|
||||||
SPLIT_EDGE_REUSED = (1 << 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Tag vertices which normals are not equal to any adjacent loop
|
typedef struct SplitFaceNewEdge {
|
||||||
* and hence split on that vertex is required.
|
struct SplitFaceNewEdge *next;
|
||||||
*
|
int new_index;
|
||||||
* Returns truth if any of vertex needs to be split.
|
int orig_index;
|
||||||
*/
|
int v1;
|
||||||
static bool split_faces_tag_verts(const Mesh *mesh, uchar *vert_flags)
|
int v2;
|
||||||
{
|
} SplitFaceNewEdge;
|
||||||
const int num_polys = mesh->totpoly;
|
|
||||||
const MVert *mvert = mesh->mvert;
|
|
||||||
const MLoop *mloop = mesh->mloop;
|
|
||||||
const MPoly *mpoly = mesh->mpoly;
|
|
||||||
float (*lnors)[3] = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
|
|
||||||
bool has_split_verts = false;
|
|
||||||
for (int poly = 0; poly < num_polys; poly++) {
|
|
||||||
const MPoly *mp = &mpoly[poly];
|
|
||||||
for (int loop = 0; loop < mp->totloop; loop++) {
|
|
||||||
const MLoop *ml = &mloop[mp->loopstart + loop];
|
|
||||||
const MVert *mv = &mvert[ml->v];
|
|
||||||
float vn[3];
|
|
||||||
normal_short_to_float_v3(vn, mv->no);
|
|
||||||
if (len_squared_v3v3(vn, lnors[mp->loopstart + loop]) > FLT_EPSILON) {
|
|
||||||
vert_flags[ml->v] |= SPLIT_VERT_NEED_SPLIT;
|
|
||||||
has_split_verts = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return has_split_verts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Count number of new vertices to be added.
|
/* Detect needed new vertices, and update accordingly loops' vertex indices.
|
||||||
*
|
* WARNING! Leaves mesh in invalid state. */
|
||||||
* Note that one of the loop where split is required will re-use
|
static int split_faces_prepare_new_verts(
|
||||||
* it's vertex in order to avoid creation of loose vertices.
|
const Mesh *mesh, MLoopNorSpaceArray *lnors_spacearr, SplitFaceNewVert **new_verts, MemArena *memarena,
|
||||||
*/
|
bool *r_need_vnors_recalc)
|
||||||
static int split_faces_count_new_verts(const Mesh *mesh, uchar *vert_flags)
|
|
||||||
{
|
{
|
||||||
const int num_polys = mesh->totpoly;
|
/* Note: if lnors_spacearr is NULL, ther is no autosmooth handling, and we only split out flat polys. */
|
||||||
const MLoop *mloop = mesh->mloop;
|
const int num_loops = mesh->totloop;
|
||||||
const MPoly *mpoly = mesh->mpoly;
|
int num_verts = mesh->totvert;
|
||||||
int num_new_verts = 0;
|
|
||||||
for (int poly = 0; poly < num_polys; poly++) {
|
|
||||||
const MPoly *mp = &mpoly[poly];
|
|
||||||
for (int loop = 0; loop < mp->totloop; loop++) {
|
|
||||||
const MLoop *ml = &mloop[mp->loopstart + loop];
|
|
||||||
if (vert_flags[ml->v] & SPLIT_VERT_NEED_SPLIT) {
|
|
||||||
if (vert_flags[ml->v] & SPLIT_VERT_REUSED) {
|
|
||||||
++num_new_verts;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vert_flags[ml->v] |= SPLIT_VERT_REUSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return num_new_verts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tag edges which are adjacent to at least one vertex tagged for split. */
|
|
||||||
static void split_faces_tag_edges(Mesh *mesh,
|
|
||||||
const uchar *vert_flags,
|
|
||||||
uchar *edge_flags)
|
|
||||||
{
|
|
||||||
const int num_polys = mesh->totpoly;
|
|
||||||
const MLoop *mloop = mesh->mloop;
|
|
||||||
const MPoly *mpoly = mesh->mpoly;
|
|
||||||
for (int poly = 0; poly < num_polys; poly++) {
|
|
||||||
const MPoly *mp = &mpoly[poly];
|
|
||||||
int loop_prev = mp->totloop - 1;
|
|
||||||
for (int loop = 0; loop < mp->totloop; loop++) {
|
|
||||||
const int poly_loop_prev = mp->loopstart + loop_prev;
|
|
||||||
const MLoop *ml = &mloop[mp->loopstart + loop];
|
|
||||||
const MLoop *ml_prev = &mloop[poly_loop_prev];
|
|
||||||
const int mv_flag = vert_flags[ml->v];
|
|
||||||
const int mv_prev_flag = vert_flags[ml_prev->v];
|
|
||||||
bool need_split = false;
|
|
||||||
if (mv_flag & SPLIT_VERT_NEED_SPLIT) {
|
|
||||||
if (mv_prev_flag & SPLIT_VERT_NEED_SPLIT) {
|
|
||||||
/* Create new edge between twp split vertices. */
|
|
||||||
need_split = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Create new edge from existing vertex to a split one. */
|
|
||||||
need_split = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (mv_prev_flag & SPLIT_VERT_NEED_SPLIT) {
|
|
||||||
/* Create new edge from split vertex to existing one. */
|
|
||||||
need_split = true;
|
|
||||||
}
|
|
||||||
if (need_split) {
|
|
||||||
edge_flags[ml_prev->e] |= SPLIT_EDGE_NEED_SPLIT;
|
|
||||||
}
|
|
||||||
loop_prev = loop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Count number of new edges to be added.
|
|
||||||
*
|
|
||||||
* Note that one of the loop where split is required will re-use
|
|
||||||
* it's edge in order to avoid creation of loose edges.
|
|
||||||
*/
|
|
||||||
static int split_faces_count_new_edges(const Mesh *mesh, uchar *edge_flags)
|
|
||||||
{
|
|
||||||
const int num_polys = mesh->totpoly;
|
|
||||||
const MLoop *mloop = mesh->mloop;
|
|
||||||
const MPoly *mpoly = mesh->mpoly;
|
|
||||||
int num_new_edges = 0;
|
|
||||||
for (int poly = 0; poly < num_polys; poly++) {
|
|
||||||
const MPoly *mp = &mpoly[poly];
|
|
||||||
for (int loop = 0; loop < mp->totloop; loop++) {
|
|
||||||
const MLoop *ml = &mloop[mp->loopstart + loop];
|
|
||||||
if (edge_flags[ml->e] & SPLIT_EDGE_NEED_SPLIT) {
|
|
||||||
if (edge_flags[ml->e] & SPLIT_EDGE_REUSED) {
|
|
||||||
++num_new_edges;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
edge_flags[ml->e] |= SPLIT_EDGE_REUSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return num_new_edges;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Perform actual split of vertices.
|
|
||||||
*
|
|
||||||
* NOTE: Will leave edges in inconsistent state.
|
|
||||||
*/
|
|
||||||
static void split_faces_split_verts(Mesh *mesh,
|
|
||||||
const int num_new_verts,
|
|
||||||
uchar *vert_flags)
|
|
||||||
{
|
|
||||||
const int num_verts = mesh->totvert - num_new_verts;
|
|
||||||
const int num_polys = mesh->totpoly;
|
|
||||||
MVert *mvert = mesh->mvert;
|
MVert *mvert = mesh->mvert;
|
||||||
MLoop *mloop = mesh->mloop;
|
MLoop *mloop = mesh->mloop;
|
||||||
MPoly *mpoly = mesh->mpoly;
|
|
||||||
const float (*lnors)[3] = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
|
|
||||||
int num_added_verts = 0;
|
|
||||||
/* Clear reused flag, we need it again. */
|
|
||||||
for (int i = 0; i < num_verts; ++i) {
|
|
||||||
vert_flags[i] &= ~SPLIT_VERT_REUSED;
|
|
||||||
}
|
|
||||||
for (int poly = 0; poly < num_polys; poly++) {
|
|
||||||
MPoly *mp = &mpoly[poly];
|
|
||||||
/* First we split all vertices to get proper flag whether they are
|
|
||||||
* split or not for all of them before handling edges.
|
|
||||||
*/
|
|
||||||
for (int loop = 0; loop < mp->totloop; loop++) {
|
|
||||||
int poly_loop = mp->loopstart + loop;
|
|
||||||
MLoop *ml = &mloop[poly_loop];
|
|
||||||
if (vert_flags[ml->v] & SPLIT_VERT_NEED_SPLIT) {
|
|
||||||
if ((vert_flags[ml->v] & SPLIT_VERT_REUSED) == 0) {
|
|
||||||
/* Ignore first split on vertex, re-use it instead. */
|
|
||||||
vert_flags[ml->v] |= SPLIT_VERT_REUSED;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Create new vertex. */
|
|
||||||
int new_vert = num_verts + num_added_verts;
|
|
||||||
CustomData_copy_data(&mesh->vdata, &mesh->vdata,
|
|
||||||
ml->v, new_vert, 1);
|
|
||||||
normal_float_to_short_v3(mvert[new_vert].no,
|
|
||||||
lnors[poly_loop]);
|
|
||||||
ml->v = new_vert;
|
|
||||||
num_added_verts++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Perform actual split of edges.
|
BLI_bitmap *verts_used = BLI_BITMAP_NEW(num_verts, __func__);
|
||||||
*
|
|
||||||
* NOTE: Will correct all edges.
|
if (lnors_spacearr) {
|
||||||
*/
|
BLI_bitmap *done_loops = BLI_BITMAP_NEW(num_loops, __func__);
|
||||||
static void split_faces_split_edges(Mesh *mesh,
|
|
||||||
const int num_new_edges,
|
MLoop *ml = mloop;
|
||||||
uchar *edge_flags)
|
MLoopNorSpace **lnor_space = lnors_spacearr->lspacearr;
|
||||||
{
|
for (int loop_idx = 0; loop_idx < num_loops; loop_idx++, ml++, lnor_space++) {
|
||||||
const int num_edges = mesh->totedge - num_new_edges;
|
if (!BLI_BITMAP_TEST(done_loops, loop_idx)) {
|
||||||
const int num_polys = mesh->totpoly;
|
const int vert_idx = ml->v;
|
||||||
MEdge *medge = mesh->medge;
|
const bool vert_used = BLI_BITMAP_TEST_BOOL(verts_used, vert_idx);
|
||||||
MLoop *mloop = mesh->mloop;
|
/* If vert is already used by another smooth fan, we need a new vert for this one. */
|
||||||
MPoly *mpoly = mesh->mpoly;
|
const int new_vert_idx = vert_used ? num_verts++ : vert_idx;
|
||||||
int num_added_edges = 0;
|
|
||||||
/* Clear reused flag, we need it again. */
|
if ((*lnor_space)->loops) {
|
||||||
for (int i = 0; i < num_edges; ++i) {
|
for (LinkNode *lnode = (*lnor_space)->loops; lnode; lnode = lnode->next) {
|
||||||
edge_flags[i] &= ~SPLIT_EDGE_REUSED;
|
const int ml_fan_idx = GET_INT_FROM_POINTER(lnode->link);
|
||||||
}
|
BLI_BITMAP_ENABLE(done_loops, ml_fan_idx);
|
||||||
for (int poly = 0; poly < num_polys; poly++) {
|
if (vert_used) {
|
||||||
MPoly *mp = &mpoly[poly];
|
mloop[ml_fan_idx].v = new_vert_idx;
|
||||||
for (int loop = 0, loop_prev = mp->totloop - 1; loop < mp->totloop; loop++) {
|
}
|
||||||
const int poly_loop_prev = mp->loopstart + loop_prev;
|
}
|
||||||
const MLoop *ml = &mloop[mp->loopstart + loop];
|
|
||||||
MLoop *ml_prev = &mloop[poly_loop_prev];
|
|
||||||
MEdge *me_prev = &medge[ml_prev->e];
|
|
||||||
if (edge_flags[ml_prev->e] & SPLIT_EDGE_NEED_SPLIT) {
|
|
||||||
if ((edge_flags[ml_prev->e] & SPLIT_EDGE_REUSED) == 0) {
|
|
||||||
edge_flags[ml_prev->e] |= SPLIT_EDGE_REUSED;
|
|
||||||
me_prev->v1 = ml_prev->v;
|
|
||||||
me_prev->v2 = ml->v;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const int index = num_edges + num_added_edges;
|
/* Single loop in this fan... */
|
||||||
CustomData_copy_data(&mesh->edata, &mesh->edata,
|
BLI_BITMAP_ENABLE(done_loops, loop_idx);
|
||||||
ml_prev->e, index, 1);
|
if (vert_used) {
|
||||||
MEdge *me_new = &medge[index];
|
ml->v = new_vert_idx;
|
||||||
me_new->v1 = ml_prev->v;
|
}
|
||||||
me_new->v2 = ml->v;
|
}
|
||||||
ml_prev->e = index;
|
|
||||||
num_added_edges++;
|
if (!vert_used) {
|
||||||
|
BLI_BITMAP_ENABLE(verts_used, vert_idx);
|
||||||
|
/* We need to update that vertex's normal here, we won't go over it again. */
|
||||||
|
/* This is important! *DO NOT* set vnor to final computed lnor, vnor should always be defined to
|
||||||
|
* 'automatic normal' value computed from its polys, not some custom normal.
|
||||||
|
* Fortunately, that's the loop normal space's 'lnor' reference vector. ;) */
|
||||||
|
normal_float_to_short_v3(mvert[vert_idx].no, (*lnor_space)->vec_lnor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Add new vert to list. */
|
||||||
|
SplitFaceNewVert *new_vert = BLI_memarena_alloc(memarena, sizeof(*new_vert));
|
||||||
|
new_vert->orig_index = vert_idx;
|
||||||
|
new_vert->new_index = new_vert_idx;
|
||||||
|
new_vert->vnor = (*lnor_space)->vec_lnor; /* See note above. */
|
||||||
|
new_vert->next = *new_verts;
|
||||||
|
*new_verts = new_vert;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loop_prev = loop;
|
}
|
||||||
|
|
||||||
|
MEM_freeN(done_loops);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* No loop normal spaces available, we only split out flat polys. */
|
||||||
|
const int num_polys = mesh->totpoly;
|
||||||
|
const MPoly *mpoly = mesh->mpoly;
|
||||||
|
|
||||||
|
/* We do that in two loops, to keep original edges/verts to smooth polys preferencially. */
|
||||||
|
const MPoly *mp = mpoly;
|
||||||
|
for (int i = 0; i < num_polys; i++, mp++) {
|
||||||
|
if (mp->flag & ME_SMOOTH) {
|
||||||
|
const MLoop *ml = &mloop[mp->loopstart];
|
||||||
|
for (int j = 0; j < mp->totloop; j++, ml++) {
|
||||||
|
/* Just mark the vertex as used/reserved, that way neighbor flat polys, if any,
|
||||||
|
* will have to create their own. */
|
||||||
|
BLI_BITMAP_ENABLE(verts_used, ml->v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mp = mpoly;
|
||||||
|
for (int i = 0; i < num_polys; i++, mp++) {
|
||||||
|
if (!(mp->flag & ME_SMOOTH)) {
|
||||||
|
MLoop *ml = &mloop[mp->loopstart];
|
||||||
|
for (int j = 0; j < mp->totloop; j++, ml++) {
|
||||||
|
const int vert_idx = ml->v;
|
||||||
|
|
||||||
|
if (BLI_BITMAP_TEST(verts_used, vert_idx)) {
|
||||||
|
/* Add new vert to list. */
|
||||||
|
const int new_vert_idx = num_verts++;
|
||||||
|
ml->v = new_vert_idx;
|
||||||
|
|
||||||
|
SplitFaceNewVert *new_vert = BLI_memarena_alloc(memarena, sizeof(*new_vert));
|
||||||
|
new_vert->orig_index = vert_idx;
|
||||||
|
new_vert->new_index = new_vert_idx;
|
||||||
|
new_vert->vnor = NULL; /* See note below about normals. */
|
||||||
|
new_vert->next = *new_verts;
|
||||||
|
*new_verts = new_vert;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BLI_BITMAP_ENABLE(verts_used, vert_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Note: there is no way to get new normals for smooth vertices here (and we don't have direct access
|
||||||
|
* to poly normals either for flat ones), so we'll have to recompute all vnors at the end... */
|
||||||
|
*r_need_vnors_recalc = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_freeN(verts_used);
|
||||||
|
|
||||||
|
return num_verts - mesh->totvert;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detect needed new edges, and update accordingly loops' edge indices.
|
||||||
|
* WARNING! Leaves mesh in invalid state. */
|
||||||
|
static int split_faces_prepare_new_edges(
|
||||||
|
const Mesh *mesh, SplitFaceNewEdge **new_edges, MemArena *memarena)
|
||||||
|
{
|
||||||
|
const int num_polys = mesh->totpoly;
|
||||||
|
int num_edges = mesh->totedge;
|
||||||
|
MEdge *medge = mesh->medge;
|
||||||
|
MLoop *mloop = mesh->mloop;
|
||||||
|
const MPoly *mpoly = mesh->mpoly;
|
||||||
|
|
||||||
|
BLI_bitmap *edges_used = BLI_BITMAP_NEW(num_edges, __func__);
|
||||||
|
EdgeHash *edges_hash = BLI_edgehash_new_ex(__func__, num_edges);
|
||||||
|
|
||||||
|
const MPoly *mp = mpoly;
|
||||||
|
for (int poly_idx = 0; poly_idx < num_polys; poly_idx++, mp++) {
|
||||||
|
MLoop *ml_prev = &mloop[mp->loopstart + mp->totloop - 1];
|
||||||
|
MLoop *ml = &mloop[mp->loopstart];
|
||||||
|
for (int loop_idx = 0; loop_idx < mp->totloop; loop_idx++, ml++) {
|
||||||
|
void **eval;
|
||||||
|
if (!BLI_edgehash_ensure_p(edges_hash, ml_prev->v, ml->v, &eval)) {
|
||||||
|
/* That edge has not been encountered yet, define it. */
|
||||||
|
if (BLI_BITMAP_TEST(edges_used, ml_prev->e)) {
|
||||||
|
/* Original edge has already been used, we need to define a new one. */
|
||||||
|
const int edge_idx = num_edges++;
|
||||||
|
*eval = SET_INT_IN_POINTER(edge_idx);
|
||||||
|
ml_prev->e = edge_idx;
|
||||||
|
|
||||||
|
SplitFaceNewEdge *new_edge = BLI_memarena_alloc(memarena, sizeof(*new_edge));
|
||||||
|
new_edge->orig_index = ml_prev->e;
|
||||||
|
new_edge->new_index = edge_idx;
|
||||||
|
new_edge->v1 = ml_prev->v;
|
||||||
|
new_edge->v2 = ml->v;
|
||||||
|
new_edge->next = *new_edges;
|
||||||
|
*new_edges = new_edge;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* We can re-use original edge. */
|
||||||
|
const int edge_idx = ml_prev->e;
|
||||||
|
medge[edge_idx].v1 = ml_prev->v;
|
||||||
|
medge[edge_idx].v2 = ml->v;
|
||||||
|
*eval = SET_INT_IN_POINTER(edge_idx);
|
||||||
|
BLI_BITMAP_ENABLE(edges_used, edge_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Edge already known, just update loop's edge index. */
|
||||||
|
ml_prev->e = GET_INT_FROM_POINTER(*eval);
|
||||||
|
}
|
||||||
|
|
||||||
|
ml_prev = ml;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_freeN(edges_used);
|
||||||
|
BLI_edgehash_free(edges_hash, NULL);
|
||||||
|
|
||||||
|
return num_edges - mesh->totedge;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform actual split of vertices. */
|
||||||
|
static void split_faces_split_new_verts(
|
||||||
|
Mesh *mesh, SplitFaceNewVert *new_verts, const int num_new_verts)
|
||||||
|
{
|
||||||
|
const int num_verts = mesh->totvert - num_new_verts;
|
||||||
|
MVert *mvert = mesh->mvert;
|
||||||
|
|
||||||
|
/* Remember new_verts is a single linklist, so its items are in reversed order... */
|
||||||
|
MVert *new_mv = &mvert[mesh->totvert - 1];
|
||||||
|
for (int i = mesh->totvert - 1; i >= num_verts ; i--, new_mv--, new_verts = new_verts->next) {
|
||||||
|
BLI_assert(new_verts->new_index == i);
|
||||||
|
CustomData_copy_data(&mesh->vdata, &mesh->vdata, new_verts->orig_index, i, 1);
|
||||||
|
if (new_verts->vnor) {
|
||||||
|
normal_float_to_short_v3(new_mv->no, new_verts->vnor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Split faces based on the edge angle.
|
/* Perform actual split of edges. */
|
||||||
* Matches behavior of face splitting in render engines.
|
static void split_faces_split_new_edges(
|
||||||
*/
|
Mesh *mesh, SplitFaceNewEdge *new_edges, const int num_new_edges)
|
||||||
void BKE_mesh_split_faces(Mesh *mesh)
|
|
||||||
{
|
{
|
||||||
const int num_verts = mesh->totvert;
|
const int num_edges = mesh->totedge - num_new_edges;
|
||||||
const int num_edges = mesh->totedge;
|
MEdge *medge = mesh->medge;
|
||||||
const int num_polys = mesh->totpoly;
|
|
||||||
if ((mesh->flag & ME_AUTOSMOOTH) == 0) {
|
/* Remember new_edges is a single linklist, so its items are in reversed order... */
|
||||||
return;
|
MEdge *new_med = &medge[mesh->totedge - 1];
|
||||||
|
for (int i = mesh->totedge - 1; i >= num_edges ; i--, new_med--, new_edges = new_edges->next) {
|
||||||
|
BLI_assert(new_edges->new_index == i);
|
||||||
|
CustomData_copy_data(&mesh->edata, &mesh->edata, new_edges->orig_index, i, 1);
|
||||||
|
new_med->v1 = new_edges->v1;
|
||||||
|
new_med->v2 = new_edges->v2;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Split faces based on the edge angle and loop normals.
|
||||||
|
* Matches behavior of face splitting in render engines.
|
||||||
|
*
|
||||||
|
* NOTE: Will leave CD_NORMAL loop data layer which is
|
||||||
|
* used by render engines to set shading up.
|
||||||
|
*/
|
||||||
|
void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
|
||||||
|
{
|
||||||
|
const int num_polys = mesh->totpoly;
|
||||||
|
|
||||||
if (num_polys == 0) {
|
if (num_polys == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BKE_mesh_tessface_clear(mesh);
|
BKE_mesh_tessface_clear(mesh);
|
||||||
/* Compute loop normals if needed. */
|
|
||||||
if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
|
MLoopNorSpaceArray *lnors_spacearr = NULL;
|
||||||
BKE_mesh_calc_normals_split(mesh);
|
MemArena *memarena;
|
||||||
|
bool need_vnors_recalc = false;
|
||||||
|
|
||||||
|
if (mesh->flag & ME_AUTOSMOOTH) {
|
||||||
|
lnors_spacearr = MEM_callocN(sizeof(*lnors_spacearr), __func__);
|
||||||
|
/* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */
|
||||||
|
BKE_mesh_calc_normals_split_ex(mesh, lnors_spacearr);
|
||||||
|
/* Stealing memarena from loop normals space array. */
|
||||||
|
memarena = lnors_spacearr->mem;
|
||||||
}
|
}
|
||||||
/* Runtime flags. */
|
else {
|
||||||
uchar *vert_flags = MEM_callocN(sizeof(*vert_flags) * num_verts,
|
/* We still have to split out flat faces... */
|
||||||
"split faces vert flags");
|
memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
|
||||||
/* Tag vertces and check whether anything is tagged. */
|
}
|
||||||
if (!split_faces_tag_verts(mesh, vert_flags)) {
|
|
||||||
/* No new vertices to be split added, can do early exit. */
|
SplitFaceNewVert *new_verts = NULL;
|
||||||
MEM_freeN(vert_flags);
|
SplitFaceNewEdge *new_edges = NULL;
|
||||||
return;
|
|
||||||
|
/* Detect loop normal spaces (a.k.a. smooth fans) that will need a new vert. */
|
||||||
|
const int num_new_verts = split_faces_prepare_new_verts(mesh, lnors_spacearr, &new_verts, memarena, &need_vnors_recalc);
|
||||||
|
|
||||||
|
if (num_new_verts > 0) {
|
||||||
|
/* Reminder: beyond this point, there is no way out, mesh is in invalid state (due to early-reassignment of
|
||||||
|
* loops' vertex and edge indices to new, to-be-created split ones). */
|
||||||
|
|
||||||
|
const int num_new_edges = split_faces_prepare_new_edges(mesh, &new_edges, memarena);
|
||||||
|
BLI_assert(num_new_edges > 0);
|
||||||
|
|
||||||
|
/* Reallocate all vert and edge related data. */
|
||||||
|
mesh->totvert += num_new_verts;
|
||||||
|
mesh->totedge += num_new_edges;
|
||||||
|
CustomData_realloc(&mesh->vdata, mesh->totvert);
|
||||||
|
CustomData_realloc(&mesh->edata, mesh->totedge);
|
||||||
|
/* Update pointers to a newly allocated memory. */
|
||||||
|
BKE_mesh_update_customdata_pointers(mesh, false);
|
||||||
|
|
||||||
|
/* Perform actual split of vertices and edges. */
|
||||||
|
split_faces_split_new_verts(mesh, new_verts, num_new_verts);
|
||||||
|
split_faces_split_new_edges(mesh, new_edges, num_new_edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: after this point mesh is expected to be valid again. */
|
||||||
|
|
||||||
|
/* CD_NORMAL is expected to be temporary only. */
|
||||||
|
if (free_loop_normals) {
|
||||||
|
CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lnors_spacearr) {
|
||||||
|
/* Also frees new_verts/edges temp data, since we used its memarena to allocate them. */
|
||||||
|
BKE_lnor_spacearr_free(lnors_spacearr);
|
||||||
|
MEM_freeN(lnors_spacearr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BLI_memarena_free(memarena);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_vnors_recalc) {
|
||||||
|
BKE_mesh_calc_normals(mesh);
|
||||||
}
|
}
|
||||||
/* Flush vertex flags to edges. */
|
|
||||||
uchar *edge_flags = MEM_callocN(sizeof(*edge_flags) * num_edges,
|
|
||||||
"split faces edge flags");
|
|
||||||
split_faces_tag_edges(mesh, vert_flags, edge_flags);
|
|
||||||
/* Count amount of new geometry. */
|
|
||||||
int num_new_verts = split_faces_count_new_verts(mesh, vert_flags);
|
|
||||||
int num_new_edges = split_faces_count_new_edges(mesh, edge_flags);
|
|
||||||
/* Reallocate all vert and edge related data. */
|
|
||||||
mesh->totvert += num_new_verts;
|
|
||||||
mesh->totedge += num_new_edges;
|
|
||||||
CustomData_realloc(&mesh->vdata, mesh->totvert);
|
|
||||||
CustomData_realloc(&mesh->edata, mesh->totedge);
|
|
||||||
/* Update pointers to a newly allocated memory. */
|
|
||||||
BKE_mesh_update_customdata_pointers(mesh, false);
|
|
||||||
/* Perform actual split of vertices and adjacent edges. */
|
|
||||||
split_faces_split_verts(mesh, num_new_verts, vert_flags);
|
|
||||||
split_faces_split_edges(mesh, num_new_edges, edge_flags);
|
|
||||||
/* CD_NORMAL is expected to be temporary only, and it's invalid at
|
|
||||||
* this point anyway.
|
|
||||||
*/
|
|
||||||
CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop);
|
|
||||||
MEM_freeN(vert_flags);
|
|
||||||
MEM_freeN(edge_flags);
|
|
||||||
#ifdef VALIDATE_MESH
|
#ifdef VALIDATE_MESH
|
||||||
BKE_mesh_validate(mesh, true, true);
|
BKE_mesh_validate(mesh, true, true);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1152,7 +1152,6 @@ void BKE_mesh_normals_loop_split(
|
|||||||
const bool use_split_normals, float split_angle,
|
const bool use_split_normals, float split_angle,
|
||||||
MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], int *r_loop_to_poly)
|
MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], int *r_loop_to_poly)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* For now this is not supported. If we do not use split normals, we do not generate anything fancy! */
|
/* For now this is not supported. If we do not use split normals, we do not generate anything fancy! */
|
||||||
BLI_assert(use_split_normals || !(r_lnors_spacearr));
|
BLI_assert(use_split_normals || !(r_lnors_spacearr));
|
||||||
|
|
||||||
|
|||||||
@@ -217,9 +217,6 @@
|
|||||||
/** \name Internal Structs
|
/** \name Internal Structs
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
typedef unsigned int uint;
|
|
||||||
typedef unsigned char ubyte;
|
|
||||||
|
|
||||||
typedef uint64_t hash_key;
|
typedef uint64_t hash_key;
|
||||||
|
|
||||||
|
|
||||||
@@ -291,7 +288,7 @@ typedef struct BChunkList {
|
|||||||
|
|
||||||
/* a chunk of an array */
|
/* a chunk of an array */
|
||||||
typedef struct BChunk {
|
typedef struct BChunk {
|
||||||
const ubyte *data;
|
const uchar *data;
|
||||||
size_t data_len;
|
size_t data_len;
|
||||||
/** number of #BChunkList using this. */
|
/** number of #BChunkList using this. */
|
||||||
int users;
|
int users;
|
||||||
@@ -332,7 +329,7 @@ static size_t bchunk_list_size(const BChunkList *chunk_list);
|
|||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
static BChunk *bchunk_new(
|
static BChunk *bchunk_new(
|
||||||
BArrayMemory *bs_mem, const ubyte *data, const size_t data_len)
|
BArrayMemory *bs_mem, const uchar *data, const size_t data_len)
|
||||||
{
|
{
|
||||||
BChunk *chunk = BLI_mempool_alloc(bs_mem->chunk);
|
BChunk *chunk = BLI_mempool_alloc(bs_mem->chunk);
|
||||||
chunk->data = data;
|
chunk->data = data;
|
||||||
@@ -345,9 +342,9 @@ static BChunk *bchunk_new(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static BChunk *bchunk_new_copydata(
|
static BChunk *bchunk_new_copydata(
|
||||||
BArrayMemory *bs_mem, const ubyte *data, const size_t data_len)
|
BArrayMemory *bs_mem, const uchar *data, const size_t data_len)
|
||||||
{
|
{
|
||||||
ubyte *data_copy = MEM_mallocN(data_len, __func__);
|
uchar *data_copy = MEM_mallocN(data_len, __func__);
|
||||||
memcpy(data_copy, data, data_len);
|
memcpy(data_copy, data, data_len);
|
||||||
return bchunk_new(bs_mem, data_copy, data_len);
|
return bchunk_new(bs_mem, data_copy, data_len);
|
||||||
}
|
}
|
||||||
@@ -367,7 +364,7 @@ static void bchunk_decref(
|
|||||||
|
|
||||||
static bool bchunk_data_compare(
|
static bool bchunk_data_compare(
|
||||||
const BChunk *chunk,
|
const BChunk *chunk,
|
||||||
const ubyte *data_base, const size_t data_base_len,
|
const uchar *data_base, const size_t data_base_len,
|
||||||
const size_t offset)
|
const size_t offset)
|
||||||
{
|
{
|
||||||
if (offset + (size_t)chunk->data_len <= data_base_len) {
|
if (offset + (size_t)chunk->data_len <= data_base_len) {
|
||||||
@@ -426,7 +423,7 @@ static void bchunk_list_decref(
|
|||||||
|
|
||||||
#ifdef USE_VALIDATE_LIST_DATA_PARTIAL
|
#ifdef USE_VALIDATE_LIST_DATA_PARTIAL
|
||||||
static size_t bchunk_list_data_check(
|
static size_t bchunk_list_data_check(
|
||||||
const BChunkList *chunk_list, const ubyte *data)
|
const BChunkList *chunk_list, const uchar *data)
|
||||||
{
|
{
|
||||||
size_t total_size = 0;
|
size_t total_size = 0;
|
||||||
for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) {
|
for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) {
|
||||||
@@ -466,7 +463,7 @@ static void bchunk_list_ensure_min_size_last(
|
|||||||
chunk_list->chunk_refs.last = cref->prev;
|
chunk_list->chunk_refs.last = cref->prev;
|
||||||
chunk_list->chunk_refs_len -= 1;
|
chunk_list->chunk_refs_len -= 1;
|
||||||
|
|
||||||
ubyte *data_merge = MEM_mallocN(data_merge_len, __func__);
|
uchar *data_merge = MEM_mallocN(data_merge_len, __func__);
|
||||||
memcpy(data_merge, chunk_prev->data, chunk_prev->data_len);
|
memcpy(data_merge, chunk_prev->data, chunk_prev->data_len);
|
||||||
memcpy(&data_merge[chunk_prev->data_len], chunk_curr->data, chunk_curr->data_len);
|
memcpy(&data_merge[chunk_prev->data_len], chunk_curr->data, chunk_curr->data_len);
|
||||||
|
|
||||||
@@ -487,8 +484,8 @@ static void bchunk_list_ensure_min_size_last(
|
|||||||
/* merge and split */
|
/* merge and split */
|
||||||
const size_t data_prev_len = split;
|
const size_t data_prev_len = split;
|
||||||
const size_t data_curr_len = data_merge_len - split;
|
const size_t data_curr_len = data_merge_len - split;
|
||||||
ubyte *data_prev = MEM_mallocN(data_prev_len, __func__);
|
uchar *data_prev = MEM_mallocN(data_prev_len, __func__);
|
||||||
ubyte *data_curr = MEM_mallocN(data_curr_len, __func__);
|
uchar *data_curr = MEM_mallocN(data_curr_len, __func__);
|
||||||
|
|
||||||
if (data_prev_len <= chunk_prev->data_len) {
|
if (data_prev_len <= chunk_prev->data_len) {
|
||||||
const size_t data_curr_shrink_len = chunk_prev->data_len - data_prev_len;
|
const size_t data_curr_shrink_len = chunk_prev->data_len - data_prev_len;
|
||||||
@@ -597,7 +594,7 @@ static void bchunk_list_append_only(
|
|||||||
static void bchunk_list_append_data(
|
static void bchunk_list_append_data(
|
||||||
const BArrayInfo *info, BArrayMemory *bs_mem,
|
const BArrayInfo *info, BArrayMemory *bs_mem,
|
||||||
BChunkList *chunk_list,
|
BChunkList *chunk_list,
|
||||||
const ubyte *data, const size_t data_len)
|
const uchar *data, const size_t data_len)
|
||||||
{
|
{
|
||||||
BLI_assert(data_len != 0);
|
BLI_assert(data_len != 0);
|
||||||
|
|
||||||
@@ -613,13 +610,13 @@ static void bchunk_list_append_data(
|
|||||||
const size_t data_merge_len = chunk_prev->data_len + data_len;
|
const size_t data_merge_len = chunk_prev->data_len + data_len;
|
||||||
/* realloc for single user */
|
/* realloc for single user */
|
||||||
if (cref->link->users == 1) {
|
if (cref->link->users == 1) {
|
||||||
ubyte *data_merge = MEM_reallocN((void *)cref->link->data, data_merge_len);
|
uchar *data_merge = MEM_reallocN((void *)cref->link->data, data_merge_len);
|
||||||
memcpy(&data_merge[chunk_prev->data_len], data, data_len);
|
memcpy(&data_merge[chunk_prev->data_len], data, data_len);
|
||||||
cref->link->data = data_merge;
|
cref->link->data = data_merge;
|
||||||
cref->link->data_len = data_merge_len;
|
cref->link->data_len = data_merge_len;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ubyte *data_merge = MEM_mallocN(data_merge_len, __func__);
|
uchar *data_merge = MEM_mallocN(data_merge_len, __func__);
|
||||||
memcpy(data_merge, chunk_prev->data, chunk_prev->data_len);
|
memcpy(data_merge, chunk_prev->data, chunk_prev->data_len);
|
||||||
memcpy(&data_merge[chunk_prev->data_len], data, data_len);
|
memcpy(&data_merge[chunk_prev->data_len], data, data_len);
|
||||||
cref->link = bchunk_new(bs_mem, data_merge, data_merge_len);
|
cref->link = bchunk_new(bs_mem, data_merge, data_merge_len);
|
||||||
@@ -654,7 +651,7 @@ static void bchunk_list_append_data(
|
|||||||
static void bchunk_list_append_data_n(
|
static void bchunk_list_append_data_n(
|
||||||
const BArrayInfo *info, BArrayMemory *bs_mem,
|
const BArrayInfo *info, BArrayMemory *bs_mem,
|
||||||
BChunkList *chunk_list,
|
BChunkList *chunk_list,
|
||||||
const ubyte *data, size_t data_len)
|
const uchar *data, size_t data_len)
|
||||||
{
|
{
|
||||||
size_t data_trim_len, data_last_chunk_len;
|
size_t data_trim_len, data_last_chunk_len;
|
||||||
bchunk_list_calc_trim_len(info, data_len, &data_trim_len, &data_last_chunk_len);
|
bchunk_list_calc_trim_len(info, data_len, &data_trim_len, &data_last_chunk_len);
|
||||||
@@ -714,7 +711,7 @@ static void bchunk_list_append(
|
|||||||
static void bchunk_list_fill_from_array(
|
static void bchunk_list_fill_from_array(
|
||||||
const BArrayInfo *info, BArrayMemory *bs_mem,
|
const BArrayInfo *info, BArrayMemory *bs_mem,
|
||||||
BChunkList *chunk_list,
|
BChunkList *chunk_list,
|
||||||
const ubyte *data,
|
const uchar *data,
|
||||||
const size_t data_len)
|
const size_t data_len)
|
||||||
{
|
{
|
||||||
BLI_assert(BLI_listbase_is_empty(&chunk_list->chunk_refs));
|
BLI_assert(BLI_listbase_is_empty(&chunk_list->chunk_refs));
|
||||||
@@ -765,13 +762,13 @@ static void bchunk_list_fill_from_array(
|
|||||||
|
|
||||||
#define HASH_INIT (5381)
|
#define HASH_INIT (5381)
|
||||||
|
|
||||||
BLI_INLINE uint hash_data_single(const ubyte p)
|
BLI_INLINE uint hash_data_single(const uchar p)
|
||||||
{
|
{
|
||||||
return (HASH_INIT << 5) + HASH_INIT + (unsigned int)p;
|
return (HASH_INIT << 5) + HASH_INIT + (unsigned int)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hash bytes, from BLI_ghashutil_strhash_n */
|
/* hash bytes, from BLI_ghashutil_strhash_n */
|
||||||
static uint hash_data(const ubyte *key, size_t n)
|
static uint hash_data(const uchar *key, size_t n)
|
||||||
{
|
{
|
||||||
const signed char *p;
|
const signed char *p;
|
||||||
unsigned int h = HASH_INIT;
|
unsigned int h = HASH_INIT;
|
||||||
@@ -788,7 +785,7 @@ static uint hash_data(const ubyte *key, size_t n)
|
|||||||
|
|
||||||
#ifdef USE_HASH_TABLE_ACCUMULATE
|
#ifdef USE_HASH_TABLE_ACCUMULATE
|
||||||
static void hash_array_from_data(
|
static void hash_array_from_data(
|
||||||
const BArrayInfo *info, const ubyte *data_slice, const size_t data_slice_len,
|
const BArrayInfo *info, const uchar *data_slice, const size_t data_slice_len,
|
||||||
hash_key *hash_array)
|
hash_key *hash_array)
|
||||||
{
|
{
|
||||||
if (info->chunk_stride != 1) {
|
if (info->chunk_stride != 1) {
|
||||||
@@ -929,7 +926,7 @@ static hash_key key_from_chunk_ref(
|
|||||||
|
|
||||||
static const BChunkRef *table_lookup(
|
static const BChunkRef *table_lookup(
|
||||||
const BArrayInfo *info, BTableRef **table, const size_t table_len, const size_t i_table_start,
|
const BArrayInfo *info, BTableRef **table, const size_t table_len, const size_t i_table_start,
|
||||||
const ubyte *data, const size_t data_len, const size_t offset, const hash_key *table_hash_array)
|
const uchar *data, const size_t data_len, const size_t offset, const hash_key *table_hash_array)
|
||||||
{
|
{
|
||||||
size_t size_left = data_len - offset;
|
size_t size_left = data_len - offset;
|
||||||
hash_key key = table_hash_array[((offset - i_table_start) / info->chunk_stride)];
|
hash_key key = table_hash_array[((offset - i_table_start) / info->chunk_stride)];
|
||||||
@@ -985,7 +982,7 @@ static hash_key key_from_chunk_ref(const BArrayInfo *info, const BChunkRef *cref
|
|||||||
|
|
||||||
static const BChunkRef *table_lookup(
|
static const BChunkRef *table_lookup(
|
||||||
const BArrayInfo *info, BTableRef **table, const size_t table_len, const uint UNUSED(i_table_start),
|
const BArrayInfo *info, BTableRef **table, const size_t table_len, const uint UNUSED(i_table_start),
|
||||||
const ubyte *data, const size_t data_len, const size_t offset, const hash_key *UNUSED(table_hash_array))
|
const uchar *data, const size_t data_len, const size_t offset, const hash_key *UNUSED(table_hash_array))
|
||||||
{
|
{
|
||||||
const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; /* TODO, cache */
|
const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; /* TODO, cache */
|
||||||
|
|
||||||
@@ -1025,7 +1022,7 @@ static const BChunkRef *table_lookup(
|
|||||||
*/
|
*/
|
||||||
static BChunkList *bchunk_list_from_data_merge(
|
static BChunkList *bchunk_list_from_data_merge(
|
||||||
const BArrayInfo *info, BArrayMemory *bs_mem,
|
const BArrayInfo *info, BArrayMemory *bs_mem,
|
||||||
const ubyte *data, const size_t data_len_original,
|
const uchar *data, const size_t data_len_original,
|
||||||
const BChunkList *chunk_list_reference)
|
const BChunkList *chunk_list_reference)
|
||||||
{
|
{
|
||||||
ASSERT_CHUNKLIST_SIZE(chunk_list_reference, chunk_list_reference->total_size);
|
ASSERT_CHUNKLIST_SIZE(chunk_list_reference, chunk_list_reference->total_size);
|
||||||
@@ -1579,7 +1576,7 @@ BArrayState *BLI_array_store_state_add(
|
|||||||
if (state_reference) {
|
if (state_reference) {
|
||||||
chunk_list = bchunk_list_from_data_merge(
|
chunk_list = bchunk_list_from_data_merge(
|
||||||
&bs->info, &bs->memory,
|
&bs->info, &bs->memory,
|
||||||
(const ubyte *)data, data_len,
|
(const uchar *)data, data_len,
|
||||||
/* re-use reference chunks */
|
/* re-use reference chunks */
|
||||||
state_reference->chunk_list);
|
state_reference->chunk_list);
|
||||||
}
|
}
|
||||||
@@ -1588,7 +1585,7 @@ BArrayState *BLI_array_store_state_add(
|
|||||||
bchunk_list_fill_from_array(
|
bchunk_list_fill_from_array(
|
||||||
&bs->info, &bs->memory,
|
&bs->info, &bs->memory,
|
||||||
chunk_list,
|
chunk_list,
|
||||||
(const ubyte *)data, data_len);
|
(const uchar *)data, data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_list->users += 1;
|
chunk_list->users += 1;
|
||||||
@@ -1655,7 +1652,7 @@ void BLI_array_store_state_data_get(
|
|||||||
BLI_assert(data_test_len == state->chunk_list->total_size);
|
BLI_assert(data_test_len == state->chunk_list->total_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ubyte *data_step = (ubyte *)data;
|
uchar *data_step = (uchar *)data;
|
||||||
for (BChunkRef *cref = state->chunk_list->chunk_refs.first; cref; cref = cref->next) {
|
for (BChunkRef *cref = state->chunk_list->chunk_refs.first; cref; cref = cref->next) {
|
||||||
BLI_assert(cref->link->users > 0);
|
BLI_assert(cref->link->users > 0);
|
||||||
memcpy(data_step, cref->link->data, cref->link->data_len);
|
memcpy(data_step, cref->link->data, cref->link->data_len);
|
||||||
|
|||||||
@@ -1575,6 +1575,29 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fix for T50736, Glare comp node using same var for two different things. */
|
||||||
|
if (!DNA_struct_elem_find(fd->filesdna, "NodeGlare", "char", "star_45")) {
|
||||||
|
FOREACH_NODETREE(main, ntree, id) {
|
||||||
|
if (ntree->type == NTREE_COMPOSIT) {
|
||||||
|
ntreeSetTypes(NULL, ntree);
|
||||||
|
for (bNode *node = ntree->nodes.first; node; node = node->next) {
|
||||||
|
if (node->type == CMP_NODE_GLARE) {
|
||||||
|
NodeGlare *ndg = node->storage;
|
||||||
|
switch (ndg->type) {
|
||||||
|
case 2: /* Grrrr! magic numbers :( */
|
||||||
|
ndg->streaks = ndg->angle;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
ndg->star_45 = ndg->angle != 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} FOREACH_NODETREE_END
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1027,6 +1027,25 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
|
|||||||
{
|
{
|
||||||
/* pass */
|
/* pass */
|
||||||
}
|
}
|
||||||
|
else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_GLARE)) {
|
||||||
|
/* Simple forward compat for fix for T50736.
|
||||||
|
* Not ideal (there is no ideal solution here), but should do for now. */
|
||||||
|
NodeGlare *ndg = node->storage;
|
||||||
|
/* Not in undo case. */
|
||||||
|
if (!wd->current) {
|
||||||
|
switch (ndg->type) {
|
||||||
|
case 2: /* Grrrr! magic numbers :( */
|
||||||
|
ndg->angle = ndg->streaks;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
ndg->angle = ndg->star_45;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
|
writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1122,7 +1122,7 @@ static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Shift borderline coordinates to the left. */
|
/* Shift borderline coordinates to the left. */
|
||||||
if (fabsf(theta - M_PI) < 0.0001f) {
|
if (fabsf(theta - (float)M_PI) < 0.0001f) {
|
||||||
theta = -M_PI;
|
theta = -M_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -230,7 +230,6 @@ void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::Unique
|
|||||||
ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature);
|
ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature);
|
||||||
ArmatureModifierData *amd = (ArmatureModifierData *)md;
|
ArmatureModifierData *amd = (ArmatureModifierData *)md;
|
||||||
amd->object = ob_arm;
|
amd->object = ob_arm;
|
||||||
struct bArmature *armature = (bArmature *)ob_arm->data;
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
bc_set_parent(ob, ob_arm, C);
|
bc_set_parent(ob, ob_arm, C);
|
||||||
|
|||||||
@@ -44,18 +44,18 @@ void GlareSimpleStarOperation::generateGlare(float *data, MemoryBuffer *inputTil
|
|||||||
xp = x + i;
|
xp = x + i;
|
||||||
tbuf1->read(c, x, y);
|
tbuf1->read(c, x, y);
|
||||||
mul_v3_fl(c, f1);
|
mul_v3_fl(c, f1);
|
||||||
tbuf1->read(tc, (settings->angle ? xm : x), ym);
|
tbuf1->read(tc, (settings->star_45 ? xm : x), ym);
|
||||||
madd_v3_v3fl(c, tc, f2);
|
madd_v3_v3fl(c, tc, f2);
|
||||||
tbuf1->read(tc, (settings->angle ? xp : x), yp);
|
tbuf1->read(tc, (settings->star_45 ? xp : x), yp);
|
||||||
madd_v3_v3fl(c, tc, f2);
|
madd_v3_v3fl(c, tc, f2);
|
||||||
c[3] = 1.0f;
|
c[3] = 1.0f;
|
||||||
tbuf1->writePixel(x, y, c);
|
tbuf1->writePixel(x, y, c);
|
||||||
|
|
||||||
tbuf2->read(c, x, y);
|
tbuf2->read(c, x, y);
|
||||||
mul_v3_fl(c, f1);
|
mul_v3_fl(c, f1);
|
||||||
tbuf2->read(tc, xm, (settings->angle ? yp : y));
|
tbuf2->read(tc, xm, (settings->star_45 ? yp : y));
|
||||||
madd_v3_v3fl(c, tc, f2);
|
madd_v3_v3fl(c, tc, f2);
|
||||||
tbuf2->read(tc, xp, (settings->angle ? ym : y));
|
tbuf2->read(tc, xp, (settings->star_45 ? ym : y));
|
||||||
madd_v3_v3fl(c, tc, f2);
|
madd_v3_v3fl(c, tc, f2);
|
||||||
c[3] = 1.0f;
|
c[3] = 1.0f;
|
||||||
tbuf2->writePixel(x, y, c);
|
tbuf2->writePixel(x, y, c);
|
||||||
@@ -73,18 +73,18 @@ void GlareSimpleStarOperation::generateGlare(float *data, MemoryBuffer *inputTil
|
|||||||
xp = x + i;
|
xp = x + i;
|
||||||
tbuf1->read(c, x, y);
|
tbuf1->read(c, x, y);
|
||||||
mul_v3_fl(c, f1);
|
mul_v3_fl(c, f1);
|
||||||
tbuf1->read(tc, (settings->angle ? xm : x), ym);
|
tbuf1->read(tc, (settings->star_45 ? xm : x), ym);
|
||||||
madd_v3_v3fl(c, tc, f2);
|
madd_v3_v3fl(c, tc, f2);
|
||||||
tbuf1->read(tc, (settings->angle ? xp : x), yp);
|
tbuf1->read(tc, (settings->star_45 ? xp : x), yp);
|
||||||
madd_v3_v3fl(c, tc, f2);
|
madd_v3_v3fl(c, tc, f2);
|
||||||
c[3] = 1.0f;
|
c[3] = 1.0f;
|
||||||
tbuf1->writePixel(x, y, c);
|
tbuf1->writePixel(x, y, c);
|
||||||
|
|
||||||
tbuf2->read(c, x, y);
|
tbuf2->read(c, x, y);
|
||||||
mul_v3_fl(c, f1);
|
mul_v3_fl(c, f1);
|
||||||
tbuf2->read(tc, xm, (settings->angle ? yp : y));
|
tbuf2->read(tc, xm, (settings->star_45 ? yp : y));
|
||||||
madd_v3_v3fl(c, tc, f2);
|
madd_v3_v3fl(c, tc, f2);
|
||||||
tbuf2->read(tc, xp, (settings->angle ? ym : y));
|
tbuf2->read(tc, xp, (settings->star_45 ? ym : y));
|
||||||
madd_v3_v3fl(c, tc, f2);
|
madd_v3_v3fl(c, tc, f2);
|
||||||
c[3] = 1.0f;
|
c[3] = 1.0f;
|
||||||
tbuf2->writePixel(x, y, c);
|
tbuf2->writePixel(x, y, c);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ void GlareStreaksOperation::generateGlare(float *data, MemoryBuffer *inputTile,
|
|||||||
int x, y, n;
|
int x, y, n;
|
||||||
unsigned int nump = 0;
|
unsigned int nump = 0;
|
||||||
float c1[4], c2[4], c3[4], c4[4];
|
float c1[4], c2[4], c3[4], c4[4];
|
||||||
float a, ang = DEG2RADF(360.0f) / (float)settings->angle;
|
float a, ang = DEG2RADF(360.0f) / (float)settings->streaks;
|
||||||
|
|
||||||
int size = inputTile->getWidth() * inputTile->getHeight();
|
int size = inputTile->getWidth() * inputTile->getHeight();
|
||||||
int size4 = size * 4;
|
int size4 = size * 4;
|
||||||
|
|||||||
@@ -92,14 +92,6 @@ typedef struct {
|
|||||||
int flag;
|
int flag;
|
||||||
} UndoCurve;
|
} UndoCurve;
|
||||||
|
|
||||||
/* Definitions needed for shape keys */
|
|
||||||
typedef struct {
|
|
||||||
void *orig_cv;
|
|
||||||
int key_index, nu_index, pt_index, vertex_index;
|
|
||||||
bool switched;
|
|
||||||
Nurb *orig_nu;
|
|
||||||
} CVKeyIndex;
|
|
||||||
|
|
||||||
void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus);
|
void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus);
|
||||||
static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split);
|
static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split);
|
||||||
static int curve_delete_segments(Object *obedit, const bool split);
|
static int curve_delete_segments(Object *obedit, const bool split);
|
||||||
@@ -139,9 +131,9 @@ void printknots(Object *obedit)
|
|||||||
|
|
||||||
/* ********************* Shape keys *************** */
|
/* ********************* Shape keys *************** */
|
||||||
|
|
||||||
static CVKeyIndex *init_cvKeyIndex(void *cv, int key_index, int nu_index, int pt_index, int vertex_index, Nurb *orig_nu)
|
static CVKeyIndex *init_cvKeyIndex(void *cv, int key_index, int nu_index, int pt_index, int vertex_index)
|
||||||
{
|
{
|
||||||
CVKeyIndex *cvIndex = MEM_callocN(sizeof(CVKeyIndex), "init_cvKeyIndex");
|
CVKeyIndex *cvIndex = MEM_callocN(sizeof(CVKeyIndex), __func__);
|
||||||
|
|
||||||
cvIndex->orig_cv = cv;
|
cvIndex->orig_cv = cv;
|
||||||
cvIndex->key_index = key_index;
|
cvIndex->key_index = key_index;
|
||||||
@@ -149,7 +141,6 @@ static CVKeyIndex *init_cvKeyIndex(void *cv, int key_index, int nu_index, int pt
|
|||||||
cvIndex->pt_index = pt_index;
|
cvIndex->pt_index = pt_index;
|
||||||
cvIndex->vertex_index = vertex_index;
|
cvIndex->vertex_index = vertex_index;
|
||||||
cvIndex->switched = false;
|
cvIndex->switched = false;
|
||||||
cvIndex->orig_nu = orig_nu;
|
|
||||||
|
|
||||||
return cvIndex;
|
return cvIndex;
|
||||||
}
|
}
|
||||||
@@ -175,7 +166,12 @@ static void init_editNurb_keyIndex(EditNurb *editnurb, ListBase *origBase)
|
|||||||
origbezt = orignu->bezt;
|
origbezt = orignu->bezt;
|
||||||
pt_index = 0;
|
pt_index = 0;
|
||||||
while (a--) {
|
while (a--) {
|
||||||
keyIndex = init_cvKeyIndex(origbezt, key_index, nu_index, pt_index, vertex_index, orignu);
|
/* We cannot keep *any* reference to curve obdata,
|
||||||
|
* it might be replaced and freed while editcurve remain in use (in viewport render case e.g.).
|
||||||
|
* Note that we could use a pool to avoid lots of malloc's here, but... not really a problem for now. */
|
||||||
|
BezTriple *origbezt_cpy = MEM_mallocN(sizeof(*origbezt), __func__);
|
||||||
|
*origbezt_cpy = *origbezt;
|
||||||
|
keyIndex = init_cvKeyIndex(origbezt_cpy, key_index, nu_index, pt_index, vertex_index);
|
||||||
BLI_ghash_insert(gh, bezt, keyIndex);
|
BLI_ghash_insert(gh, bezt, keyIndex);
|
||||||
key_index += 12;
|
key_index += 12;
|
||||||
vertex_index += 3;
|
vertex_index += 3;
|
||||||
@@ -190,7 +186,12 @@ static void init_editNurb_keyIndex(EditNurb *editnurb, ListBase *origBase)
|
|||||||
origbp = orignu->bp;
|
origbp = orignu->bp;
|
||||||
pt_index = 0;
|
pt_index = 0;
|
||||||
while (a--) {
|
while (a--) {
|
||||||
keyIndex = init_cvKeyIndex(origbp, key_index, nu_index, pt_index, vertex_index, orignu);
|
/* We cannot keep *any* reference to curve obdata,
|
||||||
|
* it might be replaced and freed while editcurve remain in use (in viewport render case e.g.).
|
||||||
|
* Note that we could use a pool to avoid lots of malloc's here, but... not really a problem for now. */
|
||||||
|
BPoint *origbp_cpy = MEM_mallocN(sizeof(*origbp_cpy), __func__);
|
||||||
|
*origbp_cpy = *origbp;
|
||||||
|
keyIndex = init_cvKeyIndex(origbp_cpy, key_index, nu_index, pt_index, vertex_index);
|
||||||
BLI_ghash_insert(gh, bp, keyIndex);
|
BLI_ghash_insert(gh, bp, keyIndex);
|
||||||
key_index += 4;
|
key_index += 4;
|
||||||
bp++;
|
bp++;
|
||||||
@@ -251,23 +252,22 @@ static int getKeyIndexOrig_keyIndex(EditNurb *editnurb, void *cv)
|
|||||||
return index->key_index;
|
return index->key_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyIndex_delCV(EditNurb *editnurb, const void *cv)
|
static void keyIndex_delBezt(EditNurb *editnurb, BezTriple *bezt)
|
||||||
{
|
{
|
||||||
if (!editnurb->keyindex) {
|
if (!editnurb->keyindex) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLI_ghash_remove(editnurb->keyindex, cv, NULL, MEM_freeN);
|
BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt);
|
||||||
}
|
|
||||||
|
|
||||||
static void keyIndex_delBezt(EditNurb *editnurb, BezTriple *bezt)
|
|
||||||
{
|
|
||||||
keyIndex_delCV(editnurb, bezt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyIndex_delBP(EditNurb *editnurb, BPoint *bp)
|
static void keyIndex_delBP(EditNurb *editnurb, BPoint *bp)
|
||||||
{
|
{
|
||||||
keyIndex_delCV(editnurb, bp);
|
if (!editnurb->keyindex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
|
static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
|
||||||
@@ -283,7 +283,7 @@ static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
|
|||||||
a = nu->pntsu;
|
a = nu->pntsu;
|
||||||
|
|
||||||
while (a--) {
|
while (a--) {
|
||||||
BLI_ghash_remove(editnurb->keyindex, bezt, NULL, MEM_freeN);
|
BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt);
|
||||||
bezt++;
|
bezt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -292,7 +292,7 @@ static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
|
|||||||
a = nu->pntsu * nu->pntsv;
|
a = nu->pntsu * nu->pntsv;
|
||||||
|
|
||||||
while (a--) {
|
while (a--) {
|
||||||
BLI_ghash_remove(editnurb->keyindex, bp, NULL, MEM_freeN);
|
BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp);
|
||||||
bp++;
|
bp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -536,6 +536,7 @@ static GHash *dupli_keyIndexHash(GHash *keyindex)
|
|||||||
CVKeyIndex *newIndex = MEM_mallocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index");
|
CVKeyIndex *newIndex = MEM_mallocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index");
|
||||||
|
|
||||||
memcpy(newIndex, index, sizeof(CVKeyIndex));
|
memcpy(newIndex, index, sizeof(CVKeyIndex));
|
||||||
|
newIndex->orig_cv = MEM_dupallocN(index->orig_cv);
|
||||||
|
|
||||||
BLI_ghash_insert(gh, cv, newIndex);
|
BLI_ghash_insert(gh, cv, newIndex);
|
||||||
}
|
}
|
||||||
@@ -625,7 +626,7 @@ static void calc_keyHandles(ListBase *nurb, float *key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calc_shapeKeys(Object *obedit)
|
static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
|
||||||
{
|
{
|
||||||
Curve *cu = (Curve *)obedit->data;
|
Curve *cu = (Curve *)obedit->data;
|
||||||
|
|
||||||
@@ -637,7 +638,7 @@ static void calc_shapeKeys(Object *obedit)
|
|||||||
KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1);
|
KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1);
|
||||||
BezTriple *bezt, *oldbezt;
|
BezTriple *bezt, *oldbezt;
|
||||||
BPoint *bp, *oldbp;
|
BPoint *bp, *oldbp;
|
||||||
Nurb *nu;
|
Nurb *nu, *newnu;
|
||||||
int totvert = BKE_nurbList_verts_count(&editnurb->nurbs);
|
int totvert = BKE_nurbList_verts_count(&editnurb->nurbs);
|
||||||
|
|
||||||
float (*ofs)[3] = NULL;
|
float (*ofs)[3] = NULL;
|
||||||
@@ -707,20 +708,25 @@ static void calc_shapeKeys(Object *obedit)
|
|||||||
|
|
||||||
currkey = cu->key->block.first;
|
currkey = cu->key->block.first;
|
||||||
while (currkey) {
|
while (currkey) {
|
||||||
int apply_offset = (ofs && (currkey != actkey) && (editnurb->shapenr - 1 == currkey->relative));
|
const bool apply_offset = (ofs && (currkey != actkey) && (editnurb->shapenr - 1 == currkey->relative));
|
||||||
|
|
||||||
float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data");
|
float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data");
|
||||||
ofp = oldkey = currkey->data;
|
ofp = oldkey = currkey->data;
|
||||||
|
|
||||||
nu = editnurb->nurbs.first;
|
nu = editnurb->nurbs.first;
|
||||||
|
/* We need to restore to original curve into newnurb, *not* editcurve's nurbs.
|
||||||
|
* Otherwise, in case we update obdata *without* leaving editmode (e.g. viewport render), we would
|
||||||
|
* invalidate editcurve. */
|
||||||
|
newnu = newnurbs->first;
|
||||||
i = 0;
|
i = 0;
|
||||||
while (nu) {
|
while (nu) {
|
||||||
if (currkey == actkey) {
|
if (currkey == actkey) {
|
||||||
int restore = actkey != cu->key->refkey;
|
const bool restore = actkey != cu->key->refkey;
|
||||||
|
|
||||||
if (nu->bezt) {
|
if (nu->bezt) {
|
||||||
bezt = nu->bezt;
|
bezt = nu->bezt;
|
||||||
a = nu->pntsu;
|
a = nu->pntsu;
|
||||||
|
BezTriple *newbezt = newnu->bezt;
|
||||||
while (a--) {
|
while (a--) {
|
||||||
int j;
|
int j;
|
||||||
oldbezt = getKeyIndexOrig_bezt(editnurb, bezt);
|
oldbezt = getKeyIndexOrig_bezt(editnurb, bezt);
|
||||||
@@ -729,7 +735,7 @@ static void calc_shapeKeys(Object *obedit)
|
|||||||
copy_v3_v3(fp, bezt->vec[j]);
|
copy_v3_v3(fp, bezt->vec[j]);
|
||||||
|
|
||||||
if (restore && oldbezt) {
|
if (restore && oldbezt) {
|
||||||
copy_v3_v3(bezt->vec[j], oldbezt->vec[j]);
|
copy_v3_v3(newbezt->vec[j], oldbezt->vec[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fp += 3;
|
fp += 3;
|
||||||
@@ -737,16 +743,18 @@ static void calc_shapeKeys(Object *obedit)
|
|||||||
fp[0] = bezt->alfa;
|
fp[0] = bezt->alfa;
|
||||||
|
|
||||||
if (restore && oldbezt) {
|
if (restore && oldbezt) {
|
||||||
bezt->alfa = oldbezt->alfa;
|
newbezt->alfa = oldbezt->alfa;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp += 3; ++i; /* alphas */
|
fp += 3; ++i; /* alphas */
|
||||||
bezt++;
|
bezt++;
|
||||||
|
newbezt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bp = nu->bp;
|
bp = nu->bp;
|
||||||
a = nu->pntsu * nu->pntsv;
|
a = nu->pntsu * nu->pntsv;
|
||||||
|
BPoint *newbp = newnu->bp;
|
||||||
while (a--) {
|
while (a--) {
|
||||||
oldbp = getKeyIndexOrig_bp(editnurb, bp);
|
oldbp = getKeyIndexOrig_bp(editnurb, bp);
|
||||||
|
|
||||||
@@ -755,12 +763,13 @@ static void calc_shapeKeys(Object *obedit)
|
|||||||
fp[3] = bp->alfa;
|
fp[3] = bp->alfa;
|
||||||
|
|
||||||
if (restore && oldbp) {
|
if (restore && oldbp) {
|
||||||
copy_v3_v3(bp->vec, oldbp->vec);
|
copy_v3_v3(newbp->vec, oldbp->vec);
|
||||||
bp->alfa = oldbp->alfa;
|
newbp->alfa = oldbp->alfa;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp += 4;
|
fp += 4;
|
||||||
bp++;
|
bp++;
|
||||||
|
newbp++;
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1196,11 +1205,6 @@ void ED_curve_editnurb_load(Object *obedit)
|
|||||||
|
|
||||||
remap_hooks_and_vertex_parents(obedit);
|
remap_hooks_and_vertex_parents(obedit);
|
||||||
|
|
||||||
/* We have to apply shapekeys *before* copying nurbs into newnurb, otherwise the reset to
|
|
||||||
* refkey/original curve data that has to be done when editing non-refkey shapekey would be useless,
|
|
||||||
* only affecting editnurb and not ob->data. */
|
|
||||||
calc_shapeKeys(obedit);
|
|
||||||
|
|
||||||
for (nu = editnurb->first; nu; nu = nu->next) {
|
for (nu = editnurb->first; nu; nu = nu->next) {
|
||||||
newnu = BKE_nurb_duplicate(nu);
|
newnu = BKE_nurb_duplicate(nu);
|
||||||
BLI_addtail(&newnurb, newnu);
|
BLI_addtail(&newnurb, newnu);
|
||||||
@@ -1210,6 +1214,11 @@ void ED_curve_editnurb_load(Object *obedit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We have to pass also new copied nurbs, since we want to restore original curve (without edited shapekey)
|
||||||
|
* on obdata, but *not* on editcurve itself (ED_curve_editnurb_load call does not always implies freeing
|
||||||
|
* of editcurve, e.g. when called to generate render data...). */
|
||||||
|
calc_shapeKeys(obedit, &newnurb);
|
||||||
|
|
||||||
cu->nurb = newnurb;
|
cu->nurb = newnurb;
|
||||||
|
|
||||||
ED_curve_updateAnimPaths(obedit->data);
|
ED_curve_updateAnimPaths(obedit->data);
|
||||||
@@ -1236,8 +1245,7 @@ void ED_curve_editnurb_make(Object *obedit)
|
|||||||
|
|
||||||
if (editnurb) {
|
if (editnurb) {
|
||||||
BKE_nurbList_free(&editnurb->nurbs);
|
BKE_nurbList_free(&editnurb->nurbs);
|
||||||
BKE_curve_editNurb_keyIndex_free(editnurb);
|
BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
|
||||||
editnurb->keyindex = NULL;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
editnurb = MEM_callocN(sizeof(EditNurb), "editnurb");
|
editnurb = MEM_callocN(sizeof(EditNurb), "editnurb");
|
||||||
@@ -1318,8 +1326,7 @@ static int separate_exec(bContext *C, wmOperator *op)
|
|||||||
ED_curve_editnurb_make(newob);
|
ED_curve_editnurb_make(newob);
|
||||||
newedit = newcu->editnurb;
|
newedit = newcu->editnurb;
|
||||||
BKE_nurbList_free(&newedit->nurbs);
|
BKE_nurbList_free(&newedit->nurbs);
|
||||||
BKE_curve_editNurb_keyIndex_free(newedit);
|
BKE_curve_editNurb_keyIndex_free(&newedit->keyindex);
|
||||||
newedit->keyindex = NULL;
|
|
||||||
BLI_movelisttolist(&newedit->nurbs, &newnurb);
|
BLI_movelisttolist(&newedit->nurbs, &newnurb);
|
||||||
|
|
||||||
/* 4. put old object out of editmode and delete separated geometry */
|
/* 4. put old object out of editmode and delete separated geometry */
|
||||||
@@ -6119,7 +6126,7 @@ static void undoCurve_to_editCurve(void *ucu, void *UNUSED(edata), void *cu_v)
|
|||||||
BKE_nurbList_free(editbase);
|
BKE_nurbList_free(editbase);
|
||||||
|
|
||||||
if (undoCurve->undoIndex) {
|
if (undoCurve->undoIndex) {
|
||||||
BLI_ghash_free(editnurb->keyindex, NULL, MEM_freeN);
|
BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
|
||||||
editnurb->keyindex = dupli_keyIndexHash(undoCurve->undoIndex);
|
editnurb->keyindex = dupli_keyIndexHash(undoCurve->undoIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6197,8 +6204,7 @@ static void free_undoCurve(void *ucv)
|
|||||||
|
|
||||||
BKE_nurbList_free(&undoCurve->nubase);
|
BKE_nurbList_free(&undoCurve->nubase);
|
||||||
|
|
||||||
if (undoCurve->undoIndex)
|
BKE_curve_editNurb_keyIndex_free(&undoCurve->undoIndex);
|
||||||
BLI_ghash_free(undoCurve->undoIndex, NULL, MEM_freeN);
|
|
||||||
|
|
||||||
free_fcurves(&undoCurve->fcurves);
|
free_fcurves(&undoCurve->fcurves);
|
||||||
free_fcurves(&undoCurve->drivers);
|
free_fcurves(&undoCurve->drivers);
|
||||||
|
|||||||
@@ -2216,7 +2216,6 @@ static void ui_litem_estimate_column(uiLayout *litem)
|
|||||||
{
|
{
|
||||||
uiItem *item;
|
uiItem *item;
|
||||||
int itemw, itemh;
|
int itemw, itemh;
|
||||||
bool min_size_flag = true;
|
|
||||||
|
|
||||||
litem->w = 0;
|
litem->w = 0;
|
||||||
litem->h = 0;
|
litem->h = 0;
|
||||||
@@ -2224,18 +2223,12 @@ static void ui_litem_estimate_column(uiLayout *litem)
|
|||||||
for (item = litem->items.first; item; item = item->next) {
|
for (item = litem->items.first; item; item = item->next) {
|
||||||
ui_item_size(item, &itemw, &itemh);
|
ui_item_size(item, &itemw, &itemh);
|
||||||
|
|
||||||
min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
|
|
||||||
|
|
||||||
litem->w = MAX2(litem->w, itemw);
|
litem->w = MAX2(litem->w, itemw);
|
||||||
litem->h += itemh;
|
litem->h += itemh;
|
||||||
|
|
||||||
if (item->next)
|
if (item->next)
|
||||||
litem->h += litem->space;
|
litem->h += litem->space;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (min_size_flag) {
|
|
||||||
litem->item.flag |= UI_ITEM_MIN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ui_litem_layout_column(uiLayout *litem)
|
static void ui_litem_layout_column(uiLayout *litem)
|
||||||
@@ -3134,8 +3127,6 @@ static void ui_item_align(uiLayout *litem, short nr)
|
|||||||
else if (item->type == ITEM_LAYOUT_BOX) {
|
else if (item->type == ITEM_LAYOUT_BOX) {
|
||||||
box = (uiLayoutItemBx *)item;
|
box = (uiLayoutItemBx *)item;
|
||||||
box->roundbox->alignnr = nr;
|
box->roundbox->alignnr = nr;
|
||||||
BLI_remlink(&litem->root->block->buttons, box->roundbox);
|
|
||||||
BLI_addhead(&litem->root->block->buttons, box->roundbox);
|
|
||||||
}
|
}
|
||||||
else if (((uiLayout *)item)->align) {
|
else if (((uiLayout *)item)->align) {
|
||||||
ui_item_align((uiLayout *)item, nr);
|
ui_item_align((uiLayout *)item, nr);
|
||||||
|
|||||||
@@ -619,7 +619,7 @@ static Mesh *bake_mesh_new_from_object(Main *bmain, Scene *scene, Object *ob)
|
|||||||
ED_object_editmode_load(ob);
|
ED_object_editmode_load(ob);
|
||||||
|
|
||||||
Mesh *me = BKE_mesh_new_from_object(bmain, scene, ob, 1, 2, 0, 0);
|
Mesh *me = BKE_mesh_new_from_object(bmain, scene, ob, 1, 2, 0, 0);
|
||||||
BKE_mesh_split_faces(me);
|
BKE_mesh_split_faces(me, true);
|
||||||
|
|
||||||
return me;
|
return me;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,8 +181,8 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
|
|||||||
View3D *v3d = (View3D *)sa->spacedata.first;
|
View3D *v3d = (View3D *)sa->spacedata.first;
|
||||||
|
|
||||||
if (ar) {
|
if (ar) {
|
||||||
RegionView3D *rv3d = ar->regiondata;
|
RegionView3D *rv3d;
|
||||||
if (rv3d && (rv3d->viewlock & RV3D_LOCKED) == 0) {
|
if ((ar->regiontype == RGN_TYPE_WINDOW) && (rv3d = ar->regiondata) && (rv3d->viewlock & RV3D_LOCKED) == 0) {
|
||||||
*r_v3d = v3d;
|
*r_v3d = v3d;
|
||||||
*r_ar = ar;
|
*r_ar = ar;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -90,19 +90,6 @@ bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
|
|||||||
return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre);
|
return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool view3d_operator_offset_lock_check(bContext *C, wmOperator *op)
|
|
||||||
{
|
|
||||||
View3D *v3d = CTX_wm_view3d(C);
|
|
||||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
|
||||||
if (ED_view3d_offset_lock_check(v3d, rv3d)) {
|
|
||||||
BKE_report(op->reports, RPT_WARNING, "View offset is locked");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ********************** view3d_edit: view manipulations ********************* */
|
/* ********************** view3d_edit: view manipulations ********************* */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2596,6 +2583,19 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
|
|||||||
|
|
||||||
|
|
||||||
/* ************************ viewdolly ******************************** */
|
/* ************************ viewdolly ******************************** */
|
||||||
|
static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
View3D *v3d = CTX_wm_view3d(C);
|
||||||
|
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||||
|
if (ED_view3d_offset_lock_check(v3d, rv3d)) {
|
||||||
|
BKE_report(op->reports, RPT_WARNING, "Cannot dolly when the view offset is locked");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void view_dolly_mouseloc(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac)
|
static void view_dolly_mouseloc(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac)
|
||||||
{
|
{
|
||||||
RegionView3D *rv3d = ar->regiondata;
|
RegionView3D *rv3d = ar->regiondata;
|
||||||
@@ -2746,7 +2746,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||||||
{
|
{
|
||||||
ViewOpsData *vod;
|
ViewOpsData *vod;
|
||||||
|
|
||||||
if (view3d_operator_offset_lock_check(C, op))
|
if (viewdolly_offset_lock_check(C, op))
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
|
|
||||||
/* makes op->customdata */
|
/* makes op->customdata */
|
||||||
@@ -4364,41 +4364,24 @@ static EnumPropertyItem prop_view_pan_items[] = {
|
|||||||
{0, NULL, 0, NULL, NULL}
|
{0, NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int viewpan_exec(bContext *C, wmOperator *op)
|
static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
{
|
{
|
||||||
ScrArea *sa = CTX_wm_area(C);
|
int x = 0, y = 0;
|
||||||
ARegion *ar = CTX_wm_region(C);
|
int pandir = RNA_enum_get(op->ptr, "type");
|
||||||
View3D *v3d = CTX_wm_view3d(C);
|
|
||||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
|
||||||
float vec[3];
|
|
||||||
const float co_zero[3] = {0.0f};
|
|
||||||
float mval_f[2] = {0.0f, 0.0f};
|
|
||||||
float zfac;
|
|
||||||
int pandir;
|
|
||||||
|
|
||||||
if (view3d_operator_offset_lock_check(C, op))
|
if (pandir == V3D_VIEW_PANRIGHT) { x = -32; }
|
||||||
return OPERATOR_CANCELLED;
|
else if (pandir == V3D_VIEW_PANLEFT) { x = 32; }
|
||||||
|
else if (pandir == V3D_VIEW_PANUP) { y = -25; }
|
||||||
|
else if (pandir == V3D_VIEW_PANDOWN) { y = 25; }
|
||||||
|
|
||||||
pandir = RNA_enum_get(op->ptr, "type");
|
viewops_data_alloc(C, op);
|
||||||
|
viewops_data_create(C, op, event);
|
||||||
|
ViewOpsData *vod = op->customdata;
|
||||||
|
|
||||||
ED_view3d_camera_lock_init(v3d, rv3d);
|
viewmove_apply(vod, vod->oldx + x, vod->oldy + y);
|
||||||
|
|
||||||
zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL);
|
ED_view3d_depth_tag_update(vod->rv3d);
|
||||||
if (pandir == V3D_VIEW_PANRIGHT) { mval_f[0] = -32.0f; }
|
viewops_data_free(C, op);
|
||||||
else if (pandir == V3D_VIEW_PANLEFT) { mval_f[0] = 32.0f; }
|
|
||||||
else if (pandir == V3D_VIEW_PANUP) { mval_f[1] = -25.0f; }
|
|
||||||
else if (pandir == V3D_VIEW_PANDOWN) { mval_f[1] = 25.0f; }
|
|
||||||
ED_view3d_win_to_delta(ar, mval_f, vec, zfac);
|
|
||||||
add_v3_v3(rv3d->ofs, vec);
|
|
||||||
|
|
||||||
if (rv3d->viewlock & RV3D_BOXVIEW)
|
|
||||||
view3d_boxview_sync(sa, ar);
|
|
||||||
|
|
||||||
ED_view3d_depth_tag_update(rv3d);
|
|
||||||
|
|
||||||
ED_view3d_camera_lock_sync(v3d, rv3d);
|
|
||||||
|
|
||||||
ED_region_tag_redraw(ar);
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
@@ -4411,7 +4394,7 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot)
|
|||||||
ot->idname = "VIEW3D_OT_view_pan";
|
ot->idname = "VIEW3D_OT_view_pan";
|
||||||
|
|
||||||
/* api callbacks */
|
/* api callbacks */
|
||||||
ot->exec = viewpan_exec;
|
ot->invoke = viewpan_invoke;
|
||||||
ot->poll = ED_operator_region_view3d_active;
|
ot->poll = ED_operator_region_view3d_active;
|
||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
|
|||||||
@@ -67,8 +67,6 @@
|
|||||||
# define BIG_LONG SWAP_LONG
|
# define BIG_LONG SWAP_LONG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef unsigned char uchar;
|
|
||||||
|
|
||||||
#define IMB_DPI_DEFAULT 72.0f
|
#define IMB_DPI_DEFAULT 72.0f
|
||||||
|
|
||||||
#endif /* __IMBUF_H__ */
|
#endif /* __IMBUF_H__ */
|
||||||
|
|||||||
@@ -668,7 +668,8 @@ typedef struct NodeScriptDict {
|
|||||||
/* qdn: glare node */
|
/* qdn: glare node */
|
||||||
typedef struct NodeGlare {
|
typedef struct NodeGlare {
|
||||||
char quality, type, iter;
|
char quality, type, iter;
|
||||||
char angle, pad_c1, size, pad[2];
|
/* XXX angle is only kept for backward/forward compatibility, was used for two different things, see T50736. */
|
||||||
|
char angle DNA_DEPRECATED, pad_c1, size, star_45, streaks;
|
||||||
float colmod, mix, threshold, fade;
|
float colmod, mix, threshold, fade;
|
||||||
float angle_ofs, pad_f1;
|
float angle_ofs, pad_f1;
|
||||||
} NodeGlare;
|
} NodeGlare;
|
||||||
|
|||||||
@@ -209,6 +209,11 @@ static void rna_Mesh_flip_normals(Mesh *mesh)
|
|||||||
DAG_id_tag_update(&mesh->id, 0);
|
DAG_id_tag_update(&mesh->id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rna_Mesh_split_faces(Mesh *mesh, int free_loop_normals)
|
||||||
|
{
|
||||||
|
BKE_mesh_split_faces(mesh, free_loop_normals != 0);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void RNA_api_mesh(StructRNA *srna)
|
void RNA_api_mesh(StructRNA *srna)
|
||||||
@@ -240,8 +245,10 @@ void RNA_api_mesh(StructRNA *srna)
|
|||||||
func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split");
|
func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split");
|
||||||
RNA_def_function_ui_description(func, "Free split vertex normals");
|
RNA_def_function_ui_description(func, "Free split vertex normals");
|
||||||
|
|
||||||
func = RNA_def_function(srna, "split_faces", "BKE_mesh_split_faces");
|
func = RNA_def_function(srna, "split_faces", "rna_Mesh_split_faces");
|
||||||
RNA_def_function_ui_description(func, "Split faces based on the edge angle");
|
RNA_def_function_ui_description(func, "Split faces based on the edge angle");
|
||||||
|
RNA_def_boolean(func, "free_loop_normals", 1, "Free Loop Notmals",
|
||||||
|
"Free loop normals custom data layer");
|
||||||
|
|
||||||
func = RNA_def_function(srna, "calc_tangents", "rna_Mesh_calc_tangents");
|
func = RNA_def_function(srna, "calc_tangents", "rna_Mesh_calc_tangents");
|
||||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||||
|
|||||||
@@ -5721,8 +5721,8 @@ static void def_cmp_glare(StructRNA *srna)
|
|||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "streaks", PROP_INT, PROP_NONE);
|
prop = RNA_def_property(srna, "streaks", PROP_INT, PROP_NONE);
|
||||||
RNA_def_property_int_sdna(prop, NULL, "angle");
|
RNA_def_property_int_sdna(prop, NULL, "streaks");
|
||||||
RNA_def_property_range(prop, 2, 16);
|
RNA_def_property_range(prop, 1, 16);
|
||||||
RNA_def_property_ui_text(prop, "Streaks", "Total number of streaks");
|
RNA_def_property_ui_text(prop, "Streaks", "Total number of streaks");
|
||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||||
|
|
||||||
@@ -5739,7 +5739,7 @@ static void def_cmp_glare(StructRNA *srna)
|
|||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_rotate_45", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_rotate_45", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_sdna(prop, NULL, "angle", 0);
|
RNA_def_property_boolean_sdna(prop, NULL, "star_45", 0);
|
||||||
RNA_def_property_ui_text(prop, "Rotate 45", "Simple star filter: add 45 degree rotation offset");
|
RNA_def_property_ui_text(prop, "Rotate 45", "Simple star filter: add 45 degree rotation offset");
|
||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||||
|
|
||||||
|
|||||||
@@ -300,7 +300,7 @@ static void displaceModifier_do(
|
|||||||
float (*tex_co)[3];
|
float (*tex_co)[3];
|
||||||
float weight = 1.0f; /* init value unused but some compilers may complain */
|
float weight = 1.0f; /* init value unused but some compilers may complain */
|
||||||
float (*vert_clnors)[3] = NULL;
|
float (*vert_clnors)[3] = NULL;
|
||||||
float local_mat[4][4] = {0};
|
float local_mat[4][4] = {{0}};
|
||||||
const bool use_global_direction = dmd->space == MOD_DISP_SPACE_GLOBAL;
|
const bool use_global_direction = dmd->space == MOD_DISP_SPACE_GLOBAL;
|
||||||
|
|
||||||
if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return;
|
if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return;
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node)
|
|||||||
ndg->colmod = 0.25;
|
ndg->colmod = 0.25;
|
||||||
ndg->mix = 0;
|
ndg->mix = 0;
|
||||||
ndg->threshold = 1;
|
ndg->threshold = 1;
|
||||||
ndg->angle = 4;
|
ndg->star_45 = true;
|
||||||
|
ndg->streaks = 4;
|
||||||
ndg->angle_ofs = 0.0f;
|
ndg->angle_ofs = 0.0f;
|
||||||
ndg->fade = 0.9;
|
ndg->fade = 0.9;
|
||||||
ndg->size = 8;
|
ndg->size = 8;
|
||||||
|
|||||||
@@ -1351,7 +1351,7 @@ static int arg_handle_render_frame(int argc, const char **argv, void *data)
|
|||||||
|
|
||||||
re = RE_NewRender(scene->id.name);
|
re = RE_NewRender(scene->id.name);
|
||||||
BLI_begin_threaded_malloc();
|
BLI_begin_threaded_malloc();
|
||||||
BKE_reports_init(&reports, RPT_PRINT);
|
BKE_reports_init(&reports, RPT_STORE);
|
||||||
|
|
||||||
RE_SetReports(re, &reports);
|
RE_SetReports(re, &reports);
|
||||||
for (int i = 0; i < frames_range_len; i++) {
|
for (int i = 0; i < frames_range_len; i++) {
|
||||||
@@ -1366,6 +1366,7 @@ static int arg_handle_render_frame(int argc, const char **argv, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
RE_SetReports(re, NULL);
|
RE_SetReports(re, NULL);
|
||||||
|
BKE_reports_clear(&reports);
|
||||||
BLI_end_threaded_malloc();
|
BLI_end_threaded_malloc();
|
||||||
MEM_freeN(frame_range_arr);
|
MEM_freeN(frame_range_arr);
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user