Skip to main content

BREP, STL, OBJ and PLY

File formats split into two families, and the difference decides what you can do with a shape once it comes back.

An exact format keeps the geometry itself: this edge is a circle of radius 3. A mesh format keeps only flat triangles laid over the surface. Both look the same on screen until you come close, but only one can still be filleted, measured to the last digit or cut cleanly.

FormatKeepsSaveRead
BREPExact geometry and topology, in OCCT's own formatsaveShapeBrep, saveShapeBrepBinaryloadBrep, loadBrepBinary
STEP, IGESExact geometry, for other CAD programsSee STEP and IGESSee STEP and IGES
STLTriangles, as 3D printers and slicers read themsaveShapeStlloadStl
OBJTriangles, as most 3D programs read themsaveShapeObjassembly.manager.loadObjToDoc
PLYTriangles with a normal per vertexsaveShapePly-

Each save function starts a browser download. Its ...AndReturn twin also hands the file's contents back to your script, and with tryDownload set to false it skips the download.

The same part both ways​

This drum with rounded edges goes out and comes back twice. Through BREP, 2.6 KB of text, it returns as the same 5 faces. Through STL, 263 KB at a precision of 0.1, it returns as 828 flat triangles. Each triangle is its own face, drawn here with its edges:

Bitbybit Platform

One part, read back from BREP and from STL in Rete

rete logoRete
Script Source (rete)
{
"id": "rete-v2-json",
"nodes": {
"drum": {
"id": "drum",
"name": "bitbybit.occt.shapes.solid.createCylinder",
"customName": "cylinder",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 3,
"height": 5,
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
],
"angle": 360,
"originOnCenter": false
},
"inputs": {},
"position": [
40,
40
]
},
"part": {
"id": "part",
"name": "bitbybit.occt.fillets.filletEdges",
"customName": "fillet edges",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 0.6
},
"inputs": {
"shape": {
"connections": [
{
"node": "drum",
"output": "result",
"data": {}
}
]
}
},
"position": [
460,
40
]
},
"brep": {
"id": "brep",
"name": "bitbybit.occt.io.saveShapeBrepAndReturn",
"customName": "save brep and return",
"async": true,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"fileName": "part.brep",
"tryDownload": false,
"withTriangulation": false
},
"inputs": {
"shape": {
"connections": [
{
"node": "part",
"output": "result",
"data": {}
}
]
}
},
"position": [
880,
40
]
},
"stl": {
"id": "stl",
"name": "bitbybit.occt.io.saveShapeStlAndReturn",
"customName": "save shape stl and return",
"async": true,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"fileName": "part.stl",
"precision": 0.1,
"adjustYtoZ": false,
"tryDownload": false,
"binary": false
},
"inputs": {
"shape": {
"connections": [
{
"node": "part",
"output": "result",
"data": {}
}
]
}
},
"position": [
880,
380
]
},
"exact": {
"id": "exact",
"name": "bitbybit.occt.io.loadBrep",
"customName": "load brep",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"brepData": {
"connections": [
{
"node": "brep",
"output": "result",
"data": {}
}
]
}
},
"position": [
1300,
40
]
},
"facets": {
"id": "facets",
"name": "bitbybit.occt.io.loadStl",
"customName": "load stl",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"asFaces": true,
"adjustZtoY": false
},
"inputs": {
"stlData": {
"connections": [
{
"node": "stl",
"output": "result",
"data": {}
}
]
}
},
"position": [
1300,
280
]
},
"beside": {
"id": "beside",
"name": "bitbybit.occt.transforms.translate",
"customName": "translate",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"translation": [
8,
0,
0
]
},
"inputs": {
"shape": {
"connections": [
{
"node": "facets",
"output": "result",
"data": {}
}
]
}
},
"position": [
1720,
40
]
},
"steel": {
"id": "steel",
"name": "bitbybit.draw.optionsOcctShape",
"customName": "options occt shape",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"faceOpacity": 1,
"edgeOpacity": 1,
"edgeColour": "#5f6773",
"faceColour": "#ff0000",
"vertexColour": "#ff00ff",
"edgeWidth": 2,
"edgeWidthBySize": false,
"vertexSize": 0.03,
"drawEdges": true,
"drawFaces": true,
"drawVertices": false,
"precision": 0.01,
"angularDeflection": 0.5,
"relativeDeflection": false,
"precisionShare": 0,
"drawEdgeIndexes": false,
"edgeIndexHeight": 0.06,
"edgeIndexColour": "#ff00ff",
"drawFaceIndexes": false,
"faceIndexHeight": 0.06,
"faceIndexColour": "#0000ff",
"drawTwoSided": false,
"backFaceColour": "#0000ff",
"backFaceOpacity": 1,
"edgeArrowSize": 0,
"edgeArrowAngle": 15,
"keepMeshData": false,
"allowQualityDecrease": true,
"forceFaceDeflection": false,
"drawIsoCurves": false,
"isoCurvesU": 5,
"isoCurvesV": 5,
"isoCurvesColour": "#808080",
"surfaceAnalysis": "none",
"draftDirection": [
0,
1,
0
]
},
"inputs": {
"faceMaterial": {
"connections": [
{
"node": "steelMaterial",
"output": "result",
"data": {}
}
]
}
},
"position": [
460,
380
]
},
"steelMaterial": {
"id": "steelMaterial",
"name": "bitbybit.draw.createPBRMaterial",
"customName": "create pbr material",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"name": "PBRMaterial",
"baseColor": "#eef0f2",
"metallic": 0.7,
"roughness": 0.3,
"alpha": 1,
"emissiveColor": "#000000",
"emissiveIntensity": 1,
"zOffset": 0,
"zOffsetUnits": 0,
"alphaMode": "opaque",
"alphaCutoff": 0.5,
"doubleSided": false,
"wireframe": false,
"unlit": false
},
"inputs": {},
"position": [
40,
472
]
},
"drawExact": {
"id": "drawExact",
"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": "exact",
"output": "result",
"data": {}
}
]
},
"options": {
"connections": [
{
"node": "steel",
"output": "result",
"data": {}
}
]
}
},
"position": [
2140,
40
]
},
"drawBeside": {
"id": "drawBeside",
"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": "beside",
"output": "result",
"data": {}
}
]
},
"options": {
"connections": [
{
"node": "steel",
"output": "result",
"data": {}
}
]
}
},
"position": [
2140,
334
]
},
"view": {
"id": "view",
"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": [
6,
13,
-19
],
"lookAt": [
4,
2,
0
],
"lowerBetaLimit": 1,
"upperBetaLimit": 179,
"angularSensibilityX": 1000,
"angularSensibilityY": 1000,
"maxZ": 1000,
"panningSensibility": 1000,
"wheelPrecision": 3
},
"inputs": {},
"position": [
2140,
628
]
}
},
"modules": {}
}

loadStl has two ways to read a file. With asFaces on, each triangle becomes a planar face, as here, which sewing can join into a shell. With it off, one face carries the whole mesh, which is light to draw but not for modelling.

precision sets how far a triangle may stray from the surface when a mesh is written. A smaller number gives a smoother surface and a larger file.

Which to use​

  • To keep working on a shape in Bitbybit, use BREP: loadBrep brings back the same shape, placement and orientation included.
  • To hand a shape to another CAD program, use STEP.
  • To print a shape, use STL. To take it into a 3D program, use OBJ or glTF.