Slide 1

Slide 1 text

IFC5 Technical prototypes Thomas Krijnen – Aug 29, Denver CO, USA https:/ /speakerdeck.com/aothms

Slide 2

Slide 2 text

Prototype - v1 https:/ /github.com/AECgeeks/ecs-prototype Lessons learned: - type relationships (where components are ‘inherited’ from type to occurence) are necessary to maintain IFC<=4 functionality - type relationships are somewhat complex and deserve should not be modelled as regular components - id prefixing for instantiated ‘typical’ parts - name/tag as an additional key to bind a component to an entity (e.g RepresentationIdentifier, PropertySet.Name)

Slide 3

Slide 3 text

Prototype - v1 https:/ /github.com/AECgeeks/ecs-prototype

Slide 4

Slide 4 text

Prototype - v1 https:/ /github.com/AECgeeks/ecs-prototype

Slide 5

Slide 5 text

Prototype – v2 https:/ /github.com/tomvandig/eccg

Slide 6

Slide 6 text

Prototype – v2 https:/ /github.com/tomvandig/eccg Lessons learned: - Name prefix everything. Not just ‘typical parts’. - Think about composition at a fundamental level, not just as another ordinary component

Slide 7

Slide 7 text

Prototype – v3 https:/ /github.com/tomvandig/schema-lang/tree/master - Universal tree in serialization simplifies composition for end-user and developer - Maintain a strict separation between naming+placement and domain-specific schema definitions. An element’s name path does not equate to it’s domain- specific decomposition path. - Classification only through components is sometimes somewhat painful - Importance of schemas and validation - Inclusion of layers as ‘conflict-free multi-author data composition’

Slide 8

Slide 8 text

Prototype – v3 https:/ /github.com/tomvandig/schema-lang/tree/master

Slide 9

Slide 9 text

Prototype – v4 https:/ /github.com/aothms/ifc-usdj - USD-compatibility is possible without the bagage and platform inneutrality of C++ OpenUSD. - USD composition unifies several concepts that are currently expressed as schema-level mechanisms in IFC or ECS-based prototypes. Such as occurence-type, mapped-item and perhaps also property set relationships.

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

Prototype – v5 A component-based reinterpretation of procedural geometry graphs is possible. Where components are universal triangle meshes, but with appropriate tagging their procedural role is annotated. NB: The geometry is still fully explicit and static. Akin to IFC4 ReferenceView (which was an inversion from complexity to reliability).

Slide 14

Slide 14 text

#usda 1.0 ( upAxis = "Z" ) def Xform "wall" { matrix4d xformOp:transform = ( (0, -1, 0, 0), (1, 0, 0, ... uniform token[] xformOpOrder = ["xformOp:transform"] def Xform "ifc5" { def Mesh "body" { int[] faceVertexCounts = [3, 3, 3, 3, 3, 3, 3, 3... int[] faceVertexIndices = [3, 118, 117, 118, 3, ... point3f[] points = [(0.3, -0.3, 0), (9.7, -0.3, ... } def BasisCurves "directrix" { int[] curveVertexCounts = [2] point3f[] points = [(0, -0.3, 0), (0, -0.3, 3.5)] uniform token type = "linear" float[] widths = [0.01, 0.01] } def Mesh "basis" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(0.3, -0.3, 0), (9.7, -0.3, ... } def "clip" { def Mesh "plane0" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(-0.01, -0.31, 0.4942265... } def Mesh "plane1" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(5, -0.31, 3.3867514), (... } } } def Xform "window" { matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, ... uniform token[] xformOpOrder = ["xformOp:transform"] def Xform "ifc5" { def Mesh "void" { int[] faceVertexCounts = [3, 3, 3, 3, 3, 3, ... int[] faceVertexIndices = [1, 0, 3, 2, 1, 3,... point3f[] points = [(-0.5, -0.115, 0.5), (-0... } } } }

Slide 15

Slide 15 text

#usda 1.0 ( upAxis = "Z" ) def Xform "wall" { matrix4d xformOp:transform = ( (0, -1, 0, 0), (1, 0, 0, ... uniform token[] xformOpOrder = ["xformOp:transform"] def Xform "ifc5" { def Mesh "body" { int[] faceVertexCounts = [3, 3, 3, 3, 3, 3, 3, 3... int[] faceVertexIndices = [3, 118, 117, 118, 3, ... point3f[] points = [(0.3, -0.3, 0), (9.7, -0.3, ... } def BasisCurves "directrix" { int[] curveVertexCounts = [2] point3f[] points = [(0, -0.3, 0), (0, -0.3, 3.5)] uniform token type = "linear" float[] widths = [0.01, 0.01] } def Mesh "basis" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(0.3, -0.3, 0), (9.7, -0.3, ... } def "clip" { def Mesh "plane0" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(-0.01, -0.31, 0.4942265... } def Mesh "plane1" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(5, -0.31, 3.3867514), (... } } } def Xform "window" { matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, ... uniform token[] xformOpOrder = ["xformOp:transform"] def Xform "ifc5" { def Mesh "void" { int[] faceVertexCounts = [3, 3, 3, 3, 3, 3, ... int[] faceVertexIndices = [1, 0, 3, 2, 1, 3,... point3f[] points = [(-0.5, -0.115, 0.5), (-0... } } } }

