Browse Source

Primitives: support texture coordinates and tangents in cubeSolid().

Well, guess why I was postponing this for so long, because there are way
too many combinations, then there's too many ways each variant can go
wrong, one has to document and test everything REAL GOOd and even then
it likely doesn't contain all variants people may want.
pull/674/head
Vladimír Vondruš 12 months ago
parent
commit
0f7598220d
  1. 1315
      doc/artwork/primitives-cube.svg
  2. 4
      doc/snippets/README.md
  3. 45
      doc/snippets/primitives-cube-all-same.svg
  4. 50
      doc/snippets/primitives-cube-negative-x-up-negative-x-down.svg
  5. 52
      doc/snippets/primitives-cube-negative-x-up-negative-z-down.svg
  6. 45
      doc/snippets/primitives-cube-negative-x-up-positive-x-down.svg
  7. 47
      doc/snippets/primitives-cube-negative-x-up-positive-z-down.svg
  8. 50
      doc/snippets/primitives-cube-positive-up-negative-down.svg
  9. 42
      doc/snippets/primitives-cube-positive-z-up-positive-x-down.svg
  10. 45
      doc/snippets/primitives-cube-positive-z-up-positive-z-down.svg
  11. 2
      src/Magnum/Primitives/CMakeLists.txt
  12. 511
      src/Magnum/Primitives/Cube.cpp
  13. 119
      src/Magnum/Primitives/Cube.h
  14. 2
      src/Magnum/Primitives/Test/CMakeLists.txt
  15. 506
      src/Magnum/Primitives/Test/CubeTest.cpp

1315
doc/artwork/primitives-cube.svg

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 171 KiB

4
doc/snippets/README.md

@ -36,3 +36,7 @@ The `doc/artwork/line-quad-data-other.svg` is derived from
making the canvas smaller, the `doc/artwork/line-quad-data.svg` is then derived making the canvas smaller, the `doc/artwork/line-quad-data.svg` is then derived
from `doc/artwork/line-quad-data-other.svg` by removing the "other" layer and from `doc/artwork/line-quad-data-other.svg` by removing the "other" layer and
making the canvas smaller yet again. making the canvas smaller yet again.
### primitives-cube-*.svg
Like above, created from `doc/artwork/primitives-cube.svg`.

45
doc/snippets/primitives-cube-all-same.svg

