Skip to main content

Frost Flower

OCCT category icon with a stylized logo representation

❄️ Create a delicate 3D printable snowflake using interpolated curves and 12-fold rotational symmetry! This tutorial demonstrates how smooth B-spline curves and offset operations can create organic, nature-inspired shapes.

The algorithm:

  1. Define branch points - a simple zigzag pattern for one branch
  2. Interpolate a smooth curve - creates flowing organic lines
  3. Rotate 180° the branch to create bilateral symmetry
  4. Combine wires into a single branch pair
  5. Create outer and inner offsets - hollow structure for the branch
  6. Create face from wires - outer and reversed inner wire form a hollow face
  7. Rotate copies at 30° intervals (0°, 30°, 60°, 90°, 120°, 150°) for 12-fold symmetry
  8. Boolean union to merge all faces into one shape
  9. Extrude the unified face to create a 3D solid
Bitbybit Platform

Snowflake ornament

rete logoRete
Script Source (rete)
{
"id": "rete-v2-json",
"nodes": {
"10790118cdf49ef5": {
"id": "10790118cdf49ef5",
"name": "bitbybit.lists.createList",
"customName": "branch points",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "b2c3d4e5f6a7b8c9",
"output": "result",
"data": {}
},
{
"node": "c3d4e5f6a7b8c9d0",
"output": "result",
"data": {}
},
{
"node": "d4e5f6a7b8c9d0e1",
"output": "result",
"data": {}
},
{
"node": "e5f6a7b8c9d0e1f2",
"output": "result",
"data": {}
},
{
"node": "f6a7b8c9d0e1f2a3",
"output": "result",
"data": {}
}
]
}
},
"position": [
-19.189718877162463,
-112.3488571445287
]
},
"b2c3d4e5f6a7b8c9": {
"id": "b2c3d4e5f6a7b8c9",
"name": "bitbybit.vector.vectorXYZ",
"customName": "p1 center",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 0,
"z": 0
},
"inputs": {},
"position": [
-500,
-829.3909592519012
]
},
"c3d4e5f6a7b8c9d0": {
"id": "c3d4e5f6a7b8c9d0",
"name": "bitbybit.vector.vectorXYZ",
"customName": "p2",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0.3,
"y": 1.5,
"z": 0
},
"inputs": {
"y": {
"connections": [
{
"node": "a7b8c9d0e1f2a3b4",
"output": "result",
"data": {}
}
]
}
},
"position": [
-502.9649600050009,
-432.45784415768435
]
},
"d4e5f6a7b8c9d0e1": {
"id": "d4e5f6a7b8c9d0e1",
"name": "bitbybit.vector.vectorXYZ",
"customName": "p3",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": -0.2,
"y": 2.5,
"z": 0
},
"inputs": {
"y": {
"connections": [
{
"node": "b8c9d0e1f2a3b4c5",
"output": "result",
"data": {}
}
]
}
},
"position": [
-500.3648459590738,
-94.84724933772955
]
},
"e5f6a7b8c9d0e1f2": {
"id": "e5f6a7b8c9d0e1f2",
"name": "bitbybit.vector.vectorXYZ",
"customName": "p4",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0.4,
"y": 3.5,
"z": 0
},
"inputs": {
"y": {
"connections": [
{
"node": "c9d0e1f2a3b4c5d6",
"output": "result",
"data": {}
}
]
}
},
"position": [
-499.33146676313015,
241.20028778349584
]
},
"f6a7b8c9d0e1f2a3": {
"id": "f6a7b8c9d0e1f2a3",
"name": "bitbybit.vector.vectorXYZ",
"customName": "p5 tip",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 4,
"z": 0
},
"inputs": {
"y": {
"connections": [
{
"node": "d0e1f2a3b4c5d6e7",
"output": "result",
"data": {}
}
]
}
},
"position": [
-501.04900375684275,
583.0171073307207
]
},
"a7b8c9d0e1f2a3b4": {
"id": "a7b8c9d0e1f2a3b4",
"name": "bitbybit.math.twoNrOperation",
"customName": "scale p2",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"first": 1.5,
"second": 1,
"operation": "multiply"
},
"inputs": {
"second": {
"connections": [
{
"node": "1e850d8dc20caff8",
"output": "result",
"data": {}
}
]
}
},
"position": [
-900.6044812680875,
-394.05341251949295
]
},
"b8c9d0e1f2a3b4c5": {
"id": "b8c9d0e1f2a3b4c5",
"name": "bitbybit.math.twoNrOperation",
"customName": "scale p3",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"first": 2.5,
"second": 1,
"operation": "multiply"
},
"inputs": {
"second": {
"connections": [
{
"node": "1e850d8dc20caff8",
"output": "result",
"data": {}
}
]
}
},
"position": [
-901.6946134678033,
-57.86819114370999
]
},
"c9d0e1f2a3b4c5d6": {
"id": "c9d0e1f2a3b4c5d6",
"name": "bitbybit.math.twoNrOperation",
"customName": "scale p4",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"first": 3.5,
"second": 1,
"operation": "multiply"
},
"inputs": {
"second": {
"connections": [
{
"node": "1e850d8dc20caff8",
"output": "result",
"data": {}
}
]
}
},
"position": [
-901.7349754193569,
279.76755591216505
]
},
"d0e1f2a3b4c5d6e7": {
"id": "d0e1f2a3b4c5d6e7",
"name": "bitbybit.math.twoNrOperation",
"customName": "scale p5",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"first": 4,
"second": 1,
"operation": "multiply"
},
"inputs": {
"second": {
"connections": [
{
"node": "1e850d8dc20caff8",
"output": "result",
"data": {}
}
]
}
},
"position": [
-904.1493607486843,
622.9298609814933
]
},
"1e850d8dc20caff8": {
"id": "1e850d8dc20caff8",
"name": "bitbybit.math.numberSlider",
"customName": "size",
"data": {
"options": {
"min": 0.5,
"max": 2,
"step": 0.1,
"width": 350,
"updateOnDrag": false
},
"number": 0.8
},
"inputs": {},
"position": [
-1606.0985639130654,
8.059750241166496
]
},
"f2a3b4c5d6e7f8a9": {
"id": "f2a3b4c5d6e7f8a9",
"name": "bitbybit.occt.shapes.wire.interpolatePoints",
"customName": "branch wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"periodic": false,
"tolerance": 0.00001
},
"inputs": {
"points": {
"connections": [
{
"node": "10790118cdf49ef5",
"output": "list",
"data": {}
}
]
}
},
"position": [
350,
-150
]
},
"ffe20eaeb32b3bf3": {
"id": "ffe20eaeb32b3bf3",
"name": "bitbybit.lists.createList",
"customName": "branch pair",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "f2a3b4c5d6e7f8a9",
"output": "result",
"data": {}
},
{
"node": "f36e80a97decb81f",
"output": "result",
"data": {}
}
]
}
},
"position": [
1291.4100259202773,
-283.2006960053717
]
},
"c5d6e7f8a9b0c1d2": {
"id": "c5d6e7f8a9b0c1d2",
"name": "bitbybit.occt.shapes.wire.combineEdgesAndWiresIntoAWire",
"customName": "combine pair",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shapes": {
"connections": [
{
"node": "ffe20eaeb32b3bf3",
"output": "list",
"data": {}
}
]
}
},
"position": [
1668.199732984824,
-318.4404083821864
]
},
"d8e9f0a1b2c3d4e5": {
"id": "d8e9f0a1b2c3d4e5",
"name": "bitbybit.babylon.material.pbrMetallicRoughness.create",
"customName": "ice material",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"name": "Ice Material",
"baseColor": "#aed6f1",
"emissiveColor": "#5dade2",
"metallic": 0.1,
"roughness": 0.3,
"alpha": 1,
"backFaceCulling": false,
"zOffset": 2
},
"inputs": {},
"position": [
6177.793312393963,
658.0492290944441
]
},
"f36e80a97decb81f": {
"id": "f36e80a97decb81f",
"name": "bitbybit.occt.transforms.rotate",
"customName": "rotate",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"axis": [
0,
0,
1
],
"angle": 180
},
"inputs": {
"shape": {
"connections": [
{
"node": "f2a3b4c5d6e7f8a9",
"output": "result",
"data": {}
}
]
},
"axis": {
"connections": [
{
"node": "c618b8b468644f69",
"output": "result",
"data": {}
}
]
}
},
"position": [
814.9207572250788,
13.526956147226372
]
},
"c618b8b468644f69": {
"id": "c618b8b468644f69",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 0,
"z": 1
},
"inputs": {},
"position": [
354.34131852780666,
247.436177661857
]
},
"aafc1a1cc4f05cc9": {
"id": "aafc1a1cc4f05cc9",
"name": "bitbybit.vector.span",
"customName": "span",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"step": 30,
"min": 0,
"max": 150
},
"inputs": {},
"position": [
3994.6539471789133,
542.1165752364911
]
},
"c4cc647386d496dc": {
"id": "c4cc647386d496dc",
"name": "bitbybit.occt.transforms.rotate",
"customName": "rotate",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"axis": [
0,
0,
1
],
"angle": 0
},
"inputs": {
"axis": {
"connections": [
{
"node": "2a6358261ce5c0ec",
"output": "result",
"data": {}
}
]
},
"angle": {
"connections": [
{
"node": "a96ec7afaa952e7e",
"output": "result",
"data": {}
}
]
},
"shape": {
"connections": [
{
"node": "4fc11aa9465e7979",
"output": "result",
"data": {}
}
]
}
},
"position": [
4835.030692763062,
77.89488642183412
]
},
"2a6358261ce5c0ec": {
"id": "2a6358261ce5c0ec",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 0,
"z": 1
},
"inputs": {},
"position": [
3992.159011248188,
203.70760024122325
]
},
"a96ec7afaa952e7e": {
"id": "a96ec7afaa952e7e",
"name": "bitbybit.lists.flatten",
"customName": "flatten",
"data": {
"nrLevels": 1
},
"inputs": {
"list": {
"connections": [
{
"node": "aafc1a1cc4f05cc9",
"output": "result",
"data": {}
}
]
}
},
"position": [
4380.026815245925,
577.7207099160814
]
},
"6c9ae97ce51ddd9a": {
"id": "6c9ae97ce51ddd9a",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "c4cc647386d496dc",
"output": "result",
"data": {}
}
]
}
},
"position": [
5267.154058434832,
118.35312435492582
]
},
"e59d5309cfd324a3": {
"id": "e59d5309cfd324a3",
"name": "bitbybit.occt.operations.offset",
"customName": "offset",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"distance": 0.2,
"tolerance": 0.1
},
"inputs": {
"shape": {
"connections": [
{
"node": "c5d6e7f8a9b0c1d2",
"output": "result",
"data": {}
}
]
}
},
"position": [
2233.846702112692,
-106.24786077242689
]
},
"9e6506e07218e5a3": {
"id": "9e6506e07218e5a3",
"name": "bitbybit.occt.booleans.union",
"customName": "union",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"keepEdges": false
},
"inputs": {
"shapes": {
"connections": [
{
"node": "6c9ae97ce51ddd9a",
"output": "list",
"data": {}
}
]
}
},
"position": [
5643.297343841302,
78.95068988656377
]
},
"07387c14a53ebb24": {
"id": "07387c14a53ebb24",
"name": "bitbybit.occt.operations.offset",
"customName": "offset",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"distance": 0.4,
"tolerance": 0.1
},
"inputs": {
"shape": {
"connections": [
{
"node": "c5d6e7f8a9b0c1d2",
"output": "result",
"data": {}
}
]
}
},
"position": [
2234.3856310618603,
-562.0330783760298
]
},
"4fc11aa9465e7979": {
"id": "4fc11aa9465e7979",
"name": "bitbybit.occt.shapes.face.createFaceFromWires",
"customName": "face from wires",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"planar": true
},
"inputs": {
"shapes": {
"connections": [
{
"node": "5de1b098fce6dfcf",
"output": "list",
"data": {}
}
]
}
},
"position": [
3995.4108912768634,
-227.03899956655695
]
},
"5b529ffd1e568e39": {
"id": "5b529ffd1e568e39",
"name": "bitbybit.occt.shapes.wire.reversedWire",
"customName": "reversed wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shape": {
"connections": [
{
"node": "e59d5309cfd324a3",
"output": "result",
"data": {}
}
]
}
},
"position": [
2780.21747433819,
-111.00950762810912
]
},
"5de1b098fce6dfcf": {
"id": "5de1b098fce6dfcf",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "07387c14a53ebb24",
"output": "result",
"data": {}
},
{
"node": "5b529ffd1e568e39",
"output": "result",
"data": {}
}
]
}
},
"position": [
3414.7858123370843,
-198.74496479338936
]
},
"6230b98666b9d6aa": {
"id": "6230b98666b9d6aa",
"name": "bitbybit.occt.operations.extrude",
"customName": "extrude",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"direction": [
0,
1,
0
]
},
"inputs": {
"shape": {
"connections": [
{
"node": "9e6506e07218e5a3",
"output": "result",
"data": {}
}
]
},
"direction": {
"connections": [
{
"node": "c428418880b0f286",
"output": "result",
"data": {}
}
]
}
},
"position": [
6562.383745239804,
310.6838197635185
]
},
"c428418880b0f286": {
"id": "c428418880b0f286",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 0,
"z": 0.2
},
"inputs": {},
"position": [
5641.977218824047,
399.4563808447789
]
},
"d70c1db8bd4f5bda": {
"id": "d70c1db8bd4f5bda",
"name": "bitbybit.draw.drawAnyAsync",
"customName": "draw any async",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"entity": {
"connections": [
{
"node": "6230b98666b9d6aa",
"output": "result",
"data": {}
}
]
},
"options": {
"connections": [
{
"node": "f15d2dae484d0420",
"output": "result",
"data": {}
}
]
}
},
"position": [
7018.838053887316,
449.91706231399286
]
},
"f15d2dae484d0420": {
"id": "f15d2dae484d0420",
"name": "bitbybit.draw.optionsOcctShapeMaterial",
"customName": "options occt shape material",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"precision": 0.01,
"drawEdges": false,
"edgeColour": "#ffffff",
"edgeWidth": 2
},
"inputs": {
"faceMaterial": {
"connections": [
{
"node": "d8e9f0a1b2c3d4e5",
"output": "result",
"data": {}
}
]
}
},
"position": [
6565.390708494095,
623.8495899202425
]
},
"3686b8996a912c6e": {
"id": "3686b8996a912c6e",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "d70c1db8bd4f5bda",
"output": "result",
"data": {}
}
]
}
},
"position": [
7435.644536917809,
485.5881162747557
]
},
"68f7335e5351419f": {
"id": "68f7335e5351419f",
"name": "bitbybit.advanced.navigation.zoomOn",
"customName": "zoom on",
"async": true,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"meshes": [],
"includeChildren": true,
"animationSpeed": 0.8,
"offset": 0,
"doNotUpdateMaxZ": true
},
"inputs": {
"meshes": {
"connections": [
{
"node": "3686b8996a912c6e",
"output": "list",
"data": {}
}
]
}
},
"position": [
7819.690818307023,
444.7169923460303
]
}
}
}

