diff options
author | meta-androcto <meta.androcto1@gmail.com> | 2017-04-13 11:48:35 +0300 |
---|---|---|
committer | meta-androcto <meta.androcto1@gmail.com> | 2017-04-13 11:48:35 +0300 |
commit | 90dcb91c8b2aa653b922bbc35003faed09c7f54a (patch) | |
tree | 93622ca864e8c1343a47f7a6a026591e068ac7bb /add_mesh_extra_objects | |
parent | 0b2d9d5394c8c8a1506b5d8bc53ae3b61ec89eef (diff) |
add mesh extra objects: add triangle mesh: T36524
Diffstat (limited to 'add_mesh_extra_objects')
-rw-r--r-- | add_mesh_extra_objects/__init__.py | 4 | ||||
-rw-r--r-- | add_mesh_extra_objects/add_mesh_triangles.py | 299 |
2 files changed, 302 insertions, 1 deletions
diff --git a/add_mesh_extra_objects/__init__.py b/add_mesh_extra_objects/__init__.py index b3eb833d..a4290b35 100644 --- a/add_mesh_extra_objects/__init__.py +++ b/add_mesh_extra_objects/__init__.py @@ -61,6 +61,7 @@ if "bpy" in locals(): importlib.reload(geodesic_classes_271) importlib.reload(third_domes_panel_271) importlib.reload(vefm_271) + importlib.reload(add_mesh_triangles) else: from . import add_mesh_star from . import add_mesh_twisted_torus @@ -83,6 +84,7 @@ else: from . import add_mesh_beam_builder from . import Wallfactory from . import Blocks + from . import add_mesh_triangles from .geodesic_domes import add_shape_geodesic from .geodesic_domes import forms_271 @@ -162,7 +164,7 @@ class INFO_MT_mesh_math_add(Menu): layout.operator("mesh.primitive_xyz_function_surface", text="XYZ Math Surface") self.layout.operator("mesh.primitive_solid_add", text="Regular Solid") - + self.layout.operator("mesh.make_triangle", icon = "MESH_DATA") class INFO_MT_mesh_mech(Menu): # Define the "Math Function" menu diff --git a/add_mesh_extra_objects/add_mesh_triangles.py b/add_mesh_extra_objects/add_mesh_triangles.py new file mode 100644 index 00000000..c1a57469 --- /dev/null +++ b/add_mesh_extra_objects/add_mesh_triangles.py @@ -0,0 +1,299 @@ +bl_info = { + "name": "Triangles", + "description": "Create different types of tirangles.", + "author": "Sjaak-de-Draak", + "version": (1, 0), + "blender": (2, 68, 0), + "location": "View3D > Add > Mesh", + "warning": "First Version", # used for warning icon and text in addons panel + "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/" + "Scripts/Triangles", + "tracker_url": "http://projects.blender.org/tracker/index.php?" + "func=detail&aid=<number>", + "category": "Add Mesh"} + +""" +This script provides a triangle mesh primitive +and a toolbar menu to further specify settings +""" + +import math +import bpy +import mathutils +import types + +# make the mathutils Vector type accessible as Vector +Vector=mathutils.Vector + +def checkEditMode(): + ## Check if we are in edit mode + ## Returns: 1 if True + ## 0 if False + if (bpy.context.active_object.mode == 'EDIT'): + return 1; + return 0; + +def exitEditMode(): + ## Check if we are in edit mode (cuz we don't want this when creating a new Mesh) + ## If we are then toggle back to object mode + # Check if there are active objects + if (bpy.context.active_object != None ): + # Only the active object should be in edit mode + if (bpy.context.active_object.mode == 'EDIT'): + bpy.ops.object.editmode_toggle() + +class MakeTriangle(bpy.types.Operator): + bl_idname = "mesh.make_triangle" + bl_label = "Triangle" + bl_options = {"REGISTER", "UNDO"} + nothing=0 + + Ya = 0.0 + Xb = 0.0 + Xc = 0.0 + Vertices = [ ] + Faces = [ ] + + triangleTypeList = [('ISOSCELES', "Isosceles", "Two equal sides", 0), + ('EQUILATERAL', "Equilateral", "Three equal sides and angles (60°)", 1), + ('ISOSCELESRIGHTANGLE', "Isosceles right angled", "90° angle and two equal sides", 2), + ('SCALENERIGHTANGLE', "Scalene right angled", "90° angle, no equal sides", 3)] + + triangleFaceList = [('DEFAULT', "Normal", "1 Tri(angle) face", 0), + ('TRIANGLES', "3 Tri faces", "4 Verticies & 3 Tri(angle) faces", 1), + ('QUADS', "3 Quad faces", "7 Verticies & 3 Quad faces", 2), + ('SAFEQUADS', "6 Quad faces", "12 Verticies & 6 Quad faces", 3)] + + # add definitions for some manipulation buttons + flipX = bpy.props.BoolProperty(name="Flip X sign", + description="Draw on the other side of the X axis (Mirror on Y axis)", + default = False) + flipY = bpy.props.BoolProperty(name="Flip Y sign", + description="Draw on the other side of the Y axis (Mirror on X axis)", + default = False) + scale = bpy.props.FloatProperty(name="Scale", + description="Triangle scale", + default=1.0, min=1.0) + triangleType = bpy.props.EnumProperty(items=triangleTypeList, + name="Type", + description="Triangle Type") + triangleFace = bpy.props.EnumProperty(items=triangleFaceList, + name="Face types", + description="Triangle Face Types") + at_3Dcursor = bpy.props.BoolProperty(name="At 3D Cursor", + description="Draw the triangle where the 3D cursor is", + default = False) + + + def draw(self, context): + layout = self.layout + + row = layout.row(align=True) + row.label(text="Type: ") + + row.prop(self, "triangleType", text="") + + row = layout.row(align=True) + row.prop(self, "at_3Dcursor", text="3D Cursor") + row.prop(self, "scale") + + row = layout.row(align=True) + row.label(text="Face Type: ") + row.prop(self, "triangleFace", text="") + + col = layout.column(align=True) + col.prop(self, "flipX") + col.prop(self, "flipY") + #end draw + + def drawBasicTriangleShape(self): + # set everything to 0 + X = Xa = Xb = Xc = 0.0 + Y = Ya = Yb = Yc = 0.0 + Z = Za = Zb = Zc = 0.0 + + scale=self.scale + Xsign = -1 if self.flipX else 1 + Ysign = -1 if self.flipY else 1 + + # Isosceles (2 equal sides) + if ( self.triangleType == 'ISOSCELES' ): + # below a simple triangle containing 2 triangles with 1:2 side ratio + Ya=(1 * Ysign * scale) + A=Vector([0.0, Ya, 0.0]) + Xb=(0.5 * Xsign * scale) + B=Vector([Xb, 0.0, 0.0]) + Xc=(-0.5 * Xsign * scale) + C=Vector([Xc, 0.0, 0.0]) + + self.Ya=Ya + self.Xb=Xb + self.Xc=Xc + self.Vertices = [A, B, C,] + return True + + # Equilateral (all sides equal) + if ( self.triangleType == 'EQUILATERAL' ): + Ya=(math.sqrt(0.75) * Ysign * scale) + A=Vector([0.0, Ya, 0.0]) + Xb=(0.5 * Xsign * scale) + B=Vector([Xb, 0.0, 0.0]) + Xc=(-0.5 * Xsign * scale) + C=Vector([Xc, 0.0, 0.0]) + + self.Ya=Ya + self.Xb=Xb + self.Xc=Xc + self.Vertices = [A, B, C,] + return True + + # Isosceles right angled ( 1, 1, sqrt(2) ) + if ( self.triangleType == 'ISOSCELESRIGHTANGLE' ): + Ya=(1 * Ysign * scale) + A=Vector([0.0, Ya, 0.0]) + Xb=0.0 + B=Vector([Xb, 0.0, 0.0]) + Xc=(1 * Xsign * scale) + C=Vector([Xc, 0.0, 0.0]) + + self.Ya=Ya + self.Xb=Xb + self.Xc=Xc + self.Vertices = [A, B, C,] + return True + + # Scalene right angled ( 3, 4, 5 ) + if ( self.triangleType == 'SCALENERIGHTANGLE' ): + Ya=(1 * Ysign * scale) + A=Vector([0.0, Ya, 0.0]) + Xb=0 + B=Vector([Xb, 0.0, 0.0]) + Xc=(0.75 * Xsign * scale) + C=Vector([Xc, 0.0, 0.0]) + + self.Ya=Ya + self.Xb=Xb + self.Xc=Xc + self.Vertices = [A, B, C,] + return True + return False + + def addFaces(self, fType=None): + Ya=self.Ya + Xb=self.Xb + Xc=self.Xc + + if (self.triangleFace == 'DEFAULT'): + self.Faces=[[0,1,2]] + return True + + if (self.triangleFace == 'TRIANGLES'): + A=Vector([0.0, Ya, 0.0]) + B=Vector([Xb, 0.0, 0.0]) + C=Vector([Xc, 0.0, 0.0]) + D=Vector([((A.x + B.x + C.x) /3), ((A.y + B.y + C.y) /3), ((A.z + B.z + C.z) /3)]) + + self.Vertices = [A, B, C, D,] + self.Faces=[[0,1,3], [1,2,3], [2,0,3]] + return True + + if (self.triangleFace == 'QUADS'): + A=Vector([0.0, Ya, 0.0]) + B=Vector([Xb, 0.0, 0.0]) + C=Vector([Xc, 0.0, 0.0]) + D=Vector([((A.x + B.x + C.x) /3), ((A.y + B.y + C.y) /3), ((A.z + B.z + C.z) /3)]) + AB = A.lerp(B, 0.5) + AC = A.lerp(C, 0.5) + BC = B.lerp(C, 0.5) + + self.Vertices = [A, AB, B, BC, C, AC, D,] + self.Faces=[[0,1,6,5], [1,2,3,6], [3,4,5,6]] + return True + + if (self.triangleFace == 'SAFEQUADS'): + A=Vector([0.0, Ya, 0.0]) + B=Vector([Xb, 0.0, 0.0]) + C=Vector([Xc, 0.0, 0.0]) + D=Vector([((A.x + B.x + C.x) /3), ((A.y + B.y + C.y) /3), ((A.z + B.z + C.z) /3)]) + E = A.lerp(D, 0.5) + AB = A.lerp(B, 0.5) + AC = A.lerp(C, 0.5) + BC = B.lerp(C, 0.5) + AAB = AB.lerp(A, 0.5) + AAC = AC.lerp(A, 0.5) + BBA = AB.lerp(B, 0.5) + BBC = BC.lerp(B, 0.5) + BCC = BC.lerp(C, 0.5) + CCA = AC.lerp(C, 0.5) + + self.Vertices = [A, AAB, BBA, B, BBC, BC, BCC, C, CCA, AAC, D, E,] + self.Faces=[[0,1,11,9], [1,2,10,11], [2,3,4,10], [4,5,6,10], [6,7,8,10], [8,9,11,10]] + return True + return False + + + def action_common(self, context): + # definitions: + # a triangle consists of 3 points: A, B, C + # a 'safer' subdividable triangle consists of 4 points: A, B, C, D + # a subdivide friendly triangle consists of 7 points: A, B, C, D, AB, AC, BC + # a truely subdivide friendly triangle consists of (3x4=)12 points: A, B, C, D, E, BC, AAB, AAC, BBA, BBC, BCC, CCA + + BasicShapeCreated=False + ShapeFacesCreated=False + go=0 + + # + # call the functions for creating the triangles and test if successfull + # + BasicShapeCreated=self.drawBasicTriangleShape() + if (BasicShapeCreated): + ShapeFacesCreated=self.addFaces() + if (ShapeFacesCreated): + go=1 + + if (go == 1): + NewMesh = bpy.data.meshes.new("Triangle") + NewMesh.from_pydata(self.Vertices, [], self.Faces) + + NewMesh.update() + NewObj = bpy.data.objects.new("Triangle", NewMesh) + context.scene.objects.link(NewObj) + + # before doing the deselect make sure edit mode isn't active + exitEditMode() + bpy.ops.object.select_all(action = "DESELECT") + NewObj.select = True + context.scene.objects.active = NewObj + if (self.at_3Dcursor == True): + # we'll need to be sure there is actually an object selected + if (NewObj.select == True): + # we also have to check if we're considered to be in 3D View (view3d) + if (bpy.ops.view3d.snap_selected_to_cursor.poll() == True): + bpy.ops.view3d.snap_selected_to_cursor() + else: + # as we weren't considered to be in 3D View + # the object couldn't be moved to the 3D cursor + # so to avoid confusion we change the at_3Dcursor boolean to false + self.at_3Dcursor = False + else: + print("Failed to create triangle: ") + print("Triangle type: %s" % self.triangleType) + print("Face type: %s" % self.triangleFace) + print("Ya: %s" % self.Ya) + print("Xb: %s" % self.Xb) + print("Xc: %s" % self.Xc) + print("Vertices: %s" % self.Vertices) + print("Faces: %s" % self.Faces) + + #end action_common + + def execute(self, context) : + self.action_common(context) + return {"FINISHED"} + #end execute + + def invoke(self, context, event) : + self.action_common(context) + return {"FINISHED"} + #end invoke |