Skip to main content

Compounded Drawing

OCCT category icon with a stylized logo representation

Building on the fundamental concepts from the compound shapes introduction, this tutorial demonstrates how to apply compound techniques to complex, real-world scenarios. We'll explore a sophisticated example that creates a parametric hexagonal pattern on a curved surface, showing how compounds dramatically improve rendering performance while enabling organized management of complex geometries.

The Challenge: Complex Parametric Patterns

When working with parametric designs that generate hundreds or thousands of individual geometric elements, performance becomes critical. Consider a scenario where you need to create a hexagonal frame pattern across a curved surface - each hexagon consists of multiple faces, wires, and edges that would normally require individual rendering calls.

Without compounds, such patterns would overwhelm the graphics pipeline with separate draw calls for each element. The solution lies in strategically grouping related elements into compounds before rendering, transforming what could be thousands of individual operations into just a few efficient compound draws.

Advanced Compound Application: Hexagonal Surface Pattern

The example below demonstrates this principle through a complex workflow that creates a parametric hexagonal pattern on a lofted surface. This real-world scenario showcases several advanced compound techniques:

Surface Creation: First, we generate a complex curved surface by lofting between three interpolated wire curves with different point configurations.

Pattern Generation: The surface is subdivided into hexagonal patterns using two different scaling approaches - one regular and one scaled - creating complementary geometric sets.

Strategic Grouping: Rather than rendering each hexagonal frame individually, we use pattern filtering to group frames into logical sets, then create separate compounds for each group.

Efficient Rendering: Finally, we render only two compound entities instead of potentially hundreds of individual faces, with different materials applied to each compound group.

Bitbybit Platform

Compounding hex frames into single entity will render faster

