Frozen Snowflake
❄️ Create an intricate frozen snowflake ornament using zigzag patterns between hexagons, advanced lofting techniques, and selective face extrusion! This tutorial demonstrates how to build complex organic shapes by combining multiple loft surfaces and extracting specific faces for detailed geometry.
The algorithm:
- Create hexagon wire pairs - two sets of concentric hexagons at different heights (y = 0.2 and y = 0)
- Generate zigzag patterns - create jagged wires between inner/outer hexagon pairs
- Scale zigzag wires - scale one pattern by 3x and another by 6x to create depth variation
- Create three loft surfaces - connect zigzag wires with smooth lofted surfaces
- Extract faces from lofts - decompose each loft surface into individual faces
- Filter specific faces - select every 2nd face from each loft for the spikey effect
- Extrude filtered faces - push selected faces outward to create 3D protrusions
- Create two compounds - group extruded faces into two sets with different materials
- Render with metallic materials - apply blue and cyan PBR materials for an icy appearance
- Rete
- Blockly
- TypeScript
{
"id": "rete-v2-json",
"nodes": {
"e80cdb6f2a431e95": {
"id": "e80cdb6f2a431e95",
"name": "bitbybit.occt.shapes.wire.createNGonWire",
"customName": "ngon wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
],
"nrCorners": 6,
"radius": 3
},
"inputs": {
"center": {
"connections": [
{
"node": "1185f8d207a3f82e",
"output": "result",
"data": {}
}
]
}
},
"position": [
223.890625,
310.51953125
]
},
"b3883706e0c58c9f": {
"id": "b3883706e0c58c9f",
"name": "bitbybit.occt.shapes.wire.createNGonWire",
"customName": "ngon wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
],
"nrCorners": 6,
"radius": 3.7
},
"inputs": {
"center": {
"connections": [
{
"node": "ad48f922ed47c3e2",
"output": "result",
"data": {}
}
]
}
},
"position": [
222.859375,
708.19921875
]
},
"8075b1389d37c96a": {
"id": "8075b1389d37c96a",
"name": "bitbybit.occt.shapes.wire.createZigZagBetweenTwoWires",
"customName": "zig zag between two wires",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"nrZigZags": 4,
"inverse": false,
"divideByEqualDistance": false,
"zigZagsPerEdge": true
},
"inputs": {
"wire1": {
"connections": [
{
"node": "e80cdb6f2a431e95",
"output": "result",
"data": {}
}
]
},
"wire2": {
"connections": [
{
"node": "b3883706e0c58c9f",
"output": "result",
"data": {}
}
]
},
"nrZigZags": {
"connections": [
{
"node": "f67582e9ca42c8a6",
"output": "result",
"data": {}
}
]
}
},
"position": [
1143.6196063316072,
458.42883100162123
]
},
"5a78940ae3ae81bf": {
"id": "5a78940ae3ae81bf",
"name": "bitbybit.occt.transforms.scale",
"customName": "scale",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"factor": 3
},
"inputs": {
"shape": {
"connections": [
{
"node": "8075b1389d37c96a",
"output": "result",
"data": {}
}
]
}
},
"position": [
1678.3054790399979,
315.35343739190205
]
},
"ff1794dca2b99779": {
"id": "ff1794dca2b99779",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "9beb7dcb04fa6f42",
"output": "result",
"data": {}
},
{
"node": "8075b1389d37c96a",
"output": "result",
"data": {}
},
{
"node": "5a78940ae3ae81bf",
"output": "result",
"data": {}
},
{
"node": "7d877c9750dedefe",
"output": "result",
"data": {}
}
]
}
},
"position": [
2246.534379113014,
714.9278109363955
]
},
"b7378baa676913a9": {
"id": "b7378baa676913a9",
"name": "bitbybit.occt.shapes.face.getFaces",
"customName": "get faces",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shape": {
"connections": [
{
"node": "0c4159e76b58d633",
"output": "result",
"data": {}
}
]
}
},
"position": [
3072.7181735710606,
-107.3755019687693
]
},
"ad48f922ed47c3e2": {
"id": "ad48f922ed47c3e2",
"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.2,
"z": 0
},
"inputs": {},
"position": [
-162.37221187003445,
747.7184658018467
]
},
"1185f8d207a3f82e": {
"id": "1185f8d207a3f82e",
"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.2,
"z": 0
},
"inputs": {},
"position": [
-252.94258547497708,
311.90388593601784
]
},
"9dd41f3330ad0fff": {
"id": "9dd41f3330ad0fff",
"name": "bitbybit.occt.shapes.wire.createNGonWire",
"customName": "ngon wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
],
"nrCorners": 6,
"radius": 2
},
"inputs": {},
"position": [
235.2104156475863,
1116.294670621434
]
},
"9beb7dcb04fa6f42": {
"id": "9beb7dcb04fa6f42",
"name": "bitbybit.occt.shapes.wire.createZigZagBetweenTwoWires",
"customName": "zig zag between two wires",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"nrZigZags": 4,
"inverse": false,
"divideByEqualDistance": false,
"zigZagsPerEdge": true
},
"inputs": {
"wire1": {
"connections": [
{
"node": "9dd41f3330ad0fff",
"output": "result",
"data": {}
}
]
},
"wire2": {
"connections": [
{
"node": "de72420ac9cadfc7",
"output": "result",
"data": {}
}
]
},
"nrZigZags": {
"connections": [
{
"node": "f67582e9ca42c8a6",
"output": "result",
"data": {}
}
]
}
},
"position": [
1145.0759404649393,
948.6945784133306
]
},
"de72420ac9cadfc7": {
"id": "de72420ac9cadfc7",
"name": "bitbybit.occt.shapes.wire.createNGonWire",
"customName": "ngon wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
],
"nrCorners": 6,
"radius": 2.5
},
"inputs": {},
"position": [
234.75634001881605,
1540.2366231866586
]
},
"7d877c9750dedefe": {
"id": "7d877c9750dedefe",
"name": "bitbybit.occt.transforms.scale",
"customName": "scale",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"factor": 6
},
"inputs": {
"shape": {
"connections": [
{
"node": "9beb7dcb04fa6f42",
"output": "result",
"data": {}
}
]
}
},
"position": [
1694.2801683982289,
963.7382210340952
]
},
"0c4159e76b58d633": {
"id": "0c4159e76b58d633",
"name": "bitbybit.occt.operations.loftAdvanced",
"customName": "loft advanced",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"makeSolid": false,
"closed": false,
"periodic": false,
"straight": true,
"nrPeriodicSections": 10,
"useSmoothing": false,
"maxUDegree": 3,
"tolerance": 1e-7,
"parType": "approxCentripetal"
},
"inputs": {
"shapes": {
"connections": [
{
"node": "ff1794dca2b99779",
"output": "list",
"data": {}
}
]
}
},
"position": [
2708.447723102907,
-104.23992507282833
]
},
"849b48485b173809": {
"id": "849b48485b173809",
"name": "bitbybit.lists.removeNthItem",
"customName": "remove nth item",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"nth": 2,
"offset": 1,
"clone": true
},
"inputs": {
"list": {
"connections": [
{
"node": "b7378baa676913a9",
"output": "result",
"data": {}
}
]
}
},
"position": [
3447.7421219811436,
-108.69127893785503
]
},
"735e266df2ec4cf2": {
"id": "735e266df2ec4cf2",
"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": "04cdeb3875ee9a50",
"output": "result",
"data": {}
}
]
}
},
"position": [
4205.480366859519,
-114.5636121542974
]
},
"faa67c56c26b00eb": {
"id": "faa67c56c26b00eb",
"name": "bitbybit.occt.transforms.translate",
"customName": "translate",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"translation": [
0,
0,
0
]
},
"inputs": {
"shape": {
"connections": [
{
"node": "f2b028b1b290cc43",
"output": "result",
"data": {}
}
]
},
"translation": {
"connections": [
{
"node": "50b5bcf24783c2d0",
"output": "result",
"data": {}
}
]
}
},
"position": [
3678.039390687034,
841.1418147999855
]
},
"f2b028b1b290cc43": {
"id": "f2b028b1b290cc43",
"name": "bitbybit.occt.operations.loftAdvanced",
"customName": "loft advanced",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"makeSolid": false,
"closed": false,
"periodic": false,
"straight": true,
"nrPeriodicSections": 10,
"useSmoothing": false,
"maxUDegree": 3,
"tolerance": 1e-7,
"parType": "approxCentripetal"
},
"inputs": {
"shapes": {
"connections": [
{
"node": "fa37a24a00e9e039",
"output": "list",
"data": {}
}
]
}
},
"position": [
2708.0150410587903,
594.0054557471906
]
},
"50b5bcf24783c2d0": {
"id": "50b5bcf24783c2d0",
"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.3,
"z": 0
},
"inputs": {},
"position": [
3208.226060825467,
1001.0510781161385
]
},
"79f69312a516b971": {
"id": "79f69312a516b971",
"name": "bitbybit.occt.shapes.face.getFaces",
"customName": "get faces",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shape": {
"connections": [
{
"node": "faa67c56c26b00eb",
"output": "result",
"data": {}
}
]
}
},
"position": [
4092.994902626245,
907.0530327484794
]
},
"4695a402fdf6afd1": {
"id": "4695a402fdf6afd1",
"name": "bitbybit.lists.removeNthItem",
"customName": "remove nth item",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"nth": 2,
"offset": 0,
"clone": true
},
"inputs": {
"list": {
"connections": [
{
"node": "79f69312a516b971",
"output": "result",
"data": {}
},
{
"node": "ab072b3e3f027a3c",
"output": "result",
"data": {}
}
]
}
},
"position": [
4509.1843820805625,
1086.9670362367706
]
},
"b4138bacefb47375": {
"id": "b4138bacefb47375",
"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": {
"direction": {
"connections": [
{
"node": "b886129aad2ed5f6",
"output": "result",
"data": {}
}
]
},
"shape": {
"connections": [
{
"node": "66e90d08acfea68b",
"output": "result",
"data": {}
}
]
}
},
"position": [
5351.011354362222,
1203.707202747882
]
},
"66e90d08acfea68b": {
"id": "66e90d08acfea68b",
"name": "bitbybit.lists.flatten",
"customName": "flatten",
"data": {
"nrLevels": 1
},
"inputs": {
"list": {
"connections": [
{
"node": "4695a402fdf6afd1",
"output": "result",
"data": {}
}
]
}
},
"position": [
4915.336005115206,
1124.9584323931854
]
},
"b886129aad2ed5f6": {
"id": "b886129aad2ed5f6",
"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.3,
"z": 0
},
"inputs": {},
"position": [
4901.471907206477,
1372.2206605187941
]
},
"f67582e9ca42c8a6": {
"id": "f67582e9ca42c8a6",
"name": "bitbybit.math.numberSlider",
"customName": "number slider",
"data": {
"options": {
"min": 2,
"max": 5,
"step": 1,
"width": 350,
"updateOnDrag": false
},
"number": 5
},
"inputs": {},
"position": [
107.42804981132838,
-17.9636555623008
]
},
"fe6c5624fb703309": {
"id": "fe6c5624fb703309",
"name": "bitbybit.draw.drawAnyAsync",
"customName": "draw any async",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"options": {
"connections": [
{
"node": "d7263477e555ac17",
"output": "result",
"data": {}
}
]
},
"entity": {
"connections": [
{
"node": "362d9bf9cc3cb4d4",
"output": "result",
"data": {}
}
]
}
},
"position": [
5924.723449566433,
-111.53178530658113
]
},
"d7263477e555ac17": {
"id": "d7263477e555ac17",
"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": 4
},
"inputs": {
"faceMaterial": {
"connections": [
{
"node": "8e33f6727b0706bb",
"output": "result",
"data": {}
}
]
}
},
"position": [
5486.94470128069,
156.23056701043086
]
},
"8e33f6727b0706bb": {
"id": "8e33f6727b0706bb",
"name": "bitbybit.babylon.material.pbrMetallicRoughness.create",
"customName": "pbr metallic roughness",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"name": "Custom Material",
"baseColor": "#94b4ff",
"emissiveColor": "#000000",
"metallic": 0.8,
"roughness": 0.2,
"alpha": 1,
"backFaceCulling": false,
"zOffset": 2
},
"inputs": {},
"position": [
5118.512257722949,
194.58498038781784
]
},
"fa37a24a00e9e039": {
"id": "fa37a24a00e9e039",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "7d877c9750dedefe",
"output": "result",
"data": {}
},
{
"node": "5a78940ae3ae81bf",
"output": "result",
"data": {}
}
]
}
},
"position": [
2241.129104922553,
896.0115541514479
]
},
"7de1706cdd750bf5": {
"id": "7de1706cdd750bf5",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "9beb7dcb04fa6f42",
"output": "result",
"data": {}
},
{
"node": "8075b1389d37c96a",
"output": "result",
"data": {}
}
]
}
},
"position": [
2235.6843003071995,
1077.9650153204825
]
},
"cd345a51b893f357": {
"id": "cd345a51b893f357",
"name": "bitbybit.occt.operations.loftAdvanced",
"customName": "loft advanced",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"makeSolid": false,
"closed": false,
"periodic": false,
"straight": true,
"nrPeriodicSections": 10,
"useSmoothing": false,
"maxUDegree": 3,
"tolerance": 1e-7,
"parType": "approxCentripetal"
},
"inputs": {
"shapes": {
"connections": [
{
"node": "7de1706cdd750bf5",
"output": "list",
"data": {}
}
]
}
},
"position": [
2709.313991949925,
1302.9969569747925
]
},
"385f313eaddac4e2": {
"id": "385f313eaddac4e2",
"name": "bitbybit.occt.transforms.translate",
"customName": "translate",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"translation": [
0,
0,
0
]
},
"inputs": {
"shape": {
"connections": [
{
"node": "cd345a51b893f357",
"output": "result",
"data": {}
}
]
}
},
"position": [
3670.6457956495497,
1266.3298042429847
]
},
"ab072b3e3f027a3c": {
"id": "ab072b3e3f027a3c",
"name": "bitbybit.occt.shapes.face.getFaces",
"customName": "get faces",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shape": {
"connections": [
{
"node": "385f313eaddac4e2",
"output": "result",
"data": {}
}
]
}
},
"position": [
4085.3186674463977,
1290.1892980768341
]
},
"98d98c391055bb28": {
"id": "98d98c391055bb28",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "b4138bacefb47375",
"output": "result",
"data": {}
}
]
}
},
"position": [
5729.299371583634,
1240.7771167032029
]
},
"362d9bf9cc3cb4d4": {
"id": "362d9bf9cc3cb4d4",
"name": "bitbybit.occt.shapes.compound.makeCompound",
"customName": "make compound",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shapes": {
"connections": [
{
"node": "acb0dd7668d380c5",
"output": "list",
"data": {}
}
]
}
},
"position": [
4961.545668209146,
-122.31719569645998
]
},
"272f0500401f4a00": {
"id": "272f0500401f4a00",
"name": "bitbybit.occt.shapes.compound.makeCompound",
"customName": "make compound",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shapes": {
"connections": [
{
"node": "98d98c391055bb28",
"output": "list",
"data": {}
}
]
}
},
"position": [
6107.978877130744,
1197.0619441137005
]
},
"9242ef5035943028": {
"id": "9242ef5035943028",
"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": "272f0500401f4a00",
"output": "result",
"data": {}
}
]
},
"options": {
"connections": [
{
"node": "590176fd8a13c6db",
"output": "result",
"data": {}
}
]
}
},
"position": [
6613.714741969893,
1192.5795174038262
]
},
"590176fd8a13c6db": {
"id": "590176fd8a13c6db",
"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": "b26de7648f7f1454",
"output": "result",
"data": {}
}
]
}
},
"position": [
6110.858628800067,
1474.248536407265
]
},
"b26de7648f7f1454": {
"id": "b26de7648f7f1454",
"name": "bitbybit.babylon.material.pbrMetallicRoughness.create",
"customName": "pbr metallic roughness",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"name": "Custom Material",
"baseColor": "#33ffc2",
"emissiveColor": "#000000",
"metallic": 0.8,
"roughness": 0.2,
"alpha": 1,
"backFaceCulling": false,
"zOffset": 0
},
"inputs": {},
"position": [
5730.1753562835,
1514.5514298621156
]
},
"4c222d1fffea0b26": {
"id": "4c222d1fffea0b26",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "fe6c5624fb703309",
"output": "result",
"data": {}
}
]
}
},
"position": [
6314.722918633292,
-71.48278221495036
]
},
"f93171cee29f0049": {
"id": "f93171cee29f0049",
"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.2,
"doNotUpdateMaxZ": true
},
"inputs": {
"meshes": {
"connections": [
{
"node": "4c222d1fffea0b26",
"output": "list",
"data": {}
}
]
}
},
"position": [
6694.456483050785,
-113.61952779763146
]
},
"04cdeb3875ee9a50": {
"id": "04cdeb3875ee9a50",
"name": "bitbybit.lists.flatten",
"customName": "flatten",
"data": {
"nrLevels": 1
},
"inputs": {
"list": {
"connections": [
{
"node": "849b48485b173809",
"output": "result",
"data": {}
}
]
}
},
"position": [
3832.0181812557166,
-76.42665207494241
]
},
"acb0dd7668d380c5": {
"id": "acb0dd7668d380c5",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "735e266df2ec4cf2",
"output": "result",
"data": {}
}
]
}
},
"position": [
4594.637545631506,
-77.03737187519735
]
},
"1c52e4db105a151a": {
"id": "1c52e4db105a151a",
"name": "bitbybit.babylon.scene.enableSkybox",
"customName": "enable skybox",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"skybox": "city",
"size": 1000,
"blur": 0.1,
"environmentIntensity": 0.7,
"hideSkybox": true
},
"inputs": {},
"position": [
314.5707100259427,
2120.3398542926925
]
}
}
}
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable id="nrZigZags">nrZigZags</variable><variable id="innerHex1">innerHex1</variable><variable id="outerHex1">outerHex1</variable><variable id="zigzag1">zigzag1</variable><variable id="zigzag1Scaled">zigzag1Scaled</variable><variable id="innerHex2">innerHex2</variable><variable id="outerHex2">outerHex2</variable><variable id="zigzag2">zigzag2</variable><variable id="zigzag2Scaled">zigzag2Scaled</variable><variable id="loft1">loft1</variable><variable id="loft2">loft2</variable><variable id="loft2Translated">loft2Translated</variable><variable id="loft3">loft3</variable><variable id="faces1">faces1</variable><variable id="face1ToExtrude">everySecondMain</variable><variable id="BD=.Rc?^-]J?Yn)OWU@/">everySecondEnd1</variable><variable id="faces2">faces2</variable><variable id="ymT!IKI4bx(R[`J,I}8x">everySecondEnd2</variable><variable id="faces3">faces3</variable><variable id="facesListForExtrusion">facesListForExtrusion</variable><variable id="currentFace">currentFace</variable><variable id="allExtrudedFaces">allExtrudedFaces</variable><variable id="extrudedFace">extrudedFace</variable><variable id="4Cn|rq8yI:j#T#VL(}]`">allExtrudedFaces2</variable><variable id="_.(0K]M?g*AK~FgnLD?K">currentFace2</variable><variable id="compound1">compound1</variable><variable id="compound2">compound2</variable></variables><block type="bitbybit.babylon.scene.enableSkybox" id="pGff/MMQJp1km-#^FWN7" x="-402" y="-510"><value name="Skybox"><block type="bitbybit.babylon.enums.skyboxEnum" id="H#s/UcsAi}Vsb-U`+GAk"><field name="bitbybit.babylon.enums.skyboxEnum">'city'</field></block></value><value name="Size"><block type="math_number" id="w2YA9{-7AkJ+`}=X}Zb/"><field name="NUM">1000</field></block></value><value name="Blur"><block type="math_number" id="J$d3NUD9KjBE-bqhA4{M"><field name="NUM">0.1</field></block></value><value name="EnvironmentIntensity"><block type="math_number" id="5ct4D[lax7(h7@6wk08?"><field name="NUM">0.7</field></block></value><value name="HideSkybox"><block type="logic_boolean" id="!L.![oDh(Ty5/?e;fB|]"><field name="BOOL">TRUE</field></block></value><next><block type="variables_set" id="set_nrzigzags"><field name="VAR" id="nrZigZags">nrZigZags</field><value name="VALUE"><block type="math_number" id="nrzigzags_val"><field name="NUM">5</field></block></value><next><block type="variables_set" id="set_inner1"><field name="VAR" id="innerHex1">innerHex1</field><value name="VALUE"><block type="bitbybit.occt.shapes.wire.createNGonWire" id="inner_hex_1"><value name="Center"><block type="bitbybit.vector.vectorXYZ" id="center1"><value name="X"><block type="math_number" id="x1"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="y1"><field name="NUM">0.2</field></block></value><value name="Z"><block type="math_number" id="z1"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="dir1"><value name="X"><block type="math_number" id="dx1"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="dy1"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="dz1"><field name="NUM">0</field></block></value></block></value><value name="NrCorners"><block type="math_number" id="corners1"><field name="NUM">6</field></block></value><value name="Radius"><block type="math_number" id="radius1"><field name="NUM">3</field></block></value></block></value><next><block type="variables_set" id="set_outer1"><field name="VAR" id="outerHex1">outerHex1</field><value name="VALUE"><block type="bitbybit.occt.shapes.wire.createNGonWire" id="outer_hex_1"><value name="Center"><block type="bitbybit.vector.vectorXYZ" id="center1b"><value name="X"><block type="math_number" id="x1b"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="y1b"><field name="NUM">0.2</field></block></value><value name="Z"><block type="math_number" id="z1b"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="dir1b"><value name="X"><block type="math_number" id="dx1b"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="dy1b"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="dz1b"><field name="NUM">0</field></block></value></block></value><value name="NrCorners"><block type="math_number" id="corners1b"><field name="NUM">6</field></block></value><value name="Radius"><block type="math_number" id="radius1b"><field name="NUM">3.7</field></block></value></block></value><next><block type="variables_set" id="set_zigzag1"><field name="VAR" id="zigzag1">zigzag1</field><value name="VALUE"><block type="bitbybit.occt.shapes.wire.createZigZagBetweenTwoWires" id="zigzag_1"><value name="Wire1"><block type="variables_get" id="get_inner1"><field name="VAR" id="innerHex1">innerHex1</field></block></value><value name="Wire2"><block type="variables_get" id="get_outer1"><field name="VAR" id="outerHex1">outerHex1</field></block></value><value name="NrZigZags"><block type="variables_get" id="get_nrzigzags1"><field name="VAR" id="nrZigZags">nrZigZags</field></block></value><value name="Inverse"><block type="logic_boolean" id="inv1"><field name="BOOL">FALSE</field></block></value><value name="DivideByEqualDistance"><block type="logic_boolean" id="div1"><field name="BOOL">FALSE</field></block></value><value name="ZigZagsPerEdge"><block type="logic_boolean" id="edge1"><field name="BOOL">TRUE</field></block></value></block></value><next><block type="variables_set" id="set_zigzag1_scaled"><field name="VAR" id="zigzag1Scaled">zigzag1Scaled</field><value name="VALUE"><block type="bitbybit.occt.transforms.scale" id="scale_1"><value name="Shape"><block type="variables_get" id="get_zigzag1"><field name="VAR" id="zigzag1">zigzag1</field></block></value><value name="Factor"><block type="math_number" id="factor1"><field name="NUM">3</field></block></value></block></value><next><block type="variables_set" id="set_inner2"><field name="VAR" id="innerHex2">innerHex2</field><value name="VALUE"><block type="bitbybit.occt.shapes.wire.createNGonWire" id="inner_hex_2"><value name="Center"><block type="bitbybit.vector.vectorXYZ" id="center2"><value name="X"><block type="math_number" id="x2"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="y2"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="z2"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="dir2"><value name="X"><block type="math_number" id="dx2"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="dy2"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="dz2"><field name="NUM">0</field></block></value></block></value><value name="NrCorners"><block type="math_number" id="corners2"><field name="NUM">6</field></block></value><value name="Radius"><block type="math_number" id="radius2"><field name="NUM">2</field></block></value></block></value><next><block type="variables_set" id="set_outer2"><field name="VAR" id="outerHex2">outerHex2</field><value name="VALUE"><block type="bitbybit.occt.shapes.wire.createNGonWire" id="outer_hex_2"><value name="Center"><block type="bitbybit.vector.vectorXYZ" id="center2b"><value name="X"><block type="math_number" id="x2b"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="y2b"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="z2b"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="dir2b"><value name="X"><block type="math_number" id="dx2b"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="dy2b"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="dz2b"><field name="NUM">0</field></block></value></block></value><value name="NrCorners"><block type="math_number" id="corners2b"><field name="NUM">6</field></block></value><value name="Radius"><block type="math_number" id="radius2b"><field name="NUM">2.5</field></block></value></block></value><next><block type="variables_set" id="set_zigzag2"><field name="VAR" id="zigzag2">zigzag2</field><value name="VALUE"><block type="bitbybit.occt.shapes.wire.createZigZagBetweenTwoWires" id="zigzag_2"><value name="Wire1"><block type="variables_get" id="get_inner2"><field name="VAR" id="innerHex2">innerHex2</field></block></value><value name="Wire2"><block type="variables_get" id="get_outer2"><field name="VAR" id="outerHex2">outerHex2</field></block></value><value name="NrZigZags"><block type="variables_get" id="get_nrzigzags2"><field name="VAR" id="nrZigZags">nrZigZags</field></block></value><value name="Inverse"><block type="logic_boolean" id="inv2"><field name="BOOL">FALSE</field></block></value><value name="DivideByEqualDistance"><block type="logic_boolean" id="div2"><field name="BOOL">FALSE</field></block></value><value name="ZigZagsPerEdge"><block type="logic_boolean" id="edge2"><field name="BOOL">TRUE</field></block></value></block></value><next><block type="variables_set" id="set_zigzag2_scaled"><field name="VAR" id="zigzag2Scaled">zigzag2Scaled</field><value name="VALUE"><block type="bitbybit.occt.transforms.scale" id="scale_2"><value name="Shape"><block type="variables_get" id="get_zigzag2"><field name="VAR" id="zigzag2">zigzag2</field></block></value><value name="Factor"><block type="math_number" id="factor2"><field name="NUM">6</field></block></value></block></value><next><block type="variables_set" id="set_loft1"><field name="VAR" id="loft1">loft1</field><value name="VALUE"><block type="bitbybit.occt.operations.loftAdvanced" id="loft_1"><value name="Shapes"><block type="lists_create_with" id="loft1_shapes"><mutation items="4"></mutation><value name="ADD0"><block type="variables_get" id="get_zz2"><field name="VAR" id="zigzag2">zigzag2</field></block></value><value name="ADD1"><block type="variables_get" id="get_zz1"><field name="VAR" id="zigzag1">zigzag1</field></block></value><value name="ADD2"><block type="variables_get" id="get_zz1s"><field name="VAR" id="zigzag1Scaled">zigzag1Scaled</field></block></value><value name="ADD3"><block type="variables_get" id="get_zz2s"><field name="VAR" id="zigzag2Scaled">zigzag2Scaled</field></block></value></block></value><value name="MakeSolid"><block type="logic_boolean" id="solid1"><field name="BOOL">FALSE</field></block></value><value name="Closed"><block type="logic_boolean" id="closed1"><field name="BOOL">FALSE</field></block></value><value name="Periodic"><block type="logic_boolean" id="periodic1"><field name="BOOL">FALSE</field></block></value><value name="Straight"><block type="logic_boolean" id="straight1"><field name="BOOL">TRUE</field></block></value><value name="NrPeriodicSections"><block type="math_number" id="nrperiodic1"><field name="NUM">10</field></block></value><value name="UseSmoothing"><block type="logic_boolean" id="smooth1"><field name="BOOL">FALSE</field></block></value><value name="MaxUDegree"><block type="math_number" id="maxu1"><field name="NUM">3</field></block></value><value name="Tolerance"><block type="math_number" id="tol1"><field name="NUM">1e-7</field></block></value><value name="ParType"><block type="text" id="partype1"><field name="TEXT">approxCentripetal</field></block></value></block></value><next><block type="variables_set" id="set_loft2"><field name="VAR" id="loft2">loft2</field><value name="VALUE"><block type="bitbybit.occt.operations.loftAdvanced" id="loft_2"><value name="Shapes"><block type="lists_create_with" id="loft2_shapes"><mutation items="2"></mutation><value name="ADD0"><block type="variables_get" id="get_zz2s_2"><field name="VAR" id="zigzag2Scaled">zigzag2Scaled</field></block></value><value name="ADD1"><block type="variables_get" id="get_zz1s_2"><field name="VAR" id="zigzag1Scaled">zigzag1Scaled</field></block></value></block></value><value name="MakeSolid"><block type="logic_boolean" id="solid2"><field name="BOOL">FALSE</field></block></value><value name="Closed"><block type="logic_boolean" id="closed2"><field name="BOOL">FALSE</field></block></value><value name="Periodic"><block type="logic_boolean" id="periodic2"><field name="BOOL">FALSE</field></block></value><value name="Straight"><block type="logic_boolean" id="straight2"><field name="BOOL">TRUE</field></block></value><value name="NrPeriodicSections"><block type="math_number" id="nrperiodic2"><field name="NUM">10</field></block></value><value name="UseSmoothing"><block type="logic_boolean" id="smooth2"><field name="BOOL">FALSE</field></block></value><value name="MaxUDegree"><block type="math_number" id="maxu2"><field name="NUM">3</field></block></value><value name="Tolerance"><block type="math_number" id="tol2"><field name="NUM">1e-7</field></block></value><value name="ParType"><block type="text" id="partype2"><field name="TEXT">approxCentripetal</field></block></value></block></value><next><block type="variables_set" id="set_loft2t"><field name="VAR" id="loft2Translated">loft2Translated</field><value name="VALUE"><block type="bitbybit.occt.transforms.translate" id="translate_loft2"><value name="Shape"><block type="variables_get" id="get_loft2"><field name="VAR" id="loft2">loft2</field></block></value><value name="Translation"><block type="bitbybit.vector.vectorXYZ" id="trans_vec"><value name="X"><block type="math_number" id="tx"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="ty"><field name="NUM">0.3</field></block></value><value name="Z"><block type="math_number" id="tz"><field name="NUM">0</field></block></value></block></value></block></value><next><block type="variables_set" id="set_loft3"><field name="VAR" id="loft3">loft3</field><value name="VALUE"><block type="bitbybit.occt.operations.loftAdvanced" id="loft_3"><value name="Shapes"><block type="lists_create_with" id="loft3_shapes"><mutation items="2"></mutation><value name="ADD0"><block type="variables_get" id="get_zz2_3"><field name="VAR" id="zigzag2">zigzag2</field></block></value><value name="ADD1"><block type="variables_get" id="get_zz1_3"><field name="VAR" id="zigzag1">zigzag1</field></block></value></block></value><value name="MakeSolid"><block type="logic_boolean" id="solid3"><field name="BOOL">FALSE</field></block></value><value name="Closed"><block type="logic_boolean" id="closed3"><field name="BOOL">FALSE</field></block></value><value name="Periodic"><block type="logic_boolean" id="periodic3"><field name="BOOL">FALSE</field></block></value><value name="Straight"><block type="logic_boolean" id="straight3"><field name="BOOL">TRUE</field></block></value><value name="NrPeriodicSections"><block type="math_number" id="nrperiodic3"><field name="NUM">10</field></block></value><value name="UseSmoothing"><block type="logic_boolean" id="smooth3"><field name="BOOL">FALSE</field></block></value><value name="MaxUDegree"><block type="math_number" id="maxu3"><field name="NUM">3</field></block></value><value name="Tolerance"><block type="math_number" id="tol3"><field name="NUM">1e-7</field></block></value><value name="ParType"><block type="text" id="partype3"><field name="TEXT">approxCentripetal</field></block></value></block></value><next><block type="variables_set" id="set_faces1"><field name="VAR" id="faces1">faces1</field><value name="VALUE"><block type="base_time_await_return" id="G/nl77Czz;p$a/8ys%{V"><value name="Promise"><block type="bitbybit.occt.shapes.face.getFaces" id="get_faces_1"><value name="Shape"><block type="variables_get" id="loft1_for_faces"><field name="VAR" id="loft1">loft1</field></block></value></block></value></block></value><next><block type="variables_set" id="set_face1_filtered"><field name="VAR" id="face1ToExtrude">everySecondMain</field><value name="VALUE"><block type="bitbybit.lists.getNthItem" id="hc:IXx2|uFTQVoMDG#wX"><value name="List"><block type="variables_get" id="get_faces1_var"><field name="VAR" id="faces1">faces1</field></block></value><value name="Nth"><block type="math_number" id="ELU,ihx7:a6%fK;H69`K"><field name="NUM">2</field></block></value><value name="Offset"><block type="math_number" id="Bqo`.l#Ayy=Xq0+`sHwb"><field name="NUM">1</field></block></value><value name="Clone"><block type="logic_boolean" id="160E_Nv8*yevZ~8uZ6_6"><field name="BOOL">TRUE</field></block></value></block></value><next><block type="variables_set" id="K`TI(UVfmF09aq#BRsr("><field name="VAR" id="BD=.Rc?^-]J?Yn)OWU@/">everySecondEnd1</field><value name="VALUE"><block type="base_time_await_return" id=";+37he(jxn:jtaWHEqA+"><value name="Promise"><block type="bitbybit.occt.shapes.face.getFaces" id="get_faces_2"><value name="Shape"><block type="variables_get" id="loft2t_for_faces"><field name="VAR" id="loft2Translated">loft2Translated</field></block></value></block></value></block></value><next><block type="variables_set" id="set_faces2"><field name="VAR" id="faces2">faces2</field><value name="VALUE"><block type="bitbybit.lists.getNthItem" id="v?Fr[OY-DXhNs11YO5,1"><value name="List"><block type="variables_get" id="TCI2.urG0e~qWW$:|!6b"><field name="VAR" id="BD=.Rc?^-]J?Yn)OWU@/">everySecondEnd1</field></block></value><value name="Nth"><block type="math_number" id="t)eVEvQh9W3zn7fx!}.)"><field name="NUM">2</field></block></value><value name="Offset"><block type="math_number" id="vpEwxWSgc_P#!,-HA7OU"><field name="NUM">0</field></block></value><value name="Clone"><block type="logic_boolean" id="Y}:CY@+AJ#q@lVwly1Q*"><field name="BOOL">TRUE</field></block></value></block></value><next><block type="variables_set" id=";}#%pUI8BaXF83m!^-|-"><field name="VAR" id="ymT!IKI4bx(R[`J,I}8x">everySecondEnd2</field><value name="VALUE"><block type="base_time_await_return" id="A2U)ywt.]m.N_Z:+0sbI"><value name="Promise"><block type="bitbybit.occt.shapes.face.getFaces" id="tT?Y{G9dgx@zT,vL:u:."><value name="Shape"><block type="variables_get" id="7/Y_mypDC0=nW_^s%iF]"><field name="VAR" id="loft3">loft3</field></block></value></block></value></block></value><next><block type="variables_set" id="set_faces3"><field name="VAR" id="faces3">faces3</field><value name="VALUE"><block type="bitbybit.lists.getNthItem" id="Tps;WAMLB9A+D5)?%b+D"><value name="List"><block type="variables_get" id="#hY$F}%LD01}OUIVE=vX"><field name="VAR" id="ymT!IKI4bx(R[`J,I}8x">everySecondEnd2</field></block></value><value name="Nth"><block type="math_number" id="QiEFax2vyiBWb3v?Hy2Y"><field name="NUM">2</field></block></value><value name="Offset"><block type="math_number" id="|:D-[8bM3U_r-:D6Fj^c"><field name="NUM">0</field></block></value><value name="Clone"><block type="logic_boolean" id="aD5LmIff20?Y,.6GD{Q0"><field name="BOOL">TRUE</field></block></value></block></value><next><block type="variables_set" id="init_extrusion_list"><field name="VAR" id="facesListForExtrusion">facesListForExtrusion</field><value name="VALUE"><block type="lists_create_with" id="create_faces_list"><mutation items="0"></mutation></block></value><next><block type="controls_forEach" id="loop_faces2"><field name="VAR" id="currentFace">currentFace</field><value name="LIST"><block type="variables_get" id="get_faces2_loop"><field name="VAR" id="faces2">faces2</field></block></value><statement name="DO"><block type="lists_setIndex" id="append_face2"><mutation at="false"></mutation><field name="MODE">INSERT</field><field name="WHERE">LAST</field><value name="LIST"><block type="variables_get" id="get_list_append2"><field name="VAR" id="facesListForExtrusion">facesListForExtrusion</field></block></value><value name="TO"><block type="variables_get" id="get_current_face2"><field name="VAR" id="currentFace">currentFace</field></block></value></block></statement><next><block type="controls_forEach" id="loop_faces3"><field name="VAR" id="currentFace">currentFace</field><value name="LIST"><block type="variables_get" id="get_faces3_loop"><field name="VAR" id="faces3">faces3</field></block></value><statement name="DO"><block type="lists_setIndex" id="append_face3"><mutation at="false"></mutation><field name="MODE">INSERT</field><field name="WHERE">LAST</field><value name="LIST"><block type="variables_get" id="get_list_append3"><field name="VAR" id="facesListForExtrusion">facesListForExtrusion</field></block></value><value name="TO"><block type="variables_get" id="get_current_face3"><field name="VAR" id="currentFace">currentFace</field></block></value></block></statement><next><block type="variables_set" id="init_extruded_list"><field name="VAR" id="allExtrudedFaces">allExtrudedFaces</field><value name="VALUE"><block type="lists_create_with" id="create_extruded_list"><mutation items="0"></mutation></block></value><next><block type="controls_forEach" id="loop_extrude"><field name="VAR" id="currentFace">currentFace</field><value name="LIST"><block type="variables_get" id="get_faces_for_extrude"><field name="VAR" id="facesListForExtrusion">facesListForExtrusion</field></block></value><statement name="DO"><block type="variables_set" id="extrude_current"><field name="VAR" id="extrudedFace">extrudedFace</field><value name="VALUE"><block type="bitbybit.occt.operations.extrude" id="extrude_face"><value name="Shape"><block type="variables_get" id="get_current_for_extrude"><field name="VAR" id="currentFace">currentFace</field></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="extrude_dir"><value name="X"><block type="math_number" id="exdir_x"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="exdir_y"><field name="NUM">0.3</field></block></value><value name="Z"><block type="math_number" id="exdir_z"><field name="NUM">0</field></block></value></block></value></block></value><next><block type="lists_setIndex" id="append_extruded"><mutation at="false"></mutation><field name="MODE">INSERT</field><field name="WHERE">LAST</field><value name="LIST"><block type="variables_get" id="get_extruded_list"><field name="VAR" id="allExtrudedFaces">allExtrudedFaces</field></block></value><value name="TO"><block type="variables_get" id="get_extruded_face"><field name="VAR" id="extrudedFace">extrudedFace</field></block></value></block></next></block></statement><next><block type="variables_set" id="*[lst4?afeI$X4S-)%$$"><field name="VAR" id="4Cn|rq8yI:j#T#VL(}]`">allExtrudedFaces2</field><value name="VALUE"><block type="lists_create_with" id=",rPnVvn)!Ojy%r(sIhx{"><mutation items="0"></mutation></block></value><next><block type="controls_forEach" id=";G/(C.V52126?2CwOMA{"><field name="VAR" id="_.(0K]M?g*AK~FgnLD?K">currentFace2</field><value name="LIST"><block type="variables_get" id="WlX|C79|+4c}fQ]e]a@t"><field name="VAR" id="face1ToExtrude">everySecondMain</field></block></value><statement name="DO"><block type="variables_set" id="q[z)iT{kNO,hIi(/v-GS"><field name="VAR" id="extrudedFace">extrudedFace</field><value name="VALUE"><block type="bitbybit.occt.operations.extrude" id="o0xc|WAx[^Wo,%SjR%#a"><value name="Shape"><block type="variables_get" id="TI;BI3mB2l2d1;k*MGLE"><field name="VAR" id="_.(0K]M?g*AK~FgnLD?K">currentFace2</field></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="z.p2?W(ZU$f`5+$:_#If"><value name="X"><block type="math_number" id="e8B#7N`,m|?803@[!8bZ"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="os2~x_-HLy0GQC`5{Ibv"><field name="NUM">0.3</field></block></value><value name="Z"><block type="math_number" id="Ux?c.LjGc[F8|f!A%,{Z"><field name="NUM">0</field></block></value></block></value></block></value><next><block type="lists_setIndex" id=":(:_5k3DwF9kHLEqO!KS"><mutation at="false"></mutation><field name="MODE">INSERT</field><field name="WHERE">LAST</field><value name="LIST"><block type="variables_get" id="m%0J-}7aqu43l|x98]A="><field name="VAR" id="4Cn|rq8yI:j#T#VL(}]`">allExtrudedFaces2</field></block></value><value name="TO"><block type="variables_get" id="V/8rSj!Z_hdF8G1]|VR|"><field name="VAR" id="extrudedFace">extrudedFace</field></block></value></block></next></block></statement><next><block type="variables_set" id="set_compound1"><field name="VAR" id="compound1">compound1</field><value name="VALUE"><block type="bitbybit.occt.shapes.compound.makeCompound" id="make_compound1"><value name="Shapes"><block type="variables_get" id="xtvAa*?}[:-p00T%~o$C"><field name="VAR" id="4Cn|rq8yI:j#T#VL(}]`">allExtrudedFaces2</field></block></value></block></value><next><block type="variables_set" id="set_compound2"><field name="VAR" id="compound2">compound2</field><value name="VALUE"><block type="bitbybit.occt.shapes.compound.makeCompound" id="make_compound2"><value name="Shapes"><block type="variables_get" id="get_all_extruded"><field name="VAR" id="allExtrudedFaces">allExtrudedFaces</field></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw1"><value name="Entity"><block type="variables_get" id="get_compound1_draw"><field name="VAR" id="compound1">compound1</field></block></value><value name="Options"><block type="bitbybit.draw.optionsOcctShapeMaterial" id="draw_opt1"><value name="Precision"><block type="math_number" id="prec1"><field name="NUM">0.01</field></block></value><value name="FaceMaterial"><block type="bitbybit.babylon.material.pbrMetallicRoughness.create" id="mat1"><value name="Name"><block type="text" id="name1"><field name="TEXT">Material 1</field></block></value><value name="BaseColor"><block type="colour_picker" id="base1"><field name="COLOUR">#94b4ff</field></block></value><value name="EmissiveColor"><block type="colour_picker" id="emis1"><field name="COLOUR">#000000</field></block></value><value name="Metallic"><block type="math_number" id="metal1"><field name="NUM">0.8</field></block></value><value name="Roughness"><block type="math_number" id="rough1"><field name="NUM">0.2</field></block></value><value name="Alpha"><block type="math_number" id="alpha1"><field name="NUM">1</field></block></value><value name="BackFaceCulling"><block type="logic_boolean" id="cull1"><field name="BOOL">FALSE</field></block></value><value name="ZOffset"><block type="math_number" id="zoff1"><field name="NUM">2</field></block></value></block></value><value name="DrawEdges"><block type="logic_boolean" id="edges1"><field name="BOOL">FALSE</field></block></value><value name="EdgeColour"><block type="colour_picker" id="edgecol1"><field name="COLOUR">#ffffff</field></block></value><value name="EdgeWidth"><block type="math_number" id="edgewid1"><field name="NUM">4</field></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw2"><value name="Entity"><block type="variables_get" id="get_compound2_draw"><field name="VAR" id="compound2">compound2</field></block></value><value name="Options"><block type="bitbybit.draw.optionsOcctShapeMaterial" id="draw_opt2"><value name="Precision"><block type="math_number" id="prec2"><field name="NUM">0.01</field></block></value><value name="FaceMaterial"><block type="bitbybit.babylon.material.pbrMetallicRoughness.create" id="mat2"><value name="Name"><block type="text" id="name2"><field name="TEXT">Material 2</field></block></value><value name="BaseColor"><block type="colour_picker" id="base2"><field name="COLOUR">#33ffc2</field></block></value><value name="EmissiveColor"><block type="colour_picker" id="emis2"><field name="COLOUR">#000000</field></block></value><value name="Metallic"><block type="math_number" id="metal2"><field name="NUM">0.8</field></block></value><value name="Roughness"><block type="math_number" id="rough2"><field name="NUM">0.2</field></block></value><value name="Alpha"><block type="math_number" id="alpha2"><field name="NUM">1</field></block></value><value name="BackFaceCulling"><block type="logic_boolean" id="cull2"><field name="BOOL">FALSE</field></block></value><value name="ZOffset"><block type="math_number" id="zoff2"><field name="NUM">0</field></block></value></block></value><value name="DrawEdges"><block type="logic_boolean" id="edges2"><field name="BOOL">FALSE</field></block></value><value name="EdgeColour"><block type="colour_picker" id="edgecol2"><field name="COLOUR">#ffffff</field></block></value><value name="EdgeWidth"><block type="math_number" id="edgewid2"><field name="NUM">2</field></block></value></block></value></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></xml>
const { NGonWireDto, ZigZagBetweenTwoWiresDto, ShapesDto, ExtrudeDto, approxParametrizationTypeEnum } = Bit.Inputs.OCCT;
const { LoftAdvancedDto } = Bit.Inputs.OCCT;
const { TranslateDto, ScaleDto } = Bit.Inputs.OCCT;
const { PBRMetallicRoughnessDto } = Bit.Inputs.BabylonMaterial;
const { DrawOcctShapeOptions } = Bit.Inputs.Draw;
const { SkyboxDto } = Bit.Inputs.BabylonScene;
const { skyboxEnum } = Bit.Inputs.Base;
const { ZoomOnDto } = Bit.Advanced.Navigation;
type Point3 = Bit.Inputs.Base.Point3;
type TopoDSWirePointer = Bit.Inputs.OCCT.TopoDSWirePointer;
type TopoDSFacePointer = Bit.Inputs.OCCT.TopoDSFacePointer;
type TopoDSShapePointer = Bit.Inputs.OCCT.TopoDSShapePointer;
const { wire, face, compound } = bitbybit.occt.shapes;
const { operations, transforms } = bitbybit.occt;
const start = async () => {
const skyboxOpt = new SkyboxDto();
skyboxOpt.skybox = skyboxEnum.city;
skyboxOpt.hideSkybox = true;
bitbybit.babylon.scene.enableSkybox(skyboxOpt);
const nrZigZags = 5;
// Create first set of hexagon wires
const innerHex1Dto = new NGonWireDto();
innerHex1Dto.center = [0, 0.2, 0];
innerHex1Dto.direction = [0, 1, 0];
innerHex1Dto.nrCorners = 6;
innerHex1Dto.radius = 3;
const innerHex1 = await wire.createNGonWire(innerHex1Dto);
const outerHex1Dto = new NGonWireDto();
outerHex1Dto.center = [0, 0.2, 0];
outerHex1Dto.direction = [0, 1, 0];
outerHex1Dto.nrCorners = 6;
outerHex1Dto.radius = 3.7;
const outerHex1 = await wire.createNGonWire(outerHex1Dto);
const innerHex2Dto = new NGonWireDto();
innerHex2Dto.center = [0, 0, 0];
innerHex2Dto.direction = [0, 1, 0];
innerHex2Dto.nrCorners = 6;
innerHex2Dto.radius = 2;
const innerHex2 = await wire.createNGonWire(innerHex2Dto);
const outerHex2Dto = new NGonWireDto();
outerHex2Dto.center = [0, 0, 0];
outerHex2Dto.direction = [0, 1, 0];
outerHex2Dto.nrCorners = 6;
outerHex2Dto.radius = 2.5;
const outerHex2 = await wire.createNGonWire(outerHex2Dto);
// Create zigzag wires between hexagons
const zigzag1Dto = new ZigZagBetweenTwoWiresDto<TopoDSWirePointer>();
zigzag1Dto.wire1 = innerHex1;
zigzag1Dto.wire2 = outerHex1;
zigzag1Dto.nrZigZags = nrZigZags;
zigzag1Dto.inverse = false;
zigzag1Dto.divideByEqualDistance = false;
zigzag1Dto.zigZagsPerEdge = true;
const zigzag1 = await wire.createZigZagBetweenTwoWires(zigzag1Dto);
const scale1Dto = new ScaleDto<TopoDSWirePointer>();
scale1Dto.shape = zigzag1;
scale1Dto.factor = 3;
const zigzag1Scaled = await transforms.scale(scale1Dto);
const zigzag2Dto = new ZigZagBetweenTwoWiresDto<TopoDSWirePointer>();
zigzag2Dto.wire1 = innerHex2;
zigzag2Dto.wire2 = outerHex2;
zigzag2Dto.nrZigZags = nrZigZags;
zigzag2Dto.inverse = false;
zigzag2Dto.divideByEqualDistance = false;
zigzag2Dto.zigZagsPerEdge = true;
const zigzag2 = await wire.createZigZagBetweenTwoWires(zigzag2Dto);
const scale2Dto = new ScaleDto<TopoDSWirePointer>();
scale2Dto.shape = zigzag2;
scale2Dto.factor = 6;
const zigzag2Scaled = await transforms.scale(scale2Dto);
// Create loft surfaces
const loft1Dto = new LoftAdvancedDto<TopoDSWirePointer>();
loft1Dto.shapes = [zigzag2, zigzag1, zigzag1Scaled, zigzag2Scaled];
loft1Dto.makeSolid = false;
loft1Dto.closed = false;
loft1Dto.periodic = false;
loft1Dto.straight = true;
loft1Dto.nrPeriodicSections = 10;
loft1Dto.useSmoothing = false;
loft1Dto.maxUDegree = 3;
loft1Dto.tolerance = 1e-7;
loft1Dto.parType = approxParametrizationTypeEnum.approxCentripetal;
const loft1 = await operations.loftAdvanced(loft1Dto);
const loft2Dto = new LoftAdvancedDto<TopoDSWirePointer>();
loft2Dto.shapes = [zigzag2Scaled, zigzag1Scaled];
loft2Dto.makeSolid = false;
loft2Dto.closed = false;
loft2Dto.periodic = false;
loft2Dto.straight = true;
loft2Dto.nrPeriodicSections = 10;
loft2Dto.useSmoothing = false;
loft2Dto.maxUDegree = 3;
loft2Dto.tolerance = 1e-7;
loft1Dto.parType = approxParametrizationTypeEnum.approxCentripetal;
const loft2 = await operations.loftAdvanced(loft2Dto);
const translateDto = new TranslateDto<TopoDSShapePointer>();
translateDto.shape = loft2;
translateDto.translation = [0, 0.3, 0];
const loft2Translated = await transforms.translate(translateDto);
const loft3Dto = new LoftAdvancedDto<TopoDSWirePointer>();
loft3Dto.shapes = [zigzag2, zigzag1];
loft3Dto.makeSolid = false;
loft3Dto.closed = false;
loft3Dto.periodic = false;
loft3Dto.straight = true;
loft3Dto.nrPeriodicSections = 10;
loft3Dto.useSmoothing = false;
loft3Dto.maxUDegree = 3;
loft3Dto.tolerance = 1e-7;
loft1Dto.parType = approxParametrizationTypeEnum.approxCentripetal;
const loft3 = await operations.loftAdvanced(loft3Dto);
// Extract and filter faces
const faces1All = await face.getFaces({ shape: loft1 });
const everySecondMain = bitbybit.lists.getNthItem({
list: faces1All,
nth: 2,
offset: 1,
clone: true
});
const faces2All = await face.getFaces({ shape: loft2Translated });
const everySecondEnd1 = bitbybit.lists.getNthItem({
list: faces2All,
nth: 2,
offset: 0,
clone: true
});
const faces3All = await face.getFaces({ shape: loft3 });
const everySecondEnd2 = bitbybit.lists.getNthItem({
list: faces3All,
nth: 2,
offset: 0,
clone: true
});
// Combine faces for extrusion
const facesForExtrusion: TopoDSFacePointer[] = [
...everySecondEnd1,
...everySecondEnd2
];
// Extrude all faces
const extrudedFaces: TopoDSShapePointer[] = [];
for (const faceToExtrude of facesForExtrusion) {
const extrudeDto = new ExtrudeDto<TopoDSFacePointer>();
extrudeDto.shape = faceToExtrude;
extrudeDto.direction = [0, 0.3, 0];
const extruded = await operations.extrude(extrudeDto);
extrudedFaces.push(extruded);
}
const extrudedFacesMain: TopoDSShapePointer[] = [];
for (const faceToExtrude of everySecondMain) {
const extrudeDto = new ExtrudeDto<TopoDSFacePointer>();
extrudeDto.shape = faceToExtrude;
extrudeDto.direction = [0, 0.3, 0];
const extruded = await operations.extrude(extrudeDto);
extrudedFacesMain.push(extruded);
}
// Create compounds
const compoundDto1 = new ShapesDto<TopoDSShapePointer>();
compoundDto1.shapes = extrudedFacesMain;
const compound1 = await compound.makeCompound(compoundDto1);
const compoundDto2 = new ShapesDto<TopoDSShapePointer>();
compoundDto2.shapes = extrudedFaces;
const compound2 = await compound.makeCompound(compoundDto2);
// Create materials
const material1Dto = new PBRMetallicRoughnessDto();
material1Dto.name = 'Material 1';
material1Dto.baseColor = '#94b4ff';
material1Dto.emissiveColor = '#000000';
material1Dto.metallic = 0.8;
material1Dto.roughness = 0.2;
material1Dto.alpha = 1;
material1Dto.backFaceCulling = false;
material1Dto.zOffset = 2;
const material1 = bitbybit.babylon.material.pbrMetallicRoughness.create(material1Dto);
const material2Dto = new PBRMetallicRoughnessDto();
material2Dto.name = 'Material 2';
material2Dto.baseColor = '#33ffc2';
material2Dto.emissiveColor = '#000000';
material2Dto.metallic = 0.8;
material2Dto.roughness = 0.2;
material2Dto.alpha = 1;
material2Dto.backFaceCulling = false;
material2Dto.zOffset = 0;
const material2 = bitbybit.babylon.material.pbrMetallicRoughness.create(material2Dto);
// Draw the compounds
const drawOptions1 = new DrawOcctShapeOptions();
drawOptions1.precision = 0.01;
drawOptions1.faceMaterial = material1;
drawOptions1.drawEdges = false;
drawOptions1.edgeColour = '#ffffff';
drawOptions1.edgeWidth = 4;
await bitbybit.draw.drawAnyAsync({
entity: compound1,
options: drawOptions1
});
const drawOptions2 = new DrawOcctShapeOptions();
drawOptions2.precision = 0.01;
drawOptions2.faceMaterial = material2;
drawOptions2.drawEdges = false;
drawOptions2.edgeColour = '#ffffff';
drawOptions2.edgeWidth = 2;
const drawnMesh = await bitbybit.draw.drawAnyAsync({
entity: compound2,
options: drawOptions2
});
const zoomOnOptions = new ZoomOnDto();
zoomOnOptions.offset = -0.1;
zoomOnOptions.meshes = [drawnMesh];
bitbybit.advanced.navigation.zoomOn(zoomOnOptions);
};
start();
How It Works
Hexagonal Foundation
The snowflake starts with two sets of concentric hexagons:
- First set (y = 0.2): Inner radius 3.0, outer radius 3.7 - forms the main structure
- Second set (y = 0.0): Inner radius 2.0, outer radius 2.5 - forms the base layer
All hexagons have 6 corners and are oriented with their normal pointing in the Y direction (upward).
Zigzag Pattern Generation
The createZigZagBetweenTwoWires operation creates jagged connecting patterns:
- zigzag1: Connects between the first hexagon pair (radii 3.0 ↔ 3.7)
- zigzag2: Connects between the second hexagon pair (radii 2.0 ↔ 2.5)
- nrZigZags = 5: Creates 5 zigzag segments per edge (30 total around each hexagon)
- zigZagsPerEdge = true: Distributes zigzags evenly across each of the 6 hexagon edges
Scaled Variations
To create depth and complexity:
- zigzag1Scaled: The first zigzag pattern scaled 3x larger (radius ~9 to ~11.1)
- zigzag2Scaled: The second zigzag pattern scaled 6x larger (radius ~12 to ~15)
This scaling creates dramatic size variation between inner and outer layers.
Advanced Lofting
Three loft surfaces are created using loftAdvanced with straight interpolation:
-
loft1 (Main surface): Connects 4 wires in sequence:
zigzag2 → zigzag1 → zigzag1Scaled → zigzag2Scaled- Creates a complex surface transitioning through all scale variations
- Forms the central "crown" of the snowflake
-
loft2 (Translated cap): Connects
zigzag2Scaled → zigzag1Scaled- Translated 0.3 units upward along Y-axis
- Forms the raised "tips" layer
-
loft3 (Base): Connects
zigzag2 → zigzag1- Remains at the base position
- Forms the foundation structure
Selective Face Extraction
This is where the magic happens! Each loft surface is decomposed into its constituent faces, then filtered:
- loft1 faces: Extract every 2nd face starting at offset 1 → creates the main spiky protrusions
- loft2Translated faces: Extract every 2nd face starting at offset 0 → creates the raised end caps
- loft3 faces: Extract every 2nd face starting at offset 0 → creates the base end caps
The getNthItem filtering creates the characteristic "every-other-spike" pattern that makes the snowflake look organic and complex rather than uniformly smooth.
Face Extrusion
All filtered faces are extruded 0.3 units along the Y-axis:
- Main faces (from loft1): Form the central spiky structure
- End faces (from loft2 & loft3): Form the raised and base caps
Each face becomes a 3D protrusion, creating the frozen, crystalline appearance.
Compound Organization
The extruded faces are organized into two compounds:
- Compound 1: Main faces with blue metallic material (#94b4ff)
- Compound 2: End cap faces with cyan metallic material (#33ffc2)
This two-tone approach adds visual interest and depth to the final rendering.
Customization ❄️
- nrZigZags variable: Change from 5 to 3-7 for different spike density (fewer = chunkier spikes, more = finer detail)
- Hexagon radii: Adjust the 3.0, 3.7, 2.0, 2.5 values to change the overall proportions
- Scale factors: Modify the 3x and 6x scaling to adjust depth (try 2x and 4x for subtler effects, or 4x and 8x for dramatic)
- Extrusion distance: Change 0.3 to adjust spike height (try 0.2 for subtle, 0.5 for dramatic)
- Face filtering offset: Change the nth/offset parameters to select different faces
- Materials: Experiment with different metallic/roughness values and colors for various ice effects
Technical Insights
Why Loft Advanced?
The loftAdvanced operation with straight: true creates ruled surfaces - straight lines connecting corresponding points on each wire. This creates sharp, geometric transitions perfect for crystalline structures rather than smooth organic curves.
The Power of Face Filtering
By extracting and extruding only specific faces (every 2nd one), we create:
- Negative space: Gaps between protrusions that catch light and shadow
- Geometric complexity: From simple lofts to intricate 3D structure
- Performance optimization: Fewer faces to extrude than processing all faces
Compound vs Boolean Union
Unlike the frost-flower tutorial which uses boolean union, this design uses compounds:
- Pros: Faster computation, preserves individual faces, allows multiple materials
- Cons: Not a single unified solid (but perfect for visualization and decoration)
Rendering & Visualization Tips
- Materials: The metallic PBR materials with high metallic (0.8) and low roughness (0.2) create realistic ice crystals
- Colors: Blue (#94b4ff) and cyan (#33ffc2) evoke frozen water and winter themes
- Lighting: The compound approach with different zOffsets creates depth in the rendering
- Scale: The default size (~30 units) works well for visualization - adjust based on your scene
- Camera: The complex geometry looks best when viewed from slightly above at an angle
- Animation: Try rotating slowly around the Y-axis to show off the intricate spike patterns
Happy modeling! ❄️✨



