Could use some help with creating side faces of triangles.
why not use solidify modifier?
@ zeffii
Its not about using it. I know i could use solidify modifier.
@ zeffii
Its about learning something new.
I have already created four other addons using that code.
about faces/vertices/edges removing, do you find a way through bpy.data ?
@ littleneo
import bpy
ob_act = bpy.context.active_object
for ob in bpy.data.objects:
print(ob)
#bpy.data.objects.remove(ob_act)
# it is possible to remove ob_act if you remove users
'''
if "Cube" in bpy.data.meshes:
mesh = bpy.data.meshes["Cube"]
print("removing mesh", mesh)
bpy.data.meshes.remove(mesh)
'''
print (bpy.data.objects)
# prints ( bpy_collection[3], BlendDataObjects )
me = ob_act.data
print(me)
print(me.faces)
# prints ( bpy_collection[6], MeshFaces )
# me.faces is a collection just like BlendDataObjects but remove() function does not work
# I have been trying to figure it out but there is not that many pages about collections
# there should be something like these me.faces.remove(me.faces[0]) to remove face data
maybe someone else knows how to do that or if it is even possible but people are not that eager to help.
Everything works now.
Used wrong function to create sides of triangles, those are quads not tris.
To use
Go to edit mode.
Select faces.
Click ‘Test’ button.
v normal added
It would be VERY interesting if your script had also the inverse function for faces generation I think.
I mean to generate faces where there is none at the moment, and leave it empty where there’s faces.
(mmm easier to do with quads I suppose)
@ littleneo
Good idea.
I will think about it, but i am not sure how to do that.
New version
Corrected calculation of thickness of the faces when using v normals.
Distance slider now moves faces differently.
Corrected creation of side faces.
Added random when using v normals.
To do
Correct calculation of normals in some cases.
Can not recalculate normals to be on outside
I think i just created new solidify tool and i was just trying to learn how to add faces.
More pictures
Attachments
Small update
Added labels to sliders
Not an update
i’m not able to run the code at the moment, but that looks like an off-by-one bug, get yourself the addon called ‘index visualiser’ (search these forums… or go to the scripts section on blender.org). index visualizer displays the indices of verts/edges/faces, you’ll be able to see if there is a vertex created where you expect or not
n = len(list_1)
if n == 3:
add_tri(me_o, list_2, 1)
add_tri(me_o, list_1, 1)
for i in range(n):
add_quad(me_o, [ list_1[i], list_1[(i + 1) % n], list_2[(i + 1) % n], list_2[i] ], 1)
else:
add_quad(me_o, list_2, 1)
add_quad(me_o, list_1, 1)
for i in range(n):
add_quad(me_o, [ list_1[i], list_1[(i + 1) % n], list_2[(i + 1) % n], list_2[i] ], 1)
or, at that level of indentation consider a small change in style.
if n == 3:
add_tri(me_o, list_2, 1)
add_tri(me_o, list_1, 1)
else:
add_quad(me_o, list_2, 1)
add_quad(me_o, list_1, 1)
for i in range(n):
modval = (i + 1) % n
param_2 = [ list_1[i], list_1[modval], list_2[modval], list_2[i] ]
add_quad(me_o, param_2, 1)
i’m aware this stuff was commented out…
interesting…
>>> bpy.context.active_object.data.faces[0].vertices[0]
1
>>> bpy.context.active_object.data.faces[0].vertices[1]
3
>>> bpy.context.active_object.data.faces[0].vertices[2]
5
>>> bpy.context.active_object.data.faces[0].vertices[3]
7
>>> bpy.context.active_object.data.faces[1].vertices[0]
6
>>> bpy.context.active_object.data.faces[1].vertices[1]
4
>>> bpy.context.active_object.data.faces[1].vertices[2]
2
>>> bpy.context.active_object.data.faces[1].vertices[3]
Traceback (most recent call last):
File "<blender_console>", line 1, in <module>
IndexError: bpy_prop_array[index]: index 3 out of range
>>>
i’m thinking with an empty mesh, the first vertex in a mesh might (for some reason) have to be 0. ( but you have list_2 = [6,4,2,0])
add_quad(me_o, list_1, 1) # out
deque_list = collections.deque(list_2)
deque_list.rotate(1)
list_2 = list(deque_list)
add_quad(me_o, list_2, 1) # in
so… with little modification (including to add_quad)
poke around with this ( seems to work ), you might want to do a check on your very first face creation and rotate until the first element is 0.
# -*- coding: utf-8 -*-
# ***** BEGIN GPL LICENSE BLOCK *****
#
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENCE BLOCK *****
# ------ ------
bl_info = {
'name': 'split_solidify',
'author': '',
'version': (0, 0, 1),
'blender': (2, 5, 8),
'api': 38045,
'location': 'View3D > Tool Shelf',
'description': '',
'warning': '',
'wiki_url': '',
'tracker_url': '',
'category': 'Mesh' }
# ------ ------
import bpy
import random
from bpy.props import FloatProperty, EnumProperty, PointerProperty, BoolProperty, IntProperty
from math import cos
import collections
# ------ ------
def edit_mode_out(): # edit mode out
bpy.ops.object.mode_set(mode = 'OBJECT')
def edit_mode_in(): # edit mode in
bpy.ops.object.mode_set(mode = 'EDIT')
def add_quad(msh, lst, n): # lst - list of face indexes, must be 4 n - number of faces
msh.faces.add(n)
msh.faces[-1].vertices_raw = lst
#msh.update(calc_edges = True)
def add_tri(msh, lst, n): # lst - list of face indexes, must be 3 n - number of faces
msh.faces.add(n)
msh.faces[-1].vertices = lst
#msh.update(calc_edges = True)
# ------ ------
class t_buf():
me_data = []
# ------ ------
class t_p_group0(bpy.types.PropertyGroup):
enum_ = EnumProperty( items =( ('opt0', 'f normal', ''),
('opt1', 'v normal', '') ),
name = 'test',
default = 'opt0' )
bool_ = BoolProperty( name = 'Delete original face',
default = True )
bool_1 = BoolProperty( name = 'Random',
default = False )
'''
# ------ ------
def f_(me_o, opp, th, context, rnd):
c_e = context.scene.t_my_custom_props.enum_
c_ran = context.scene.t_my_custom_props.bool_1
me = t_buf.me_data
list_0 = [f for f in me.faces if f.select]
dict_1 = {}
for f in list_0:
list_1 = []
list_2 = []
if c_ran == True:
d = rnd * random.randrange( 0, 10 )
else:
d = opp
for vi in f.vertices:
v = me.vertices[vi]
f_no = f.normal
v_no = v.normal
v.select = False
tmp = [0, 0, 0]
tmp1 = [0, 0, 0]
for i in range(3):
if c_e == 'opt0':
tmp1[i] = v.co[i] + (d * f.normal[i])
tmp[i] = v.co[i] + ( (d - th) * f.normal[i])
elif c_e == 'opt1':
angle_ = v_no.angle(f_no)
h = th / cos(angle_) # corrected thickness calculation
tmp[i] = v.co[i] + (d * f.normal[i])
tmp1[i] = tmp[i] + (-h * v.normal[i])
me_o.vertices.add(2)
me_o.vertices[-2].co = tuple(tmp1)
me_o.vertices[-1].co = tuple(tmp)
list_1.append(me_o.vertices[-2].index)
list_2.append(me_o.vertices[-1].index)
n = len(list_1)
if n == 3:
add_tri(me_o, list_2, 1)
add_tri(me_o, list_1, 1)
for i in range(n):
add_quad(me_o, [ list_1[i], list_1[(i + 1) % n], list_2[(i + 1) % n], list_2[i] ], 1)
else:
add_quad(me_o, list_2, 1)
add_quad(me_o, list_1, 1)
for i in range(n):
add_quad(me_o, [ list_1[i], list_1[(i + 1) % n], list_2[(i + 1) % n], list_2[i] ], 1)
me_o.update(calc_edges = True)
'''
# ------ ------
def f_(me_o, opp, th, context, rnd):
c_e = context.scene.t_my_custom_props.enum_
c_ran = context.scene.t_my_custom_props.bool_1
me = t_buf.me_data
list_0 = [f for f in me.faces if f.select]
# iteration = 0
for f in list_0:
# if iteration == 1: break
list_1 = []
list_2 = []
if c_ran == True:
d = rnd * random.randrange(0, 10)
else:
d = opp
for vi in f.vertices:
v = me.vertices[vi]
f_no = f.normal # f normal
v_no = v.normal # v normal
tmp = [0, 0, 0]
tmp1 = [0, 0, 0]
for i in range(3):
if c_e == 'opt0':
tmp[i] = v.co[i] + (d * f_no[i]) # out
tmp1[i] = v.co[i] + ((d - th) * f_no[i]) # in
#tmp1[i] = v.co[i] + (d * f.normal[i])
#tmp[i] = v.co[i] + ( (d - th) * f.normal[i])
elif c_e == 'opt1':
#angle_ = v_no.angle(f_no)
#h = th / cos(angle_) # corrected thickness calculation
#tmp[i] = v.co[i] + (d * f.normal[i])
#tmp1[i] = tmp[i] + (-h * v.normal[i])
pass
me_o.vertices.add(2)
me_o.vertices[-1].co = tuple(tmp) # out
me_o.vertices[-2].co = tuple(tmp1) # in
vert_1 = me_o.vertices[-1]
vert_2 = me_o.vertices[-2]
print('-1 out ', vert_1.index, vert_1.co)
print('-2 in ', vert_2.index, vert_2.co)
list_1.append(me_o.vertices[-1].index) # out
list_2.append(me_o.vertices[-2].index) # in
list_2.reverse() # < flip normal
n = len(list_1)
if n == 3:
add_tri(me_o, list_1, 1) # out
add_tri(me_o, list_2, 1) # in
else:
add_quad(me_o, list_1, 1) # out
deque_list = collections.deque(list_2)
deque_list.rotate(1)
list_2 = list(deque_list)
add_quad(me_o, list_2, 1) # in
#iteration += 1
me_o.update(calc_edges = True)
# ------ panel 0 ------
class t_p0(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
#bl_idname = 't_p0_id'
bl_label = 'Split solidify'
bl_context = 'mesh_edit'
def draw(self, context):
layout = self.layout
layout.prop(context.scene.t_my_custom_props, 'enum_', expand = True)
layout.prop(context.scene.t_my_custom_props, 'bool_')
layout.prop(context.scene.t_my_custom_props, 'bool_1')
layout.operator('t.op0_id', text = 'Split solidify')
# ------ operator 0 ------
class t_op0(bpy.types.Operator):
bl_idname = 't.op0_id'
bl_label = 'Split solidify'
bl_options = {'REGISTER', 'UNDO'}
opp = FloatProperty( default = 0.4, min = -100.0, max = 100.0, step = 10, precision = 3 )
th = FloatProperty( default = 0.04, min = -100.0, max = 100.0, step = 1, precision = 3 )
rnd = FloatProperty( default = 0.06, min = -10.0, max = 10.0, step = 1, precision = 3 )
def draw(self, context):
c_ran = context.scene.t_my_custom_props.bool_1
layout = self.layout
if c_ran == False:
layout.label('Distance')
layout.prop(self, 'opp')
else:
layout.label('Random val.')
layout.prop(self, 'rnd')
layout.label('Thickness')
layout.prop(self, 'th')
def execute(self, context):
c_b = context.scene.t_my_custom_props.bool_
opp = self.opp
th = self.th
rnd = self.rnd
edit_mode_out()
# -- -- -- --
ob_act = context.active_object
me_o = ob_act.data
t_buf.me_data = me_o.copy()
# -- -- -- --
edit_mode_in()
if c_b == True:
bpy.ops.mesh.delete(type = 'FACE')
else:
pass
edit_mode_out()
# -- -- -- --
f_(me_o, opp, th, context, rnd)
# -- -- -- --
edit_mode_in()
#bpy.ops.mesh.normals_make_consistent(inside = False)
bpy.data.meshes.remove(t_buf.me_data)
return {'FINISHED'}
# ------ classes to register ------
class_list = [ t_p0,
t_op0,
t_p_group0 ]
# ------ register ------
def register():
for c in class_list:
bpy.utils.register_class(c)
bpy.types.Scene.t_my_custom_props = PointerProperty(type = t_p_group0)
# ------ unregister ------
def unregister():
for c in class_list:
bpy.utils.unregister_class(c)
del bpy.context.scene['t_my_custom_props']
# ------ ------
if __name__ == "__main__":
register()