rete logoRete
Script Source (rete)
{
"id": "rete-v2-json",
"nodes": {
"bottomwire": {
"id": "bottomwire",
"name": "bitbybit.occt.shapes.wire.interpolatePoints",
"customName": "bottom wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"periodic": false,
"tolerance": 0.1
},
"inputs": {
"points": {
"connections": [
{
"node": "09aaa33913f67046",
"output": "result",
"data": {}
}
]
}
},
"position": [
804.3759428936219,
255.41502016627993
]
},
"middlewire": {
"id": "middlewire",
"name": "bitbybit.occt.shapes.wire.interpolatePoints",
"customName": "middle wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"periodic": false,
"tolerance": 0.1
},
"inputs": {
"points": {
"connections": [
{
"node": "c7e788a8b84974ea",
"output": "result",
"data": {}
}
]
}
},
"position": [
800,
600
]
},
"topwire": {
"id": "topwire",
"name": "bitbybit.occt.shapes.wire.interpolatePoints",
"customName": "top wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"periodic": false,
"tolerance": 0.1
},
"inputs": {
"points": {
"connections": [
{
"node": "4923cc4b9415e46a",
"output": "result",
"data": {}
}
]
}
},
"position": [
801.717534733165,
951.8166792524057
]
},
"5885a89725e9fbe0": {
"id": "5885a89725e9fbe0",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "bottomwire",
"output": "result",
"data": {}
},
{
"node": "middlewire",
"output": "result",
"data": {}
},
{
"node": "topwire",
"output": "result",
"data": {}
}
]
}
},
"position": [
1200,
600
]
},
"loftface": {
"id": "loftface",
"name": "bitbybit.occt.operations.loft",
"customName": "loft surface",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"makeSolid": false
},
"inputs": {
"shapes": {
"connections": [
{
"node": "5885a89725e9fbe0",
"output": "list",
"data": {}
}
]
}
},
"position": [
1595.0487702041482,
559.6926796377796
]
},
"f9dbfe1c98680d76": {
"id": "f9dbfe1c98680d76",
"name": "bitbybit.occt.shapes.face.getFace",
"customName": "get face",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"index": 0
},
"inputs": {
"shape": {
"connections": [
{
"node": "loftface",
"output": "result",
"data": {}
}
]
}
},
"position": [
1980.2487300409268,
559.7041116519489
]
},
"17be61c967bdbffc": {
"id": "17be61c967bdbffc",
"name": "bitbybit.occt.shapes.face.subdivideToHexagonWires",
"customName": "subdivide to hexagon wires",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"nrHexagonsU": 10,
"nrHexagonsV": 10,
"flatU": false,
"offsetFromBorderU": 0,
"offsetFromBorderV": 0,
"extendUUp": false,
"extendUBottom": false,
"extendVUp": false,
"extendVBottom": false
},
"inputs": {
"shape": {
"connections": [
{
"node": "f9dbfe1c98680d76",
"output": "result",
"data": {}
}
]
},
"nrHexagonsU": {
"connections": [
{
"node": "0367a65ba902b339",
"output": "result",
"data": {}
}
]
},
"nrHexagonsV": {
"connections": [
{
"node": "f568f51be48df32f",
"output": "result",
"data": {}
}
]
}
},
"position": [
2490.036274919156,
553.9247536340029
]
},
"02937902d77e3099": {
"id": "02937902d77e3099",
"name": "bitbybit.occt.shapes.face.subdivideToHexagonWires",
"customName": "subdivide to hexagon wires",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"nrHexagonsU": 10,
"nrHexagonsV": 10,
"flatU": false,
"offsetFromBorderU": 0,
"offsetFromBorderV": 0,
"extendUUp": false,
"extendUBottom": false,
"extendVUp": false,
"extendVBottom": false
},
"inputs": {
"shape": {
"connections": [
{
"node": "f9dbfe1c98680d76",
"output": "result",
"data": {}
}
]
},
"nrHexagonsU": {
"connections": [
{
"node": "0367a65ba902b339",
"output": "result",
"data": {}
}
]
},
"scalePatternV": {
"connections": [
{
"node": "b3d925482eba7c1d",
"output": "result",
"data": {}
}
]
},
"scalePatternU": {
"connections": [
{
"node": "b3d925482eba7c1d",
"output": "result",
"data": {}
}
]
},
"nrHexagonsV": {
"connections": [
{
"node": "f568f51be48df32f",
"output": "result",
"data": {}
}
]
}
},
"position": [
2485.953782467995,
1370.418357408917
]
},
"bbe58b7a15d92c2f": {
"id": "bbe58b7a15d92c2f",
"name": "bitbybit.lists.flatten",
"customName": "flatten",
"data": {
"nrLevels": 1
},
"inputs": {
"list": {
"connections": [
{
"node": "02937902d77e3099",
"output": "result",
"data": {}
}
]
}
},
"position": [
2859.4256379145177,
1411.0019530979657
]
},
"f9e0d2238290f7f7": {
"id": "f9e0d2238290f7f7",
"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": "bbe58b7a15d92c2f",
"output": "result",
"data": {}
}
]
}
},
"position": [
3225.9296811342447,
1372.4776309555743
]
},
"316fd1d3d87b256f": {
"id": "316fd1d3d87b256f",
"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": false
},
"inputs": {
"shapes": {
"connections": [
{
"node": "ab81430e8cb96958",
"output": "result",
"data": {}
}
]
}
},
"position": [
5112.912404370474,
1051.6631227938249
]
},
"67068806a2d1259e": {
"id": "67068806a2d1259e",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "f9e0d2238290f7f7",
"output": "result",
"data": {}
}
]
}
},
"position": [
3587.3344654899656,
1409.037231519246
]
},
"0e0d2df57073ad69": {
"id": "0e0d2df57073ad69",
"name": "bitbybit.lists.flipLists",
"customName": "flip lists",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"clone": true
},
"inputs": {
"list": {
"connections": [
{
"node": "da45c87c0cad7573",
"output": "list",
"data": {}
}
]
}
},
"position": [
4369.400631061372,
1081.305088555142
]
},
"da45c87c0cad7573": {
"id": "da45c87c0cad7573",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "17be61c967bdbffc",
"output": "result",
"data": {}
},
{
"node": "67068806a2d1259e",
"output": "list",
"data": {}
}
]
}
},
"position": [
3999.3386274573427,
1121.9828766382495
]
},
"ab81430e8cb96958": {
"id": "ab81430e8cb96958",
"name": "bitbybit.lists.flatten",
"customName": "flatten",
"data": {
"nrLevels": 1
},
"inputs": {
"list": {
"connections": [
{
"node": "0e0d2df57073ad69",
"output": "result",
"data": {}
}
]
}
},
"position": [
4736.0567498732935,
1117.8968252406555
]
},
"f8d0dc03aa2b2ac4": {
"id": "f8d0dc03aa2b2ac4",
"name": "bitbybit.text.areaCreate",
"customName": "text area",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"options": {
"width": 292,
"height": 35
},
"text": "[[-30, 0, -20], [-10, 0, 0], [0, 0, 10], [10, 0, 0],[30, 0, -20]]\n\n"
},
"inputs": {},
"position": [
42.38544650004519,
260.68610662806805
]
},
"a1351efae39cf796": {
"id": "a1351efae39cf796",
"name": "bitbybit.text.areaCreate",
"customName": "text area",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"options": {
"width": 284,
"height": 32
},
"text": "[[-20, 20, -10], [-5, 20, 15], [0, 20, 20], [5, 20, 15],[20, 20, -10]]\n\n"
},
"inputs": {},
"position": [
45.653379576308,
603.3144633544662
]
},
"c7e788a8b84974ea": {
"id": "c7e788a8b84974ea",
"name": "bitbybit.json.parse",
"customName": "parse",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"text": "[0, 0, 0]"
},
"inputs": {
"text": {
"connections": [
{
"node": "a1351efae39cf796",
"output": "result",
"data": {}
}
]
}
},
"position": [
427.9731290182838,
601.4072961194012
]
},
"09aaa33913f67046": {
"id": "09aaa33913f67046",
"name": "bitbybit.json.parse",
"customName": "parse",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"text": "[0, 0, 0]"
},
"inputs": {
"text": {
"connections": [
{
"node": "f8d0dc03aa2b2ac4",
"output": "result",
"data": {}
}
]
}
},
"position": [
439.2109544164346,
260.0904145164821
]
},
"88ad8cfc1367b146": {
"id": "88ad8cfc1367b146",
"name": "bitbybit.text.areaCreate",
"customName": "text area",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"options": {
"width": 242,
"height": 30
},
"text": "[[-15, 30, 0], [-5, 30, 5], [0, 30, 10], [5, 30, 5],[15, 30, 0]]\n\n"
},
"inputs": {},
"position": [
56.36380730589735,
960.4638852035587
]
},
"4923cc4b9415e46a": {
"id": "4923cc4b9415e46a",
"name": "bitbybit.json.parse",
"customName": "parse",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"text": "[0, 0, 0]"
},
"inputs": {
"text": {
"connections": [
{
"node": "88ad8cfc1367b146",
"output": "result",
"data": {}
}
]
}
},
"position": [
427.04410360712416,
957.5124738568434
]
},
"8189bc84029d30af": {
"id": "8189bc84029d30af",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "316fd1d3d87b256f",
"output": "result",
"data": {}
}
]
}
},
"position": [
5520.546804372246,
1083.580155421671
]
},
"8915debdbefaef77": {
"id": "8915debdbefaef77",
"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": "ecd00106b8d42973",
"output": "result",
"data": {}
}
]
},
"entity": {
"connections": [
{
"node": "d5861077d4424f64",
"output": "result",
"data": {}
}
]
}
},
"position": [
7858.947647642291,
1516.5912829621361
]
},
"8f0e43d996ce2eb7": {
"id": "8f0e43d996ce2eb7",
"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": [
1330.016240926373,
3921.8377573989997
]
},
"0367a65ba902b339": {
"id": "0367a65ba902b339",
"name": "bitbybit.math.numberSlider",
"customName": "number slider",
"data": {
"options": {
"min": 10,
"max": 30,
"step": 1,
"width": 350,
"updateOnDrag": false
},
"number": 28
},
"inputs": {},
"position": [
107.64800114272066,
1452.3963806505471
]
},
"b3d925482eba7c1d": {
"id": "b3d925482eba7c1d",
"name": "bitbybit.json.parse",
"customName": "parse",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"text": "[0.7]"
},
"inputs": {},
"position": [
2006.2758597691181,
1349.6087847915644
]
},
"f568f51be48df32f": {
"id": "f568f51be48df32f",
"name": "bitbybit.math.numberSlider",
"customName": "number slider",
"data": {
"options": {
"min": 10,
"max": 30,
"step": 1,
"width": 350,
"updateOnDrag": false
},
"number": 10
},
"inputs": {},
"position": [
93.72338722042218,
1622.754313570655
]
},
"4c586ec9c4ab3043": {
"id": "4c586ec9c4ab3043",
"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": "#9a57ff",
"emissiveColor": "#000000",
"metallic": 0.1,
"roughness": 0.9,
"alpha": 1,
"backFaceCulling": false,
"zOffset": 2
},
"inputs": {},
"position": [
6839.387051047384,
2267.7088364430565
]
},
"ecd00106b8d42973": {
"id": "ecd00106b8d42973",
"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": true,
"edgeColour": "#000000",
"edgeWidth": 10
},
"inputs": {
"faceMaterial": {
"connections": [
{
"node": "4c586ec9c4ab3043",
"output": "result",
"data": {}
}
]
}
},
"position": [
7212.179378860794,
2229.5471681797653
]
},
"6cc3ec2270f0f390": {
"id": "6cc3ec2270f0f390",
"name": "bitbybit.babylon.scene.adjustActiveArcRotateCamera",
"customName": "adjust active arc rotate camera",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"position": [
10,
10,
10
],
"lookAt": [
0,
0,
0
],
"lowerBetaLimit": 1,
"upperBetaLimit": 179,
"angularSensibilityX": 1000,
"angularSensibilityY": 1000,
"maxZ": 1000,
"panningSensibility": 1000,
"wheelPrecision": 3
},
"inputs": {
"position": {
"connections": [
{
"node": "e4512632da197338",
"output": "result",
"data": {}
}
]
},
"lookAt": {
"connections": [
{
"node": "55b07f2f7d8f577e",
"output": "result",
"data": {}
}
]
}
},
"position": [
1332.5534259486913,
2424.9313448977655
]
},
"e4512632da197338": {
"id": "e4512632da197338",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 44,
"y": 30,
"z": 44
},
"inputs": {},
"position": [
895.8472178437926,
2328.381466574848
]
},
"55b07f2f7d8f577e": {
"id": "55b07f2f7d8f577e",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 15,
"z": 0
},
"inputs": {},
"position": [
927.3725883128666,
2681.3055795464165
]
},
"fe7b1b1c90bd0590": {
"id": "fe7b1b1c90bd0590",
"name": "bitbybit.babylon.scene.drawDirectionalLight",
"customName": "draw directional light",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"direction": [
-100,
-100,
-100
],
"intensity": 3,
"diffuse": "#ffffff",
"specular": "#ffffff",
"shadowGeneratorMapSize": 1024,
"enableShadows": true,
"shadowDarkness": 0,
"shadowUsePercentageCloserFiltering": true,
"shadowContactHardeningLightSizeUVRatio": 0.2,
"shadowBias": 0.0001,
"shadowNormalBias": 0.002,
"shadowMaxZ": 1000,
"shadowMinZ": 0
},
"inputs": {},
"position": [
1222.3502318577364,
3179.147253041469
]
},
"239c0e87d6e0cdd4": {
"id": "239c0e87d6e0cdd4",
"name": "bitbybit.babylon.scene.twoColorLinearGradient",
"customName": "two color linear gradient",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"colorFrom": "#050506",
"colorTo": "#627a9d",
"direction": "to top",
"stopFrom": 0,
"stopTo": 100
},
"inputs": {},
"position": [
1327.3963302073716,
1961.9059336308726
]
},
"15c03b332fd55df6": {
"id": "15c03b332fd55df6",
"name": "bitbybit.draw.drawGridMesh",
"customName": "draw grid mesh",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"width": 400,
"height": 400,
"subdivisions": 10,
"majorUnitFrequency": 10,
"minorUnitVisibility": 0.45,
"gridRatio": 0.5,
"opacity": 0.5,
"backFaceCulling": false,
"mainColor": "#ffffff",
"secondaryColor": "#ffffff"
},
"inputs": {},
"position": [
1336.466465987358,
4357.944233774137
]
},
"7d1027a93b5b2619": {
"id": "7d1027a93b5b2619",
"name": "bitbybit.lists.getByPattern",
"customName": "get by pattern",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"pattern": [
true,
true,
false
]
},
"inputs": {
"pattern": {
"connections": [
{
"node": "e9a93cdbdf16819d",
"output": "result",
"data": {}
}
]
},
"list": {
"connections": [
{
"node": "8189bc84029d30af",
"output": "list",
"data": {}
}
]
}
},
"position": [
6821.9547052052885,
902.7806529537286
]
},
"e9a93cdbdf16819d": {
"id": "e9a93cdbdf16819d",
"name": "bitbybit.json.parse",
"customName": "parse",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"text": "[true, true, false]"
},
"inputs": {},
"position": [
6231.440080230604,
735.9141562600582
]
},
"1f7e28416bd200a8": {
"id": "1f7e28416bd200a8",
"name": "bitbybit.json.parse",
"customName": "parse",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"text": "[false, false, true]"
},
"inputs": {},
"position": [
6226.398722388475,
424.0462857990449
]
},
"6f2f0e0dd03167c5": {
"id": "6f2f0e0dd03167c5",
"name": "bitbybit.lists.getByPattern",
"customName": "get by pattern",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"pattern": [
true,
true,
false
]
},
"inputs": {
"pattern": {
"connections": [
{
"node": "1f7e28416bd200a8",
"output": "result",
"data": {}
}
]
},
"list": {
"connections": [
{
"node": "8189bc84029d30af",
"output": "list",
"data": {}
}
]
}
},
"position": [
6824.268799573109,
576.1749391729782
]
},
"c2deafb81bb08232": {
"id": "c2deafb81bb08232",
"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": "6f2f0e0dd03167c5",
"output": "result",
"data": {}
}
]
}
},
"position": [
7266.34315852178,
572.3471079241745
]
},
"d5861077d4424f64": {
"id": "d5861077d4424f64",
"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": "7d1027a93b5b2619",
"output": "result",
"data": {}
}
]
}
},
"position": [
7272.267298234055,
899.6742737531788
]
},
"c69d6a51b91dbdf8": {
"id": "c69d6a51b91dbdf8",
"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": "c2deafb81bb08232",
"output": "result",
"data": {}
}
]
},
"options": {
"connections": [
{
"node": "d75a575149ad341e",
"output": "result",
"data": {}
}
]
}
},
"position": [
7857.222309875908,
1152.8397016480505
]
},
"d75a575149ad341e": {
"id": "d75a575149ad341e",
"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": true,
"edgeColour": "#000000",
"edgeWidth": 10
},
"inputs": {
"faceMaterial": {
"connections": [
{
"node": "eb3040ea87ee07c3",
"output": "result",
"data": {}
}
]
}
},
"position": [
7217.627028488199,
1685.691706959804
]
},
"eb3040ea87ee07c3": {
"id": "eb3040ea87ee07c3",
"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": "#000000",
"emissiveColor": "#000000",
"metallic": 0.9,
"roughness": 0.23,
"alpha": 1,
"backFaceCulling": false,
"zOffset": 2
},
"inputs": {},
"position": [
6844.143721750346,
1723.6048498848063
]
}
}
}

