Merge branch 'master' into blender2.8
This commit is contained in:
@@ -226,6 +226,7 @@ class CyclesRender_PT_geometery(CyclesButtonsPanel, Panel):
|
||||
|
||||
scene = context.scene
|
||||
cscene = scene.cycles
|
||||
ccscene = scene.cycles_curves
|
||||
|
||||
if cscene.feature_set == 'EXPERIMENTAL':
|
||||
split = layout.split()
|
||||
@@ -252,6 +253,25 @@ class CyclesRender_PT_geometery(CyclesButtonsPanel, Panel):
|
||||
row.prop(cscene, "volume_step_size")
|
||||
row.prop(cscene, "volume_max_steps")
|
||||
|
||||
layout.prop(ccscene, "use_curves", text="Use Hair")
|
||||
col = layout.column()
|
||||
col.active = ccscene.use_curves
|
||||
|
||||
col.prop(ccscene, "primitive", text="Primitive")
|
||||
col.prop(ccscene, "shape", text="Shape")
|
||||
|
||||
if not (ccscene.primitive in {'CURVE_SEGMENTS', 'LINE_SEGMENTS'} and ccscene.shape == 'RIBBONS'):
|
||||
col.prop(ccscene, "cull_backfacing", text="Cull back-faces")
|
||||
|
||||
if ccscene.primitive == 'TRIANGLES' and ccscene.shape == 'THICK':
|
||||
col.prop(ccscene, "resolution", text="Resolution")
|
||||
elif ccscene.primitive == 'CURVE_SEGMENTS':
|
||||
col.prop(ccscene, "subdivisions", text="Curve subdivisions")
|
||||
|
||||
row = col.row()
|
||||
row.prop(ccscene, "minimum_width", text="Min Pixels")
|
||||
row.prop(ccscene, "maximum_width", text="Max Ext.")
|
||||
|
||||
|
||||
class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Light Paths"
|
||||
@@ -1391,43 +1411,6 @@ class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
|
||||
layout.template_ID(slot, "texture", new="texture.new")
|
||||
|
||||
|
||||
class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Cycles Hair Rendering"
|
||||
bl_context = "particle"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
psys = context.particle_system
|
||||
return CyclesButtonsPanel.poll(context) and psys and psys.settings.type == 'HAIR'
|
||||
|
||||
def draw_header(self, context):
|
||||
ccscene = context.scene.cycles_curves
|
||||
self.layout.prop(ccscene, "use_curves", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
scene = context.scene
|
||||
ccscene = scene.cycles_curves
|
||||
|
||||
layout.active = ccscene.use_curves
|
||||
|
||||
layout.prop(ccscene, "primitive", text="Primitive")
|
||||
layout.prop(ccscene, "shape", text="Shape")
|
||||
|
||||
if not (ccscene.primitive in {'CURVE_SEGMENTS', 'LINE_SEGMENTS'} and ccscene.shape == 'RIBBONS'):
|
||||
layout.prop(ccscene, "cull_backfacing", text="Cull back-faces")
|
||||
|
||||
if ccscene.primitive == 'TRIANGLES' and ccscene.shape == 'THICK':
|
||||
layout.prop(ccscene, "resolution", text="Resolution")
|
||||
elif ccscene.primitive == 'CURVE_SEGMENTS':
|
||||
layout.prop(ccscene, "subdivisions", text="Curve subdivisions")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(ccscene, "minimum_width", text="Min Pixels")
|
||||
row.prop(ccscene, "maximum_width", text="Max Ext.")
|
||||
|
||||
|
||||
class CyclesRender_PT_bake(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Bake"
|
||||
bl_context = "render"
|
||||
|
||||
@@ -597,8 +597,8 @@ static void create_mesh(Scene *scene,
|
||||
Mesh *mesh,
|
||||
BL::Mesh& b_mesh,
|
||||
const vector<Shader*>& used_shaders,
|
||||
bool subdivision=false,
|
||||
bool subdivide_uvs=true)
|
||||
bool subdivision = false,
|
||||
bool subdivide_uvs = true)
|
||||
{
|
||||
/* count vertices and faces */
|
||||
int numverts = b_mesh.vertices.length();
|
||||
@@ -671,28 +671,10 @@ static void create_mesh(Scene *scene,
|
||||
int shader = clamp(f->material_index(), 0, used_shaders.size()-1);
|
||||
bool smooth = f->use_smooth() || use_loop_normals;
|
||||
|
||||
/* split vertices if normal is different
|
||||
/* Create triangles.
|
||||
*
|
||||
* note all vertex attributes must have been set here so we can split
|
||||
* and copy attributes in split_vertex without remapping later */
|
||||
if(use_loop_normals) {
|
||||
BL::Array<float, 12> loop_normals = f->split_normals();
|
||||
|
||||
for(int i = 0; i < n; i++) {
|
||||
float3 loop_N = make_float3(loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]);
|
||||
|
||||
if(N[vi[i]] != loop_N) {
|
||||
int new_vi = mesh->split_vertex(vi[i]);
|
||||
|
||||
/* set new normal and vertex index */
|
||||
N = attr_N->data_float3();
|
||||
N[new_vi] = loop_N;
|
||||
vi[i] = new_vi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* create triangles */
|
||||
* NOTE: Autosmooth is already taken care about.
|
||||
*/
|
||||
if(n == 4) {
|
||||
if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) ||
|
||||
is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])))
|
||||
@@ -724,24 +706,8 @@ static void create_mesh(Scene *scene,
|
||||
|
||||
vi.reserve(n);
|
||||
for(int i = 0; i < n; i++) {
|
||||
/* NOTE: Autosmooth is already taken care about. */
|
||||
vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index();
|
||||
|
||||
/* split vertices if normal is different
|
||||
*
|
||||
* note all vertex attributes must have been set here so we can split
|
||||
* and copy attributes in split_vertex without remapping later */
|
||||
if(use_loop_normals) {
|
||||
float3 loop_N = get_float3(b_mesh.loops[p->loop_start() + i].normal());
|
||||
|
||||
if(N[vi[i]] != loop_N) {
|
||||
int new_vi = mesh->split_vertex(vi[i]);
|
||||
|
||||
/* set new normal and vertex index */
|
||||
N = attr_N->data_float3();
|
||||
N[new_vi] = loop_N;
|
||||
vi[i] = new_vi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* create subd faces */
|
||||
@@ -961,7 +927,13 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
|
||||
|
||||
mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental);
|
||||
|
||||
BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, need_undeformed, mesh->subdivision_type);
|
||||
BL::Mesh b_mesh = object_to_mesh(b_data,
|
||||
b_ob,
|
||||
b_scene,
|
||||
true,
|
||||
!preview,
|
||||
need_undeformed,
|
||||
mesh->subdivision_type);
|
||||
|
||||
if(b_mesh) {
|
||||
if(render_layer.use_surfaces && !hide_tris) {
|
||||
@@ -1086,7 +1058,13 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
|
||||
|
||||
if(ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
|
||||
/* get derived mesh */
|
||||
b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, false, false);
|
||||
b_mesh = object_to_mesh(b_data,
|
||||
b_ob,
|
||||
b_scene,
|
||||
true,
|
||||
!preview,
|
||||
false,
|
||||
Mesh::SUBDIVISION_NONE);
|
||||
}
|
||||
|
||||
if(!b_mesh) {
|
||||
@@ -1157,10 +1135,12 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
|
||||
{
|
||||
/* no motion, remove attributes again */
|
||||
if(b_mesh.vertices.length() != numverts) {
|
||||
VLOG(1) << "Topology differs, disabling motion blur.";
|
||||
VLOG(1) << "Topology differs, disabling motion blur for object "
|
||||
<< b_ob.name();
|
||||
}
|
||||
else {
|
||||
VLOG(1) << "No actual deformation motion for object " << b_ob.name();
|
||||
VLOG(1) << "No actual deformation motion for object "
|
||||
<< b_ob.name();
|
||||
}
|
||||
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
if(attr_mN)
|
||||
|
||||
@@ -580,7 +580,7 @@ static void populate_bake_data(BakeData *data, const
|
||||
BL::BakePixel bp = pixel_array;
|
||||
|
||||
int i;
|
||||
for(i=0; i < num_pixels; i++) {
|
||||
for(i = 0; i < num_pixels; i++) {
|
||||
if(bp.object_id() == object_id) {
|
||||
data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy());
|
||||
} else {
|
||||
|
||||
@@ -48,12 +48,12 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
|
||||
bool apply_modifiers,
|
||||
bool render,
|
||||
bool calc_undeformed,
|
||||
bool subdivision)
|
||||
Mesh::SubdivisionType subdivision_type)
|
||||
{
|
||||
bool subsurf_mod_show_render;
|
||||
bool subsurf_mod_show_viewport;
|
||||
|
||||
if(subdivision) {
|
||||
if(subdivision_type != Mesh::SUBDIVISION_NONE) {
|
||||
BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
|
||||
|
||||
subsurf_mod_show_render = subsurf_mod.show_render();
|
||||
@@ -65,7 +65,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
|
||||
|
||||
BL::Mesh me = data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, false, calc_undeformed);
|
||||
|
||||
if(subdivision) {
|
||||
if(subdivision_type != Mesh::SUBDIVISION_NONE) {
|
||||
BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
|
||||
|
||||
subsurf_mod.show_render(subsurf_mod_show_render);
|
||||
@@ -74,9 +74,14 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
|
||||
|
||||
if((bool)me) {
|
||||
if(me.use_auto_smooth()) {
|
||||
me.calc_normals_split();
|
||||
if(subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK) {
|
||||
me.calc_normals_split();
|
||||
}
|
||||
else {
|
||||
me.split_faces();
|
||||
}
|
||||
}
|
||||
if(!subdivision) {
|
||||
if(subdivision_type == Mesh::SUBDIVISION_NONE) {
|
||||
me.calc_tessface(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,6 +497,7 @@ class SequencerButtonsPanel_Output:
|
||||
|
||||
class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Edit Strip"
|
||||
bl_category = "Strip"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -563,6 +564,7 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel):
|
||||
|
||||
class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Effect Strip"
|
||||
bl_category = "Strip"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -701,6 +703,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
|
||||
|
||||
class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Strip Input"
|
||||
bl_category = "Strip"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -795,6 +798,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
|
||||
|
||||
class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Sound"
|
||||
bl_category = "Strip"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -848,6 +852,7 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
|
||||
|
||||
class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Scene"
|
||||
bl_category = "Strip"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -894,6 +899,7 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
|
||||
|
||||
class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Mask"
|
||||
bl_category = "Strip"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -923,6 +929,7 @@ class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel):
|
||||
|
||||
class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Filter"
|
||||
bl_category = "Strip"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -977,6 +984,7 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
|
||||
|
||||
class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Proxy/Timecode"
|
||||
bl_category = "Strip"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -1109,6 +1117,7 @@ class SEQUENCER_PT_view_safe_areas(SequencerButtonsPanel_Output, Panel):
|
||||
|
||||
class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Modifiers"
|
||||
bl_category = "Modifiers"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -1211,6 +1220,7 @@ class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel):
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
|
||||
_context_path = "scene.sequence_editor.active_strip"
|
||||
_property_type = (bpy.types.Sequence,)
|
||||
bl_category = "Strip"
|
||||
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
||||
@@ -1014,7 +1014,7 @@ static bool cloth_points_collision_response_static(ClothModifierData *clmd, Coll
|
||||
}
|
||||
|
||||
BLI_INLINE bool cloth_point_face_collision_params(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3],
|
||||
float r_nor[3], float *r_lambda, float r_w[4])
|
||||
float r_nor[3], float *r_lambda, float r_w[3])
|
||||
{
|
||||
float edge1[3], edge2[3], p2face[3], p1p2[3], v0p2[3];
|
||||
float nor_v0p2, nor_p1p2;
|
||||
@@ -1026,7 +1026,7 @@ BLI_INLINE bool cloth_point_face_collision_params(const float p1[3], const float
|
||||
|
||||
nor_v0p2 = dot_v3v3(v0p2, r_nor);
|
||||
madd_v3_v3v3fl(p2face, p2, r_nor, -nor_v0p2);
|
||||
interp_weights_face_v3(r_w, v0, v1, v2, NULL, p2face);
|
||||
interp_weights_tri_v3(r_w, v0, v1, v2, p2face);
|
||||
|
||||
sub_v3_v3v3(p1p2, p2, p1);
|
||||
sub_v3_v3v3(v0p2, p2, v0);
|
||||
@@ -1085,7 +1085,7 @@ static CollPair *cloth_point_collpair(
|
||||
const float *co1 = mverts[bp1].co, *co2 = mverts[bp2].co, *co3 = mverts[bp3].co;
|
||||
float lambda /*, distance1 */, distance2;
|
||||
float facenor[3], v1p1[3], v1p2[3];
|
||||
float w[4];
|
||||
float w[3];
|
||||
|
||||
if (!cloth_point_face_collision_params(p1, p2, co1, co2, co3, facenor, &lambda, w))
|
||||
return collpair;
|
||||
|
||||
@@ -3739,7 +3739,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(
|
||||
|
||||
/* velocity brush, only do on main sample */
|
||||
if (brush->flags & MOD_DPAINT_USES_VELOCITY && ss == 0 && brushVelocity) {
|
||||
float weights[4];
|
||||
float weights[3];
|
||||
float brushPointVelocity[3];
|
||||
float velocity[3];
|
||||
|
||||
@@ -3748,7 +3748,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(
|
||||
const int v3 = mloop[mlooptri[hitTri].tri[2]].v;
|
||||
|
||||
/* calculate barycentric weights for hit point */
|
||||
interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, hitCoord);
|
||||
interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, hitCoord);
|
||||
|
||||
/* simple check based on brush surface velocity,
|
||||
* todo: perhaps implement something that handles volume movement as well */
|
||||
|
||||
@@ -2346,6 +2346,11 @@ Mesh *BKE_mesh_new_from_object(
|
||||
|
||||
tmpmesh = BKE_mesh_add(bmain, "Mesh");
|
||||
DM_to_mesh(dm, tmpmesh, ob, mask, true);
|
||||
|
||||
/* Copy autosmooth settings from original mesh. */
|
||||
Mesh *me = (Mesh *)ob->data;
|
||||
tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH);
|
||||
tmpmesh->smoothresh = me->smoothresh;
|
||||
}
|
||||
|
||||
/* BKE_mesh_add/copy gives us a user count we don't need */
|
||||
|
||||
@@ -758,15 +758,14 @@ static void obstacles_from_derivedmesh_task_cb(void *userdata, const int z)
|
||||
/* find the nearest point on the mesh */
|
||||
if (BLI_bvhtree_find_nearest(data->tree->tree, ray_start, &nearest, data->tree->nearest_callback, data->tree) != -1) {
|
||||
const MLoopTri *lt = &data->looptri[nearest.index];
|
||||
float weights[4];
|
||||
float weights[3];
|
||||
int v1, v2, v3;
|
||||
|
||||
/* calculate barycentric weights for nearest point */
|
||||
v1 = data->mloop[lt->tri[0]].v;
|
||||
v2 = data->mloop[lt->tri[1]].v;
|
||||
v3 = data->mloop[lt->tri[2]].v;
|
||||
interp_weights_face_v3(
|
||||
weights, data->mvert[v1].co, data->mvert[v2].co, data->mvert[v3].co, NULL, nearest.co);
|
||||
interp_weights_tri_v3(weights, data->mvert[v1].co, data->mvert[v2].co, data->mvert[v3].co, nearest.co);
|
||||
|
||||
// DG TODO
|
||||
if (data->has_velocity)
|
||||
@@ -1454,7 +1453,7 @@ static void sample_derivedmesh(
|
||||
|
||||
/* find the nearest point on the mesh */
|
||||
if (BLI_bvhtree_find_nearest(treeData->tree, ray_start, &nearest, treeData->nearest_callback, treeData) != -1) {
|
||||
float weights[4];
|
||||
float weights[3];
|
||||
int v1, v2, v3, f_index = nearest.index;
|
||||
float n1[3], n2[3], n3[3], hit_normal[3];
|
||||
|
||||
@@ -1471,7 +1470,7 @@ static void sample_derivedmesh(
|
||||
v1 = mloop[mlooptri[f_index].tri[0]].v;
|
||||
v2 = mloop[mlooptri[f_index].tri[1]].v;
|
||||
v3 = mloop[mlooptri[f_index].tri[2]].v;
|
||||
interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co);
|
||||
interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, nearest.co);
|
||||
|
||||
if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && velocity_map) {
|
||||
/* apply normal directional velocity */
|
||||
|
||||
@@ -323,10 +323,8 @@ bool clip_segment_v3_plane_n(
|
||||
float r_p1[3], float r_p2[3]);
|
||||
|
||||
/****************************** Interpolation ********************************/
|
||||
|
||||
/* tri or quad, d can be NULL */
|
||||
void interp_weights_face_v3(float w[4],
|
||||
const float a[3], const float b[3], const float c[3], const float d[3], const float p[3]);
|
||||
void interp_weights_tri_v3(float w[3], const float a[3], const float b[3], const float c[3], const float p[3]);
|
||||
void interp_weights_quad_v3(float w[4], const float a[3], const float b[3], const float c[3], const float d[3], const float p[3]);
|
||||
void interp_weights_poly_v3(float w[], float v[][3], const int n, const float co[3]);
|
||||
void interp_weights_poly_v2(float w[], float v[][2], const int n, const float co[2]);
|
||||
|
||||
|
||||
@@ -2950,7 +2950,15 @@ static bool barycentric_weights(const float v1[3], const float v2[3], const floa
|
||||
}
|
||||
}
|
||||
|
||||
void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float co[3])
|
||||
void interp_weights_tri_v3(float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3])
|
||||
{
|
||||
float n[3];
|
||||
|
||||
normal_tri_v3(n, v1, v2, v3);
|
||||
barycentric_weights(v1, v2, v3, co, n, w);
|
||||
}
|
||||
|
||||
void interp_weights_quad_v3(float w[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float co[3])
|
||||
{
|
||||
float w2[3];
|
||||
|
||||
@@ -2963,7 +2971,7 @@ void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], co
|
||||
w[1] = 1.0f;
|
||||
else if (equals_v3v3(co, v3))
|
||||
w[2] = 1.0f;
|
||||
else if (v4 && equals_v3v3(co, v4))
|
||||
else if (equals_v3v3(co, v4))
|
||||
w[3] = 1.0f;
|
||||
else {
|
||||
/* otherwise compute barycentric interpolation weights */
|
||||
@@ -2971,35 +2979,24 @@ void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], co
|
||||
bool degenerate;
|
||||
|
||||
sub_v3_v3v3(n1, v1, v3);
|
||||
if (v4) {
|
||||
sub_v3_v3v3(n2, v2, v4);
|
||||
}
|
||||
else {
|
||||
sub_v3_v3v3(n2, v2, v3);
|
||||
}
|
||||
sub_v3_v3v3(n2, v2, v4);
|
||||
cross_v3_v3v3(n, n1, n2);
|
||||
|
||||
/* OpenGL seems to split this way, so we do too */
|
||||
if (v4) {
|
||||
degenerate = barycentric_weights(v1, v2, v4, co, n, w);
|
||||
SWAP(float, w[2], w[3]);
|
||||
degenerate = barycentric_weights(v1, v2, v4, co, n, w);
|
||||
SWAP(float, w[2], w[3]);
|
||||
|
||||
if (degenerate || (w[0] < 0.0f)) {
|
||||
/* if w[1] is negative, co is on the other side of the v1-v3 edge,
|
||||
* so we interpolate using the other triangle */
|
||||
degenerate = barycentric_weights(v2, v3, v4, co, n, w2);
|
||||
if (degenerate || (w[0] < 0.0f)) {
|
||||
/* if w[1] is negative, co is on the other side of the v1-v3 edge,
|
||||
* so we interpolate using the other triangle */
|
||||
degenerate = barycentric_weights(v2, v3, v4, co, n, w2);
|
||||
|
||||
if (!degenerate) {
|
||||
w[0] = 0.0f;
|
||||
w[1] = w2[0];
|
||||
w[2] = w2[1];
|
||||
w[3] = w2[2];
|
||||
}
|
||||
if (!degenerate) {
|
||||
w[0] = 0.0f;
|
||||
w[1] = w2[0];
|
||||
w[2] = w2[1];
|
||||
w[3] = w2[2];
|
||||
}
|
||||
}
|
||||
else {
|
||||
barycentric_weights(v1, v2, v3, co, n, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -119,12 +119,10 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
|
||||
else
|
||||
but = uiDefButR_prop(block, UI_BTYPE_TEXT, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
|
||||
|
||||
PropertySubType subtype = RNA_property_subtype(prop);
|
||||
if (!(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME) || (block->flag & UI_BLOCK_LIST_ITEM))) {
|
||||
UI_but_flag_enable(but, UI_BUT_VALUE_CLEAR);
|
||||
}
|
||||
if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
|
||||
UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
|
||||
/* TEXTEDIT_UPDATE is usally used for search buttons. For these we also want
|
||||
* the 'x' icon to clear search string, so setting VALUE_CLEAR flag, too. */
|
||||
UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE | UI_BUT_VALUE_CLEAR);
|
||||
}
|
||||
break;
|
||||
case PROP_POINTER:
|
||||
|
||||
@@ -5693,11 +5693,11 @@ static int sculpt_set_detail_size_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
WM_operator_properties_create_ptr(&props_ptr, ot);
|
||||
|
||||
if (sd->flags & SCULPT_DYNTOPO_DETAIL_CONSTANT) {
|
||||
set_brush_rc_props(&props_ptr, "sculpt", "constant_detail", NULL, 0);
|
||||
RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.constant_detail");
|
||||
set_brush_rc_props(&props_ptr, "sculpt", "constant_detail_resolution", NULL, 0);
|
||||
RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.constant_detail_resolution");
|
||||
}
|
||||
else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
|
||||
set_brush_rc_props(&props_ptr, "sculpt", "constant_detail", NULL, 0);
|
||||
set_brush_rc_props(&props_ptr, "sculpt", "constant_detail_resolution", NULL, 0);
|
||||
RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_percent");
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -502,51 +502,57 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa)
|
||||
void nla_buttons_register(ARegionType *art)
|
||||
{
|
||||
PanelType *pt;
|
||||
|
||||
|
||||
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel animdata");
|
||||
strcpy(pt->idname, "NLA_PT_animdata");
|
||||
strcpy(pt->label, N_("Animation Data"));
|
||||
strcpy(pt->category, "Animations");
|
||||
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
pt->draw = nla_panel_animdata;
|
||||
pt->poll = nla_animdata_panel_poll;
|
||||
pt->flag = PNL_DEFAULT_CLOSED;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
|
||||
|
||||
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel track");
|
||||
strcpy(pt->idname, "NLA_PT_track");
|
||||
strcpy(pt->label, N_("Active Track"));
|
||||
strcpy(pt->category, "Animations");
|
||||
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
pt->draw = nla_panel_track;
|
||||
pt->poll = nla_track_panel_poll;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
|
||||
|
||||
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
|
||||
strcpy(pt->idname, "NLA_PT_properties");
|
||||
strcpy(pt->label, N_("Active Strip"));
|
||||
strcpy(pt->category, "Animations");
|
||||
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
pt->draw = nla_panel_properties;
|
||||
pt->poll = nla_strip_panel_poll;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
|
||||
|
||||
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
|
||||
strcpy(pt->idname, "NLA_PT_actionclip");
|
||||
strcpy(pt->label, N_("Action Clip"));
|
||||
strcpy(pt->category, "Animations");
|
||||
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
pt->draw = nla_panel_actclip;
|
||||
pt->poll = nla_strip_actclip_panel_poll;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
|
||||
|
||||
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation");
|
||||
strcpy(pt->idname, "NLA_PT_evaluation");
|
||||
strcpy(pt->label, N_("Evaluation"));
|
||||
strcpy(pt->category, "Animations");
|
||||
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
pt->draw = nla_panel_evaluation;
|
||||
pt->poll = nla_strip_eval_panel_poll;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
|
||||
|
||||
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
|
||||
strcpy(pt->idname, "NLA_PT_modifiers");
|
||||
strcpy(pt->label, N_("Modifiers"));
|
||||
strcpy(pt->category, "Modifiers");
|
||||
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
pt->draw = nla_panel_modifiers;
|
||||
pt->poll = nla_strip_eval_panel_poll;
|
||||
|
||||
@@ -27,8 +27,7 @@ vec3 calculate_view_space_normal(in vec3 viewposition)
|
||||
{
|
||||
vec3 normal = cross(normalize(dFdx(viewposition)),
|
||||
ssao_params.w * normalize(dFdy(viewposition)));
|
||||
normalize(normal);
|
||||
return normal;
|
||||
return normalize(normal);
|
||||
}
|
||||
|
||||
float calculate_ssao_factor(float depth)
|
||||
|
||||
@@ -174,8 +174,10 @@ typedef enum PropertyFlag {
|
||||
* and collections */
|
||||
PROP_ANIMATABLE = (1 << 1),
|
||||
|
||||
/* This flag means when the property's widget is in 'textedit' mode, it will be updated after every typed char,
|
||||
* instead of waiting final validation. Used e.g. for text searchbox. */
|
||||
/* This flag means when the property's widget is in 'textedit' mode, it will be updated
|
||||
* after every typed char, instead of waiting final validation. Used e.g. for text searchbox.
|
||||
* It will also cause UI_BUT_VALUE_CLEAR to be set for text buttons. We could add an own flag
|
||||
* for search/filter properties, but this works just fine for now. */
|
||||
PROP_TEXTEDIT_UPDATE = (1 << 31),
|
||||
|
||||
/* icon */
|
||||
|
||||
@@ -240,6 +240,9 @@ void RNA_api_mesh(StructRNA *srna)
|
||||
func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split");
|
||||
RNA_def_function_ui_description(func, "Free split vertex normals");
|
||||
|
||||
func = RNA_def_function(srna, "split_faces", "BKE_mesh_split_faces");
|
||||
RNA_def_function_ui_description(func, "Spli faces based on the edge angle");
|
||||
|
||||
func = RNA_def_function(srna, "calc_tangents", "rna_Mesh_calc_tangents");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func,
|
||||
|
||||
@@ -5569,12 +5569,17 @@ static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *ve
|
||||
/* interpolate speed vectors from strand surface */
|
||||
face= mesh->face[*index];
|
||||
|
||||
co1= mesh->co[face[0]];
|
||||
co2= mesh->co[face[1]];
|
||||
co3= mesh->co[face[2]];
|
||||
co4= (face[3])? mesh->co[face[3]]: NULL;
|
||||
co1 = mesh->co[face[0]];
|
||||
co2 = mesh->co[face[1]];
|
||||
co3 = mesh->co[face[2]];
|
||||
|
||||
interp_weights_face_v3(w, co1, co2, co3, co4, strand->vert->co);
|
||||
if (face[3]) {
|
||||
co4 = mesh->co[face[3]];
|
||||
interp_weights_quad_v3(w, co1, co2, co3, co4, strand->vert->co);
|
||||
}
|
||||
else {
|
||||
interp_weights_tri_v3(w, co1, co2, co3, strand->vert->co);
|
||||
}
|
||||
|
||||
zero_v4(speed);
|
||||
madd_v4_v4fl(speed, winspeed[face[0]], w[0]);
|
||||
|
||||
@@ -1190,9 +1190,14 @@ static void sample_occ_surface(ShadeInput *shi)
|
||||
co1 = mesh->co[face[0]];
|
||||
co2 = mesh->co[face[1]];
|
||||
co3 = mesh->co[face[2]];
|
||||
co4 = (face[3]) ? mesh->co[face[3]] : NULL;
|
||||
|
||||
interp_weights_face_v3(w, co1, co2, co3, co4, strand->vert->co);
|
||||
if (face[3]) {
|
||||
co4 = mesh->co[face[3]];
|
||||
interp_weights_quad_v3(w, co1, co2, co3, co4, strand->vert->co);
|
||||
}
|
||||
else {
|
||||
interp_weights_tri_v3(w, co1, co2, co3, strand->vert->co);
|
||||
}
|
||||
|
||||
zero_v3(shi->ao);
|
||||
zero_v3(shi->env);
|
||||
|
||||
@@ -6,9 +6,46 @@ import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import tempfile
|
||||
|
||||
|
||||
class COLORS_ANSI:
|
||||
RED = '\033[00;31m'
|
||||
GREEN = '\033[00;32m'
|
||||
ENDC = '\033[0m'
|
||||
|
||||
|
||||
class COLORS_DUMMY:
|
||||
RED = ''
|
||||
GREEN = ''
|
||||
ENDC = ''
|
||||
|
||||
COLORS = COLORS_DUMMY
|
||||
|
||||
|
||||
def printMessage(type, status, message):
|
||||
if type == 'SUCCESS':
|
||||
print(COLORS.GREEN, end="")
|
||||
elif type == 'FAILURE':
|
||||
print(COLORS.RED, end="")
|
||||
status_text = ...
|
||||
if status == 'RUN':
|
||||
status_text = " RUN "
|
||||
elif status == 'OK':
|
||||
status_text = " OK "
|
||||
elif status == 'PASSED':
|
||||
status_text = " PASSED "
|
||||
elif status == 'FAILED':
|
||||
status_text = " FAILED "
|
||||
else:
|
||||
status_text = status
|
||||
print("[{}]" . format(status_text), end="")
|
||||
print(COLORS.ENDC, end="")
|
||||
print(" {}" . format(message))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def render_file(filepath):
|
||||
command = (
|
||||
BLENDER,
|
||||
@@ -83,16 +120,32 @@ def verify_output(filepath):
|
||||
def run_test(filepath):
|
||||
testname = test_get_name(filepath)
|
||||
spacer = "." * (32 - len(testname))
|
||||
print(testname, spacer, end="")
|
||||
sys.stdout.flush()
|
||||
printMessage('SUCCESS', 'RUN', testname)
|
||||
time_start = time.time()
|
||||
error = render_file(filepath)
|
||||
status = "FAIL"
|
||||
if not error:
|
||||
if verify_output(filepath):
|
||||
print("PASS")
|
||||
else:
|
||||
if not verify_output(filepath):
|
||||
error = "VERIFY"
|
||||
if error:
|
||||
print("FAIL", error)
|
||||
time_end = time.time()
|
||||
elapsed_ms = int((time_end - time_start) * 1000)
|
||||
if not error:
|
||||
printMessage('SUCCESS', 'OK', "{} ({} ms)" .
|
||||
format(testname, elapsed_ms))
|
||||
else:
|
||||
if error == "NO_CYCLES":
|
||||
print("Can't perform tests because Cycles failed to load!")
|
||||
return False
|
||||
elif error == "NO_START":
|
||||
print('Can not perform tests because blender fails to start.',
|
||||
'Make sure INSTALL target was run.')
|
||||
return False
|
||||
elif error == 'VERIFY':
|
||||
print("Rendered result is different from reference image")
|
||||
else:
|
||||
print("Unknown error %r" % error)
|
||||
printMessage('FAILURE', 'FAILED', "{} ({} ms)" .
|
||||
format(testname, elapsed_ms))
|
||||
return error
|
||||
|
||||
|
||||
@@ -105,30 +158,38 @@ def blend_list(path):
|
||||
|
||||
|
||||
def run_all_tests(dirpath):
|
||||
passed_tests = []
|
||||
failed_tests = []
|
||||
all_files = list(blend_list(dirpath))
|
||||
all_files.sort()
|
||||
printMessage('SUCCESS', "==========",
|
||||
"Running {} tests from 1 test case." . format(len(all_files)))
|
||||
time_start = time.time()
|
||||
for filepath in all_files:
|
||||
error = run_test(filepath)
|
||||
testname = test_get_name(filepath)
|
||||
if error:
|
||||
if error == "NO_CYCLES":
|
||||
print("Can't perform tests because Cycles failed to load!")
|
||||
return False
|
||||
elif error == "NO_START":
|
||||
print('Can not perform tests because blender fails to start.',
|
||||
'Make sure INSTALL target was run.')
|
||||
return False
|
||||
elif error == 'VERIFY':
|
||||
pass
|
||||
else:
|
||||
print("Unknown error %r" % error)
|
||||
testname = test_get_name(filepath)
|
||||
failed_tests.append(testname)
|
||||
else:
|
||||
passed_tests.append(testname)
|
||||
time_end = time.time()
|
||||
elapsed_ms = int((time_end - time_start) * 1000)
|
||||
print("")
|
||||
printMessage('SUCCESS', "==========",
|
||||
"{} tests from 1 test case ran. ({} ms total)" .
|
||||
format(len(all_files), elapsed_ms))
|
||||
printMessage('SUCCESS', 'PASSED', "{} tests." .
|
||||
format(len(passed_tests)))
|
||||
if failed_tests:
|
||||
printMessage('FAILURE', 'FAILED', "{} tests, listed below:" .
|
||||
format(len(failed_tests)))
|
||||
failed_tests.sort()
|
||||
print("\n\nFAILED tests:")
|
||||
for test in failed_tests:
|
||||
print(" ", test)
|
||||
printMessage('FAILURE', "FAILED", "{}" . format(test))
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -145,10 +206,14 @@ def main():
|
||||
parser = create_argparse()
|
||||
args = parser.parse_args()
|
||||
|
||||
global COLORS
|
||||
global BLENDER, ROOT, IDIFF
|
||||
global TEMP_FILE, TEMP_FILE_MASK, TEST_SCRIPT
|
||||
global VERBOSE
|
||||
|
||||
if os.environ.get("CYCLESTEST_COLOR") is not None:
|
||||
COLORS = COLORS_ANSI
|
||||
|
||||
BLENDER = args.blender[0]
|
||||
ROOT = args.testdir[0]
|
||||
IDIFF = args.idiff[0]
|
||||
|
||||
Reference in New Issue
Block a user