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
from `doc/artwork/line-quad-data-other.svg` by removing the "other" layer and
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
Axis.cpp
Crosshair.cpp
Cube.cpp
Gradient.cpp
Grid.cpp
Icosphere.cpp
@ -46,6 +45,7 @@ set(MagnumPrimitives_GracefulAssert_SRCS
Capsule.cpp
Circle.cpp
Cone.cpp
Cube.cpp
Cylinder.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 */
constexpr UnsignedShort IndicesSolid[]{
/* 3--2
| /|
|/ |
0--1 */
0, 1, 2, 0, 2, 3, /* +Z */
4, 5, 6, 4, 6, 7, /* +X */
8, 9, 10, 8, 10, 11, /* +Y */
@ -47,34 +51,44 @@ constexpr struct VertexSolid {
Vector3 position;
Vector3 normal;
} 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}}, /* +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}},
/* 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}}, /* +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}},
/* 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}}, /* +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}},
/* 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}}, /* -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}},
/* 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}}, /* -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}},
/* 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}}, /* -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}}
};
constexpr Trade::MeshAttributeData AttributesSolid[]{
@ -96,6 +110,481 @@ Trade::MeshData cubeSolid() {
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
Crosshair.cpp for details. */
constexpr struct VertexSolidStrip {

119
src/Magnum/Primitives/Cube.h

@ -27,28 +27,139 @@
*/
/** @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/Trade/Trade.h"
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
2x2x2 cube, centered at origin. @ref MeshPrimitive::Triangles with
@ref MeshIndexType::UnsignedShort indices, interleaved
@ref VertexFormat::Vector3 positions and flat @ref VertexFormat::Vector3
normals. The returned instance references @ref Trade::DataFlag::Global data ---
pass the mesh through @ref MeshTools::copy() to get a mutable copy, if needed.
normals. If no @p flags are passed, the returned instance references
@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
@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(CubeFlags flags);
#endif
/**
@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(PrimitivesCircleTest CircleTest.cpp LIBRARIES MagnumPrimitivesTestLib)
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(PrimitivesCylinderTest CylinderTest.cpp LIBRARIES MagnumPrimitivesTestLib)
corrade_add_test(PrimitivesGradientTest GradientTest.cpp LIBRARIES MagnumPrimitives)

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

@ -24,11 +24,15 @@
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/String.h>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/String.h>
#include "Magnum/Mesh.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/Trade/MeshData.h"
@ -38,20 +42,263 @@ struct CubeTest: TestSuite::Tester {
explicit CubeTest();
void solid();
template<CubeFlag flag = CubeFlag{}> void solidTextureCoordinates();
void solidInvalid();
void solidStrip();
void solidStripGlsl();
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() {
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::solidStripGlsl,
&CubeTest::wireframe});
}
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_VERIFY(cube.isIndexed());
@ -65,6 +312,259 @@ void CubeTest::solid() {
(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() {
Trade::MeshData cube = Primitives::cubeSolidStrip();

Loading…
Cancel
Save