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 #####
21 "author": "Pontiac, Fourmadmen, Dreampainter",
23 "blender": (2, 57, 0),
24 "location": "View3D > Add > Mesh > Gemstones",
25 "description": "Adds various gemstone (Diamond & Gem) meshes.",
27 "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"
28 "Scripts/Add_Mesh/Add_Gemstones",
29 "category": "Add Mesh",
33 from mathutils
import *
35 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
):
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)
56 # A very simple "bridge" tool.
57 # Connects two equally long vertex rows with faces.
58 # Returns a list of the new faces (list of lists)
60 # vertIdx1 ... First vertex list (list of vertex indices).
61 # vertIdx2 ... Second vertex list (list of vertex indices).
62 # closed ... Creates a loop (first & last are closed).
63 # flipped ... Invert the normal of the face(s).
65 # Note: You can set vertIdx1 to a single vertex index to create
66 # a fan/star of faces.
67 # Note: If both vertex idx list are the same length they have
68 # to have at least 2 vertices.
69 def createFaces(vertIdx1
, vertIdx2
, closed
=False, flipped
=False):
72 if not vertIdx1
or not vertIdx2
:
75 if len(vertIdx1
) < 2 and len(vertIdx2
) < 2:
79 if (len(vertIdx1
) != len(vertIdx2
)):
80 if (len(vertIdx1
) == 1 and len(vertIdx2
) > 1):
88 # Bridge the start with the end.
95 face
.append(vertIdx1
[total
- 1])
99 face
= [vertIdx2
[0], vertIdx1
[0]]
101 face
.append(vertIdx1
[total
- 1])
102 face
.append(vertIdx2
[total
- 1])
105 # Bridge the rest of the faces.
106 for num
in range(total
- 1):
109 face
= [vertIdx2
[num
], vertIdx1
[0], vertIdx2
[num
+ 1]]
111 face
= [vertIdx2
[num
], vertIdx1
[num
],
112 vertIdx1
[num
+ 1], vertIdx2
[num
+ 1]]
116 face
= [vertIdx1
[0], vertIdx2
[num
], vertIdx2
[num
+ 1]]
118 face
= [vertIdx1
[num
], vertIdx2
[num
],
119 vertIdx2
[num
+ 1], vertIdx1
[num
+ 1]]
125 # @todo Clean up vertex&face creation process a bit.
126 def add_gem(r1
, r2
, seg
, h1
, h2
):
130 seg = number of segments
133 Generates the vertices and faces of the gem
138 a
= 2.0 * pi
/ seg
# Angle between segments
139 offset
= a
/ 2.0 # Middle between segments
141 r3
= ((r1
+ r2
) / 2.0) / cos(offset
) # Middle of crown
142 r4
= (r1
/ 2.0) / cos(offset
) # Middle of pavilion
143 h3
= h2
/ 2.0 # Middle of crown height
144 h4
= -h1
/ 2.0 # Middle of pavilion height
147 vert_tip
= len(verts
)
148 verts
.append(Vector((0.0, 0.0, -h1
)))
150 # Middle vertex of the flat side (crown)
151 vert_flat
= len(verts
)
152 verts
.append(Vector((0.0, 0.0, h2
)))
157 s2
= sin(offset
+ i
* a
)
159 c2
= cos(offset
+ i
* a
)
161 verts
.append((r4
* s1
, r4
* c1
, h4
)) # Middle of pavilion
162 verts
.append((r1
* s2
, r1
* c2
, 0.0)) # Pavilion
163 verts
.append((r3
* s1
, r3
* c1
, h3
)) # Middle crown
164 edgeloop_flat
.append(len(verts
))
165 verts
.append((r2
* s2
, r2
* c2
, h2
)) # Crown
169 for index
in range(seg
):
171 j
= ((index
+ 1) % seg
) * 4
173 faces
.append([j
+ 2, vert_tip
, i
+ 2, i
+ 3]) # Tip -> Middle of pav
174 faces
.append([j
+ 2, i
+ 3, j
+ 3]) # Middle of pav -> pav
175 faces
.append([j
+ 3, i
+ 3, j
+ 4]) # Pav -> Middle crown
176 faces
.append([j
+ 4, i
+ 3, i
+ 4, i
+ 5]) # Crown quads
177 faces
.append([j
+ 4, i
+ 5, j
+ 5]) # Middle crown -> crown
179 faces_flat
= createFaces([vert_flat
], edgeloop_flat
, closed
=True)
180 faces
.extend(faces_flat
)
185 def add_diamond(segments
, girdle_radius
, table_radius
,
186 crown_height
, pavilion_height
):
189 z_axis
= (0.0, 0.0, -1.0)
194 height_flat
= crown_height
196 height_tip
= -pavilion_height
198 # Middle vertex of the flat side (crown)
199 vert_flat
= len(verts
)
200 verts
.append(Vector((0.0, 0.0, height_flat
)))
203 vert_tip
= len(verts
)
204 verts
.append(Vector((0.0, 0.0, height_tip
)))
209 for index
in range(segments
):
210 quat
= Quaternion(z_axis
, (index
/ segments
) * PI_2
)
212 # angle = PI_2 * index / segments # UNUSED
215 verts_flat
.append(len(verts
))
216 vec
= quat
* Vector((table_radius
, 0.0, height_flat
))
219 # Row for the middle/girdle
220 verts_girdle
.append(len(verts
))
221 vec
= quat
* Vector((girdle_radius
, 0.0, height_middle
))
225 faces_flat
= createFaces([vert_flat
], verts_flat
, closed
=True,
228 faces_side
= createFaces(verts_girdle
, verts_flat
, closed
=True)
230 faces_tip
= createFaces([vert_tip
], verts_girdle
, closed
=True)
232 faces
.extend(faces_tip
)
233 faces
.extend(faces_side
)
234 faces
.extend(faces_flat
)
239 class AddDiamond(bpy
.types
.Operator
):
240 """Add a diamond mesh"""
241 bl_idname
= "mesh.primitive_diamond_add"
242 bl_label
= "Add Diamond"
243 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
245 segments
= IntProperty(name
="Segments",
246 description
="Number of segments for the diamond",
250 girdle_radius
= FloatProperty(name
="Girdle Radius",
251 description
="Girdle radius of the diamond",
255 table_radius
= FloatProperty(name
="Table Radius",
256 description
="Girdle radius of the diamond",
260 crown_height
= FloatProperty(name
="Crown Height",
261 description
="Crown height of the diamond",
265 pavilion_height
= FloatProperty(name
="Pavilion Height",
266 description
="Pavilion height of the diamond",
271 def execute(self
, context
):
272 verts
, faces
= add_diamond(self
.segments
,
276 self
.pavilion_height
)
278 obj
= create_mesh_object(context
, verts
, [], faces
, "Diamond")
283 class AddGem(bpy
.types
.Operator
):
284 """Add a diamond gem"""
285 bl_idname
= "mesh.primitive_gem_add"
287 bl_description
= "Create an offset faceted gem"
288 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
290 segments
= IntProperty(name
="Segments",
291 description
="Longitudial segmentation",
295 pavilion_radius
= FloatProperty(name
="Radius",
296 description
="Radius of the gem",
300 crown_radius
= FloatProperty(name
="Table Radius",
301 description
="Radius of the table(top)",
305 crown_height
= FloatProperty(name
="Table height",
306 description
="Height of the top half",
310 pavilion_height
= FloatProperty(name
="Pavilion height",
311 description
="Height of bottom half",
316 def execute(self
, context
):
319 verts
, faces
= add_gem(
320 self
.pavilion_radius
,
323 self
.pavilion_height
,
326 obj
= create_mesh_object(context
, verts
, [], faces
, "Gem")