Understanding the Workflow: Step-by-Step Breakdown

Let's examine how this complex example demonstrates advanced compound usage by breaking down the key phases:

Phase 1: Surface Creation Through Lofting

The workflow begins by creating a complex curved surface that will serve as the foundation for our hexagonal pattern. This involves several steps:

  1. Point Definition: Three distinct sets of 3D points define the profile curves at different heights - bottom, middle, and top levels with varying shapes and positions.

  2. Wire Interpolation: Each point set is converted into smooth interpolated wires using interpolatePoints(), creating the skeletal framework for the surface.

  3. Surface Lofting: The three wires are lofted together using operations.loft() to create a complex curved surface that transitions smoothly between the different profile shapes.

This foundational surface provides the 3D canvas on which our hexagonal pattern will be projected.

Phase 2: Dual Pattern Generation

The core innovation of this example lies in creating two complementary hexagonal patterns on the same surface:

  1. Primary Pattern: The surface is subdivided using face.subdivideToHexagonWires() with standard parameters, creating an array of hexagonal wire outlines.

  2. Secondary Pattern: A second subdivision is created using the same parameters but with added scaling factors (scalePatternU and scalePatternV set to 0.7), producing smaller hexagons that nest within the primary pattern.

  3. Wire Direction Management: The wires from the secondary pattern are reversed using wire.reversedWire() to ensure proper face creation when combined with the primary pattern wires.