How It Works

Branch Design

Each branch is defined by 5 points creating a gentle zigzag pattern:

  • Center point at origin (0, 0, 0)
  • Alternating left/right offsets as Y increases (0.3, -0.2, 0.4...)
  • Tip point centered for a clean finish (0, 4*size, 0)

The interpolatePoints operation creates a smooth B-spline curve through these points.

Bilateral Symmetry

The branch wire is rotated 180° around the Z-axis, creating a mirrored copy. Both wires are then combined into a single wire, forming the classic "double-branched" snowflake arm look.

Creating Hollow Structure

Instead of solid geometry, this creates a delicate hollow branch:

  1. Outer offset: The combined wire is offset outward by 0.4 units
  2. Inner offset: The combined wire is offset outward by 0.2 units, then reversed (direction flipped)
  3. Face from wires: The outer and reversed inner wire create a face with a hollow center - like a ribbon

12-Fold Symmetry

The hollow face is rotated at 30° intervals (0°, 30°, 60°, 90°, 120°, 150°), creating 6 rotated copies plus the original. This creates a complex 12-branch pattern when the bilateral branches overlap, giving the appearance of intricate snowflake geometry.

Final 3D Solid

  1. Boolean Union: All rotated faces are merged into a single flat 2D shape
  2. Extrude: The unified shape is extruded 0.2 units along the Z-axis to create the final 3D printable solid

Customization ❄️

  • Size slider: Scale the entire snowflake (controls the Y coordinates of branch points)
  • Offset distances: Adjust the 0.4 and 0.2 values to change the branch thickness
  • Edit point positions: Modify the zigzag pattern for different branch styles
  • Rotation angles: Change the 30° step to create different symmetries (try 60° for 6-fold, or 45° for 8-fold)

3D Printing Tips

  • The offset technique creates thin, elegant branches - great for decorative ornaments
  • The boolean union creates a single manifold mesh - no intersecting geometry!
  • 0.1-0.15mm layer height for fine detail
  • 10-15% infill (it's mostly thin walls anyway)
  • White or translucent filament for icy look
  • Consider adding a small cylinder at the center for a hanging hole

Happy holidays! ❄️