IFC is a standard format for storing building information models (BIM). It is used in the architecture, engineering and construction (AEC) industry.
It’s an open, vendor-neutral and non-proprietary format, which means everyone has access to the full specification how everything should work and everyone can implement it. And it is supported by a lot of software:
An excellent overview of the format goals is in this video: Introduction to OpenBIM, Native IFC, and Open Source AEC.
Specifications:
Related links:
As we like open 3D standards in Castle Game Engine (Michalis is preaching about his love for glTF and X3D at various conferences) so IFC naturally joins our capabilities.
First of all, you can just open any supported IFC file with any of our tools. Like this:
Get or make a sample IFC file:
For example take one of the testcases from Community-Sample-Test-Files for IFC 4.x. Rename the file from .json
→ .ifcjson
.
Or create IFC file using Blender and BonsaiBIM add-on, a great add-on that turns Blender into a full-featured IFC editor. Save the IFC to .ifcjson
format.
Then open it using Castle Model Viewer.
Check out the dedicated example using IFC classes to add and modify walls, that can load, save and display IFC models. It’s in the examples/ifc/ directory of the engine sources.
We can load and save the IFC entities listed in API docs of CastleIfc
unit. This includes over 100 classes reflecting the IFC specification.
All the defined IFC entities can be loaded and saved to IFC files in the JSON encoding, with the .ifcjson
extension.
Note
|
We require to use .ifcjson extension for IFC files in JSON encoding, not just .json . That’s because we also support another popular format, Spine animations, that uses .json extension.
|
We convert a lot of "presentational" IFC entities to X3D nodes and display them.
A lot of IFC content is just "metadata" for our engine, that is: we load and save it, and you can use it from Pascal (by looking at IFC classes properties, or by looking at X3D nodes metadata like MyGroup.MetadataString['IFC_Name']
, MyGroup.MetadataString['IFC_Description']
). But it doesn’t affect the display in any way.
We load various IFC containers and lists to the corresponding X3D TGroupNode
.
The transformation hierarchy (following TIfcObjectPlacement
including TIfcObjectPlacement.PlacementRelTo
) is expressed using X3D TTransformNode
.
We display these 3D shape entities:
lines: TIfcPolyline
in IFC, TLineSetNode
in X3D
indexed lines: TIfcIndexedPolyCurve
in IFC, TIndexedLineSetNode
in X3D
extrusion of a cross-section along a direction: TIfcExtrudedAreaSolid
in IFC, TExtrusionNode
in X3D
mesh: TIfcPolygonalFaceSet
in IFC, TIndexedFaceSetNode
in X3D
Our conversion from IFC to X3D allows to display IFC models using Castle Game Engine (using TCastleScene
) and allows to literally convert between model formats, from IFC to any format we can save (X3D, STL, and soon glTF).
X3D nodes can be mapped back to IFC classes, which is useful e.g. for picking 3D objects using mouse. Castle Game Engine has APIs to determine what X3D node has been picked, and then you can map it back to an IFC "product" (like a wall, a window, a door) using TCastleIfcMapping.NodeToProduct
.
Note
|
Let us know if you need more features related to IFC. Bug reports and PRs are welcome, as well as donations toward the IFC support, we’re happy to provide commercial support for companies too. We’re committed to IFC support. Michalis talks at conferences how he loves open 3D standards --- well, IFC is one of them! |
Basically, you don’t need to learn anything new to use IFC with Castle Game Engine.
Load a sample IFC file:
using the TCastleSceneCore.Load
method,
or by setting TCastleSceneCore.Url
property to the IFC file.
Just follow the manual page about viewports and scenes and subsequent pages about TCastleScene
usage.
You can then modify the TCastleScene
contents (a set of X3D nodes rooted in TCastleSceneCore.RootNode
) and save it back to IFC using the TCastleSceneCore.Save
method.
Warning
|
TODO: Saving described above (from X3D → IFC) is not yet implemented. It is possible we will implement it. For now, it is actually more powerful to use the approach described lower, to work directly with IFC classes and save using IfcJsonSave .
|
You can also use the LoadNode
and SaveNode
methods to load and save TX3DRootNode
instance, without the need for a full TCastleScene
. This makes sense if you don’t need to display the model at all.
There is another way to use IFC support that allows you to utilize the full power of IFC and work directly with IFC classes. All IFC entities and other types are expressed as natural Pascal classes, enums etc.
In contrast to the approach described in the previous section ("Loading and saving IFC in TCastleScene"), where you load and save IFC files but your "single source of truth" about the model is the state of TCastleScene
(which means: set of X3D nodes), in this new approach your "single source of truth" is your hierarchy of IFC classes. This approach is also called "native BIM" by various tools in the IFC ecosystem.
The advantage of this approach is that you work with the IFC concepts directly. You can modify the IFC data, and make the displayed scene to reflect the changes. So:
You use classes from CastleIfc
unit, following exactly the same concepts and names as the IFC specification.
You don’t wonder "how this metadata was mapped to X3D node" because you don’t need to inspect X3D nodes to investigate what’s inside the IFC file.
Round-trip (read IFC, save it back) preserves exactly the input. Because you keep the TIfcFile
instance existing. You load to TIfcFile
, keep it and modify it, then save it back to file.
In contrast, when working only with TX3DRootNode
and discarding the IFC-native information, the writer has to create new IFC data from X3D nodes, inside X3DToIfc
.
This necessarily "drops" some information (otherwise we’d need to replicate all the IFC information using only X3D metadata, which would be a big work given lots of IFC classes and concepts that are hard to transfer both ways like IFC PlacementRelTo
; and it would likely be unnecessary work — since people who want to use IFC natively are better served by just using IFC classes from Pascal).
To follow this approach, load IFC files using IfcJsonLoad
:
var
IfcFile: TIfcFile;
begin
IfcFile := IfcJsonLoad('castle-data:/my_file.ifcjson');
// ...
end;
and then operate on the loaded IfcFile
, exploring the properties of TIfcFile
and everything inside, rooted in TIfcFile.Project
. The documentation of all the IFC classes is part of our API documentation: see CastleIfc
.
Inspect and modify the properties of IFC classes as you wish. At one point, you can:
Save to result back to file using IfcJsonSave
. Like this:
IfcJsonSave(IfcFile, 'output.ifcjson');
Convert the IFC to a set of X3D nodes (to display them using TCastleScene
) using IfcToX3D
. If you only want to do it once, do it like this (but if you want to do it multiple times, read next point):
var
MyRoot: TX3DRootNode;
begin
MyRoot := IfcToX3D(IfcFile);
MyScene.Load(MyRoot, true);
end;
You can also load and then efficiently update multiple times the displayed scene (update display each time when you change the IFC classes).
This is done by using TCastleIfcMapping
class. Like this:
var
IfcFile: TIfcFile;
IfcMapping: TCastleIfcMapping;
begin
IfcFile := IfcFromJson('castle-data:/my_file.ifcjson');
try
IfcMapping := TCastleIfcMapping.Create;
try
// convert IfcFile to X3D, in a way that allows to efficiently update it later
IfcMapping.Load(IfcFile, 'castle-data:/');
// display the result using MyScene:TCastleScene; it will own the IfcMapping.RootNode
MyScene.Load(IfcMapping.RootNode, true);
// modify IfcFile, e.g. add a new wall
// TODO make this example correct, but still try to keep it as simple as possible
IfcFile.Walls.Add(TIfcWall.Create);
// modify the contents of RootNode, to reflect above new wall.
// the MyScene displaying it will automatically reflect the changes
IfcMapping.Update(IfcFile);
finally FreeAndNil(IfcMapping) end;
finally FreeAndNil(IfcFile)
end;
Consult the examples/ifc/ example application (in the engine sources) for a full code following this approach.
This work has been sponsored by the Sorpetaler Fensterbau GmbH company. Thank you!
To improve this documentation just edit this page and create a pull request to cge-www repository.