Creating Game Data

IFC (Industry Foundation Classes) format support

1. Introduction

Castle Game Engine supports loading 3D models in the IFC (Industry Foundation Classes) format.

IFC example in Castle Game Engine Same IFC example loaded in Blender (with BonsaiBIM add-on) Same IFC example loaded in FreeCAD

2. What is IFC?

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:

  • FreeCAD, BonsaiBIM support it as a "first-class citizen", so they can load, save and internally they "think" using IFC concepts,

  • popular proprietary CAD software like Revit, ArchiCAD can export to this format too.

If you want to learn more about the IFC format, follow these links:

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.

3. Testing

  1. 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:

    Then open it using Castle Model Viewer.

  2. 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.

4. Supported IFC features

4.1. Saving and loading

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.
Note
If you’re looking for conversion between .ifcjson and .ifc (STEP encoding), you can use the Python conversion scripts (our fork with some fixes).

4.2. Display and conversion to X3D nodes

We convert a lot of "presentational" IFC entities to X3D nodes and display them.

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.

4.3. Utilities and examples

We define some utility methods to operate on IFC classes:

These utility methods provide easy API to perform common operations, like adding and moving elements represented by transformed meshes. These utilities are not strictly necessary to build/modify IFC content, but they make some usage simpler.

Examples:

  • See lower on this page for example usage of these methods to easily add walls and floors.

  • Our example examples/ifc/ shows the usage of these methods to make a small IFC editor in Castle Game Engine, that can load, save and display IFC models. The created IFC files can be then opened in other IFC tools, like BonsaiBIM or FreeCAD.

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!

4.4. Interchange with other IFC tools, like BonsaiBIM and FreeCAD

The IFC files saved by our engine can be opened back in other IFC tools like BonsaiBIM and FreeCAD (after conversion from IFC JSON to STEP using Python conversion scripts). They work regardless if you build IFC structure from scratch in our engine or load + modify some existing IFC model.

This allows to develop a specialized IFC tools in Castle Game Engine that can be used in the IFC ecosystem. We can consume and produce IFC files that "play well" with other software, and everything "thinks" using IFC classes.

To test this, IFC files produced by our example examples/ifc/ can be verified to look the same in BonsaiBIM and FreeCAD:

IFC example in Castle Game Engine Same IFC example loaded in Blender (with BonsaiBIM add-on) Same IFC example loaded in FreeCAD
Note
Above, we added some lights for display in our engine, just to make it look fancy :) These are not part of the IFC standard. There are other graphic features in our engine you could use, like shadows using shadow volumes, tweaking MyScene.RenderOptions.WireframeEffect.

5. Loading IFC in TCastleScene

Basically, you don’t need to learn anything new to use IFC with Castle Game Engine.

Load a sample IFC file:

Just follow the manual page about viewports and scenes and subsequent pages about TCastleScene usage.

You can also use the LoadNode method to load TX3DRootNode instance, without the need for a full TCastleScene. This makes sense if you don’t need to display the model at all.

Note

The IFC files follow the convention of "Z axis is up". This is different to Castle Game Engine convention (consistent with glTF, X3D, and some other game engines) of "Y axis is up".

Sometimes you can just ignore this difference. Everything works. Just setup your camera to look natural with "Z up".

But for most projects, we advise to display IFC models to follow the "Y up" convention. This will make e.g. physics works in natural way (our gravity pulls down in -Y by default). And it will make IFC models match glTF and X3D models better. To do this you can rotate the TCastleScene instance (where the IFC model is loaded) by 90 degrees around X axis. Just set MyIfcScene.Rotation to Vector4(1, 0, 0, Deg(-90)).

6. Working with IFC classes (native IFC in Castle Game Engine)

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:

  1. Save to result back to file using IfcJsonSave. Like this:

    IfcJsonSave(IfcFile, 'output.ifcjson');
  2. 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;
  3. 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;
      Wall: TIfcWall;
    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
          Wall := TIfcWall.Create(IfcFile);
          Wall.AddBoxRepresentation(IfcFile.Project.ModelContext,
            Box3D(
              Vector3(0, 0, 0),
              Vector3(10, 0.5, 2) // Z is "up", by convention, in IFC
            ));
          IfcFile.Project.BestContainer.AddContainedElement(Wall);
    
          // 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;
    end;

Consult the examples/ifc/ example application (in the engine sources) for a full code following this approach.

7. Credits

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.

Creating Game Data