3D Workspace
Home
Assets
Affiliate Program
Sign up/Log in
?
Upgrade
DCC Bridge
3D Creation Made Simple
Text & Image to 3D Model in seconds
One-Click Texturing & Smart Detail Editing
Free Credits Monthly
Start Free
Anonymous1765799492
12-15 11:55
Model Name
hand grenade 3d model
Tags
weapon
rendering
realistic
Input
Prompt
import bpy import math # ========================= # ROKLESS GRENADE CONTAINER (COSMETIC) - BODY ONLY (mm) # ========================= # ---- Scene Units (mm) ---- def set_units_mm(): sc = bpy.context.scene sc.unit_settings.system = 'METRIC' sc.unit_settings.scale_length = 0.001 # 1 Blender unit = 1mm sc.unit_settings.length_unit = 'MILLIMETERS' def clear_scene(): bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete(use_global=False) def shade_smooth(obj): bpy.context.view_layer.objects.active = obj obj.select_set(True) bpy.ops.object.shade_smooth() obj.select_set(False) def add_material(name, rgba, rough=0.65): mat = bpy.data.materials.new(name=name) mat.use_nodes = True bsdf = mat.node_tree.nodes.get("Principled BSDF") bsdf.inputs["Base Color"].default_value = rgba bsdf.inputs["Roughness"].default_value = rough return mat # ========================= # PARAMETERS (mm) # ========================= OUTER_HEIGHT = 115.0 OUTER_DIAMETER_MAX = 62.0 OUTER_DIAMETER_BOTTOM = 56.0 TOP_DIAMETER = 38.0 BASE_SECTION_HEIGHT = 18.0 BASE_LIP_HEIGHT = 2.5 BASE_GAP = 0.4 RING_COUNT = 6 RING_ZONE_Z0 = 22.0 RING_ZONE_Z1 = 98.0 GROOVE_DEPTH = 1.2 GROOVE_MAJOR_RADIUS_FACTOR = 0.98 # how close torus sits to body radius VERTICAL_GROOVE_COUNT = 4 VERTICAL_GROOVE_DEPTH = 1.0 BEVEL_RADIUS = 0.8 SUBDIV_LEVEL = 2 # Decorative Lever (non-functional) LEVER_LENGTH = 62.0 LEVER_WIDTH = 10.0 LEVER_THICKNESS = 3.5 LEVER_OFFSET_Z = OUTER_HEIGHT - 10.0 # Top opening visual (not mechanism) OPENING_DIAMETER = 18.0 TOP_CAP_HEIGHT = 20.0 TOP_SEAM_GAP = 0.4 # ========================= # BODY BUILD # ========================= def create_main_body(): # Start with a cylinder then sculpt the silhouette bpy.ops.mesh.primitive_cylinder_add( vertices=64, radius=OUTER_DIAMETER_MAX/2.0, depth=OUTER_HEIGHT, location=(0, 0, OUTER_HEIGHT/2.0) ) body = bpy.context.object body.name = "Grenade_Body" # Enter edit mode to taper bottom to OUTER_DIAMETER_BOTTOM bpy.ops.object.mode_set(mode='OBJECT') me = body.data z_min = min(v.co.z for v in me.vertices) # select bottom verts for v in me.vertices: v.select = abs(v.co.z - z_min) < 1e-6 bpy.ops.object.mode_set(mode='EDIT') scale = OUTER_DIAMETER_BOTTOM / OUTER_DIAMETER_MAX bpy.ops.transform.resize(value=(scale, scale, 1.0)) bpy.ops.object.mode_set(mode='OBJECT') # Subdivision for smooth cosmetic feel sub = body.modifiers.new(name="Subdiv", type='SUBSURF') sub.levels = SUBDIV_LEVEL sub.render_levels = SUBDIV_LEVEL # Bevel to control highlights bev = body.modifiers.new(name="Bevel", type='BEVEL') bev.width = BEVEL_RADIUS bev.segments = 2 bev.limit_method = 'ANGLE' bev.angle_limit = math.radians(45) return body def boolean_grooves_horizontal(body): """Cut shallow horizontal grooves using torus cutters.""" cutters = [] radius = OUTER_DIAMETER_MAX/2.0 if RING_COUNT <= 1: return for i in range(RING_COUNT): t = i / (RING_COUNT - 1) z = RING_ZONE_Z0 + (RING_ZONE_Z1 - RING_ZONE_Z0) * t bpy.ops.mesh.primitive_torus_add( major_radius=radius * GROOVE_MAJOR_RADIUS_FACTOR, minor_radius=GROOVE_DEPTH, major_segments=48, minor_segments=12, location=(0, 0, z), rotation=(math.radians(90), 0, 0) ) tor = bpy.context.object tor.name = f"Cut_HGroove_{i+1}" cutters.append(tor) # join cutters bpy.ops.object.select_all(action='DESELECT') for c in cutters: c.select_set(True) bpy.context.view_layer.objects.active = cutters[0] bpy.ops.object.join() cutter = bpy.context.object cutter.name = "Cutter_HGrooves" # boolean bpy.ops.object.select_all(action='DESELECT') body.select_set(True) bpy.context.view_layer.objects.active = body mod = body.modifiers.new(name="Bool_HGrooves", type='BOOLEAN') mod.operation = 'DIFFERENCE' mod.solver = 'EXACT' mod.object = cutter bpy.ops.object.modifier_apply(modifier=mod.name) # delete cutter bpy.ops.object.select_all(action='DESELECT') cutter.select_set(True) bpy.ops.object.delete() def boolean_grooves_vertical(body): """Cut vertical panel grooves using thin box cutters rotated around Z.""" if VERTICAL_GROOVE_COUNT <= 0: return cutters = [] radius = OUTER_DIAMETER_MAX/2.0 groove_depth = VERTICAL_GROOVE_DEPTH # cutter size: thin box that intersects body cut_w = groove_depth * 2.5 cut_d = radius * 2.2 cut_h = OUTER_HEIGHT * 0.75 for i in range(VERTICAL_GROOVE_COUNT): ang = (2*math.pi / VERTICAL_GROOVE_COUNT) * i bpy.ops.mesh.primitive_cube_add(size=1, location=(0, 0, OUTER_HEIGHT*0.55)) c = bpy.context.object c.name = f"Cut_VGroove_{i+1}" c.scale = (cut_w, cut_d, cut_h/2.0) # rotate around Z and offset slightly to cut surface c.rotation_euler = (0, 0, ang) # push outward so it intersects the shell surface area c.location.x = math.cos(ang) * (radius * 0.65) c.location.y = math.sin(ang) * (radius * 0.65) cutters.append(c) # join cutters bpy.ops.object.select_all(action='DESELECT') for c in cutters: c.select_set(True) bpy.context.view_layer.objects.active = cutters[0] bpy.ops.object.join() cutter = bpy.context.object cutter.name = "Cutter_VGrooves" # boolean bpy.ops.object.select_all(action='DESELECT') body.select_set(True) bpy.context.view_layer.objects.active = body mod = body.modifiers.new(name="Bool_VGrooves", type='BOOLEAN') mod.operation = 'DIFFERENCE' mod.solver = 'EXACT' mod.object = cutter bpy.ops.object.modifier_apply(modifier=mod.name) # delete cutter bpy.ops.object.select_all(action='DESELECT') cutter.select_set(True) bpy.ops.object.delete() def create_bottom_base(): # Base cylinder slightly smaller to show seam base_h = BASE_SECTION_HEIGHT base_r = OUTER_DIAMETER_BOTTOM/2.0 bpy.ops.mesh.primitive_cylinder_add( vertices=64, radius=base_r, depth=base_h, location=(0, 0, base_h/2.0) ) base = bpy.context.object base.name = "Bottom_Twist_Base" # small lip for grip bpy.ops.mesh.primitive_cylinder_add( vertices=64, radius=base_r + 0.8, depth=BASE_LIP_HEIGHT, location=(0, 0, BASE_LIP_HEIGHT/2.0 + (base_h - BASE_LIP_HEIGHT)) ) lip = bpy.context.object lip.name = "Bottom_Base_Lip" # join base + lip bpy.ops.object.select_all(action='DESELECT') base.select_set(True) lip.select_set(True) bpy.context.view_layer.objects.active = base bpy.ops.object.join() # bevel & smooth bev = base.modifiers.new(name="Bevel", type='BEVEL') bev.width = 0.8 bev.segments = 2 bev.limit_method = 'ANGLE' bev.angle_limit = math.radians(45) return base def create_top_housing(): # top housing cylinder r = TOP_DIAMETER/2.0 h = TOP_CAP_HEIGHT bpy.ops.mesh.primitive_cylinder_add( vertices=64, radius=r, depth=h, location=(0, 0, OUTER_HEIGHT - h/2.0 + TOP_SEAM_GAP) ) top = bpy.context.object top.name = "Top_Housing" # opening visual (a shallow inset) bpy.ops.mesh.primitive_cylinder_add( vertices=64, radius=OPENING_DIAMETER/2.0, depth=4.0, location=(0, 0, OUTER_HEIGHT + TOP_SEAM_GAP - 2.0) ) opening = bpy.context.object opening.name = "Top_Opening_Inset" # boolean inset bpy.ops.object.select_all(action='DESELECT') top.select_set(True) bpy.context.view_layer.objects.active = top mod = top.modifiers.new(name="Bool_Opening", type='BOOLEAN') mod.operation = 'DIFFERENCE' mod.solver = 'EXACT' mod.object = opening bpy.ops.object.modifier_apply(modifier=mod.name) # delete cutter bpy.ops.object.select_all(action='DESELECT') opening.select_set(True) bpy.ops.object.delete() # bevel bev = top.modifiers.new(name="Bevel", type='BEVEL') bev.width = 0.8 bev.segments = 2 bev.limit_method = 'ANGLE' bev.angle_limit = math.radians(45) return top def create_decorative_lever(): # Simple lever as a beveled cube, non-functional bpy.ops.mesh.primitive_cube_add(size=1, location=(0, 0, LEVER_OFFSET_Z)) lever = bpy.context.object lever.name = "Decorative_Lever" lever.scale = (LEVER_LENGTH/2.0, LEVER_WIDTH/2.0, LEVER_THICKNESS/2.0) # Move to side like reference (hangs down) lever.location.x = (OUTER_DIAMETER_MAX/2.0) + (LEVER_WIDTH/2.0) + 2.0 lever.location.y = 0.0 lever.location.z = OUTER_HEIGHT - 12.0 # Tilt slightly backward lever.rotation_euler = (math.radians(0), math.radians(0), math.radians(0)) bev = lever.modifiers.new(name="Bevel", type='BEVEL') bev.width = 1.2 bev.segments = 3 bpy.ops.object.modifier_apply(modifier=bev.name) return lever # ========================= # RUN # ========================= clear_scene() set_units_mm() # materials mat_black = add_material("Matte_Black", (0.02, 0.02, 0.02, 1.0), rough=0.65) mat_red = add_material("Brand_Red", (0.8, 0.02, 0.02, 1.0), rough=0.45) # body body = create_main_body() boolean_grooves_horizontal(body) boolean_grooves_vertical(body) # apply modifiers after booleans for stability (optional) # If you want editable, comment out these applies and keep modifiers live. for m in list(body.modifiers): if m.type in {'SUBSURF', 'BEVEL'}: bpy.context.view_layer.objects.active = body bpy.ops.object.modifier_apply(modifier=m.name) # base & top base = create_bottom_base() top = create_top_housing() lever = create_decorative_lever() # parent for easy movement base.parent = body top.parent = body lever.parent = top # lever attached to top housing (decorative) # assign materials body.data.materials.append(mat_black) base.data.materials.append(mat_black) top.data.materials.append(mat_black) lever.data.materials.append(mat_black) # change to mat_red if you want red lever # smoothing shade_smooth(body) shade_smooth(base) shade_smooth(top) shade_smooth(lever) # quick light/camera (optional) bpy.ops.object.light_add(type='AREA', location=(180, -180, 180)) light = bpy.context.object light.data.energy = 2000 light.data.size = 250 bpy.ops.object.camera_add(location=(220, -220, 140), rotation=(math.radians(65), 0, math.radians(45))) bpy.context.scene.camera = bpy.context.object print("DONE: Body-only cosmetic container created (outer shell + base + top + decorative lever).")
Detailed Info
Related Models
Enter invite code
Enter invite code to get credits!