Phase 3: Frame Construction and Strategic Grouping

The two wire sets are combined to create individual hexagonal frames:

  1. Frame Assembly: Each hexagon frame is created by pairing a wire from the primary pattern with the corresponding reversed wire from the secondary pattern, then using face.createFaceFromWires() to create the actual geometric face.

  2. Pattern-Based Filtering: Using bitbybit.lists.getByPattern(), the frames are separated into logical groups. The patterns [true, true, false] and [false, false, true] create alternating groupings that distribute the frames across different visual layers.

  3. Compound Creation: Each filtered group is consolidated into a separate compound using compound.makeCompound(), transforming hundreds of individual faces into just two cohesive entities.

Phase 4: Optimized Rendering with Material Differentiation

The final phase demonstrates the rendering advantages of compounds:

  1. Material Assignment: Different materials are created for each compound group - a purple metallic material for the first compound and a black metallic material for the second.

  2. Single Draw Calls: Instead of rendering each hexagonal frame individually (which could be hundreds of draw calls), only two bitbybit.draw.drawAnyAsync() calls are made - one for each compound.

  3. Unified Processing: The graphics pipeline processes each compound as a single mesh, dramatically reducing computational overhead while maintaining the visual complexity of the pattern.

Performance Impact Analysis

This example demonstrates several critical performance optimizations that compounds enable:

GPU Efficiency: Without compounds, a pattern with 280 hexagonal frames would require 280 separate GPU draw calls. With compounds, this reduces to just 2 draw calls - a 99% reduction in rendering overhead.

Memory Consolidation: Individual geometries each require separate memory allocation and management. Compounds consolidate this into unified memory blocks, reducing fragmentation and improving cache efficiency.

Transformation Performance: If you needed to rotate or translate this entire pattern, compounds allow you to transform both groups with just two operations instead of potentially hundreds of individual transformations.

Material Management: Rather than managing materials for hundreds of individual objects, you only need to manage materials for the compound groups, simplifying state changes and reducing GPU state switching overhead.

Best Practices for Complex Patterns

This example illustrates several important patterns for effective compound usage:

  1. Logical Grouping: Group geometries that share similar properties (materials, transformation behavior, visibility states) into the same compound.

  2. Pattern-Based Organization: Use systematic filtering (like the pattern-based selection shown) to create logical hierarchies rather than arbitrary groupings.

  3. Strategic Timing: Create compounds after all individual geometry generation is complete but before rendering operations begin.

  4. Balance Complexity: While compounds improve performance, extremely large compounds can become unwieldy. Consider breaking very large patterns into multiple logical compound groups.

  5. Material Strategy: Design your material workflow around compound groupings rather than individual geometries to maximize the rendering efficiency gains.

This advanced example demonstrates how compounds scale from simple grouping mechanisms to sophisticated performance optimization tools in complex parametric design workflows.