Slide 16

Slide 16 text

#usda 1.0 ( upAxis = "Z" ) def Xform "wall" { matrix4d xformOp:transform = ( (0, -1, 0, 0), (1, 0, 0, ... uniform token[] xformOpOrder = ["xformOp:transform"] def Xform "ifc5" { def Mesh "body" { int[] faceVertexCounts = [3, 3, 3, 3, 3, 3, 3, 3... int[] faceVertexIndices = [3, 118, 117, 118, 3, ... point3f[] points = [(0.3, -0.3, 0), (9.7, -0.3, ... } def BasisCurves "directrix" { int[] curveVertexCounts = [2] point3f[] points = [(0, -0.3, 0), (0, -0.3, 3.5)] uniform token type = "linear" float[] widths = [0.01, 0.01] } def Mesh "basis" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(0.3, -0.3, 0), (9.7, -0.3, ... } def "clip" { def Mesh "plane0" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(-0.01, -0.31, 0.4942265... } def Mesh "plane1" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(5, -0.31, 3.3867514), (... } } } def Xform "window" { matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, ... uniform token[] xformOpOrder = ["xformOp:transform"] def Xform "ifc5" { def Mesh "void" { int[] faceVertexCounts = [3, 3, 3, 3, 3, 3, ... int[] faceVertexIndices = [1, 0, 3, 2, 1, 3,... point3f[] points = [(-0.5, -0.115, 0.5), (-0... } } } }

Slide 17

Slide 17 text

#usda 1.0 ( upAxis = "Z" ) def Xform "wall" { matrix4d xformOp:transform = ( (0, -1, 0, 0), (1, 0, 0, ... uniform token[] xformOpOrder = ["xformOp:transform"] def Xform "ifc5" { def Mesh "body" { int[] faceVertexCounts = [3, 3, 3, 3, 3, 3, 3, 3... int[] faceVertexIndices = [3, 118, 117, 118, 3, ... point3f[] points = [(0.3, -0.3, 0), (9.7, -0.3, ... } def BasisCurves "directrix" { int[] curveVertexCounts = [2] point3f[] points = [(0, -0.3, 0), (0, -0.3, 3.5)] uniform token type = "linear" float[] widths = [0.01, 0.01] } def Mesh "basis" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(0.3, -0.3, 0), (9.7, -0.3, ... } def "clip" { def Mesh "plane0" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(-0.01, -0.31, 0.4942265... } def Mesh "plane1" { int[] faceVertexCounts = [4] int[] faceVertexIndices = [0, 1, 2, 3] point3f[] points = [(5, -0.31, 3.3867514), (... } } } def Xform "window" { matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, ... uniform token[] xformOpOrder = ["xformOp:transform"] def Xform "ifc5" { def Mesh "void" { int[] faceVertexCounts = [3, 3, 3, 3, 3, 3, ... int[] faceVertexIndices = [1, 0, 3, 2, 1, 3,... point3f[] points = [(-0.5, -0.115, 0.5), (-0... } } } }

Slide 18

Slide 18 text

Equivalent IFC4 monster

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Entity Component * Prim API Schema IsA Schema 1 parent 1 * Schema Non-applied Single-applied Multi-applied ECS qualities of USD

Slide 21

Slide 21 text

Observations Schema language is also USD. So you can compose on schema level as well (e.g publish Addenda and TC as new layers) Schema language is not very expressive in terms of constraining relationships or cardinality (but can be added as userdefined data in the schema for a bespoke validator). USD allows user-defined data on prims so things like PropertySingleValue (wrap user-defined data in a class) is not necessary. But standardized property sets can equally well be layered schemas.

Slide 22

Slide 22 text

Observations We don’t necessarily need to define IsA schemas in IFC5 (it would make things a bit more OOPy with inheritance), we can stick to the existing USD ones and treat them as ‘entities’ in ECS. But it can be useful to constrain the possible application of API schemas (apiSchemaCanOnlyApplyTo). E.g so that we cannot apply a material to a property set. I feel this is an under explored part of using a pure ECS in a heterogeneous context. Placement needs to live directly on the Prim, because otherwise it doesn’t participate in the hierarchy.

Slide 23

Slide 23 text

Observations Geometry is also not a APISchema, but would be named subprims (because e.g UsdGeomMesh is an IsA Schema). This is in fact beautiful because it allows to substitute geometry with decomposition. For property sets we need to choose between inheritance, schema relationships or subprims (or references which are inheritance + subprims).

Slide 24

Slide 24 text

Observations The universal tree eliminates the need for a divide between rooted and non-rooted definitions. This is a massive opportunity to clean up duplicated constructs (e.g IfcProfileProperties). But is also a responsibility to form meaningful and consistent trees.