@ -0,0 +1,45 @@
<svg viewBox="0 0 176 136" style="width: 176px; height: 136px;" class="m-image">
<defs>
<marker id="c" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="a" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="b" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="d" overflow="visible" markerHeight="1" markerWidth="1" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke"/>
</marker>
</defs>
<g>
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<path transform="translate(-2.3651 -68.775)" d="m34.365 172.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<g stroke="#2f83cc">
<path transform="translate(-2.3651 -68.775)" d="m74.365 172.78v-32" marker-end="url(#b)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path transform="translate(-2.3651 -68.775)" d="m66.365 132.78h-32" marker-end="url(#b)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path transform="translate(-2.3651 -68.775)" d="m34.365 172.78h32" marker-end="url(#b)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<path transform="translate(-2.3651 -68.775)" d="m74.365 100.78h32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path transform="translate(-2.3651 -68.775)" d="m114.37 132.78v-32" marker-end="url(#d)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path transform="translate(-2.3651 -68.775)" d="m74.365 172.78h32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path transform="translate(-2.3651 -68.775)" d="m114.37 132.78h32" marker-end="url(#a)" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path transform="translate(-2.3651 -68.775)" d="m146.37 172.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path transform="translate(-2.3651 -68.775)" d="m146.37 172.78h-32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path transform="translate(-2.3651 -68.775)" d="m74.365 100.78v32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path transform="translate(-2.3651 -68.775)" d="m66.365 132.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<g font-family="'Source Sans Pro'">
<text transform="matrix(3.7795 0 0 3.7795 -295.82 -188.5)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -255.96 -188.5)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Y</tspan></text>
<text transform="translate(-2.3651 -68.775)" x="130.15706" y="162.02304" dominant-baseline="auto" fill="#2f83cc" font-size="16px" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="130.15706" y="162.02304" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="16px" stop-color="#000000" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Z</tspan></text>
<g font-size="4.2334px" stroke-width=".26458">
<text transform="matrix(3.7795 0 0 3.7795 -215.96 -228.5)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -295.6 -228.5)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -255.66 -228.5)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Y</tspan></text>
</g>
</g>
<rect x="28" y="8" width="120" height="120" fill="none" stroke="#dcdcdc" stroke-linecap="round" stroke-linejoin="round" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

50
doc/snippets/primitives-cube-negative-x-up-negative-x-down.svg

@ -0,0 +1,50 @@
<svg viewBox="0 0 176 136" style="width: 176px; height: 136px;" class="m-image">
<defs>
<marker id="c" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="a" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="b" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="d" overflow="visible" markerHeight="1" markerWidth="1" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke"/>
</marker>
</defs>
<g transform="translate(-2.3651 -68.775)">
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="m126.37 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m126.37 152.78h-32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78h-32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78h32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78v-32" marker-end="url(#d)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 112.78h32" marker-end="url(#b)" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<g stroke="#cd3431">
<path d="m54.365 152.78h32" marker-end="url(#a)" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 112.78v-32" marker-end="url(#a)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 160.78v32" marker-end="url(#a)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<path d="m54.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<g font-family="'Source Sans Pro'" font-size="4.2334px" stroke-width=".26458" text-anchor="middle">
<text transform="matrix(3.7795 0 0 3.7795 -313.45 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -273.59 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -233.51 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -193.65 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -313.24 -179.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Y</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -313.29 -99.721)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Y</tspan></text>
</g>
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<g stroke="#dcdcdc">
<path d="m10.365 76.775h40v120h-40z" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m10.365 116.78h160v40h-160" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m90.365 116.78v40" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m130.37 116.78v40" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<path d="m14.365 160.78h32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

52
doc/snippets/primitives-cube-negative-x-up-negative-z-down.svg

@ -0,0 +1,52 @@
<svg viewBox="0 0 176 136" style="width: 176px; height: 136px;" class="m-image">
<defs>
<marker id="c" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="a" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="b" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="d" overflow="visible" markerHeight="1" markerWidth="1" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke"/>
</marker>
</defs>
<g transform="translate(-2.3651 -68.775)">
<g font-family="'Source Sans Pro'" font-size="4.2334px" stroke-width=".26458">
<text transform="matrix(3.7795 0 0 3.7795 -313.45 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -273.59 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -233.51 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -193.65 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -313.24 -179.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Y</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -193.29 -99.721)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Y</tspan></text>
</g>
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<g stroke="#dcdcdc">
<path d="m10.365 116.78v-40h40v80" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m90.365 116.78v40" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m130.37 116.78v80h40v-40" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m10.365 116.78h160v40h-160z" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<g>
<path d="m54.365 152.78h32" marker-end="url(#a)" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m126.37 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m126.37 152.78h-32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78h-32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78h32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78v-32" marker-end="url(#d)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 112.78h32" marker-end="url(#b)" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 112.78h32" marker-end="url(#b)" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<g stroke="#cd3431">
<path d="m54.365 152.78h32" marker-end="url(#a)" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 112.78v-32" marker-end="url(#a)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 160.78h-32" marker-end="url(#a)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<path d="m166.37 160.78v32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

45
doc/snippets/primitives-cube-negative-x-up-positive-x-down.svg

@ -0,0 +1,45 @@
<svg viewBox="0 0 176 136" style="width: 176px; height: 136px;" class="m-image">
<defs>
<marker id="c" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="a" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="b" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="d" overflow="visible" markerHeight="1" markerWidth="1" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke"/>
</marker>
</defs>
<g transform="translate(-2.3651 -68.775)">
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="m126.37 192.78v-32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m126.37 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m126.37 152.78h-32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78h-32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78h32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78v-32" marker-end="url(#d)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 112.78h32" marker-end="url(#b)" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 152.78h32" marker-end="url(#a)" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 112.78v-32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m126.37 192.78h-32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<g font-family="'Source Sans Pro'" font-size="4.2334px" stroke-width=".26458" text-anchor="middle">
<text transform="matrix(3.7795 0 0 3.7795 -313.45 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -273.59 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -233.51 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -193.65 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -313.24 -179.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Y</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -233.29 -99.721)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Y</tspan></text>
</g>
<g fill="none" stroke="#dcdcdc" stroke-linecap="round" stroke-linejoin="round">
<path d="m10.365 116.78h160v40h-160" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m10.365 156.78v-80h40v80" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m90.365 116.78v80h40v-80" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

47
doc/snippets/primitives-cube-negative-x-up-positive-z-down.svg

@ -0,0 +1,47 @@
<svg viewBox="0 0 176 136" style="width: 176px; height: 136px;" class="m-image">
<defs>
<marker id="c" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="a" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="b" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="d" overflow="visible" markerHeight="1" markerWidth="1" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke"/>
</marker>
</defs>
<g transform="translate(-2.3651 -68.775)">
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<g>
<path d="m126.37 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m126.37 152.78h-32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78h-32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78h32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78v-32" marker-end="url(#d)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 112.78h32" marker-end="url(#b)" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<g stroke="#cd3431">
<path d="m54.365 152.78h32" marker-end="url(#a)" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 112.78v-32" marker-end="url(#a)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m86.365 192.78h-32" marker-end="url(#a)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<path d="m86.365 192.78v-32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path transform="translate(2.3651 68.775)" d="m8 88v-80h40v120h40v-80" stop-color="#000000" stroke="#dcdcdc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<g font-family="'Source Sans Pro'" font-size="4.2334px" stroke-width=".26458" text-anchor="middle">
<text transform="matrix(3.7795 0 0 3.7795 -313.45 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -273.59 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -233.51 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -193.65 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -313.24 -179.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Y</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -273.29 -99.721)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Y</tspan></text>
</g>
<path d="m10.365 116.78h160v40h-160" fill="none" stroke="#dcdcdc" stroke-linecap="round" stroke-linejoin="round" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m130.37 116.78v40" fill="none" stroke="#dcdcdc" stroke-linecap="round" stroke-linejoin="round" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

50
doc/snippets/primitives-cube-positive-up-negative-down.svg

@ -0,0 +1,50 @@
<svg viewBox="0 0 176 136" style="width: 176px; height: 136px;" class="m-image">
<defs>
<marker id="c" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="a" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="b" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="d" overflow="visible" markerHeight="1" markerWidth="1" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke"/>
</marker>
</defs>
<g transform="translate(-2.3651 -68.775)">
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="m34.365 172.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<g stroke="#2f83cc">
<path d="m74.365 172.78v-32" marker-end="url(#b)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m66.365 132.78h-32" marker-end="url(#b)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m34.365 172.78h32" marker-end="url(#b)" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<path d="m74.365 100.78h32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m114.37 132.78v-32" marker-end="url(#d)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m74.365 172.78h32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m114.37 132.78h32" marker-end="url(#a)" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m146.37 172.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m146.37 172.78h-32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m74.365 100.78v32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m66.365 132.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<g font-family="'Source Sans Pro'">
<text transform="matrix(3.7795 0 0 3.7795 -293.45 -119.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -253.59 -119.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Y</tspan></text>
<text x="130.15706" y="162.02304" dominant-baseline="auto" fill="#2f83cc" font-size="16px" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="130.15706" y="162.02304" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="16px" stop-color="#000000" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Z</tspan></text>
<g font-size="4.2334px" stroke-width=".26458">
<text transform="matrix(3.7795 0 0 3.7795 -213.59 -159.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -293.24 -159.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -253.29 -159.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="default"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Y</tspan></text>
</g>
</g>
<g fill="none" stroke="#dcdcdc" stroke-linecap="round" stroke-linejoin="round">
<path d="m30.365 96.775v80h120v-80z" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m70.365 96.775v80" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m110.37 96.775v80" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m30.365 136.78h120" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

42
doc/snippets/primitives-cube-positive-z-up-positive-x-down.svg

@ -0,0 +1,42 @@
<svg viewBox="0 0 176 136" style="width: 176px; height: 136px;" class="m-image">
<defs>
<marker id="c" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="a" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="b" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="d" overflow="visible" markerHeight="1" markerWidth="1" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke"/>
</marker>
</defs>
<g transform="translate(-2.3651 -68.775)">
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="m126.37 192.78v-32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m126.37 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m126.37 152.78h-32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78h-32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78h32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78v-32" marker-end="url(#d)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 80.775v32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 80.775h32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 152.78h32" marker-end="url(#a)" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m126.37 192.78h-32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<g font-family="'Source Sans Pro'" font-size="4.2334px" stroke-width=".26458" text-anchor="middle">
<text transform="matrix(3.7795 0 0 3.7795 -313.45 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -273.59 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -233.51 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -193.65 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -273.59 -179.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Y</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -233.29 -99.721)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Y</tspan></text>
</g>
<path d="m50.365 156.78v-80h40v120h40v-80" fill="none" stroke="#dcdcdc" stroke-linecap="round" stroke-linejoin="round" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m10.365 116.78h160v40h-160z" fill="none" stroke="#dcdcdc" stroke-linecap="round" stroke-linejoin="round" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

45
doc/snippets/primitives-cube-positive-z-up-positive-z-down.svg

@ -0,0 +1,45 @@
<svg viewBox="0 0 176 136" style="width: 176px; height: 136px;" class="m-image">
<defs>
<marker id="c" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="a" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="b" overflow="visible" markerHeight="0.75" markerWidth="0.75" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke" stroke-linecap="round"/>
</marker>
<marker id="d" overflow="visible" markerHeight="1" markerWidth="1" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
<path transform="rotate(180 .125 0)" d="m3-3-3 3 3 3" fill="none" stroke="context-stroke"/>
</marker>
</defs>
<g transform="translate(-2.3651 -68.775)">
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="m126.37 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m126.37 152.78h-32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78h-32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m14.365 152.78h32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m166.37 152.78v-32" marker-end="url(#d)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 80.775h32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 152.78h32" marker-end="url(#a)" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 192.78v-32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 192.78h32" marker-end="url(#a)" stop-color="#000000" stroke="#cd3431" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 80.775v32" marker-end="url(#b)" stop-color="#000000" stroke="#2f83cc" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m54.365 152.78v-32" marker-end="url(#c)" stop-color="#000000" stroke="#3bd267" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
<g font-family="'Source Sans Pro'" font-size="4.2334px" stroke-width=".26458" text-anchor="middle">
<text transform="matrix(3.7795 0 0 3.7795 -313.45 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -273.59 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -233.51 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#cd3431" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+X</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -193.65 -139.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#2f83cc" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Z</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -273.24 -179.72)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">+Y</tspan></text>
<text transform="matrix(3.7795 0 0 3.7795 -273.29 -99.721)" x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" stop-color="#000000" text-align="center" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" xml:space="preserve"><tspan x="90.929169" y="74.545097" dominant-baseline="auto" fill="#3bd267" font-family="'Source Sans Pro'" font-size="4.2334px" stop-color="#000000" stroke-width=".26458" text-align="center" text-anchor="middle" style="-inkscape-stroke:none;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;line-height:1.25;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal">−Y</tspan></text>
</g>
<g fill="none" stroke="#dcdcdc" stroke-linecap="round" stroke-linejoin="round">
<path d="m50.365 76.775h40v120h-40z" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m130.37 116.78v40" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path d="m10.365 116.78h160v40h-160z" style="-inkscape-stroke:none;font-variation-settings:normal"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

2
src/Magnum/Primitives/CMakeLists.txt

@ -31,7 +31,6 @@ set(CMAKE_FOLDER "Magnum/Primitives")
set(MagnumPrimitives_SRCS set(MagnumPrimitives_SRCS
Axis.cpp Axis.cpp
Crosshair.cpp Crosshair.cpp
Cube.cpp
Gradient.cpp Gradient.cpp
Grid.cpp Grid.cpp
Icosphere.cpp Icosphere.cpp
@ -46,6 +45,7 @@ set(MagnumPrimitives_GracefulAssert_SRCS
Capsule.cpp Capsule.cpp
Circle.cpp Circle.cpp
Cone.cpp Cone.cpp
Cube.cpp
Cylinder.cpp Cylinder.cpp
UVSphere.cpp) UVSphere.cpp)

511
src/Magnum/Primitives/Cube.cpp

@ -36,6 +36,10 @@ namespace {
/* not 8-bit because GPUs (and Vulkan) don't like it nowadays */ /* not 8-bit because GPUs (and Vulkan) don't like it nowadays */
constexpr UnsignedShort IndicesSolid[]{ constexpr UnsignedShort IndicesSolid[]{
/* 3--2
| /|
|/ |
0--1 */
0, 1, 2, 0, 2, 3, /* +Z */ 0, 1, 2, 0, 2, 3, /* +Z */
4, 5, 6, 4, 6, 7, /* +X */ 4, 5, 6, 4, 6, 7, /* +X */
8, 9, 10, 8, 10, 11, /* +Y */ 8, 9, 10, 8, 10, 11, /* +Y */
@ -47,34 +51,44 @@ constexpr struct VertexSolid {
Vector3 position; Vector3 position;
Vector3 normal; Vector3 normal;
} VerticesSolid[]{ } VerticesSolid[]{
/* 11----10 23 14----15
/ +Y / 6 /| | |
8------9 / | 22 | | -Z |
3------2 7 | |-X| | |
| | |+X| | 20 13----12
| +Z | | 5 | / 16----17
| | | / 21 / -Y /
0------1 4 19----18 */
/* 0, +Z */
{{-1.0f, -1.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}}, {{-1.0f, -1.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}},
{{ 1.0f, -1.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}}, {{ 1.0f, -1.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}},
{{ 1.0f, 1.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}}, /* +Z */ {{ 1.0f, 1.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}},
{{-1.0f, 1.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}}, {{-1.0f, 1.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}},
/* 4, +X */
{{ 1.0f, -1.0f, 1.0f}, { 1.0f, 0.0f, 0.0f}}, {{ 1.0f, -1.0f, 1.0f}, { 1.0f, 0.0f, 0.0f}},
{{ 1.0f, -1.0f, -1.0f}, { 1.0f, 0.0f, 0.0f}}, {{ 1.0f, -1.0f, -1.0f}, { 1.0f, 0.0f, 0.0f}},
{{ 1.0f, 1.0f, -1.0f}, { 1.0f, 0.0f, 0.0f}}, /* +X */ {{ 1.0f, 1.0f, -1.0f}, { 1.0f, 0.0f, 0.0f}},
{{ 1.0f, 1.0f, 1.0f}, { 1.0f, 0.0f, 0.0f}}, {{ 1.0f, 1.0f, 1.0f}, { 1.0f, 0.0f, 0.0f}},
/* 8, +Y */
{{-1.0f, 1.0f, 1.0f}, { 0.0f, 1.0f, 0.0f}}, {{-1.0f, 1.0f, 1.0f}, { 0.0f, 1.0f, 0.0f}},
{{ 1.0f, 1.0f, 1.0f}, { 0.0f, 1.0f, 0.0f}}, {{ 1.0f, 1.0f, 1.0f}, { 0.0f, 1.0f, 0.0f}},
{{ 1.0f, 1.0f, -1.0f}, { 0.0f, 1.0f, 0.0f}}, /* +Y */ {{ 1.0f, 1.0f, -1.0f}, { 0.0f, 1.0f, 0.0f}},
{{-1.0f, 1.0f, -1.0f}, { 0.0f, 1.0f, 0.0f}}, {{-1.0f, 1.0f, -1.0f}, { 0.0f, 1.0f, 0.0f}},
/* 12, -Z */
{{ 1.0f, -1.0f, -1.0f}, { 0.0f, 0.0f, -1.0f}}, {{ 1.0f, -1.0f, -1.0f}, { 0.0f, 0.0f, -1.0f}},
{{-1.0f, -1.0f, -1.0f}, { 0.0f, 0.0f, -1.0f}}, {{-1.0f, -1.0f, -1.0f}, { 0.0f, 0.0f, -1.0f}},
{{-1.0f, 1.0f, -1.0f}, { 0.0f, 0.0f, -1.0f}}, /* -Z */ {{-1.0f, 1.0f, -1.0f}, { 0.0f, 0.0f, -1.0f}},
{{ 1.0f, 1.0f, -1.0f}, { 0.0f, 0.0f, -1.0f}}, {{ 1.0f, 1.0f, -1.0f}, { 0.0f, 0.0f, -1.0f}},
/* 16, -Y */
{{-1.0f, -1.0f, -1.0f}, { 0.0f, -1.0f, 0.0f}}, {{-1.0f, -1.0f, -1.0f}, { 0.0f, -1.0f, 0.0f}},
{{ 1.0f, -1.0f, -1.0f}, { 0.0f, -1.0f, 0.0f}}, {{ 1.0f, -1.0f, -1.0f}, { 0.0f, -1.0f, 0.0f}},
{{ 1.0f, -1.0f, 1.0f}, { 0.0f, -1.0f, 0.0f}}, /* -Y */ {{ 1.0f, -1.0f, 1.0f}, { 0.0f, -1.0f, 0.0f}},
{{-1.0f, -1.0f, 1.0f}, { 0.0f, -1.0f, 0.0f}}, {{-1.0f, -1.0f, 1.0f}, { 0.0f, -1.0f, 0.0f}},
/* 20, -X */
{{-1.0f, -1.0f, -1.0f}, {-1.0f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, -1.0f}, {-1.0f, 0.0f, 0.0f}},
{{-1.0f, -1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}},
{{-1.0f, 1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}}, /* -X */ {{-1.0f, 1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}},
{{-1.0f, 1.0f, -1.0f}, {-1.0f, 0.0f, 0.0f}} {{-1.0f, 1.0f, -1.0f}, {-1.0f, 0.0f, 0.0f}}
}; };
constexpr Trade::MeshAttributeData AttributesSolid[]{ constexpr Trade::MeshAttributeData AttributesSolid[]{
@ -96,6 +110,481 @@ Trade::MeshData cubeSolid() {
namespace { namespace {
/* GCC 4.8 dies with "error: array must be initialized with a brace-enclosed
initializer" if it's `constexpr Vector2 TextureCoordinates[][24]`. Turning
the second dimension into a struct seems to work around the problem. */
/** @todo drop once GCC 4.8 is gone */
constexpr struct {
Vector2 v[24];
} TextureCoordinates[]{
/* All same
3--2
| |
0--1 */
{{/* 0, +Z */
{0.0f, 0.0f},
{1.0f, 0.0f},
{1.0f, 1.0f},
{0.0f, 1.0f},
/* 4, +X */
{0.0f, 0.0f},
{1.0f, 0.0f},
{1.0f, 1.0f},
{0.0f, 1.0f},
/* 8, +Y */
{0.0f, 0.0f},
{1.0f, 0.0f},
{1.0f, 1.0f},
{0.0f, 1.0f},
/* 12, -Z */
{0.0f, 0.0f},
{1.0f, 0.0f},
{1.0f, 1.0f},
{0.0f, 1.0f},
/* 16, -Y */
{0.0f, 0.0f},
{1.0f, 0.0f},
{1.0f, 1.0f},
{0.0f, 1.0f},
/* 20, -X */
{0.0f, 0.0f},
{1.0f, 0.0f},
{1.0f, 1.0f},
{0.0f, 1.0f}}},
/* Positive up, negative down
+----+----3----2 1.0
| +X | +Y | +Z |
+----+----0----1 0.5
| -X | -Y | -Z |
+----+----+----+ 0.0
0.0 0.333 0.667 1.0 */
{{/* 0, +Z */
{2.0f/3.0f, 0.5f},
{3.0f/3.0f, 0.5f},
{3.0f/3.0f, 1.0f},
{2.0f/3.0f, 1.0f},
/* 4, +X */
{0.0f/3.0f, 0.5f},
{1.0f/3.0f, 0.5f},
{1.0f/3.0f, 1.0f},
{0.0f/3.0f, 1.0f},
/* 8, +Y */
{1.0f/3.0f, 0.5f},
{2.0f/3.0f, 0.5f},
{2.0f/3.0f, 1.0f},
{1.0f/3.0f, 1.0f},
/* 12, -Z */
{2.0f/3.0f, 0.0f},
{3.0f/3.0f, 0.0f},
{3.0f/3.0f, 0.5f},
{2.0f/3.0f, 0.5f},
/* 16, -Y */
{1.0f/3.0f, 0.0f},
{2.0f/3.0f, 0.0f},
{2.0f/3.0f, 0.5f},
{1.0f/3.0f, 0.5f},
/* 20, -X */
{0.0f/3.0f, 0.0f},
{1.0f/3.0f, 0.0f},
{1.0f/3.0f, 0.5f},
{0.0f/3.0f, 0.5f}}},
/* -X up, -X down
+----+ 1.0
| +Y |
A----C----E----G----+ 0.667
| -X | +Z | +X | -Z |
B----D----F----H----+ 0.333
| -Y |
+----+ 0.0
0.0 0.25 0.5 0.75 1.0 */
{{/* 0, +Z */
{0.25f, 1.0f/3.0f}, /* D */
{0.50f, 1.0f/3.0f}, /* F */
{0.50f, 2.0f/3.0f}, /* E */
{0.25f, 2.0f/3.0f}, /* C */
/* 4, +X */
{0.50f, 1.0f/3.0f}, /* F */
{0.75f, 1.0f/3.0f}, /* H */
{0.75f, 2.0f/3.0f}, /* G */
{0.50f, 2.0f/3.0f}, /* E */
/* 8, +Y */
{0.25f, 2.0f/3.0f}, /* C */
{0.25f, 3.0f/3.0f},
{0.00f, 3.0f/3.0f},
{0.00f, 2.0f/3.0f}, /* A */
/* 12, -Z */
{0.75f, 1.0f/3.0f}, /* H */
{1.00f, 1.0f/3.0f},
{1.00f, 2.0f/3.0f},
{0.75f, 2.0f/3.0f}, /* G */
/* 16, -Y */
{0.00f, 1.0f/3.0f}, /* B */
{0.00f, 0.0f/3.0f},
{0.25f, 0.0f/3.0f},
{0.25f, 1.0f/3.0f}, /* D */
/* 20, -X */
{0.00f, 1.0f/3.0f}, /* B */
{0.25f, 1.0f/3.0f}, /* D */
{0.25f, 2.0f/3.0f}, /* C */
{0.00f, 2.0f/3.0f}}},/* A */
/* -X up, +Z down
+----+
| +Y |
A----C----E----G----+
| -X | +Z | +X | -Z |
+----D----F----H----+
| -Y |
+----+
0.0 0.25 0.5 */
{{/* 0, +Z */
{0.25f, 1.0f/3.0f}, /* D */
{0.50f, 1.0f/3.0f}, /* F */
{0.50f, 2.0f/3.0f}, /* E */
{0.25f, 2.0f/3.0f}, /* C */
/* 4, +X */
{0.50f, 1.0f/3.0f}, /* F */
{0.75f, 1.0f/3.0f}, /* H */
{0.75f, 2.0f/3.0f}, /* G */
{0.50f, 2.0f/3.0f}, /* E */
/* 8, +Y */
{0.25f, 2.0f/3.0f}, /* C */
{0.25f, 3.0f/3.0f},
{0.00f, 3.0f/3.0f},
{0.00f, 2.0f/3.0f}, /* A */
/* 12, -Z */
{0.75f, 1.0f/3.0f}, /* H */
{1.00f, 1.0f/3.0f},
{1.00f, 2.0f/3.0f},
{0.75f, 2.0f/3.0f}, /* G */
/* 16, -Y */
{0.25f, 0.0f/3.0f},
{0.50f, 0.0f/3.0f},
{0.50f, 1.0f/3.0f}, /* F */
{0.25f, 1.0f/3.0f}, /* D */
/* 20, -X */
{0.00f, 1.0f/3.0f},
{0.25f, 1.0f/3.0f}, /* D */
{0.25f, 2.0f/3.0f}, /* C */
{0.00f, 2.0f/3.0f}}},/* A */
/* -X up, +X down
+----+
| +Y |
A----C----E----G----+
| -X | +Z | +X | -Z |
+----D----F----H----+
| -Y |
+----+
0.0 0.5 0.75 */
{{/* 0, +Z */
{0.25f, 1.0f/3.0f}, /* D */
{0.50f, 1.0f/3.0f}, /* F */
{0.50f, 2.0f/3.0f}, /* E */
{0.25f, 2.0f/3.0f}, /* C */
/* 4, +X */
{0.50f, 1.0f/3.0f}, /* F */
{0.75f, 1.0f/3.0f}, /* H */
{0.75f, 2.0f/3.0f}, /* G */
{0.50f, 2.0f/3.0f}, /* E */
/* 8, +Y */
{0.25f, 2.0f/3.0f}, /* C */
{0.25f, 3.0f/3.0f},
{0.00f, 3.0f/3.0f},
{0.00f, 2.0f/3.0f}, /* A */
/* 12, -Z */
{0.75f, 1.0f/3.0f}, /* H */
{1.00f, 1.0f/3.0f},
{1.00f, 2.0f/3.0f},
{0.75f, 2.0f/3.0f}, /* G */
/* 16, -Y */
{0.75f, 0.0f/3.0f},
{0.75f, 1.0f/3.0f}, /* H */
{0.50f, 1.0f/3.0f}, /* F */
{0.50f, 0.0f/3.0f},
/* 20, -X */
{0.00f, 1.0f/3.0f},
{0.25f, 1.0f/3.0f}, /* D */
{0.25f, 2.0f/3.0f}, /* C */
{0.00f, 2.0f/3.0f}}},/* A */
/* -X up, -Z down
+----+
| +Y |
A----C----E----G----+
| -X | +Z | +X | -Z |
+----D----F----H----B
| -Y |
+----+
0.0 0.75 1.0 */
{{/* 0, +Z */
{0.25f, 1.0f/3.0f}, /* D */
{0.50f, 1.0f/3.0f}, /* F */
{0.50f, 2.0f/3.0f}, /* E */
{0.25f, 2.0f/3.0f}, /* C */
/* 4, +X */
{0.50f, 1.0f/3.0f}, /* F */
{0.75f, 1.0f/3.0f}, /* H */
{0.75f, 2.0f/3.0f}, /* G */
{0.50f, 2.0f/3.0f}, /* E */
/* 8, +Y */
{0.25f, 2.0f/3.0f}, /* C */
{0.25f, 3.0f/3.0f},
{0.00f, 3.0f/3.0f},
{0.00f, 2.0f/3.0f}, /* A */
/* 12, -Z */
{0.75f, 1.0f/3.0f}, /* H */
{1.00f, 1.0f/3.0f}, /* B */
{1.00f, 2.0f/3.0f},
{0.75f, 2.0f/3.0f}, /* G */
/* 16, -Y */
{1.00f, 1.0f/3.0f}, /* B */
{0.75f, 1.0f/3.0f}, /* H */
{0.75f, 0.0f/3.0f},
{1.00f, 0.0f/3.0f},
/* 20, -X */
{0.00f, 1.0f/3.0f},
{0.25f, 1.0f/3.0f}, /* D */
{0.25f, 2.0f/3.0f}, /* C */
{0.00f, 2.0f/3.0f}}},/* A */
/* +Z up, +Z down
+----+
| +Y |
+----C----E----G----+
| -X | +Z | +X | -Z |
+----D----F----H----+
| -Y |
+----+
0.25 0.5 */
{{/* 0, +Z */
{0.25f, 1.0f/3.0f}, /* D */
{0.50f, 1.0f/3.0f}, /* F */
{0.50f, 2.0f/3.0f}, /* E */
{0.25f, 2.0f/3.0f}, /* C */
/* 4, +X */
{0.50f, 1.0f/3.0f}, /* F */
{0.75f, 1.0f/3.0f}, /* H */
{0.75f, 2.0f/3.0f}, /* G */
{0.50f, 2.0f/3.0f}, /* E */
/* 8, +Y */
{0.25f, 2.0f/3.0f}, /* C */
{0.50f, 2.0f/3.0f}, /* E */
{0.50f, 3.0f/3.0f},
{0.25f, 3.0f/3.0f},
/* 12, -Z */
{0.75f, 1.0f/3.0f}, /* H */
{1.00f, 1.0f/3.0f},
{1.00f, 2.0f/3.0f},
{0.75f, 2.0f/3.0f}, /* G */
/* 16, -Y */
{0.25f, 0.0f/3.0f},
{0.50f, 0.0f/3.0f},
{0.50f, 1.0f/3.0f}, /* F */
{0.25f, 1.0f/3.0f}, /* D */
/* 20, -X */
{0.00f, 1.0f/3.0f},
{0.25f, 1.0f/3.0f}, /* D */
{0.25f, 2.0f/3.0f}, /* C */
{0.00f, 2.0f/3.0f}}},
/* +Z up, +X down
+----+
| +Y |
+----C----E----G----+
| -X | +Z | +X | -Z |
+----D----F----H----+
| -Y |
+----+
0.5 0.75 */
{{/* 0, +Z */
{0.25f, 1.0f/3.0f}, /* D */
{0.50f, 1.0f/3.0f}, /* F */
{0.50f, 2.0f/3.0f}, /* E */
{0.25f, 2.0f/3.0f}, /* C */
/* 4, +X */
{0.50f, 1.0f/3.0f}, /* F */
{0.75f, 1.0f/3.0f}, /* H */
{0.75f, 2.0f/3.0f}, /* G */
{0.50f, 2.0f/3.0f}, /* E */
/* 8, +Y */
{0.25f, 2.0f/3.0f}, /* C */
{0.50f, 2.0f/3.0f}, /* E */
{0.50f, 3.0f/3.0f},
{0.25f, 3.0f/3.0f},
/* 12, -Z */
{0.75f, 1.0f/3.0f}, /* H */
{1.00f, 1.0f/3.0f},
{1.00f, 2.0f/3.0f},
{0.75f, 2.0f/3.0f}, /* G */
/* 16, -Y */
{0.75f, 0.0f/3.0f},
{0.75f, 1.0f/3.0f}, /* H */
{0.50f, 1.0f/3.0f}, /* F */
{0.50f, 0.0f/3.0f},
/* 20, -X */
{0.00f, 1.0f/3.0f},
{0.25f, 1.0f/3.0f}, /* D */
{0.25f, 2.0f/3.0f}, /* C */
{0.00f, 2.0f/3.0f}}},
};
/* The tangent is the same for all four vertices in each face so it's just 6
instead of 24. GCC 4.8 dies with "error: array must be initialized with a
brace-enclosed initializer" if it's `constexpr Vector4 Tangents[][6]`.
Turning the second dimension into a struct seems to work around the
problem. */
/** @todo drop once GCC 4.8 is gone */
constexpr struct {
Vector4 v[6];
} Tangents[8]{
/* All same. Well, tangents are *not* all same in this case. */
{{{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Z */
{ 0.0f, 0.0f, -1.0f, 1.0f}, /* +X */
{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Y */
{-1.0f, 0.0f, 0.0f, 1.0f}, /* -Z */
{ 1.0f, 0.0f, 0.0f, 1.0f}, /* -Y */
{ 0.0f, 0.0f, 1.0f, 1.0f}}},/* -X */
/* Positive up, negative down */
{{{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Z */
{ 0.0f, 0.0f, -1.0f, 1.0f}, /* +X */
{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Y */
{-1.0f, 0.0f, 0.0f, 1.0f}, /* -Z */
{ 1.0f, 0.0f, 0.0f, 1.0f}, /* -Y */
{ 0.0f, 0.0f, 1.0f, 1.0f}}},/* -X */
/* -X up, -X down */
{{{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Z */
{ 0.0f, 0.0f, -1.0f, 1.0f}, /* +X */
{ 0.0f, 0.0f, 1.0f, 1.0f}, /* +Y */
{-1.0f, 0.0f, 0.0f, 1.0f}, /* -Z */
{ 0.0f, 0.0f, 1.0f, 1.0f}, /* -Y */
{ 0.0f, 0.0f, 1.0f, 1.0f}}},/* -X */
/* -X up, +Z down */
{{{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Z */
{ 0.0f, 0.0f, -1.0f, 1.0f}, /* +X */
{ 0.0f, 0.0f, 1.0f, 1.0f}, /* +Y */
{-1.0f, 0.0f, 0.0f, 1.0f}, /* -Z */
{ 1.0f, 0.0f, 0.0f, 1.0f}, /* -Y */
{ 0.0f, 0.0f, 1.0f, 1.0f}}},/* -X */
/* -X up, +X down */
{{{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Z */
{ 0.0f, 0.0f, -1.0f, 1.0f}, /* +X */
{ 0.0f, 0.0f, 1.0f, 1.0f}, /* +Y */
{-1.0f, 0.0f, 0.0f, 1.0f}, /* -Z */
{ 0.0f, 0.0f, -1.0f, 1.0f}, /* -Y */
{ 0.0f, 0.0f, 1.0f, 1.0f}}},/* -X */
/* -X up, -Z down */
{{{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Z */
{ 0.0f, 0.0f, -1.0f, 1.0f}, /* +X */
{ 0.0f, 0.0f, 1.0f, 1.0f}, /* +Y */
{-1.0f, 0.0f, 0.0f, 1.0f}, /* -Z */
{-1.0f, 0.0f, 0.0f, 1.0f}, /* -Y */
{ 0.0f, 0.0f, 1.0f, 1.0f}}},/* -X */
/* +Z up, +Z down */
{{{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Z */
{ 0.0f, 0.0f, -1.0f, 1.0f}, /* +X */
{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Y */
{-1.0f, 0.0f, 0.0f, 1.0f}, /* -Z */
{ 1.0f, 0.0f, 0.0f, 1.0f}, /* -Y */
{ 0.0f, 0.0f, 1.0f, 1.0f}}},/* -X */
/* +Z up, +X down */
{{{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Z */
{ 0.0f, 0.0f, -1.0f, 1.0f}, /* +X */
{ 1.0f, 0.0f, 0.0f, 1.0f}, /* +Y */
{-1.0f, 0.0f, 0.0f, 1.0f}, /* -Z */
{ 0.0f, 0.0f, -1.0f, 1.0f}, /* -Y */
{ 0.0f, 0.0f, 1.0f, 1.0f}}},/* -X */
};
}
Trade::MeshData cubeSolid(const CubeFlags flags) {
const UnsignedInt textureCoordinateVariant = UnsignedByte(flags) >> 1;
CORRADE_ASSERT(textureCoordinateVariant <= Containers::arraySize(TextureCoordinates),
/* Since the enum isn't really a bitflag, implementing a debug printer
for it doesn't really make sense anyway. But be at least a bit
helpful and print the assumed TextureCoordinates flag value w/o the
other bits. */
"Primitives::cubeSolid(): unrecognized texture coordinate option" << Debug::hex << UnsignedByte(flags & ~CubeFlag::Tangents), (Trade::MeshData{MeshPrimitive::Triangles, 0}));
CORRADE_ASSERT(!(flags & CubeFlag::Tangents) || textureCoordinateVariant,
"Primitives::cubeSolid(): a texture coordinate option has to be picked if tangents are enabled", (Trade::MeshData{MeshPrimitive::Triangles, 0}));
/* Return the compile-time data if nothing extra is requested */
if(!flags)
return cubeSolid();
/* Calculate attribute count and vertex size */
std::size_t stride = sizeof(Vector3) + sizeof(Vector3);
std::size_t attributeCount = 2;
if(flags & CubeFlag::Tangents) {
stride += sizeof(Vector4);
++attributeCount;
}
if(textureCoordinateVariant) {
stride += sizeof(Vector2);
++attributeCount;
}
/* Set up the layout */
Containers::Array<char> vertexData{NoInit, 24*stride};
Containers::Array<Trade::MeshAttributeData> attributeData{attributeCount};
std::size_t attributeIndex = 0;
std::size_t attributeOffset = 0;
Containers::StridedArrayView1D<Vector3> positions{vertexData,
reinterpret_cast<Vector3*>(vertexData.data() + attributeOffset),
24, std::ptrdiff_t(stride)};
attributeData[attributeIndex++] = Trade::MeshAttributeData{
Trade::MeshAttribute::Position, positions};
attributeOffset += sizeof(Vector3);
Containers::StridedArrayView1D<Vector3> normals{vertexData,
reinterpret_cast<Vector3*>(vertexData.data() + sizeof(Vector3)),
24, std::ptrdiff_t(stride)};
attributeData[attributeIndex++] = Trade::MeshAttributeData{
Trade::MeshAttribute::Normal, normals};
attributeOffset += sizeof(Vector3);
Containers::StridedArrayView1D<Vector4> tangents;
if(flags & CubeFlag::Tangents) {
tangents = Containers::StridedArrayView1D<Vector4>{vertexData,
reinterpret_cast<Vector4*>(vertexData.data() + attributeOffset),
24, std::ptrdiff_t(stride)};
attributeData[attributeIndex++] = Trade::MeshAttributeData{
Trade::MeshAttribute::Tangent, tangents};
attributeOffset += sizeof(Vector4);
}
Containers::StridedArrayView1D<Vector2> textureCoordinates;
if(textureCoordinateVariant) {
textureCoordinates = Containers::StridedArrayView1D<Vector2>{vertexData,
reinterpret_cast<Vector2*>(vertexData.data() + attributeOffset),
24, std::ptrdiff_t(stride)};
attributeData[attributeIndex++] = Trade::MeshAttributeData{
Trade::MeshAttribute::TextureCoordinates, textureCoordinates};
attributeOffset += sizeof(Vector2);
}
CORRADE_INTERNAL_ASSERT(attributeIndex == attributeCount);
CORRADE_INTERNAL_ASSERT(attributeOffset == stride);
/* Fill the data */
for(std::size_t i = 0; i != 24; ++i) {
positions[i] = VerticesSolid[i].position;
normals[i] = VerticesSolid[i].normal;
}
if(textureCoordinateVariant) {
for(std::size_t i = 0; i != 24; ++i)
textureCoordinates[i] = TextureCoordinates[textureCoordinateVariant - 1].v[i];
}
if(flags & CubeFlag::Tangents) {
for(std::size_t i = 0; i != 6; ++i)
for(std::size_t j = 0; j != 4; ++j)
tangents[i*4 + j] = Tangents[textureCoordinateVariant - 1].v[i];
}
return Trade::MeshData{MeshPrimitive::Triangles,
Trade::DataFlag::Global, IndicesSolid, Trade::MeshIndexData{IndicesSolid},
Utility::move(vertexData), Utility::move(attributeData)};
}
namespace {
/* Can't be just an array of Vector3 because MSVC 2015 is special. See /* Can't be just an array of Vector3 because MSVC 2015 is special. See
Crosshair.cpp for details. */ Crosshair.cpp for details. */
constexpr struct VertexSolidStrip { constexpr struct VertexSolidStrip {

119
src/Magnum/Primitives/Cube.h

@ -27,28 +27,139 @@
*/ */
/** @file /** @file
* @brief Function @ref Magnum::Primitives::cubeSolid(), @ref Magnum::Primitives::cubeSolidStrip(), @ref Magnum::Primitives::cubeWireframe() * @brief Enum @ref Magnum::Primitives::CubeFlag, enum set @ref Magnum::Primitives::CubeFlags, function @ref Magnum::Primitives::cubeSolid(), @ref Magnum::Primitives::cubeSolidStrip(), @ref Magnum::Primitives::cubeWireframe()
*/ */
#include <Corrade/Containers/EnumSet.h>
#include "Magnum/Primitives/visibility.h" #include "Magnum/Primitives/visibility.h"
#include "Magnum/Trade/Trade.h" #include "Magnum/Trade/Trade.h"
namespace Magnum { namespace Primitives { namespace Magnum { namespace Primitives {
/**
@brief 3D cube flag
@m_since_latest
@see @ref CubeFlags, @ref cubeSolid()
*/
enum class CubeFlag: UnsignedByte {
/**
* Texture coordinates with a single image used for all faces, oriented in
* a way that makes the image upright and not mirrored if looking from the
* default +Z direction. Useful if all faces are meant to look the same.
* Mutually exclusive with other `TextureCoordinates*` flags.
*
* @htmlinclude primitives-cube-all-same.svg
*/
TextureCoordinatesAllSame = 1 << 1,
/**
* Texture coordinates with +X, +Y, +Z faces in the top row and -X, -Y and
* -Z in the bottom row, oriented in a way that makes the image upright and
* not mirrored if looking from the default +Z direction. Useful to have a
* different texture for each face but still make use of the whole texture
* area with no wasted space. Mutually exclusive with other
* `TextureCoordinates*` flags.
*
* @htmlinclude primitives-cube-positive-up-negative-down.svg
*/
TextureCoordinatesPositiveUpNegativeDown = 2 << 1,
/**
* Texture coordinates with both upper and lower face going from -X.
* Mutually exclusive with other `TextureCoordinates*` flags.
*
* @htmlinclude primitives-cube-negative-x-up-negative-x-down.svg
*/
TextureCoordinatesNegativeXUpNegativeXDown = 3 << 1,
/**
* Texture coordinates with upper face going from -X and lower face from
* +Z. Mutually exclusive with other `TextureCoordinates*` flags.
*
* @htmlinclude primitives-cube-negative-x-up-positive-z-down.svg
*/
TextureCoordinatesNegativeXUpPositiveZDown = 4 << 1,
/**
* Texture coordinates with upper face going from -X and lower face from
* +X. Mutually exclusive with other `TextureCoordinates*` flags.
*
* @htmlinclude primitives-cube-negative-x-up-positive-x-down.svg
*/
TextureCoordinatesNegativeXUpPositiveXDown = 5 << 1,
/**
* Texture coordinates with upper face going from -X and lower face from
* -Z. Mutually exclusive with other `TextureCoordinates*` flags.
*
* @htmlinclude primitives-cube-negative-x-up-negative-z-down.svg
*/
TextureCoordinatesNegativeXUpNegativeZDown = 6 << 1,
/**
* Texture coordinates with both upper face lower face going from +Z.
* Mutually exclusive with other `TextureCoordinates*` flags.
*
* @htmlinclude primitives-cube-positive-z-up-positive-z-down.svg
*/
TextureCoordinatesPositiveZUpPositiveZDown = 7 << 1,
/**
* Texture coordinates with upper face going from +Z and lower face from
* +X. Mutually exclusive with other `TextureCoordinates*` flags.
*
* @htmlinclude primitives-cube-positive-z-up-positive-x-down.svg
*/
TextureCoordinatesPositiveZUpPositiveXDown = 8 << 1,
/**
* Generate four-component tangents. The last component can be used to
* reconstruct a bitangent as described in the documentation of
* @ref Trade::MeshAttribute::Tangent. Requires one of the
* `TextureCoordinates*` to be set in order to know the tangent direction.
*/
Tangents = 1 << 0,
};
/**
@brief 3D cube flags
@m_since_latest
@see @ref circle2DSolid()
*/
typedef Containers::EnumSet<CubeFlag> CubeFlags;
CORRADE_ENUMSET_OPERATORS(CubeFlags)
/** /**
@brief Solid 3D cube @brief Solid 3D cube
2x2x2 cube, centered at origin. @ref MeshPrimitive::Triangles with 2x2x2 cube, centered at origin. @ref MeshPrimitive::Triangles with
@ref MeshIndexType::UnsignedShort indices, interleaved @ref MeshIndexType::UnsignedShort indices, interleaved
@ref VertexFormat::Vector3 positions and flat @ref VertexFormat::Vector3 @ref VertexFormat::Vector3 positions and flat @ref VertexFormat::Vector3
normals. The returned instance references @ref Trade::DataFlag::Global data --- normals. If no @p flags are passed, the returned instance references
pass the mesh through @ref MeshTools::copy() to get a mutable copy, if needed. @ref Trade::DataFlag::Global data --- pass the mesh through
@ref MeshTools::copy() to get a mutable copy, if needed.
@image html primitives-cubesolid.png width=256px @image html primitives-cubesolid.png width=256px
@see @ref cubeSolidStrip(), @ref cubeWireframe() Expects that at most one `TextureCoordinates*` @ref CubeFlag is set. If
@ref CubeFlag::Tangents is set, expects that exactly one `TextureCoordinates*`
@ref CubeFlag is set as well. Rotate or mirror the resulting mesh texture
coordinates, positions or both to create remaining texture mapping variants.
@see @ref cubeSolidStrip(), @ref cubeWireframe(), @ref MeshTools::transform3D(),
@ref MeshTools::transformTextureCoordinates2D()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT
Trade::MeshData cubeSolid(CubeFlags flags = {});
#else
/* Make it possible to DCE the texture / tangent logic if no flags are used */
MAGNUM_PRIMITIVES_EXPORT Trade::MeshData cubeSolid(); MAGNUM_PRIMITIVES_EXPORT Trade::MeshData cubeSolid();
MAGNUM_PRIMITIVES_EXPORT Trade::MeshData cubeSolid(CubeFlags flags);
#endif
/** /**
@brief Solid 3D cube as a single strip @brief Solid 3D cube as a single strip

2
src/Magnum/Primitives/Test/CMakeLists.txt

@ -32,7 +32,7 @@ corrade_add_test(PrimitivesAxisTest AxisTest.cpp LIBRARIES MagnumPrimitives)
corrade_add_test(PrimitivesCapsuleTest CapsuleTest.cpp LIBRARIES MagnumPrimitivesTestLib) corrade_add_test(PrimitivesCapsuleTest CapsuleTest.cpp LIBRARIES MagnumPrimitivesTestLib)
corrade_add_test(PrimitivesCircleTest CircleTest.cpp LIBRARIES MagnumPrimitivesTestLib) corrade_add_test(PrimitivesCircleTest CircleTest.cpp LIBRARIES MagnumPrimitivesTestLib)
corrade_add_test(PrimitivesCrosshairTest CrosshairTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesCrosshairTest CrosshairTest.cpp LIBRARIES MagnumPrimitives)
corrade_add_test(PrimitivesCubeTest CubeTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesCubeTest CubeTest.cpp LIBRARIES MagnumPrimitivesTestLib)
corrade_add_test(PrimitivesConeTest ConeTest.cpp LIBRARIES MagnumPrimitivesTestLib) corrade_add_test(PrimitivesConeTest ConeTest.cpp LIBRARIES MagnumPrimitivesTestLib)
corrade_add_test(PrimitivesCylinderTest CylinderTest.cpp LIBRARIES MagnumPrimitivesTestLib) corrade_add_test(PrimitivesCylinderTest CylinderTest.cpp LIBRARIES MagnumPrimitivesTestLib)
corrade_add_test(PrimitivesGradientTest GradientTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesGradientTest GradientTest.cpp LIBRARIES MagnumPrimitives)

506
src/Magnum/Primitives/Test/CubeTest.cpp

@ -24,11 +24,15 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/String.h>
#include <Corrade/TestSuite/Tester.h> #include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/String.h>
#include "Magnum/Mesh.h" #include "Magnum/Mesh.h"
#include "Magnum/Math/Functions.h" #include "Magnum/Math/Functions.h"
#include "Magnum/Math/Vector3.h" #include "Magnum/Math/FunctionsBatch.h" /* minmax() */
#include "Magnum/Math/Vector4.h"
#include "Magnum/Primitives/Cube.h" #include "Magnum/Primitives/Cube.h"
#include "Magnum/Trade/MeshData.h" #include "Magnum/Trade/MeshData.h"
@ -38,20 +42,263 @@ struct CubeTest: TestSuite::Tester {
explicit CubeTest(); explicit CubeTest();
void solid(); void solid();
template<CubeFlag flag = CubeFlag{}> void solidTextureCoordinates();
void solidInvalid();
void solidStrip(); void solidStrip();
void solidStripGlsl(); void solidStripGlsl();
void wireframe(); void wireframe();
}; };
const struct {
const char* name;
Containers::Optional<CubeFlags> flags;
} SolidData[]{
{"", {}},
{"explicit empty flags", CubeFlags{}}
};
enum class CubeEdge {
/* 0 is reserved */
/* Horizontal edges */
BottomBack = 1, /* {0, -1, +1} */
BottomFront, /* {0, -1, -1} */
TopBack, /* {0, +1, +1} */
TopFront, /* {0, +1, -1} */
/* Vertical edges */
BackLeft, /* {-1, 0, +1} */
BackRight, /* {+1, 0, +1} */
FrontLeft, /* {-1, 0, -1} */
FrontRight, /* {+1, 0, -1} */
/* "Depth" edges */
BottomLeft, /* {-1, -1, 0} */
BottomRight, /* {+1, -1, 0} */
TopLeft, /* {-1, +1, 0} */
TopRight, /* {+1, +1, 0} */
};
Debug& operator<<(Debug& out, CubeEdge edge) {
switch(edge) {
#define _c(value) case CubeEdge::value: return out << #value;
_c(BottomBack)
_c(BottomFront)
_c(TopBack)
_c(TopFront)
_c(BackLeft)
_c(BackRight)
_c(FrontLeft)
_c(FrontRight)
_c(BottomLeft)
_c(BottomRight)
_c(TopLeft)
_c(TopRight)
#undef _c
}
CORRADE_INTERNAL_ASSERT_UNREACHABLE();
}
const struct {
const char* name;
CubeFlags flags;
/* +X, -X, +Y, -Y, +Z, -Z (same order as GL::CubeMapCoordinate) */
Vector2 expectedCenters[6];
/* Cases where less than 12 edges are shared have the rest zero-filled */
CubeEdge expectedSharedEdges[12];
} SolidTextureCoordinatesData[]{
{"all same", CubeFlag::TextureCoordinatesAllSame, {
{0.5f, 0.5f},
{0.5f, 0.5f},
{0.5f, 0.5f},
{0.5f, 0.5f},
{0.5f, 0.5f},
{0.5f, 0.5f}
}, {
/* (No shared edges in this case) */
}},
/* +----+----+----+ 1.0
| +X | +Y | +Z | 0.75
+----+----+----+ 0.5
| -X | -Y | -Z | 0.25
+----+----+----+ 0.0
0.0 0.333 0.667 1.0
0.167 0.5 0.833 */
{"+ up, - down", CubeFlag::TextureCoordinatesPositiveUpNegativeDown, {
{0.16667f, 0.75f}, /* +X */
{0.16667f, 0.25f}, /* -X */
{0.5f, 0.75f}, /* +Y */
{0.5f, 0.25f}, /* -Y */
{0.83333f, 0.75f}, /* +Z */
{0.83333f, 0.25f} /* -Z */
}, {
/* (*Deliberately* no shared edges in this case either. They could be
but it'd mean some faces would be rotated, which is just weird. */
}},
/* +-----+ 1.0
| +Y | 0.833
+-tl--+-----+-----+-----+ 0.667
| -X bl +Z br +X fr -Z | 0.5
+-bl--+-----+-----+-----+ 0.333
| -Y | 0.167
+-----+ 0.0
0.0 0.25 0.5 0.75 1.0
0.125 0.375 0.625 0.875 */
{"-X up, -X down", CubeFlag::TextureCoordinatesNegativeXUpNegativeXDown, {
{0.625f, 0.5f}, /* +X */
{0.125f, 0.5f}, /* -X */
{0.125f, 0.83333f}, /* +Y */
{0.125f, 0.16667f}, /* -Y */
{0.375f, 0.5f}, /* +Z */
{0.875f, 0.5f} /* -Z */
}, {
CubeEdge::TopLeft,
CubeEdge::BottomLeft,
CubeEdge::BackLeft,
CubeEdge::BackRight,
CubeEdge::FrontRight,
}},
/* +-----+
| +Y |
+-tl--+-----+-----+-----+
| -X bl +Z br +X fr -Z |
+-----+-bb--+-----+-----+
| -Y |
+-----+
0.25 0.5
0.375 */
{"-X up, +Z down", CubeFlag::TextureCoordinatesNegativeXUpPositiveZDown, {
{0.625f, 0.5f}, /* +X */
{0.125f, 0.5f}, /* -X */
{0.125f, 0.83333f}, /* +Y */
{0.375f, 0.16667f}, /* -Y */
{0.375f, 0.5f}, /* +Z */
{0.875f, 0.5f} /* -Z */
}, {
CubeEdge::TopLeft,
CubeEdge::BackLeft,
CubeEdge::BottomBack,
CubeEdge::BackRight,
CubeEdge::FrontRight,
}},
/* +-----+
| +Y |
+-tl--+-----+-----+-----+
| -X bl +Z br +X fr -Z |
+-----+-----+-br--+-----+
| -Y |
+-----+
0.5 0.75
0.625 */
{"-X up, +X down", CubeFlag::TextureCoordinatesNegativeXUpPositiveXDown, {
{0.625f, 0.5f}, /* +X */
{0.125f, 0.5f}, /* -X */
{0.125f, 0.83333f}, /* +Y */
{0.625f, 0.16667f}, /* -Y */
{0.375f, 0.5f}, /* +Z */
{0.875f, 0.5f} /* -Z */
}, {
CubeEdge::TopLeft,
CubeEdge::BackLeft,
CubeEdge::BackRight,
CubeEdge::BottomRight,
CubeEdge::FrontRight,
}},
/* +-----+
| +Y |
+-tl--+-----+-----+-----+
| -X bl +Z br +X fr -Z |
+-----+-----+-----+-bf--+
| -Y |
+-----+
0.75 1.0
0.875 */
{"-X up, -Z down", CubeFlag::TextureCoordinatesNegativeXUpNegativeZDown, {
{0.625f, 0.5f}, /* +X */
{0.125f, 0.5f}, /* -X */
{0.125f, 0.83333f}, /* +Y */
{0.875f, 0.16667f}, /* -Y */
{0.375f, 0.5f}, /* +Z */
{0.875f, 0.5f} /* -Z */
}, {
CubeEdge::TopLeft,
CubeEdge::BackLeft,
CubeEdge::BackRight,
CubeEdge::FrontRight,
CubeEdge::BottomFront,
}},
/* +-----+
| +Y |
+-----+-tb--+-----+-----+
| -X bl +Z br +X fr -Z |
+-----+-bb--+-----+-----+
| -Y |
+-----+
0.25 0.5
0.375 */
{"+Z up, +Z down", CubeFlag::TextureCoordinatesPositiveZUpPositiveZDown, {
{0.625f, 0.5f}, /* +X */
{0.125f, 0.5f}, /* -X */
{0.375f, 0.83333f}, /* +Y */
{0.375f, 0.16667f}, /* -Y */
{0.375f, 0.5f}, /* +Z */
{0.875f, 0.5f} /* -Z */
}, {
CubeEdge::TopBack,
CubeEdge::BackLeft,
CubeEdge::BackRight,
CubeEdge::BottomBack,
CubeEdge::FrontRight,
}},
/* +-----+
| +Y |
+-----+-tb--+-----+-----+
| -X bl +Z br +X fr -Z |
+-----+-bb--+-br--+-----+
| -Y |
+-----+
0.5 0.75
0.625 */
{"+Z up, +X down", CubeFlag::TextureCoordinatesPositiveZUpPositiveXDown, {
{0.625f, 0.5f}, /* +X */
{0.125f, 0.5f}, /* -X */
{0.375f, 0.83333f}, /* +Y */
{0.625f, 0.16667f}, /* -Y */
{0.375f, 0.5f}, /* +Z */
{0.875f, 0.5f} /* -Z */
}, {
CubeEdge::TopBack,
CubeEdge::BackLeft,
CubeEdge::BackRight,
CubeEdge::FrontRight,
CubeEdge::BottomRight,
}},
};
CubeTest::CubeTest() { CubeTest::CubeTest() {
addTests({&CubeTest::solid, addInstancedTests({&CubeTest::solid},
Containers::arraySize(SolidData));
addInstancedTests<CubeTest>({
&CubeTest::solidTextureCoordinates,
&CubeTest::solidTextureCoordinates<CubeFlag::Tangents>
}, Containers::arraySize(SolidTextureCoordinatesData));
addTests({&CubeTest::solidInvalid,
&CubeTest::solidStrip, &CubeTest::solidStrip,
&CubeTest::solidStripGlsl, &CubeTest::solidStripGlsl,
&CubeTest::wireframe}); &CubeTest::wireframe});
} }
void CubeTest::solid() { void CubeTest::solid() {
Trade::MeshData cube = Primitives::cubeSolid(); auto&& data = SolidData[testCaseInstanceId()];
setTestCaseDescription(data.name);
Trade::MeshData cube = data.flags ?
Primitives::cubeSolid(*data.flags) :
Primitives::cubeSolid();
CORRADE_COMPARE(cube.primitive(), MeshPrimitive::Triangles); CORRADE_COMPARE(cube.primitive(), MeshPrimitive::Triangles);
CORRADE_VERIFY(cube.isIndexed()); CORRADE_VERIFY(cube.isIndexed());
@ -65,6 +312,259 @@ void CubeTest::solid() {
(Vector3{1.0f, 0.0f, 0.0f})); (Vector3{1.0f, 0.0f, 0.0f}));
} }
template<class T> T sampleQuad(const T& a, const T& b, const T& c, const T& d, Vector2 t) {
/* Assuming the vertex order is the following, which means the second lerp
has to be in a flipped direction in order to give expected result.
3--2
| |
0--1 */
return Math::lerp(Math::lerp(a, b, t[0]),
Math::lerp(d, c, t[0]), t[1]);
}
template<CubeFlag flag> void CubeTest::solidTextureCoordinates() {
auto&& data = SolidTextureCoordinatesData[testCaseInstanceId()];
setTestCaseDescription(data.name);
setTestCaseTemplateName(flag == CubeFlag::Tangents ? "CubeFlag::Tangents" : "");
Trade::MeshData cube = Primitives::cubeSolid(data.flags|flag);
Containers::StridedArrayView1D<const Vector3> positions = cube.attribute<Vector3>(Trade::MeshAttribute::Position);
Containers::StridedArrayView1D<const Vector2> textureCoordinates = cube.attribute<Vector2>(Trade::MeshAttribute::TextureCoordinates);
/* Same as in solid(), to verify basic sanity */
CORRADE_COMPARE(cube.primitive(), MeshPrimitive::Triangles);
CORRADE_VERIFY(cube.isIndexed());
CORRADE_COMPARE(cube.indexCount(), 36);
CORRADE_COMPARE(cube.vertexCount(), 24);
CORRADE_COMPARE(cube.attributeCount(), 3 + (flag == CubeFlag::Tangents ? 1 : 0));
CORRADE_COMPARE(cube.indices<UnsignedShort>()[17], 11);
CORRADE_COMPARE(positions[4], (Vector3{1.0f, -1.0f, 1.0f}));
CORRADE_COMPARE(cube.attribute<Vector3>(Trade::MeshAttribute::Normal)[6], (Vector3{1.0f, 0.0f, 0.0f}));
/* Discover which groups of vertices correspond to which faces, in order
matching SolidTextureCoordinatesData::expectedCenters, so +X, -X, +Y,
-Y, +Z, -Z. This could be done just once but who cares, it's just a
test. It could also be hardcoded but that'll make the test tied too much
to the particular data, making it more likely that the test passes with
the data actually being completely wrong. */
Vector3 faceCenters[6]{
{+1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{0.0f, +1.0f, 0.0f},
{0.0f, -1.0f, 0.0f},
{0.0f, 0.0f, +1.0f},
{0.0f, 0.0f, -1.0f},
};
UnsignedInt faceVertexOffsets[6];
for(UnsignedInt face = 0; face != 6; ++face) {
CORRADE_ITERATION(face);
Vector3 center = sampleQuad(positions[face*4 + 0],
positions[face*4 + 1],
positions[face*4 + 2],
positions[face*4 + 3], {0.5f, 0.5f});
UnsignedInt candidate = 0;
for(; candidate != Containers::arraySize(faceCenters); ++candidate) {
if(center == faceCenters[candidate]) {
faceVertexOffsets[candidate] = face*4;
break;
}
}
CORRADE_VERIFY(candidate != Containers::arraySize(faceCenters));
}
/* Discover which groups of vertices correspond to which edges, in order
matching the CubeEdge enum above. Same as above, this could be done just
once, or hardcoded, etc., but it's not. */
Vector3 edgeCenters[12] {
{0.0f, -1.0f, +1.0f}, /* BottomBack */
{0.0f, -1.0f, -1.0f}, /* BottomFront */
{0.0f, +1.0f, +1.0f}, /* TopBack */
{0.0f, +1.0f, -1.0f}, /* TopFront */
{-1.0f, 0.0f, +1.0f}, /* BackLeft */
{+1.0f, 0.0f, +1.0f}, /* BackRight */
{-1.0f, 0.0f, -1.0f}, /* FrontLeft */
{+1.0f, 0.0f, -1.0f}, /* FrontRight */
{-1.0f, -1.0f, 0.0f}, /* BottomLeft */
{+1.0f, -1.0f, 0.0f}, /* BottomRight */
{-1.0f, +1.0f, 0.0f}, /* TopLeft */
{+1.0f, +1.0f, 0.0f}, /* TopRight */
};
/* Each of 12 edges is shared by exactly 2 faces */
Vector2ui edgeVertices[12][2];
for(UnsignedInt face = 0; face != 6; ++face) {
CORRADE_ITERATION(face);
/* Four edges of the quad. Assuming ordering like below, if that
wouldn't be the case, the CORRADE_VERIFY after would fail.
3--2
| |
0--1 */
for(Vector2ui edge: {
Vector2ui{face*4 + 0, face*4 + 1},
Vector2ui{face*4 + 1, face*4 + 2},
Vector2ui{face*4 + 2, face*4 + 3},
Vector2ui{face*4 + 3, face*4 + 0}
}) {
Vector3 center = Math::lerp(positions[edge[0]],
positions[edge[1]], 0.5f);
UnsignedInt candidate = 0;
for(; candidate != Containers::arraySize(edgeCenters); ++candidate) {
if(center == edgeCenters[candidate]) {
if(edgeVertices[candidate][0].isZero())
edgeVertices[candidate][0] = edge;
else if(edgeVertices[candidate][1].isZero())
edgeVertices[candidate][1] = edge;
else CORRADE_FAIL("Too many shared edges.");
break;
}
}
CORRADE_ITERATION(edge);
CORRADE_VERIFY(candidate != Containers::arraySize(edgeCenters));
}
}
/* At this point, if neither the above CORRADE_VERIFY() nor the
CORRADE_FAIL() fire, for each of the 6 faces the 4 edges were assigned,
filling all 24 array entries */
/* For each face verify that the sampled texture coordinates at the center
match the expectation */
for(UnsignedInt face = 0; face != 6; ++face) {
UnsignedInt vertexOffset = faceVertexOffsets[face];
CORRADE_ITERATION("face" << face << "at offset" << vertexOffset);
Vector2 center = sampleQuad(
textureCoordinates[vertexOffset + 0],
textureCoordinates[vertexOffset + 1],
textureCoordinates[vertexOffset + 2],
textureCoordinates[vertexOffset + 3], {0.5f, 0.5f});
CORRADE_COMPARE(center, data.expectedCenters[face]);
}
/* Verify that the expected shared edges indeed have the same texture
coordinates for both faces */
for(CubeEdge edge: data.expectedSharedEdges) {
/* When we reach an edge that's zero it's the end of the list */
if(edge == CubeEdge{})
break;
/* Sanity check -- the two edges should be filled and have contents
that aren't the same */
const Vector2ui(&vertices)[2] = edgeVertices[UnsignedInt(edge) - 1];
CORRADE_ITERATION(edge << "edge with vertices" << Debug::packed << vertices[0] << "and" << Debug::packed << vertices[1]);
CORRADE_VERIFY(!vertices[0].isZero() &&
!vertices[1].isZero());
CORRADE_VERIFY(vertices[0] != vertices[1] &&
vertices[0] != vertices[1].flipped());
/* The edge should match in one or the other direction */
Vector2 a0 = textureCoordinates[vertices[0][0]];
Vector2 a1 = textureCoordinates[vertices[0][1]];
Vector2 b0 = textureCoordinates[vertices[1][0]];
Vector2 b1 = textureCoordinates[vertices[1][1]];
CORRADE_VERIFY((a0 == b0 && a1 == b1) ||
(a0 == b1 && a1 == b0));
}
/* The texture coordinates should always span the whole [0, 0] to [1, 1]
range. That may mean the faces won't be square if using a square
texture, but in practice the texture would have a size matching the
texture coordinate layout, so e.g. with a 4:3 ratio for the
NegativeXUpNegativeXDown variant. */
CORRADE_COMPARE(Math::minmax(textureCoordinates), Containers::pair(Vector2{0.0f}, Vector2{1.0f}));
/* If tangents are enabled, check their properties also */
if(flag == CubeFlag::Tangents) {
Containers::StridedArrayView1D<const Vector3> normals = cube.attribute<Vector3>(Trade::MeshAttribute::Normal);
Containers::StridedArrayView1D<const Vector4> tangents = cube.attribute<Vector4>(Trade::MeshAttribute::Tangent);
/* Normals and tangents should be the same for all vertices in a face,
and perpendicular in all cases */
for(UnsignedInt face = 0; face != 6; ++face) {
CORRADE_ITERATION(face);
CORRADE_COMPARE(Math::dot(normals[face*4], tangents[face*4].xyz()), 0.0f);
CORRADE_COMPARE(normals[face*4].dot(), 1.0f);
CORRADE_COMPARE(tangents[face*4].xyz().dot(), 1.0f);
CORRADE_COMPARE(Math::abs(tangents[face*4].w()), 1.0f);
for(UnsignedInt vertex = 1; vertex != 4; ++vertex) {
CORRADE_ITERATION(vertex);
CORRADE_COMPARE(normals[face*4 + vertex], normals[face*4]);
CORRADE_COMPARE(tangents[face*4 + vertex], tangents[face*4]);
}
}
/* For each face, sample in a position off center on X and Y */
for(UnsignedInt face = 0; face != 6; ++face) {
CORRADE_ITERATION(face);
Vector3 center = sampleQuad(
positions[face*4 + 0], positions[face*4 + 1],
positions[face*4 + 2], positions[face*4 + 3], {0.5f, 0.5f});
Vector2 centerTexture = sampleQuad(
textureCoordinates[face*4 + 0], textureCoordinates[face*4 + 1],
textureCoordinates[face*4 + 2], textureCoordinates[face*4 + 3],
{0.5f, 0.5f});
Vector3 tangent = tangents[face*4].xyz();
Vector3 bitangent = Math::cross(normals[face*4],
tangents[face*4].xyz())*tangents[face*4].w();
Vector3 offset[]{
sampleQuad(positions[face*4 + 0], positions[face*4 + 1],
positions[face*4 + 2], positions[face*4 + 3],
{0.75f, 0.5f}),
sampleQuad(positions[face*4 + 0], positions[face*4 + 1],
positions[face*4 + 2], positions[face*4 + 3],
{0.5f, 0.75f})
};
Vector2 offsetTexture[]{
sampleQuad(textureCoordinates[face*4 + 0], textureCoordinates[face*4 + 1],
textureCoordinates[face*4 + 2], textureCoordinates[face*4 + 3],
{0.75f, 0.5f}),
sampleQuad(textureCoordinates[face*4 + 0], textureCoordinates[face*4 + 1],
textureCoordinates[face*4 + 2], textureCoordinates[face*4 + 3],
{0.5f, 0.75f})
};
for(Int i: {0, 1}) {
CORRADE_ITERATION(i);
/* If the shift is in direction of tangent, texture coordinates
should be the same in Y and different with a matching sign
in X */
if(Math::notEqual(Math::dot(offset[i] - center, tangent), 0.0f)) {
Vector2 delta = offsetTexture[i] - centerTexture;
CORRADE_COMPARE(delta.y(), 0.0f);
CORRADE_COMPARE(Math::sign(delta.x()), Math::sign(Math::dot(offset[i] - center, tangent)));
/* If the shift is in direction of bitangent, texture
coordinates should be the same in X and different with a
matching sign in Y */
} else if(Math::notEqual(Math::dot(offset[i] - center, bitangent), 0.0f)) {
Vector2 delta = offsetTexture[i] - centerTexture;
CORRADE_COMPARE(delta.x(), 0.0f);
CORRADE_COMPARE(Math::sign(delta.y()), Math::sign(Math::dot(offset[i] - center, bitangent)));
} else CORRADE_FAIL(Debug::packed << offset[i] - center << "is parallel to neither" << Debug::packed << tangent << "nor" << Debug::packed << bitangent);
}
}
}
}
void CubeTest::solidInvalid() {
CORRADE_SKIP_IF_NO_ASSERT();
Containers::String out;
Error redirectError{&out};
Primitives::cubeSolid(CubeFlag::Tangents);
Primitives::cubeSolid(CubeFlag(UnsignedInt(CubeFlag::TextureCoordinatesPositiveZUpPositiveXDown) + 2));
CORRADE_COMPARE_AS(out,
"Primitives::cubeSolid(): a texture coordinate option has to be picked if tangents are enabled\n"
"Primitives::cubeSolid(): unrecognized texture coordinate option 0x12\n",
TestSuite::Compare::String);
}
void CubeTest::solidStrip() { void CubeTest::solidStrip() {
Trade::MeshData cube = Primitives::cubeSolidStrip(); Trade::MeshData cube = Primitives::cubeSolidStrip();

Loading…
Cancel
Save