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://projects.blender.org/tracker/index.php?"\
30 "func=detail&aid=21443",
31 "category": "Add Mesh"}
35 from bpy
.props
import *
38 # Create a new mesh (object) from verts/edges/faces.
39 # verts/edges/faces ... List of vertices/edges/faces for the
40 # new mesh (as used in from_pydata).
41 # name ... Name of the new mesh (& object).
42 def create_mesh_object(context
, verts
, edges
, faces
, name
):
44 mesh
= bpy
.data
.meshes
.new(name
)
46 # Make a mesh from a list of verts/edges/faces.
47 mesh
.from_pydata(verts
, edges
, faces
)
49 # Update mesh geometry after adding stuff.
52 from bpy_extras
import object_utils
53 return object_utils
.object_data_add(context
, mesh
, operator
=None)
55 # A very simple "bridge" tool.
56 # Connects two equally long vertex rows with faces.
57 # Returns a list of the new faces (list of lists)
59 # vertIdx1 ... First vertex list (list of vertex indices).
60 # vertIdx2 ... Second vertex list (list of vertex indices).
61 # closed ... Creates a loop (first & last are closed).
62 # flipped ... Invert the normal of the face(s).
64 # Note: You can set vertIdx1 to a single vertex index to create
65 # a fan/star of faces.
66 # Note: If both vertex idx list are the same length they have
67 # to have at least 2 vertices.
68 def createFaces(vertIdx1
, vertIdx2
, closed
=False, flipped
=False):
71 if not vertIdx1
or not vertIdx2
:
74 if len(vertIdx1
) < 2 and len(vertIdx2
) < 2:
78 if (len(vertIdx1
) != len(vertIdx2
)):
79 if (len(vertIdx1
) == 1 and len(vertIdx2
) > 1):
87 # Bridge the start with the end.
94 face
.append(vertIdx1
[total
- 1])
98 face
= [vertIdx2
[0], vertIdx1
[0]]
100 face
.append(vertIdx1
[total
- 1])
101 face
.append(vertIdx2
[total
- 1])
104 # Bridge the rest of the faces.
105 for num
in range(total
- 1):
108 face
= [vertIdx2
[num
], vertIdx1
[0], vertIdx2
[num
+ 1]]
110 face
= [vertIdx2
[num
], vertIdx1
[num
],
111 vertIdx1
[num
+ 1], vertIdx2
[num
+ 1]]
115 face
= [vertIdx1
[0], vertIdx2
[num
], vertIdx2
[num
+ 1]]
117 face
= [vertIdx1
[num
], vertIdx2
[num
],
118 vertIdx2
[num
+ 1], vertIdx1
[num
+ 1]]
124 class AddElbowJoint(bpy
.types
.Operator
):
125 # Create the vertices and polygons for a simple elbow (bent pipe).
126 """Add an Elbow pipe mesh"""
127 bl_idname
= "mesh.primitive_elbow_joint_add"
128 bl_label
= "Add Pipe Elbow"
129 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
131 radius
= FloatProperty(name
="Radius",
132 description
="The radius of the pipe",
137 div
= IntProperty(name
="Divisions",
138 description
="Number of vertices (divisions)",
139 default
=32, min=3, max=256)
141 angle
= FloatProperty(name
="Angle",
142 description
="The angle of the branching pipe (i.e. the 'arm' - " \
143 "Measured from the center line of the main pipe",
144 default
=radians(45.0),
149 startLength
= FloatProperty(name
="Length Start",
150 description
="Length of the beginning of the pipe",
155 endLength
= FloatProperty(name
="End Length",
156 description
="Length of the end of the pipe",
162 def execute(self
, context
):
169 startLength
= self
.startLength
170 endLength
= self
.endLength
175 loop1
= [] # The starting circle
176 loop2
= [] # The elbow circle
177 loop3
= [] # The end circle
179 # Create start circle
180 for vertIdx
in range(div
):
181 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
182 locX
= sin(curVertAngle
)
183 locY
= cos(curVertAngle
)
185 loop1
.append(len(verts
))
186 verts
.append([locX
* radius
, locY
* radius
, locZ
])
188 # Create deformed joint circle
189 for vertIdx
in range(div
):
190 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
191 locX
= sin(curVertAngle
)
192 locY
= cos(curVertAngle
)
193 locZ
= locX
* tan(angle
/ 2.0)
194 loop2
.append(len(verts
))
195 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
198 baseEndLocX
= -endLength
* sin(angle
)
199 baseEndLocZ
= endLength
* cos(angle
)
200 for vertIdx
in range(div
):
201 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
203 locX
= sin(curVertAngle
) * radius
204 locY
= cos(curVertAngle
) * radius
208 locZ
= locX
* cos(pi
/ 2.0 - angle
)
209 locX
= locX
* sin(pi
/ 2.0 - angle
)
211 loop3
.append(len(verts
))
212 # Translate and add circle vertices to the list.
213 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
216 faces
.extend(createFaces(loop1
, loop2
, closed
=True))
217 faces
.extend(createFaces(loop2
, loop3
, closed
=True))
219 base
= create_mesh_object(context
, verts
, [], faces
, "Elbow Joint")
224 class AddTeeJoint(bpy
.types
.Operator
):
225 # Create the vertices and polygons for a simple tee (T) joint.
226 # The base arm of the T can be positioned in an angle if needed though.
227 """Add a Tee-Joint mesh"""
228 bl_idname
= "mesh.primitive_tee_joint_add"
229 bl_label
= "Add Pipe Tee-Joint"
230 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
232 radius
= FloatProperty(name
="Radius",
233 description
="The radius of the pipe",
238 div
= IntProperty(name
="Divisions",
239 description
="Number of vertices (divisions)",
244 angle
= FloatProperty(name
="Angle",
245 description
="The angle of the branching pipe (i.e. the 'arm' - " \
246 "Measured from the center line of the main pipe",
247 default
=radians(90.0),
252 startLength
= FloatProperty(name
="Length Start",
253 description
="Length of the beginning of the" \
254 " main pipe (the straight one)",
259 endLength
= FloatProperty(name
="End Length",
260 description
="Length of the end of the" \
261 " main pipe (the straight one)",
266 branchLength
= FloatProperty(name
="Arm Length",
267 description
="Length of the arm pipe (the bent one)",
273 def execute(self
, context
):
280 startLength
= self
.startLength
281 endLength
= self
.endLength
282 branchLength
= self
.branchLength
285 # Odd vertice number not supported (yet).
291 # List of vert indices of each cross section
292 loopMainStart
= [] # Vert indices for the
293 # beginning of the main pipe.
294 loopJoint1
= [] # Vert indices for joint that is used
295 # to connect the joint & loopMainStart.
296 loopJoint2
= [] # Vert indices for joint that is used
297 # to connect the joint & loopArm.
298 loopJoint3
= [] # Vert index for joint that is used
299 # to connect the joint & loopMainEnd.
300 loopArm
= [] # Vert indices for the end of the arm.
301 loopMainEnd
= [] # Vert indices for the
302 # end of the main pipe.
304 # Create start circle (main pipe)
305 for vertIdx
in range(div
):
306 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
307 locX
= sin(curVertAngle
)
308 locY
= cos(curVertAngle
)
310 loopMainStart
.append(len(verts
))
311 verts
.append([locX
* radius
, locY
* radius
, locZ
])
313 # Create deformed joint circle
316 for vertIdx
in range(div
):
317 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
318 locX
= sin(curVertAngle
)
319 locY
= cos(curVertAngle
)
322 vertTemp1
= len(verts
)
323 if vertIdx
== div
/ 2:
324 # @todo: This will possibly break if we
325 # ever support odd divisions.
326 vertTemp2
= len(verts
)
328 loopJoint1
.append(len(verts
))
329 if (vertIdx
< div
/ 2):
330 # Straight side of main pipe.
332 loopJoint3
.append(len(verts
))
335 locZ
= locX
* tan(angle
/ 2.0)
336 loopJoint2
.append(len(verts
))
338 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
340 # Create 2. deformed joint (half-)circle
342 for vertIdx
in range(div
):
343 if (vertIdx
> div
/ 2):
344 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
345 locX
= sin(curVertAngle
)
346 locY
= -cos(curVertAngle
)
347 locZ
= -(radius
* locX
* tan((pi
- angle
) / 2.0))
348 loopTemp
.append(len(verts
))
349 verts
.append([locX
* radius
, locY
* radius
, locZ
])
351 loopTemp2
= loopTemp
[:]
355 loopTemp
.append(vertTemp1
)
357 loopJoint2
.extend(loopTemp
)
361 loopTemp2
.append(vertTemp2
)
363 loopJoint3
.extend(loopTemp2
)
365 # Create end circle (branching pipe)
366 baseEndLocX
= -branchLength
* sin(angle
)
367 baseEndLocZ
= branchLength
* cos(angle
)
368 for vertIdx
in range(div
):
369 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
371 locX
= sin(curVertAngle
) * radius
372 locY
= cos(curVertAngle
) * radius
376 locZ
= locX
* cos(pi
/ 2.0 - angle
)
377 locX
= locX
* sin(pi
/ 2.0 - angle
)
379 loopArm
.append(len(verts
))
381 # Add translated circle.
382 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
384 # Create end circle (main pipe)
385 for vertIdx
in range(div
):
386 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
387 locX
= sin(curVertAngle
)
388 locY
= cos(curVertAngle
)
390 loopMainEnd
.append(len(verts
))
391 verts
.append([locX
* radius
, locY
* radius
, locZ
])
394 faces
.extend(createFaces(loopMainStart
, loopJoint1
, closed
=True))
395 faces
.extend(createFaces(loopJoint2
, loopArm
, closed
=True))
396 faces
.extend(createFaces(loopJoint3
, loopMainEnd
, closed
=True))
398 base
= create_mesh_object(context
, verts
, [], faces
, "Tee Joint")
403 class AddWyeJoint(bpy
.types
.Operator
):
404 """Add a Wye-Joint mesh"""
405 bl_idname
= "mesh.primitive_wye_joint_add"
406 bl_label
= "Add Pipe Wye-Joint"
407 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
409 radius
= FloatProperty(name
="Radius",
410 description
="The radius of the pipe",
415 div
= IntProperty(name
="Divisions",
416 description
="Number of vertices (divisions)",
421 angle1
= FloatProperty(name
="Angle 1",
422 description
="The angle of the 1. branching pipe " \
423 "(measured from the center line of the main pipe)",
424 default
=radians(45.0),
428 angle2
= FloatProperty(name
="Angle 2",
429 description
="The angle of the 2. branching pipe " \
430 "(measured from the center line of the main pipe) ",
431 default
=radians(45.0),
436 startLength
= FloatProperty(name
="Length Start",
437 description
="Length of the beginning of the" \
438 " main pipe (the straight one)",
443 branch1Length
= FloatProperty(name
="Length Arm 1",
444 description
="Length of the 1. arm",
449 branch2Length
= FloatProperty(name
="Length Arm 2",
450 description
="Length of the 2. arm",
456 def execute(self
, context
):
464 startLength
= self
.startLength
465 branch1Length
= self
.branch1Length
466 branch2Length
= self
.branch2Length
469 # Odd vertice number not supported (yet).
475 # List of vert indices of each cross section
476 loopMainStart
= [] # Vert indices for
477 # the beginning of the main pipe.
478 loopJoint1
= [] # Vert index for joint that is used
479 # to connect the joint & loopMainStart.
480 loopJoint2
= [] # Vert index for joint that
481 # is used to connect the joint & loopArm1.
482 loopJoint3
= [] # Vert index for joint that is
483 # used to connect the joint & loopArm2.
484 loopArm1
= [] # Vert idxs for end of the 1. arm.
485 loopArm2
= [] # Vert idxs for end of the 2. arm.
487 # Create start circle
488 for vertIdx
in range(div
):
489 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
490 locX
= sin(curVertAngle
)
491 locY
= cos(curVertAngle
)
493 loopMainStart
.append(len(verts
))
494 verts
.append([locX
* radius
, locY
* radius
, locZ
])
496 # Create deformed joint circle
499 for vertIdx
in range(div
):
500 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
501 locX
= sin(curVertAngle
)
502 locY
= cos(curVertAngle
)
505 vertTemp2
= len(verts
)
506 if vertIdx
== div
/ 2:
507 # @todo: This will possibly break if we
508 # ever support odd divisions.
509 vertTemp1
= len(verts
)
511 loopJoint1
.append(len(verts
))
512 if (vertIdx
> div
/ 2):
513 locZ
= locX
* tan(angle1
/ 2.0)
514 loopJoint2
.append(len(verts
))
516 locZ
= locX
* tan(-angle2
/ 2.0)
517 loopJoint3
.append(len(verts
))
519 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
521 # Create 2. deformed joint (half-)circle
523 angleJoint
= (angle2
- angle1
) / 2.0
524 for vertIdx
in range(div
):
525 if (vertIdx
> div
/ 2):
526 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
528 locX
= (-sin(curVertAngle
) * sin(angleJoint
)
529 / sin(angle2
- angleJoint
))
530 locY
= -cos(curVertAngle
)
531 locZ
= (-(sin(curVertAngle
) * cos(angleJoint
)
532 / sin(angle2
- angleJoint
)))
534 loopTemp
.append(len(verts
))
535 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
537 loopTemp2
= loopTemp
[:]
540 loopTemp
.append(vertTemp1
)
542 loopTemp
.append(vertTemp2
)
544 loopJoint2
.extend(loopTemp
)
549 loopJoint3
.extend(loopTemp2
)
551 # Create end circle (1. branching pipe)
552 baseEndLocX
= -branch1Length
* sin(angle1
)
553 baseEndLocZ
= branch1Length
* cos(angle1
)
554 for vertIdx
in range(div
):
555 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
557 locX
= sin(curVertAngle
) * radius
558 locY
= cos(curVertAngle
) * radius
562 locZ
= locX
* cos(pi
/ 2.0 - angle1
)
563 locX
= locX
* sin(pi
/ 2.0 - angle1
)
565 loopArm1
.append(len(verts
))
566 # Add translated circle.
567 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
569 # Create end circle (2. branching pipe)
570 baseEndLocX
= branch2Length
* sin(angle2
)
571 baseEndLocZ
= branch2Length
* cos(angle2
)
572 for vertIdx
in range(div
):
573 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
575 locX
= sin(curVertAngle
) * radius
576 locY
= cos(curVertAngle
) * radius
580 locZ
= locX
* cos(pi
/ 2.0 + angle2
)
581 locX
= locX
* sin(pi
/ 2.0 + angle2
)
583 loopArm2
.append(len(verts
))
584 # Add translated circle
585 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
588 faces
.extend(createFaces(loopMainStart
, loopJoint1
, closed
=True))
589 faces
.extend(createFaces(loopJoint2
, loopArm1
, closed
=True))
590 faces
.extend(createFaces(loopJoint3
, loopArm2
, closed
=True))
592 base
= create_mesh_object(context
, verts
, [], faces
, "Wye Joint")
597 class AddCrossJoint(bpy
.types
.Operator
):
598 """Add a Cross-Joint mesh"""
599 # Create the vertices and polygons for a coss (+ or X) pipe joint.
600 bl_idname
= "mesh.primitive_cross_joint_add"
601 bl_label
= "Add Pipe Cross-Joint"
602 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
604 radius
= FloatProperty(name
="Radius",
605 description
="The radius of the pipe",
610 div
= IntProperty(name
="Divisions",
611 description
="Number of vertices (divisions)",
616 angle1
= FloatProperty(name
="Angle 1",
617 description
="The angle of the 1. arm (from the main axis)",
618 default
=radians(90.0),
622 angle2
= FloatProperty(name
="Angle 2",
623 description
="The angle of the 2. arm (from the main axis)",
624 default
=radians(90.0),
628 angle3
= FloatProperty(name
="Angle 3 (center)",
629 description
="The angle of the center arm (from the main axis)",
630 default
=radians(0.0),
635 startLength
= FloatProperty(name
="Length Start",
636 description
="Length of the beginning of the " \
637 "main pipe (the straight one)",
642 branch1Length
= FloatProperty(name
="Length Arm 1",
643 description
="Length of the 1. arm",
648 branch2Length
= FloatProperty(name
="Length Arm 2",
649 description
="Length of the 2. arm",
654 branch3Length
= FloatProperty(name
="Length Arm 3 (center)",
655 description
="Length of the center arm",
661 def execute(self
, context
):
670 startLength
= self
.startLength
671 branch1Length
= self
.branch1Length
672 branch2Length
= self
.branch2Length
673 branch3Length
= self
.branch3Length
675 # Odd vertice number not supported (yet).
681 # List of vert indices of each cross section
682 loopMainStart
= [] # Vert indices for the
683 # beginning of the main pipe.
684 loopJoint1
= [] # Vert index for joint that is used
685 # to connect the joint & loopMainStart.
686 loopJoint2
= [] # Vert index for joint that is used
687 # to connect the joint & loopArm1.
688 loopJoint3
= [] # Vert index for joint that is used
689 # to connect the joint & loopArm2.
690 loopJoint4
= [] # Vert index for joint that is used
691 # to connect the joint & loopArm3.
692 loopArm1
= [] # Vert idxs for the end of the 1. arm.
693 loopArm2
= [] # Vert idxs for the end of the 2. arm.
694 loopArm3
= [] # Vert idxs for the center arm end.
696 # Create start circle
697 for vertIdx
in range(div
):
698 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
699 locX
= sin(curVertAngle
)
700 locY
= cos(curVertAngle
)
702 loopMainStart
.append(len(verts
))
703 verts
.append([locX
* radius
, locY
* radius
, locZ
])
705 # Create 1. deformed joint circle
708 for vertIdx
in range(div
):
709 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
710 locX
= sin(curVertAngle
)
711 locY
= cos(curVertAngle
)
714 vertTemp2
= len(verts
)
715 if vertIdx
== div
/ 2:
716 # @todo: This will possibly break if we
717 # ever support odd divisions.
718 vertTemp1
= len(verts
)
720 loopJoint1
.append(len(verts
))
721 if (vertIdx
> div
/ 2):
722 locZ
= locX
* tan(angle1
/ 2.0)
723 loopJoint2
.append(len(verts
))
725 locZ
= locX
* tan(-angle2
/ 2.0)
726 loopJoint3
.append(len(verts
))
728 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
730 # loopTemp2 = loopJoint2[:] # UNUSED
732 # Create 2. deformed joint circle
735 angleJoint1
= (angle1
- angle3
) / 2.0
736 angleJoint2
= (angle2
+ angle3
) / 2.0
737 for vertIdx
in range(div
):
738 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
741 # @todo: This will possibly break if
742 # we ever support odd divisions.
743 if not (vertIdx
== 0) and not (vertIdx
== div
/ 2):
745 if (vertIdx
> div
/ 2):
746 angleJoint
= angleJoint1
749 loopTempA
.append(len(verts
))
752 angleJoint
= angleJoint2
755 loopTempB
.append(len(verts
))
757 locX
= (sin(curVertAngle
) * sin(angleJoint
)
758 / sin(angle
- angleJoint
))
759 locY
= -cos(curVertAngle
)
760 locZ
= (Z
* (sin(curVertAngle
) * cos(angleJoint
)
761 / sin(angle
- angleJoint
)))
763 verts
.append([locX
* radius
, locY
* radius
, locZ
* radius
])
765 loopTempA2
= loopTempA
[:]
766 loopTempB2
= loopTempB
[:]
767 loopTempB3
= loopTempB
[:]
770 loopTempA
.append(vertTemp1
)
772 loopTempA
.append(vertTemp2
)
774 loopJoint2
.extend(loopTempA
)
778 loopJoint3
.extend(loopTempB3
)
781 loopTempA2
.append(vertTemp1
)
783 loopTempB2
.append(vertTemp2
)
784 loopJoint4
.extend(reversed(loopTempB2
))
785 loopJoint4
.extend(loopTempA2
)
787 # Create end circle (1. branching pipe)
788 baseEndLocX
= -branch1Length
* sin(angle1
)
789 baseEndLocZ
= branch1Length
* cos(angle1
)
790 for vertIdx
in range(div
):
791 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
793 locX
= sin(curVertAngle
) * radius
794 locY
= cos(curVertAngle
) * radius
798 locZ
= locX
* cos(pi
/ 2.0 - angle1
)
799 locX
= locX
* sin(pi
/ 2.0 - angle1
)
801 loopArm1
.append(len(verts
))
802 # Add translated circle.
803 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
805 # Create end circle (2. branching pipe)
806 baseEndLocX
= branch2Length
* sin(angle2
)
807 baseEndLocZ
= branch2Length
* cos(angle2
)
808 for vertIdx
in range(div
):
809 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
811 locX
= sin(curVertAngle
) * radius
812 locY
= cos(curVertAngle
) * radius
816 locZ
= locX
* cos(pi
/ 2.0 + angle2
)
817 locX
= locX
* sin(pi
/ 2.0 + angle2
)
819 loopArm2
.append(len(verts
))
820 # Add translated circle
821 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
823 # Create end circle (center pipe)
824 baseEndLocX
= branch3Length
* sin(angle3
)
825 baseEndLocZ
= branch3Length
* cos(angle3
)
826 for vertIdx
in range(div
):
827 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
829 locX
= sin(curVertAngle
) * radius
830 locY
= cos(curVertAngle
) * radius
834 locZ
= locX
* cos(pi
/ 2.0 + angle3
)
835 locX
= locX
* sin(pi
/ 2.0 + angle3
)
837 loopArm3
.append(len(verts
))
838 # Add translated circle
839 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
842 faces
.extend(createFaces(loopMainStart
, loopJoint1
, closed
=True))
843 faces
.extend(createFaces(loopJoint2
, loopArm1
, closed
=True))
844 faces
.extend(createFaces(loopJoint3
, loopArm2
, closed
=True))
845 faces
.extend(createFaces(loopJoint4
, loopArm3
, closed
=True))
847 base
= create_mesh_object(context
, verts
, [], faces
, "Cross Joint")
852 class AddNJoint(bpy
.types
.Operator
):
853 """Add a N-Joint mesh"""
854 # Create the vertices and polygons for a regular n-joint.
855 bl_idname
= "mesh.primitive_n_joint_add"
856 bl_label
= "Add Pipe N-Joint"
857 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
859 radius
= FloatProperty(name
="Radius",
860 description
="The radius of the pipe",
865 div
= IntProperty(name
="Divisions",
866 description
="Number of vertices (divisions)",
870 number
= IntProperty(name
="Arms/Joints",
871 description
="Number of joints/arms",
875 length
= FloatProperty(name
="Length",
876 description
="Length of each joint/arm",
882 def execute(self
, context
):
889 # Odd vertice number not supported (yet).
905 angleDiv
= (2.0 * pi
/ number
)
907 # Create vertices for the end circles.
908 for num
in range(number
):
910 # Create start circle
911 angle
= num
* angleDiv
913 baseEndLocX
= length
* sin(angle
)
914 baseEndLocZ
= length
* cos(angle
)
915 for vertIdx
in range(div
):
916 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
918 locX
= sin(curVertAngle
) * radius
919 locY
= cos(curVertAngle
) * radius
923 locZ
= locX
* cos(pi
/ 2.0 + angle
)
924 locX
= locX
* sin(pi
/ 2.0 + angle
)
926 circle
.append(len(verts
))
927 # Add translated circle
928 verts
.append([baseEndLocX
+ locX
, locY
, baseEndLocZ
+ locZ
])
930 loopsEndCircles
.append(circle
)
932 # Create vertices for the joint circles.
934 for vertIdx
in range(div
):
935 curVertAngle
= vertIdx
* (2.0 * pi
/ div
)
936 locX
= sin(curVertAngle
)
937 locY
= cos(curVertAngle
)
940 # Store pole vertices
943 vertTemp2
= len(verts
)
946 elif vertIdx
== div
/ 2:
947 # @todo: This will possibly break if we
948 # ever support odd divisions.
950 vertTemp1
= len(verts
)
955 if (vertIdx
> div
/ 2):
956 locZ
= -locX
* tan((pi
- angleDiv
) / 2.0)
957 loopJoint
.append(len(verts
))
962 LocXnew
= locX
* cosAng
- locZ
* sinAng
963 LocZnew
= locZ
* cosAng
+ locX
* sinAng
972 # These two vertices will only be
973 # added the very first time.
974 if vertIdx
== 0 or vertIdx
== div
/ 2:
975 verts
.append([locX
* radius
, locY
* radius
, locZ
])
977 loopsJointsTemp
.append(loopJoint
)
979 # Create complete loops (loopsJoints) out of the
980 # double number of half loops in loopsJointsTemp.
981 for halfLoopIdx
in range(len(loopsJointsTemp
)):
982 if (halfLoopIdx
== len(loopsJointsTemp
) - 1):
987 idx2
= halfLoopIdx
+ 1
990 loopJoint
.append(vertTemp2
)
991 loopJoint
.extend(reversed(loopsJointsTemp
[idx2
]))
992 loopJoint
.append(vertTemp1
)
993 loopJoint
.extend(loopsJointsTemp
[idx1
])
995 loopsJoints
.append(loopJoint
)
997 # Create faces from the two
998 # loop arrays (loopsJoints -> loopsEndCircles).
999 for loopIdx
in range(len(loopsEndCircles
)):
1001 createFaces(loopsJoints
[loopIdx
],
1002 loopsEndCircles
[loopIdx
], closed
=True))
1004 base
= create_mesh_object(context
, verts
, [], faces
, "N Joint")
1009 class INFO_MT_mesh_pipe_joints_add(bpy
.types
.Menu
):
1010 # Define the "Pipe Joints" menu
1011 bl_idname
= "INFO_MT_mesh_pipe_joints_add"
1012 bl_label
= "Pipe Joints"
1014 def draw(self
, context
):
1015 layout
= self
.layout
1016 layout
.operator_context
= 'INVOKE_REGION_WIN'
1017 layout
.operator("mesh.primitive_elbow_joint_add",
1019 layout
.operator("mesh.primitive_tee_joint_add",
1020 text
="Pipe T-Joint")
1021 layout
.operator("mesh.primitive_wye_joint_add",
1022 text
="Pipe Y-Joint")
1023 layout
.operator("mesh.primitive_cross_joint_add",
1024 text
="Pipe Cross-Joint")
1025 layout
.operator("mesh.primitive_n_joint_add",
1026 text
="Pipe N-Joint")
1028 ################################
1031 # Define "Pipe Joints" menu
1032 def menu_func(self
, context
):
1033 self
.layout
.menu("INFO_MT_mesh_pipe_joints_add", icon
="PLUGIN")
1037 bpy
.utils
.register_module(__name__
)
1039 # Add "Pipe Joints" menu to the "Add Mesh" menu
1040 bpy
.types
.INFO_MT_mesh_add
.append(menu_func
)
1044 bpy
.utils
.unregister_module(__name__
)
1046 # Remove "Pipe Joints" menu from the "Add Mesh" menu.
1047 bpy
.types
.INFO_MT_mesh_add
.remove(menu_func
)
1050 if __name__
== "__main__":