FBX: reformat props.
[blender-addons.git] / add_mesh_extra_objects / add_mesh_gemstones.py
blobd0e7a37533e53c88dc7e9412d78c2acf25833fe8
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 #####
18 '''
19 bl_info = {
20 "name": "Gemstones",
21 "author": "Pontiac, Fourmadmen, Dreampainter",
22 "version": (0, 4),
23 "blender": (2, 57, 0),
24 "location": "View3D > Add > Mesh > Gemstones",
25 "description": "Adds various gemstone (Diamond & Gem) meshes.",
26 "warning": "",
27 "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"
28 "Scripts/Add_Mesh/Add_Gemstones",
29 "category": "Add Mesh",
31 '''
32 import bpy
33 from mathutils import *
34 from math 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):
43 # Create new mesh
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.
50 mesh.update()
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):
70 faces = []
72 if not vertIdx1 or not vertIdx2:
73 return None
75 if len(vertIdx1) < 2 and len(vertIdx2) < 2:
76 return None
78 fan = False
79 if (len(vertIdx1) != len(vertIdx2)):
80 if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
81 fan = True
82 else:
83 return None
85 total = len(vertIdx2)
87 if closed:
88 # Bridge the start with the end.
89 if flipped:
90 face = [
91 vertIdx1[0],
92 vertIdx2[0],
93 vertIdx2[total - 1]]
94 if not fan:
95 face.append(vertIdx1[total - 1])
96 faces.append(face)
98 else:
99 face = [vertIdx2[0], vertIdx1[0]]
100 if not fan:
101 face.append(vertIdx1[total - 1])
102 face.append(vertIdx2[total - 1])
103 faces.append(face)
105 # Bridge the rest of the faces.
106 for num in range(total - 1):
107 if flipped:
108 if fan:
109 face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
110 else:
111 face = [vertIdx2[num], vertIdx1[num],
112 vertIdx1[num + 1], vertIdx2[num + 1]]
113 faces.append(face)
114 else:
115 if fan:
116 face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
117 else:
118 face = [vertIdx1[num], vertIdx2[num],
119 vertIdx2[num + 1], vertIdx1[num + 1]]
120 faces.append(face)
122 return faces
125 # @todo Clean up vertex&face creation process a bit.
126 def add_gem(r1, r2, seg, h1, h2):
128 r1 = pavilion radius
129 r2 = crown radius
130 seg = number of segments
131 h1 = pavilion height
132 h2 = crown height
133 Generates the vertices and faces of the gem
136 verts = []
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
146 # Tip
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)))
154 edgeloop_flat = []
155 for i in range(seg):
156 s1 = sin(i * a)
157 s2 = sin(offset + i * a)
158 c1 = cos(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
167 faces = []
169 for index in range(seg):
170 i = index * 4
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)
182 return verts, faces
185 def add_diamond(segments, girdle_radius, table_radius,
186 crown_height, pavilion_height):
188 PI_2 = pi * 2.0
189 z_axis = (0.0, 0.0, -1.0)
191 verts = []
192 faces = []
194 height_flat = crown_height
195 height_middle = 0.0
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)))
202 # Tip
203 vert_tip = len(verts)
204 verts.append(Vector((0.0, 0.0, height_tip)))
206 verts_flat = []
207 verts_girdle = []
209 for index in range(segments):
210 quat = Quaternion(z_axis, (index / segments) * PI_2)
212 # angle = PI_2 * index / segments # UNUSED
214 # Row for flat side
215 verts_flat.append(len(verts))
216 vec = quat * Vector((table_radius, 0.0, height_flat))
217 verts.append(vec)
219 # Row for the middle/girdle
220 verts_girdle.append(len(verts))
221 vec = quat * Vector((girdle_radius, 0.0, height_middle))
222 verts.append(vec)
224 # Flat face
225 faces_flat = createFaces([vert_flat], verts_flat, closed=True,
226 flipped=True)
227 # Side face
228 faces_side = createFaces(verts_girdle, verts_flat, closed=True)
229 # Tip faces
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)
236 return verts, faces
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",
247 min=3,
248 max=256,
249 default=32)
250 girdle_radius = FloatProperty(name="Girdle Radius",
251 description="Girdle radius of the diamond",
252 min=0.01,
253 max=9999.0,
254 default=1.0)
255 table_radius = FloatProperty(name="Table Radius",
256 description="Girdle radius of the diamond",
257 min=0.01,
258 max=9999.0,
259 default=0.6)
260 crown_height = FloatProperty(name="Crown Height",
261 description="Crown height of the diamond",
262 min=0.01,
263 max=9999.0,
264 default=0.35)
265 pavilion_height = FloatProperty(name="Pavilion Height",
266 description="Pavilion height of the diamond",
267 min=0.01,
268 max=9999.0,
269 default=0.8)
271 def execute(self, context):
272 verts, faces = add_diamond(self.segments,
273 self.girdle_radius,
274 self.table_radius,
275 self.crown_height,
276 self.pavilion_height)
278 obj = create_mesh_object(context, verts, [], faces, "Diamond")
280 return {'FINISHED'}
283 class AddGem(bpy.types.Operator):
284 """Add a diamond gem"""
285 bl_idname = "mesh.primitive_gem_add"
286 bl_label = "Add Gem"
287 bl_description = "Create an offset faceted gem"
288 bl_options = {'REGISTER', 'UNDO', 'PRESET'}
290 segments = IntProperty(name="Segments",
291 description="Longitudial segmentation",
292 min=3,
293 max=265,
294 default=8,)
295 pavilion_radius = FloatProperty(name="Radius",
296 description="Radius of the gem",
297 min=0.01,
298 max=9999.0,
299 default=1.0)
300 crown_radius = FloatProperty(name="Table Radius",
301 description="Radius of the table(top)",
302 min=0.01,
303 max=9999.0,
304 default=0.6)
305 crown_height = FloatProperty(name="Table height",
306 description="Height of the top half",
307 min=0.01,
308 max=9999.0,
309 default=0.35)
310 pavilion_height = FloatProperty(name="Pavilion height",
311 description="Height of bottom half",
312 min=0.01,
313 max=9999.0,
314 default=0.8)
316 def execute(self, context):
318 # create mesh
319 verts, faces = add_gem(
320 self.pavilion_radius,
321 self.crown_radius,
322 self.segments,
323 self.pavilion_height,
324 self.crown_height)
326 obj = create_mesh_object(context, verts, [], faces, "Gem")
328 return {'FINISHED'}