1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
20 "name": "Pipe Joints",
21 "author": "Buerbaum Martin (Pontiac)",
22 "version": (0, 10, 7),
23 "blender": (2, 61, 0),
24 "location": "View3D > Add > Mesh > Pipe Joints",
25 "description": "Add different types of pipe joints",
27 "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
28 "Scripts/Add_Mesh/Add_Pipe_Joints",
29 "tracker_url": "https://developer.blender.org/T21443",
30 "category": "Add Mesh"}
34 from bpy
.props
import *
37 # Create a new mesh (object) from verts/edges/faces.
38 # verts/edges/faces ... List of vertices/edges/faces for the
39 # new mesh (as used in from_pydata).
40 # name ... Name of the new mesh (& object).
41 def create_mesh_object(context
, verts
, edges
, faces
, name
):
43 mesh
= bpy
.data
.meshes
.new(name
)
45 # Make a mesh from a list of verts/edges/faces.
46 mesh
.from_pydata(verts
, edges
, faces
)
48 # Update mesh geometry after adding stuff.
51 from bpy_extras
import object_utils
52 return object_utils
.object_data_add(context
, mesh
, operator
=None)
54 # A very simple "bridge" tool.
55 # Connects two equally long vertex rows with faces.
56 # Returns a list of the new faces (list of lists)
58 # vertIdx1 ... First vertex list (list of vertex indices).
59 # vertIdx2 ... Second vertex list (list of vertex indices).
60 # closed ... Creates a loop (first & last are closed).
61 # flipped ... Invert the normal of the face(s).
63 # Note: You can set vertIdx1 to a single vertex index to create
64 # a fan/star of faces.
65 # Note: If both vertex idx list are the same length they have
66 # to have at least 2 vertices.
67 def createFaces(vertIdx1
, vertIdx2
, closed
=False, flipped
=False):
70 if not vertIdx1
or not vertIdx2
:
73 if len(vertIdx1
) < 2 and len(vertIdx2
) < 2:
77 if (len(vertIdx1
) != len(vertIdx2
)):
78 if (len(vertIdx1
) == 1 and len(vertIdx2
) > 1):
86 # Bridge the start with the end.
93 face
.append(vertIdx1
[total
- 1])
97 face
= [vertIdx2
[0], vertIdx1
[0]]
99 face
.append(vertIdx1
[total
- 1])
100 face
.append(vertIdx2
[total
- 1])
103 # Bridge the rest of the faces.
104 for num
in range(total
- 1):
107 face
= [vertIdx2
[num
], vertIdx1
[0], vertIdx2
[num
+ 1]]
109 face
= [vertIdx2
[num
], vertIdx1
[num
],
110 vertIdx1
[num
+ 1], vertIdx2
[num
+ 1]]
114 face
= [vertIdx1
[0], vertIdx2
[num
], vertIdx2
[num
+ 1]]
116 face
= [vertIdx1
[num
], vertIdx2
[num
],
117 vertIdx2
[num
+ 1], vertIdx1
[num
+ 1]]
123 class AddElbowJoint(bpy
.types
.Operator
):
124 # Create the vertices and polygons for a simple elbow (bent pipe).
125 """Add an Elbow pipe mesh"""
126 bl_idname
= "mesh.primitive_elbow_joint_add"
127 bl_label
= "Add Pipe Elbow"
128 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
130 radius
= FloatProperty(name
="Radius",
131 description
="The radius of the pipe",
136 div
= IntProperty(name
="Divisions",
137 description
="Number of vertices (divisions)",
138 default
=32, min=3, max=256)
140 angle
= FloatProperty(name
="Angle",
141 description
="The angle of the branching pipe (i.e. the 'arm' - " \
142 "Measured from the center line of the main pipe",
143 default
=radians(45.0),
148 startLength
= FloatProperty(name
="Length Start",
149 description
="Length of the beginning of the pipe",
154 endLength
= FloatProperty(name
="End Length",
155 description
="Length of the end of the pipe",
161 def execute(self
, context
):
168 startLength
= self
.startLength
169 endLength
= self
.endLength
174 loop1
= [] # The starting circle
175 loop2
= [] # The elbow circle
176 loop3
= [] # The end circle
178 # Create start circle
179 for vertIdx
in range(div
):
180 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
181 locX
= sin(curVertAngle
)
182 locY
= cos(curVertAngle
)
184 loop1
.append(len(verts
))
185 verts
.append([locX
* radius
, locY
* radius
, locZ
])
187 # Create deformed joint circle
188 for vertIdx
in range(div
):
189 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
190 locX
= sin(curVertAngle
)
191 locY
= cos(curVertAngle
)
192 locZ
= locX
* tan(angle
/ 2.0)
193 loop2
.append(len(verts
))
194 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
197 baseEndLocX
= -endLength
* sin(angle
)
198 baseEndLocZ
= endLength
* cos(angle
)
199 for vertIdx
in range(div
):
200 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
202 locX
= sin(curVertAngle
) * radius
203 locY
= cos(curVertAngle
) * radius
207 locZ
= locX
* cos(pi
/ 2.0 - angle
)
208 locX
= locX
* sin(pi
/ 2.0 - angle
)
210 loop3
.append(len(verts
))
211 # Translate and add circle vertices to the list.
212 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
215 faces
.extend(createFaces(loop1
, loop2
, closed
=True))
216 faces
.extend(createFaces(loop2
, loop3
, closed
=True))
218 base
= create_mesh_object(context
, verts
, [], faces
, "Elbow Joint")
223 class AddTeeJoint(bpy
.types
.Operator
):
224 # Create the vertices and polygons for a simple tee (T) joint.
225 # The base arm of the T can be positioned in an angle if needed though.
226 """Add a Tee-Joint mesh"""
227 bl_idname
= "mesh.primitive_tee_joint_add"
228 bl_label
= "Add Pipe Tee-Joint"
229 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
231 radius
= FloatProperty(name
="Radius",
232 description
="The radius of the pipe",
237 div
= IntProperty(name
="Divisions",
238 description
="Number of vertices (divisions)",
243 angle
= FloatProperty(name
="Angle",
244 description
="The angle of the branching pipe (i.e. the 'arm' - " \
245 "Measured from the center line of the main pipe",
246 default
=radians(90.0),
251 startLength
= FloatProperty(name
="Length Start",
252 description
="Length of the beginning of the" \
253 " main pipe (the straight one)",
258 endLength
= FloatProperty(name
="End Length",
259 description
="Length of the end of the" \
260 " main pipe (the straight one)",
265 branchLength
= FloatProperty(name
="Arm Length",
266 description
="Length of the arm pipe (the bent one)",
272 def execute(self
, context
):
279 startLength
= self
.startLength
280 endLength
= self
.endLength
281 branchLength
= self
.branchLength
284 # Odd vertice number not supported (yet).
290 # List of vert indices of each cross section
291 loopMainStart
= [] # Vert indices for the
292 # beginning of the main pipe.
293 loopJoint1
= [] # Vert indices for joint that is used
294 # to connect the joint & loopMainStart.
295 loopJoint2
= [] # Vert indices for joint that is used
296 # to connect the joint & loopArm.
297 loopJoint3
= [] # Vert index for joint that is used
298 # to connect the joint & loopMainEnd.
299 loopArm
= [] # Vert indices for the end of the arm.
300 loopMainEnd
= [] # Vert indices for the
301 # end of the main pipe.
303 # Create start circle (main pipe)
304 for vertIdx
in range(div
):
305 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
306 locX
= sin(curVertAngle
)
307 locY
= cos(curVertAngle
)
309 loopMainStart
.append(len(verts
))
310 verts
.append([locX
* radius
, locY
* radius
, locZ
])
312 # Create deformed joint circle
315 for vertIdx
in range(div
):
316 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
317 locX
= sin(curVertAngle
)
318 locY
= cos(curVertAngle
)
321 vertTemp1
= len(verts
)
322 if vertIdx
== div
/ 2:
323 # @todo: This will possibly break if we
324 # ever support odd divisions.
325 vertTemp2
= len(verts
)
327 loopJoint1
.append(len(verts
))
328 if (vertIdx
< div
/ 2):
329 # Straight side of main pipe.
331 loopJoint3
.append(len(verts
))
334 locZ
= locX
* tan(angle
/ 2.0)
335 loopJoint2
.append(len(verts
))
337 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
339 # Create 2. deformed joint (half-)circle
341 for vertIdx
in range(div
):
342 if (vertIdx
> div
/ 2):
343 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
344 locX
= sin(curVertAngle
)
345 locY
= -cos(curVertAngle
)
346 locZ
= -(radius
* locX
* tan((pi
- angle
) / 2.0))
347 loopTemp
.append(len(verts
))
348 verts
.append([locX
* radius
, locY
* radius
, locZ
])
350 loopTemp2
= loopTemp
[:]
354 loopTemp
.append(vertTemp1
)
356 loopJoint2
.extend(loopTemp
)
360 loopTemp2
.append(vertTemp2
)
362 loopJoint3
.extend(loopTemp2
)
364 # Create end circle (branching pipe)
365 baseEndLocX
= -branchLength
* sin(angle
)
366 baseEndLocZ
= branchLength
* cos(angle
)
367 for vertIdx
in range(div
):
368 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
370 locX
= sin(curVertAngle
) * radius
371 locY
= cos(curVertAngle
) * radius
375 locZ
= locX
* cos(pi
/ 2.0 - angle
)
376 locX
= locX
* sin(pi
/ 2.0 - angle
)
378 loopArm
.append(len(verts
))
380 # Add translated circle.
381 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
383 # Create end circle (main pipe)
384 for vertIdx
in range(div
):
385 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
386 locX
= sin(curVertAngle
)
387 locY
= cos(curVertAngle
)
389 loopMainEnd
.append(len(verts
))
390 verts
.append([locX
* radius
, locY
* radius
, locZ
])
393 faces
.extend(createFaces(loopMainStart
, loopJoint1
, closed
=True))
394 faces
.extend(createFaces(loopJoint2
, loopArm
, closed
=True))
395 faces
.extend(createFaces(loopJoint3
, loopMainEnd
, closed
=True))
397 base
= create_mesh_object(context
, verts
, [], faces
, "Tee Joint")
402 class AddWyeJoint(bpy
.types
.Operator
):
403 """Add a Wye-Joint mesh"""
404 bl_idname
= "mesh.primitive_wye_joint_add"
405 bl_label
= "Add Pipe Wye-Joint"
406 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
408 radius
= FloatProperty(name
="Radius",
409 description
="The radius of the pipe",
414 div
= IntProperty(name
="Divisions",
415 description
="Number of vertices (divisions)",
420 angle1
= FloatProperty(name
="Angle 1",
421 description
="The angle of the 1. branching pipe " \
422 "(measured from the center line of the main pipe)",
423 default
=radians(45.0),
427 angle2
= FloatProperty(name
="Angle 2",
428 description
="The angle of the 2. branching pipe " \
429 "(measured from the center line of the main pipe) ",
430 default
=radians(45.0),
435 startLength
= FloatProperty(name
="Length Start",
436 description
="Length of the beginning of the" \
437 " main pipe (the straight one)",
442 branch1Length
= FloatProperty(name
="Length Arm 1",
443 description
="Length of the 1. arm",
448 branch2Length
= FloatProperty(name
="Length Arm 2",
449 description
="Length of the 2. arm",
455 def execute(self
, context
):
463 startLength
= self
.startLength
464 branch1Length
= self
.branch1Length
465 branch2Length
= self
.branch2Length
468 # Odd vertice number not supported (yet).
474 # List of vert indices of each cross section
475 loopMainStart
= [] # Vert indices for
476 # the beginning of the main pipe.
477 loopJoint1
= [] # Vert index for joint that is used
478 # to connect the joint & loopMainStart.
479 loopJoint2
= [] # Vert index for joint that
480 # is used to connect the joint & loopArm1.
481 loopJoint3
= [] # Vert index for joint that is
482 # used to connect the joint & loopArm2.
483 loopArm1
= [] # Vert idxs for end of the 1. arm.
484 loopArm2
= [] # Vert idxs for end of the 2. arm.
486 # Create start circle
487 for vertIdx
in range(div
):
488 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
489 locX
= sin(curVertAngle
)
490 locY
= cos(curVertAngle
)
492 loopMainStart
.append(len(verts
))
493 verts
.append([locX
* radius
, locY
* radius
, locZ
])
495 # Create deformed joint circle
498 for vertIdx
in range(div
):
499 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
500 locX
= sin(curVertAngle
)
501 locY
= cos(curVertAngle
)
504 vertTemp2
= len(verts
)
505 if vertIdx
== div
/ 2:
506 # @todo: This will possibly break if we
507 # ever support odd divisions.
508 vertTemp1
= len(verts
)
510 loopJoint1
.append(len(verts
))
511 if (vertIdx
> div
/ 2):
512 locZ
= locX
* tan(angle1
/ 2.0)
513 loopJoint2
.append(len(verts
))
515 locZ
= locX
* tan(-angle2
/ 2.0)
516 loopJoint3
.append(len(verts
))
518 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
520 # Create 2. deformed joint (half-)circle
522 angleJoint
= (angle2
- angle1
) / 2.0
523 for vertIdx
in range(div
):
524 if (vertIdx
> div
/ 2):
525 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
527 locX
= (-sin(curVertAngle
) * sin(angleJoint
)
528 / sin(angle2
- angleJoint
))
529 locY
= -cos(curVertAngle
)
530 locZ
= (-(sin(curVertAngle
) * cos(angleJoint
)
531 / sin(angle2
- angleJoint
)))
533 loopTemp
.append(len(verts
))
534 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
536 loopTemp2
= loopTemp
[:]
539 loopTemp
.append(vertTemp1
)
541 loopTemp
.append(vertTemp2
)
543 loopJoint2
.extend(loopTemp
)
548 loopJoint3
.extend(loopTemp2
)
550 # Create end circle (1. branching pipe)
551 baseEndLocX
= -branch1Length
* sin(angle1
)
552 baseEndLocZ
= branch1Length
* cos(angle1
)
553 for vertIdx
in range(div
):
554 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
556 locX
= sin(curVertAngle
) * radius
557 locY
= cos(curVertAngle
) * radius
561 locZ
= locX
* cos(pi
/ 2.0 - angle1
)
562 locX
= locX
* sin(pi
/ 2.0 - angle1
)
564 loopArm1
.append(len(verts
))
565 # Add translated circle.
566 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
568 # Create end circle (2. branching pipe)
569 baseEndLocX
= branch2Length
* sin(angle2
)
570 baseEndLocZ
= branch2Length
* cos(angle2
)
571 for vertIdx
in range(div
):
572 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
574 locX
= sin(curVertAngle
) * radius
575 locY
= cos(curVertAngle
) * radius
579 locZ
= locX
* cos(pi
/ 2.0 + angle2
)
580 locX
= locX
* sin(pi
/ 2.0 + angle2
)
582 loopArm2
.append(len(verts
))
583 # Add translated circle
584 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
587 faces
.extend(createFaces(loopMainStart
, loopJoint1
, closed
=True))
588 faces
.extend(createFaces(loopJoint2
, loopArm1
, closed
=True))
589 faces
.extend(createFaces(loopJoint3
, loopArm2
, closed
=True))
591 base
= create_mesh_object(context
, verts
, [], faces
, "Wye Joint")
596 class AddCrossJoint(bpy
.types
.Operator
):
597 """Add a Cross-Joint mesh"""
598 # Create the vertices and polygons for a coss (+ or X) pipe joint.
599 bl_idname
= "mesh.primitive_cross_joint_add"
600 bl_label
= "Add Pipe Cross-Joint"
601 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
603 radius
= FloatProperty(name
="Radius",
604 description
="The radius of the pipe",
609 div
= IntProperty(name
="Divisions",
610 description
="Number of vertices (divisions)",
615 angle1
= FloatProperty(name
="Angle 1",
616 description
="The angle of the 1. arm (from the main axis)",
617 default
=radians(90.0),
621 angle2
= FloatProperty(name
="Angle 2",
622 description
="The angle of the 2. arm (from the main axis)",
623 default
=radians(90.0),
627 angle3
= FloatProperty(name
="Angle 3 (center)",
628 description
="The angle of the center arm (from the main axis)",
629 default
=radians(0.0),
634 startLength
= FloatProperty(name
="Length Start",
635 description
="Length of the beginning of the " \
636 "main pipe (the straight one)",
641 branch1Length
= FloatProperty(name
="Length Arm 1",
642 description
="Length of the 1. arm",
647 branch2Length
= FloatProperty(name
="Length Arm 2",
648 description
="Length of the 2. arm",
653 branch3Length
= FloatProperty(name
="Length Arm 3 (center)",
654 description
="Length of the center arm",
660 def execute(self
, context
):
669 startLength
= self
.startLength
670 branch1Length
= self
.branch1Length
671 branch2Length
= self
.branch2Length
672 branch3Length
= self
.branch3Length
674 # Odd vertice number not supported (yet).
680 # List of vert indices of each cross section
681 loopMainStart
= [] # Vert indices for the
682 # beginning of the main pipe.
683 loopJoint1
= [] # Vert index for joint that is used
684 # to connect the joint & loopMainStart.
685 loopJoint2
= [] # Vert index for joint that is used
686 # to connect the joint & loopArm1.
687 loopJoint3
= [] # Vert index for joint that is used
688 # to connect the joint & loopArm2.
689 loopJoint4
= [] # Vert index for joint that is used
690 # to connect the joint & loopArm3.
691 loopArm1
= [] # Vert idxs for the end of the 1. arm.
692 loopArm2
= [] # Vert idxs for the end of the 2. arm.
693 loopArm3
= [] # Vert idxs for the center arm end.
695 # Create start circle
696 for vertIdx
in range(div
):
697 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
698 locX
= sin(curVertAngle
)
699 locY
= cos(curVertAngle
)
701 loopMainStart
.append(len(verts
))
702 verts
.append([locX
* radius
, locY
* radius
, locZ
])
704 # Create 1. deformed joint circle
707 for vertIdx
in range(div
):
708 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
709 locX
= sin(curVertAngle
)
710 locY
= cos(curVertAngle
)
713 vertTemp2
= len(verts
)
714 if vertIdx
== div
/ 2:
715 # @todo: This will possibly break if we
716 # ever support odd divisions.
717 vertTemp1
= len(verts
)
719 loopJoint1
.append(len(verts
))
720 if (vertIdx
> div
/ 2):
721 locZ
= locX
* tan(angle1
/ 2.0)
722 loopJoint2
.append(len(verts
))
724 locZ
= locX
* tan(-angle2
/ 2.0)
725 loopJoint3
.append(len(verts
))
727 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
729 # loopTemp2 = loopJoint2[:] # UNUSED
731 # Create 2. deformed joint circle
734 angleJoint1
= (angle1
- angle3
) / 2.0
735 angleJoint2
= (angle2
+ angle3
) / 2.0
736 for vertIdx
in range(div
):
737 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
740 # @todo: This will possibly break if
741 # we ever support odd divisions.
742 if not (vertIdx
== 0) and not (vertIdx
== div
/ 2):
744 if (vertIdx
> div
/ 2):
745 angleJoint
= angleJoint1
748 loopTempA
.append(len(verts
))
751 angleJoint
= angleJoint2
754 loopTempB
.append(len(verts
))
756 locX
= (sin(curVertAngle
) * sin(angleJoint
)
757 / sin(angle
- angleJoint
))
758 locY
= -cos(curVertAngle
)
759 locZ
= (Z
* (sin(curVertAngle
) * cos(angleJoint
)
760 / sin(angle
- angleJoint
)))
762 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
764 loopTempA2
= loopTempA
[:]
765 loopTempB2
= loopTempB
[:]
766 loopTempB3
= loopTempB
[:]
769 loopTempA
.append(vertTemp1
)
771 loopTempA
.append(vertTemp2
)
773 loopJoint2
.extend(loopTempA
)
777 loopJoint3
.extend(loopTempB3
)
780 loopTempA2
.append(vertTemp1
)
782 loopTempB2
.append(vertTemp2
)
783 loopJoint4
.extend(reversed(loopTempB2
))
784 loopJoint4
.extend(loopTempA2
)
786 # Create end circle (1. branching pipe)
787 baseEndLocX
= -branch1Length
* sin(angle1
)
788 baseEndLocZ
= branch1Length
* cos(angle1
)
789 for vertIdx
in range(div
):
790 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
792 locX
= sin(curVertAngle
) * radius
793 locY
= cos(curVertAngle
) * radius
797 locZ
= locX
* cos(pi
/ 2.0 - angle1
)
798 locX
= locX
* sin(pi
/ 2.0 - angle1
)
800 loopArm1
.append(len(verts
))
801 # Add translated circle.
802 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
804 # Create end circle (2. branching pipe)
805 baseEndLocX
= branch2Length
* sin(angle2
)
806 baseEndLocZ
= branch2Length
* cos(angle2
)
807 for vertIdx
in range(div
):
808 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
810 locX
= sin(curVertAngle
) * radius
811 locY
= cos(curVertAngle
) * radius
815 locZ
= locX
* cos(pi
/ 2.0 + angle2
)
816 locX
= locX
* sin(pi
/ 2.0 + angle2
)
818 loopArm2
.append(len(verts
))
819 # Add translated circle
820 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
822 # Create end circle (center pipe)
823 baseEndLocX
= branch3Length
* sin(angle3
)
824 baseEndLocZ
= branch3Length
* cos(angle3
)
825 for vertIdx
in range(div
):
826 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
828 locX
= sin(curVertAngle
) * radius
829 locY
= cos(curVertAngle
) * radius
833 locZ
= locX
* cos(pi
/ 2.0 + angle3
)
834 locX
= locX
* sin(pi
/ 2.0 + angle3
)
836 loopArm3
.append(len(verts
))
837 # Add translated circle
838 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
841 faces
.extend(createFaces(loopMainStart
, loopJoint1
, closed
=True))
842 faces
.extend(createFaces(loopJoint2
, loopArm1
, closed
=True))
843 faces
.extend(createFaces(loopJoint3
, loopArm2
, closed
=True))
844 faces
.extend(createFaces(loopJoint4
, loopArm3
, closed
=True))
846 base
= create_mesh_object(context
, verts
, [], faces
, "Cross Joint")
851 class AddNJoint(bpy
.types
.Operator
):
852 """Add a N-Joint mesh"""
853 # Create the vertices and polygons for a regular n-joint.
854 bl_idname
= "mesh.primitive_n_joint_add"
855 bl_label
= "Add Pipe N-Joint"
856 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
858 radius
= FloatProperty(name
="Radius",
859 description
="The radius of the pipe",
864 div
= IntProperty(name
="Divisions",
865 description
="Number of vertices (divisions)",
869 number
= IntProperty(name
="Arms/Joints",
870 description
="Number of joints/arms",
874 length
= FloatProperty(name
="Length",
875 description
="Length of each joint/arm",
881 def execute(self
, context
):
888 # Odd vertice number not supported (yet).
904 angleDiv
= (2.0 * pi
/ number
)
906 # Create vertices for the end circles.
907 for num
in range(number
):
909 # Create start circle
910 angle
= num
* angleDiv
912 baseEndLocX
= length
* sin(angle
)
913 baseEndLocZ
= length
* cos(angle
)
914 for vertIdx
in range(div
):
915 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
917 locX
= sin(curVertAngle
) * radius
918 locY
= cos(curVertAngle
) * radius
922 locZ
= locX
* cos(pi
/ 2.0 + angle
)
923 locX
= locX
* sin(pi
/ 2.0 + angle
)
925 circle
.append(len(verts
))
926 # Add translated circle
927 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
929 loopsEndCircles
.append(circle
)
931 # Create vertices for the joint circles.
933 for vertIdx
in range(div
):
934 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
935 locX
= sin(curVertAngle
)
936 locY
= cos(curVertAngle
)
939 # Store pole vertices
942 vertTemp2
= len(verts
)
945 elif vertIdx
== div
/ 2:
946 # @todo: This will possibly break if we
947 # ever support odd divisions.
949 vertTemp1
= len(verts
)
954 if (vertIdx
> div
/ 2):
955 locZ
= -locX
* tan((pi
- angleDiv
) / 2.0)
956 loopJoint
.append(len(verts
))
961 LocXnew
= locX
* cosAng
- locZ
* sinAng
962 LocZnew
= locZ
* cosAng
+ locX
* sinAng
971 # These two vertices will only be
972 # added the very first time.
973 if vertIdx
== 0 or vertIdx
== div
/ 2:
974 verts
.append([locX
* radius
, locY
* radius
, locZ
])
976 loopsJointsTemp
.append(loopJoint
)
978 # Create complete loops (loopsJoints) out of the
979 # double number of half loops in loopsJointsTemp.
980 for halfLoopIdx
in range(len(loopsJointsTemp
)):
981 if (halfLoopIdx
== len(loopsJointsTemp
) - 1):
986 idx2
= halfLoopIdx
+ 1
989 loopJoint
.append(vertTemp2
)
990 loopJoint
.extend(reversed(loopsJointsTemp
[idx2
]))
991 loopJoint
.append(vertTemp1
)
992 loopJoint
.extend(loopsJointsTemp
[idx1
])
994 loopsJoints
.append(loopJoint
)
996 # Create faces from the two
997 # loop arrays (loopsJoints -> loopsEndCircles).
998 for loopIdx
in range(len(loopsEndCircles
)):
1000 createFaces(loopsJoints
[loopIdx
],
1001 loopsEndCircles
[loopIdx
], closed
=True))
1003 base
= create_mesh_object(context
, verts
, [], faces
, "N Joint")
1008 class INFO_MT_mesh_pipe_joints_add(bpy
.types
.Menu
):
1009 # Define the "Pipe Joints" menu
1010 bl_idname
= "INFO_MT_mesh_pipe_joints_add"
1011 bl_label
= "Pipe Joints"
1013 def draw(self
, context
):
1014 layout
= self
.layout
1015 layout
.operator_context
= 'INVOKE_REGION_WIN'
1016 layout
.operator("mesh.primitive_elbow_joint_add",
1018 layout
.operator("mesh.primitive_tee_joint_add",
1019 text
="Pipe T-Joint")
1020 layout
.operator("mesh.primitive_wye_joint_add",
1021 text
="Pipe Y-Joint")
1022 layout
.operator("mesh.primitive_cross_joint_add",
1023 text
="Pipe Cross-Joint")
1024 layout
.operator("mesh.primitive_n_joint_add",
1025 text
="Pipe N-Joint")
1027 ################################
1030 # Define "Pipe Joints" menu
1031 def menu_func(self
, context
):
1032 self
.layout
.menu("INFO_MT_mesh_pipe_joints_add", icon
="PLUGIN")
1036 bpy
.utils
.register_module(__name__
)
1038 # Add "Pipe Joints" menu to the "Add Mesh" menu
1039 bpy
.types
.INFO_MT_mesh_add
.append(menu_func
)
1043 bpy
.utils
.unregister_module(__name__
)
1045 # Remove "Pipe Joints" menu from the "Add Mesh" menu.
1046 bpy
.types
.INFO_MT_mesh_add
.remove(menu_func
)
1049 if __name__
== "__main__":