Merge: Small improvements to the gamnit README
authorJean Privat <jean@pryen.org>
Thu, 21 Jan 2016 01:19:45 +0000 (20:19 -0500)
committerJean Privat <jean@pryen.org>
Thu, 21 Jan 2016 01:19:45 +0000 (20:19 -0500)
Pull-Request: #1926
Reviewed-by: Jean Privat <jean@pryen.org>

36 files changed:
contrib/model_viewer/Makefile
contrib/model_viewer/README.md
contrib/model_viewer/art/icon.png
contrib/model_viewer/art/icon.xcf
contrib/model_viewer/art/next-prev-model.svg [new file with mode: 0644]
contrib/model_viewer/assets/globe/clouds.png [new file with mode: 0644]
contrib/model_viewer/assets/globe/earth.jpg [new file with mode: 0644]
contrib/model_viewer/assets/globe/elevation.jpg [new file with mode: 0644]
contrib/model_viewer/assets/globe/lights.jpg [new file with mode: 0644]
contrib/model_viewer/assets/globe/seas.jpg [new file with mode: 0644]
contrib/model_viewer/assets/ui/next.png [new file with mode: 0644]
contrib/model_viewer/assets/ui/prev.png [new file with mode: 0644]
contrib/model_viewer/libs/.gitignore [moved from lib/gamnit/examples/globe/bin/.gitignore with 100% similarity]
contrib/model_viewer/src/globe.nit [new file with mode: 0644]
contrib/model_viewer/src/model_viewer.nit
lib/android/cardboard.nit
lib/gamnit/depth/cardboard.nit [new file with mode: 0644]
lib/gamnit/depth/depth.nit
lib/gamnit/depth/more_materials.nit
lib/gamnit/depth/more_meshes.nit
lib/gamnit/depth/stereoscopic_view.nit [new file with mode: 0644]
lib/gamnit/depth/vr.nit [new file with mode: 0644]
lib/gamnit/examples/globe/Makefile [deleted file]
lib/gamnit/examples/globe/README [deleted file]
lib/gamnit/examples/globe/art/icon.png [deleted file]
lib/gamnit/examples/globe/art/icon.xcf [deleted file]
lib/gamnit/examples/globe/assets/hd/clouds.png [deleted file]
lib/gamnit/examples/globe/assets/hd/earth.jpg [deleted file]
lib/gamnit/examples/globe/assets/hd/elevation.jpg [deleted file]
lib/gamnit/examples/globe/assets/hd/lights.jpg [deleted file]
lib/gamnit/examples/globe/assets/hd/seas.jpg [deleted file]
lib/gamnit/examples/globe/org.nitlanguage.globe.txt [deleted file]
lib/gamnit/examples/globe/package.ini [deleted file]
lib/gamnit/examples/globe/src/globe.nit [deleted file]
lib/gamnit/flat.nit
lib/gamnit/keys.nit [new file with mode: 0644]

index ebd0143..4557a44 100644 (file)
@@ -29,3 +29,10 @@ res/drawable-hdpi/icon.png: art/icon.png
        convert -resize 96x96   art/icon.png res/drawable-xhdpi/icon.png
        convert -resize 144x144 art/icon.png res/drawable-xxhdpi/icon.png
        convert -resize 192x192 art/icon.png res/drawable-xxxhdpi/icon.png
+
+bin/model_viewer_vr.apk: $(shell ${NITLS} -M src/model_viewer.nit android) ${NITC} res/drawable-hdpi/icon.png libs/cardboard.jar
+       ${NITC} src/model_viewer.nit -m android -m ../../lib/gamnit/depth/vr.nit -o $@
+
+libs/cardboard.jar:
+       curl --progress-bar -o libs/cardboard.jar \
+       https://raw.githubusercontent.com/googlesamples/cardboard-java/master/CardboardSample/libs/cardboard.jar
index 3dbe22a..abbcecf 100644 (file)
@@ -1,8 +1,20 @@
 Sample portable 3D app implemented with the gamnit depth framework
 
+This application uses the _depth_ framework to load and display 3D models.
+It also applies the _flat_ framework to display the static UI elements (like the "Next model" label).
+
+The pretty earth model (`GlobeModel`) is implemented by a material with a custom graphical program.
+It renders the earth with an displaced surface, a cloud layer, city lights and Phong lighting effects on the water.
+
+# Variations
+
+* The standard application is compiled to a desktop executable at `bin/model_viewer` and an Android package at `bin/model_viewer.apk`.
+* The virtual reality variant `bin/model_viewer_vr.apk` targets Android and uses Google Cardboard for head tracking.
+
 # Art
 
 * 3D models `Tree_01` and `Oak_Fall_01` were created by Kenney.nl and published under CC0.
 * 3D model `Quandtum_BA-2_v1_1` was created by Quandtum and published under CC0.
 * Some textures on the `Quandtum_BA-2_v1_1` model have been created with images from goodtextures.com.
   These images can be used in free softwares, some restrictions still applies for modifications and other uses.
+* Globe textures credit: NASA, Visible Earth
index 416f0ff..71612a4 100644 (file)
Binary files a/contrib/model_viewer/art/icon.png and b/contrib/model_viewer/art/icon.png differ
index 4d7795b..efcf652 100644 (file)
Binary files a/contrib/model_viewer/art/icon.xcf and b/contrib/model_viewer/art/icon.xcf differ
diff --git a/contrib/model_viewer/art/next-prev-model.svg b/contrib/model_viewer/art/next-prev-model.svg
new file mode 100644 (file)
index 0000000..77f9203
--- /dev/null
@@ -0,0 +1,360 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="next-prev-model.svg">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Lend"
+       style="overflow:visible;">
+      <path
+         id="path3798"
+         style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(1.1) rotate(180) translate(1,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.98994949"
+     inkscape:cx="475.81167"
+     inkscape:cy="821.81226"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="2558"
+     inkscape:window-height="1379"
+     inkscape:window-x="2560"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
+     showguides="true"
+     inkscape:guide-bbox="true" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <g
+       id="0next"
+       inkscape:label="#g4700"
+       transform="matrix(2.0963119,0,0,2.0963119,-813.43954,-216.81189)"
+       inkscape:export-filename="/home/xymus/Downloads/next.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <g
+         style="fill:#000000"
+         id="g4593">
+        <path
+           style="fill:#000000;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+           d="m 656,188.90625 c -4.32878,5.37465 3.34038,10.18188 3.40625,15.71875 2.11338,8.14548 -1.48782,16.2744 -4.84474,23.31198 0.88119,5.68482 8.54841,3.67576 11.96974,1.43802 14.12986,-6.05994 29.36922,-9.67603 43.15625,-16.65625 3.09218,-4.66997 -4.21022,-8.11493 -8.09375,-8.84375 -14.77463,-4.36086 -28.82072,-11.74328 -43.96875,-15.28125 L 656.64299,188.7826 656,188.90625 z"
+           id="path4368"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 451.9375,188.75 c -5.34509,0.008 -7.99849,5.96579 -6.5,10.59375 -2.09613,-4.05624 -3.52928,-10.07737 -9.15625,-10.1875 -3.25871,0.18236 -10.20635,-1.84089 -9.15625,3 0,11.41667 0,22.83333 0,34.25 5.19971,1.80199 13.79841,1.01116 13.96875,-6.03125 0.0985,-2.71165 -0.65681,-5.2049 1.1875,-1.28125 0.95441,5.53108 6.4523,8.77 11.875,7.8125 7.80009,1.72283 4.14251,-7.33165 4.9375,-12.1875 0,-8.41667 0,-16.83333 0,-25.25 -2.38217,-0.41148 -4.72323,-0.9443 -7.15625,-0.71875 z"
+           id="path4306"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 470.1875,196.0625 c -12.64808,-0.34066 -20.11359,17.60573 -10.75,26.3125 8.0188,9.16453 26.01035,4.48792 26.9375,-8.09375 0.99174,-9.39292 -6.03753,-19.20046 -16.1875,-18.21875 z"
+           id="path4308"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 501.21875,196.3125 c -3.06208,-0.84258 -4.55021,2.38155 -6.46875,3.09375 -3.60528,-3.57788 -9.01254,-3.18847 -13.78125,-2.6875 -4.31554,2.98948 1.80217,7.05639 3.125,9.9375 2.32397,2.54568 3.39397,7.04813 -0.375,9 -2.90112,2.4991 -7.19482,9.00555 -1.65625,11.09375 4.68687,1.15044 10.36095,-0.12207 13.1875,-3.96875 0.63175,4.0438 3.24534,4.04893 6.78125,3.9375 3.18505,0.59869 10.28931,0.56244 8.5625,-4.46875 -2.26088,-4.29397 -8.73602,-8.18074 -7.03125,-13.53125 2.8755,-2.71034 8.79074,-8.79581 3.1875,-11.875 -1.74801,-0.66881 -3.67873,-0.64433 -5.53125,-0.53125 z"
+           id="path4310"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 513.78125,189.21875 c -3.33439,-0.75172 -10.33032,-0.65853 -8.65625,4.65625 -0.17239,4.73607 -5.5168,9.38156 -1.75,14.125 5.1229,4.49173 -1.633,13.36405 3.15625,17.75 5.21197,3.74978 14.2168,-0.4073 12.375,-7.34375 -1.90033,-4.01966 -1.1284,-8.16273 1.65625,-11.5 2.77063,-5.04265 -1.77316,-10.1534 -3.25,-14.96875 -0.87015,-1.02399 -1.78424,-3.96455 -3.53125,-2.71875 z"
+           id="path4312"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 541.34375,196.0625 c -4.51875,0.9964 -9.26842,0.30548 -13.90625,0.5 0,9.92708 0,19.85417 0,29.78125 5.13396,1.96096 13.57717,1.03604 13.78125,-5.90625 -1.81001,8.33947 12.68142,8.90492 14,1.40625 -0.42099,3.09677 0.48653,5.58173 4,5.21875 5.40653,1.4676 11.17404,-3.02327 9.90625,-8.78125 -0.45179,-7.2473 0.77332,-17.36508 -7.28125,-21.03125 -4.16728,-1.88732 -9.44992,-1.43054 -13.28125,0.53125 -2.1367,-1.34503 -4.71152,-1.89845 -7.21875,-1.71875 z m -0.1875,13.09375 c 1.01687,3.52054 0.14248,7.35414 0.0625,11.03125 0.1247,-3.44655 -1.45369,-8.40998 -0.0625,-11.03125 z M 555.09375,209 c 0.70347,2.88457 0.38291,7.67655 0.1875,9.40625 -0.81188,-2.93279 -1.20072,-6.55095 -0.1875,-9.40625 z"
+           id="path4314"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 579.0625,196.0625 c -12.68715,-0.2598 -20.18845,17.60259 -10.71875,26.34375 11.3117,13.0977 34.85871,-2.7399 25.40625,-18.03125 -2.76217,-5.26347 -8.69083,-8.82111 -14.6875,-8.3125 z m 0.90625,12.875 c 4.01822,0.26803 1.85946,7.85333 -1.71875,4.78125 -1.56836,-1.57678 -0.79054,-4.96738 1.71875,-4.78125 z"
+           id="path4316"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 618.5,189.21875 c -3.55137,0.0451 -11.28032,-1.87634 -10.8125,4.125 0.43375,2.36323 0.51137,3.57824 -2.0625,2.40625 -13.14309,-1.26298 -21.17669,16.91961 -12.21875,26.25 4.0564,5.1833 11.47205,6.13633 17.21875,4.4375 5.46388,2.80037 12.18721,-2.12647 10.9375,-8.21875 -1.31434,-9.72996 -0.19193,-19.77143 -0.5625,-29.625 -0.83333,0.20833 -1.66667,0.41667 -2.5,0.625 z m -13,19.4375 c 4.33286,-0.20831 2.30424,8.15282 -1.46875,5.125 -1.679,-1.39982 -1.18008,-5.30155 1.46875,-5.125 z"
+           id="path4318"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 631.0625,196.0625 c -12.42272,-0.34784 -19.99093,17.04802 -11.125,25.875 7.69336,9.79997 26.70839,5.09691 27.28125,-7.9375 0.93983,-9.40212 -6.13947,-18.79793 -16.15625,-17.9375 z m 1.84375,9.25 c -3.76495,-1.48752 -3.33258,5.1691 0.1875,3.75 0.90612,-0.24028 0.54495,-3.3012 -0.1875,-3.75 z"
+           id="path4320"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 653.5,189.21875 c -3.5107,0.13642 -11.08255,-1.95561 -10.84375,3.9375 0,11.0625 0,22.125 0,33.1875 5.17254,1.98449 13.72774,1.02119 13.8125,-6.03125 -0.85413,-10.49846 -0.32956,-21.14442 -0.46875,-31.71875 -0.83333,0.20833 -1.66667,0.41667 -2.5,0.625 z"
+           id="path4322"
+           inkscape:connector-curvature="0" />
+      </g>
+      <g
+         style="fill:#ffffff"
+         id="g4566">
+        <path
+           inkscape:connector-curvature="0"
+           id="path4239"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 431.13342,222.72359 5.48,0 0,-21.48 12.36,21.48 6.12,0 0,-29.56 -5.48,0 0,21.52 -12.24,-21.52 -6.24,0 0,29.56" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4241"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 482.1428,214.00359 c 0.16,-0.76 0.2,-1.24 0.2,-2.04 0,-6.88 -4.84001,-11.92 -11.44,-11.92 -6.52,0 -11.68,5.16 -11.68,11.68 0,6.47999 5.24,11.52 12,11.52 3.63999,0 6.48,-1.32001 8.8,-4 0.84,-1.04 1.4,-1.96 1.76,-3.08 l -5.8,0 c -1.36,1.6 -2.68001,2.2 -4.88,2.2 -3.16,0 -5.48,-1.68001 -6.12,-4.36 l 17.16,0 m -17.32,-4.68 c 0.84,-2.84 3,-4.4 6.16,-4.4 3.27999,0 5.44,1.56 6.12,4.4 l -12.28,0" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4243"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 483.6878,222.72359 6.4,0 4.64,-7.6 4.64,7.6 6.4,0 -7.88,-11.44 6.76,-10.72 -6,0 -3.92,6.68 -4,-6.68 -6,0 6.8,10.72 -7.84,11.44" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4245"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 509.02967,222.72359 5.32,0 0,-17.32 3.2,0 0,-4.84 -3.2,0 0,-7.4 -5.32,0 0,7.4 -2.6,0 0,4.84 2.6,0 0,17.32" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4247"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 531.4328,222.72359 5.32,0 0,-10.92 c 0,-2.2 0.2,-3.68 0.56,-4.6 0.64,-1.44 2,-2.28 3.76,-2.28 1.44,0 2.68,0.52 3.4,1.4 0.64,0.84 0.92,2.16 0.92,4.24 l 0,12.16 5.32,0 0,-10.92 c 0,-2.48 0.2,-3.72 0.76,-4.76 0.68,-1.36 2.04,-2.12 3.72,-2.12 1.32,0 2.44,0.48 3.16,1.36 0.72,0.84 1,2.08 1,4.28 l 0,12.16 5.32,0 0,-12.8 c 0,-2.68 -0.48,-4.84 -1.44,-6.36 -1.4,-2.24 -4.20001,-3.52 -7.52,-3.52 -3.12,0 -5.32001,1.04 -7.12,3.44 -1.52,-2.4 -3.48001,-3.44 -6.52,-3.44 -2.6,0 -4.2,0.72 -5.76,2.6 l 0,-2.08 -4.88,0 0,22.16" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4249"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 579.77092,200.04359 c -6.43999,0 -11.72,5.24 -11.72,11.6 0,6.39999 5.28001,11.6 11.76,11.6 6.44,0 11.8,-5.20001 11.8,-11.44 0,-6.6 -5.16001,-11.76 -11.84,-11.76 m 0.04,4.88 c 3.56,0 6.44,3.04 6.44,6.72 0,3.71999 -2.88,6.72 -6.4,6.72 -3.59999,0 -6.44,-3.00001 -6.44,-6.8 0,-3.64 2.92001,-6.64 6.4,-6.64" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4251"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 616.99592,193.16359 -5.32,0 0,9.36 c -1.56,-1.72 -4.12,-2.76 -6.92,-2.76 -6.19999,0 -11.08,5.2 -11.08,11.84 0,6.55999 4.84001,11.64 11.12,11.64 3,0 5.2,-1.00001 7.32,-3.4 l 0,2.88 4.88,0 0,-29.56 m -11.48,11.48 c 3.72,0 6.56,3 6.56,6.88 0,3.83999 -2.84,6.84 -6.44,6.84 -3.71999,0 -6.6,-3.08001 -6.6,-7 0,-3.76 2.84001,-6.72 6.48,-6.72" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4253"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 643.00217,214.00359 c 0.16,-0.76 0.2,-1.24 0.2,-2.04 0,-6.88 -4.84,-11.92 -11.44,-11.92 -6.51999,0 -11.68,5.16 -11.68,11.68 0,6.47999 5.24001,11.52 12,11.52 3.64,0 6.48,-1.32001 8.8,-4 0.84,-1.04 1.4,-1.96 1.76,-3.08 l -5.8,0 c -1.36,1.6 -2.68,2.2 -4.88,2.2 -3.16,0 -5.48,-1.68001 -6.12,-4.36 l 17.16,0 m -17.32,-4.68 c 0.84,-2.84 3,-4.4 6.16,-4.4 3.28,0 5.44,1.56 6.12,4.4 l -12.28,0" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4255"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 646.66717,222.72359 5.32,0 0,-29.56 -5.32,0 0,29.56" />
+        <g
+           id="g4650">
+          <path
+             inkscape:connector-curvature="0"
+             id="path3003"
+             d="m 676.09375,208.28125 0,4.03125 25.40625,0 0,-4.03125 -25.40625,0 z"
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.05724525;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" />
+          <path
+             inkscape:connector-curvature="0"
+             id="path4656"
+             style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+             d="m 658.13707,192.29293 48.76186,17.93097 -48.76187,17.93097 c 7.79011,-10.58644 7.74522,-25.07052 10e-6,-35.86194 z" />
+        </g>
+      </g>
+    </g>
+    <g
+       id="0prev"
+       inkscape:label="#g4666"
+       inkscape:export-filename="/home/xymus/Downloads/prev.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90"
+       transform="matrix(2.0963119,0,0,2.0963119,-87.104484,-388.33708)">
+      <g
+         style="fill:#000000"
+         id="g4605">
+        <path
+           style="fill:#000000;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+           d="m 93.03125,188.90625 c -6.672841,1.5995 -12.604304,5.44802 -19.351519,7.03986 -9.962295,4.08128 -20.797763,6.80119 -30.210981,11.74139 -3.185255,5.30141 3.906347,8.54538 8.153116,9.00997 14.54548,4.65727 28.641598,11.70524 43.659384,15.30253 5.95503,-1.61287 1.419816,-8.86058 -0.71875,-12 -3.30648,-8.69739 -1.325001,-18.75649 3.71875,-26.34375 0.871021,-3.03836 -2.624351,-5.10497 -5.25,-4.75 z"
+           id="path4360"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 94.78125,191.15625 c 0,11.75 0,23.5 0,35.25 5.199709,1.80199 13.79841,1.01116 13.96875,-6.03125 0.73785,-2.0285 -2.2096,-6.16156 1.6875,-5.15625 10.13737,-0.0717 14.44247,-13.62233 8.65625,-21 -5.45932,-7.76372 -16.32167,-4.22406 -24.3125,-5.09375 0,0.67708 0,1.35417 0,2.03125 z"
+           id="path4324"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 130.5,195.84375 c -4.47817,1.15007 -9.21902,0.63554 -13.84375,0.6875 0,9.9375 0,19.875 0,29.8125 5.13396,1.96096 13.57717,1.03604 13.78125,-5.90625 0.40744,-3.56077 -2.00329,-8.76162 0.28125,-11.40625 4.9013,0.27685 4.85349,-7.16544 3.6875,-10.84375 -0.57967,-1.52305 -2.25227,-2.63172 -3.90625,-2.34375 z"
+           id="path4326"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="M 143.84375,196.03125 C 131.29559,195.39471 123.3737,212.99969 132.375,222 c 7.74413,9.50241 26.10134,5.23632 27.21875,-7.5 1.46522,-9.18478 -6.03486,-19.22017 -15.75,-18.46875 z"
+           id="path4328"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 176.21875,196.34375 c -3.56118,-0.0722 -7.36531,1.85845 -8.4375,5.40625 -0.53483,-3.8326 -4.08839,-6.2915 -7.65625,-5.0625 -3.03486,-0.93228 -9.63906,-0.47023 -7.5625,4.28125 4.45743,8.06732 6.41912,18.39383 11.4375,25.65625 5.69264,2.56918 11.28354,-2.36473 12.25,-7.90625 2.52212,-7.43896 5.81803,-14.60939 8.65625,-21.9375 -2.89275,-0.19539 -5.78232,-0.60468 -8.6875,-0.4375 z"
+           id="path4330"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 188.34375,189.21875 c -3.5107,0.13642 -11.08255,-1.95561 -10.84375,3.9375 0,11.0625 0,22.125 0,33.1875 5.17254,1.98449 13.72774,1.02119 13.8125,-6.03125 -0.85413,-10.49846 -0.32956,-21.14442 -0.46875,-31.71875 -0.83333,0.20833 -1.66667,0.41667 -2.5,0.625 z"
+           id="path4332"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 201.1875,196.0625 c -12.69297,-0.27971 -20.18387,17.60578 -10.75,26.34375 8.33738,9.52576 26.52717,3.73426 27.25,-9.03125 1.17854,-9.18651 -7.18577,-18.17636 -16.5,-17.3125 z m 0.875,12.875 c 4.55645,0.381 1.07641,8.56275 -2.09375,4.28125 -0.9976,-1.64086 -0.15837,-4.46179 2.09375,-4.28125 z"
+           id="path4334"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 233.75,196.03125 c -4.81989,-0.42567 -7.81764,4.16091 -6.8125,8.59375 -0.0779,3.04011 1.21947,7.20274 -0.1875,9.625 -1.74567,-1.30416 -0.30176,-6.13336 -0.5625,-8.53125 0.23061,-3.58321 0.0464,-10.31908 -4.84375,-9 -3.18683,-0.77679 -9.36318,-0.83945 -8.59375,4.03125 0.57984,8.2257 -2.53038,19.36453 5.8125,24.6875 5.63017,3.57116 12.46231,0.43796 18.53125,1.0625 6.33372,-2.68182 2.60959,-11.04236 3.125,-16.15625 0.95881,-5.34847 1.62363,-14.9854 -6.46875,-14.3125 z"
+           id="path4336"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 245.53125,196.09375 c -7.55584,0.65612 -11.50164,10.28973 -8.1875,16.125 -4.72943,2.09654 -1.32143,7.88385 0.59375,10.875 6.12857,7.46668 20.7748,4.10946 21.40625,-6.125 1.03821,-2.70123 -1.80871,-5.51051 -1.09375,-7.625 2.9228,-7.47873 -5.48162,-14.59712 -12.71875,-13.25 z"
+           id="path4338"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 292.1875,196 c -3.17064,-0.0125 -5.54316,3.46156 -8.1875,0.46875 -6.02876,-1.14078 -12.35065,0.93994 -18.53125,0.0937 0,9.92708 0,19.85417 0,29.78125 4.60888,1.94997 12.12496,0.77468 13.46875,-3.65625 1.83044,6.9394 15.2086,5.76758 14,-2.125 -0.0462,-1.89173 0.26329,3.85684 2.09375,4.78125 3.76518,3.31061 11.9811,2.47436 11.71875,-3.625 -0.19537,-6.00494 0.69952,-12.27863 -0.875,-18.09375 -2.25403,-5.2589 -8.10856,-8.20536 -13.6875,-7.625 z m -13,12.90625 c 1.1987,2.90344 -0.19863,6.21519 0.0625,9.28125 -0.3425,-2.92895 -1.09356,-6.57759 -0.0625,-9.28125 z m 14.09375,0.0625 c 0.62659,3.29448 -0.0508,6.7046 -0.3125,10 0.0889,-3.28543 -1.26563,-7.00095 0.3125,-10 z m -14,9.65625 c 0.17144,1.67745 -0.0842,-0.2242 0,0 z"
+           id="path4340"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 317.125,196.0625 c -12.69297,-0.27971 -20.18387,17.60578 -10.75,26.34375 8.33738,9.52576 26.52717,3.73426 27.25,-9.03125 1.17854,-9.18651 -7.18577,-18.17636 -16.5,-17.3125 z m 0.875,12.875 c 4.55645,0.381 1.07641,8.56275 -2.09375,4.28125 -0.9976,-1.64086 -0.15837,-4.46179 2.09375,-4.28125 z"
+           id="path4342"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 356.53125,189.21875 c -3.66512,-0.0965 -11.6229,-1.76238 -10.8125,4.46875 1.26863,4.08017 -3.49927,1.02615 -5.78125,2.25 -11.5878,2.30296 -16.50311,18.59696 -7.875,26.78125 4.21779,4.55956 11.08624,5.32421 16.59375,3.71875 5.46388,2.80037 12.18721,-2.12647 10.9375,-8.21875 -1.31434,-9.72996 -0.19193,-19.77143 -0.5625,-29.625 -0.83333,0.20833 -1.66667,0.41667 -2.5,0.625 z m -12.84375,19.4375 c 4.57248,0.35151 1.71186,8.45181 -1.84375,4.90625 -1.3651,-1.60613 -0.77522,-5.19193 1.84375,-4.90625 z"
+           id="path4344"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="M 369.46875,196.03125 C 356.92059,195.39471 348.9987,212.99969 358,222 c 7.74413,9.50241 26.10134,5.23632 27.21875,-7.5 1.46522,-9.18478 -6.03486,-19.22017 -15.75,-18.46875 z"
+           id="path4346"
+           inkscape:connector-curvature="0" />
+        <path
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 391.53125,189.21875 c -3.55206,0.0423 -11.28168,-1.87282 -10.8125,4.125 0,11 0,22 0,33 5.13396,1.96096 13.57717,1.03604 13.78125,-5.90625 -0.82876,-10.54724 -0.34724,-21.22452 -0.46875,-31.84375 -0.83333,0.20833 -1.66667,0.41667 -2.5,0.625 z"
+           id="path4348"
+           inkscape:connector-curvature="0" />
+      </g>
+      <g
+         style="fill:#ffffff"
+         transform="translate(0,40)"
+         id="g4634">
+        <path
+           inkscape:connector-curvature="0"
+           id="path4258"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 98.793227,182.72359 5.480003,0 0,-11.24 1.76,0 c 4.19999,0 6.12,-0.32 7.76,-1.32 2.39999,-1.48 3.88,-4.48001 3.88,-7.88 0,-3.4 -1.44001,-6.2 -4,-7.76 -1.68,-1 -3.64001,-1.36 -7.56,-1.36 l -7.320003,0 0,29.56 m 5.480003,-16.48 0,-7.84 1.84,0 c 1.8,0 2.6,0.08 3.48,0.28 1.6,0.44 2.56,1.84 2.56,3.68 0,1.44 -0.64,2.56 -1.8,3.2 -0.84,0.44 -2.36001,0.68 -4.48,0.68 l -1.6,0" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4260"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 120.6551,182.72359 5.32,0 0,-12.32 c 0,-3.44 1.56001,-5.16 4.76,-5.24 l 0,-5.12 -0.4,0 c -2.28,0 -3.4,0.64 -4.8,2.68 l 0,-2.16 -4.88,0 0,22.16" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4262"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 155.4276,174.00359 c 0.16,-0.76 0.2,-1.24 0.2,-2.04 0,-6.88 -4.84,-11.92 -11.44,-11.92 -6.51999,0 -11.68,5.16 -11.68,11.68 0,6.47999 5.24001,11.52 12,11.52 3.64,0 6.48,-1.32001 8.8,-4 0.84,-1.04 1.4,-1.96 1.76,-3.08 l -5.8,0 c -1.36,1.6 -2.68,2.2 -4.88,2.2 -3.15999,0 -5.48,-1.68001 -6.12,-4.36 l 17.16,0 m -17.32,-4.68 c 0.84,-2.84 3.00001,-4.4 6.16,-4.4 3.28,0 5.44,1.56 6.12,4.4 l -12.28,0" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4264"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 165.8926,182.72359 4.24,0 8.92,-22.16 -6,0 -5.04,14.68 -5.12,-14.68 -5.92,0 8.92,22.16" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4266"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 181.51448,182.72359 5.32,0 0,-22.16 -5.32,0 0,22.16 m 0,-24.56 5.32,0 0,-5 -5.32,0 0,5" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4268"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 201.88385,160.04359 c -6.43999,0 -11.72,5.24 -11.72,11.6 0,6.39999 5.28001,11.6 11.76,11.6 6.44,0 11.8,-5.20001 11.8,-11.44 0,-6.6 -5.16,-11.76 -11.84,-11.76 m 0.04,4.88 c 3.56,0 6.44,3.04 6.44,6.72 0,3.71999 -2.88,6.72 -6.4,6.72 -3.59999,0 -6.44,-3.00001 -6.44,-6.8 0,-3.64 2.92001,-6.64 6.4,-6.64" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4270"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 236.46885,160.56359 -5.32,0 0,10.44 c 0,2.91999 -0.2,4.36 -0.84,5.32 -0.76,1.28 -2.24,2.04 -4.04,2.04 -1.36,0 -2.4,-0.44 -3.12,-1.4 -0.76,-0.96 -1.08,-2.60001 -1.08,-5.56 l 0,-10.84 -5.32,0 0,11.88 c 0,3.75999 0.44,5.68 1.68,7.52 1.48,2.11999 3.88,3.28 6.76,3.28 2.68,0 4.36,-0.68 6.36,-2.64 l 0,2.12 4.92,0 0,-22.16" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4272"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 239.33323,175.68359 c 0.24,2.15999 0.6,3.28 1.48,4.48 1.44,1.92 3.96,3.08 6.64,3.08 4.43999,0 7.92,-3.32001 7.92,-7.56 0,-1.92 -0.72,-3.52 -2.08,-4.6 -0.84,-0.72 -2.16,-1.28 -4.08,-1.88 -2.16,-0.68 -2.16,-0.68 -2.68,-0.92 -0.72,-0.32 -1.08,-0.84 -1.08,-1.48 0,-1.08 0.88,-1.88 2.04,-1.88 1.12,0 1.84,0.6 2.08,1.76 l 5.2,0 c -0.08,-1.88 -0.52,-3 -1.6,-4.2 -1.4,-1.56 -3.48001,-2.44 -5.68,-2.44 -4.12,0 -7.36,2.96 -7.36,6.76 0,3.23999 1.76,5.08 6.16,6.56 2.03999,0.68 2.2,0.76 2.76,1.12 0.64,0.4 1,1 1,1.72 0,1.24 -1.04,2.16 -2.4,2.16 -1.56,0 -2.44,-0.8 -2.96,-2.68 l -5.36,0" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4274"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 269.48323,182.72359 5.32,0 0,-10.92 c 0,-2.2 0.2,-3.68 0.56,-4.6 0.64,-1.44 2,-2.28 3.76,-2.28 1.44,0 2.68,0.52 3.4,1.4 0.64,0.84 0.92,2.16 0.92,4.24 l 0,12.16 5.32,0 0,-10.92 c 0,-2.48 0.2,-3.72 0.76,-4.76 0.68,-1.36 2.04,-2.12 3.72,-2.12 1.32,0 2.44,0.48 3.16,1.36 0.72,0.84 1,2.08 1,4.28 l 0,12.16 5.32,0 0,-12.8 c 0,-2.68 -0.48,-4.84 -1.44,-6.36 -1.4,-2.24 -4.20001,-3.52 -7.52,-3.52 -3.12,0 -5.32,1.04 -7.12,3.44 -1.52,-2.4 -3.48001,-3.44 -6.52,-3.44 -2.6,0 -4.2,0.72 -5.76,2.6 l 0,-2.08 -4.88,0 0,22.16" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4276"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 317.82135,160.04359 c -6.43999,0 -11.72,5.24 -11.72,11.6 0,6.39999 5.28001,11.6 11.76,11.6 6.44,0 11.8,-5.20001 11.8,-11.44 0,-6.6 -5.16,-11.76 -11.84,-11.76 m 0.04,4.88 c 3.56,0 6.44,3.04 6.44,6.72 0,3.71999 -2.88,6.72 -6.4,6.72 -3.59999,0 -6.44,-3.00001 -6.44,-6.8 0,-3.64 2.92001,-6.64 6.4,-6.64" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4278"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 355.04635,153.16359 -5.32,0 0,9.36 c -1.56,-1.72 -4.12,-2.76 -6.92,-2.76 -6.19999,0 -11.08,5.2 -11.08,11.84 0,6.55999 4.84001,11.64 11.12,11.64 3,0 5.2,-1.00001 7.32,-3.4 l 0,2.88 4.88,0 0,-29.56 m -11.48,11.48 c 3.72,0 6.56,3 6.56,6.88 0,3.83999 -2.84,6.84 -6.44,6.84 -3.71999,0 -6.6,-3.08001 -6.6,-7 0,-3.76 2.84001,-6.72 6.48,-6.72" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4280"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 381.0526,174.00359 c 0.16,-0.76 0.2,-1.24 0.2,-2.04 0,-6.88 -4.84,-11.92 -11.44,-11.92 -6.51999,0 -11.68,5.16 -11.68,11.68 0,6.47999 5.24001,11.52 12,11.52 3.64,0 6.48,-1.32001 8.8,-4 0.84,-1.04 1.4,-1.96 1.76,-3.08 l -5.8,0 c -1.36,1.6 -2.68,2.2 -4.88,2.2 -3.15999,0 -5.48,-1.68001 -6.12,-4.36 l 17.16,0 m -17.32,-4.68 c 0.84,-2.84 3.00001,-4.4 6.16,-4.4 3.28,0 5.44,1.56 6.12,4.4 l -12.28,0" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path4282"
+           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:URW Gothic L;-inkscape-font-specification:URW Gothic L Semi-Bold"
+           d="m 384.7176,182.72359 5.32,0 0,-29.56 -5.32,0 0,29.56" />
+        <g
+           id="g4658">
+          <path
+             inkscape:connector-curvature="0"
+             id="path4217"
+             d="m 51.375,168.28125 0,4.03125 25.40625,0 0,-4.03125 -25.40625,0 z"
+             style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.05724525;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" />
+          <path
+             inkscape:connector-curvature="0"
+             id="path4664"
+             style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+             d="M 94.74648,188.2978 45.984619,170.36683 94.746482,152.43586 c -7.790106,10.58644 -7.74522,25.07052 -2e-6,35.86194 z" />
+        </g>
+      </g>
+    </g>
+  </g>
+</svg>
diff --git a/contrib/model_viewer/assets/globe/clouds.png b/contrib/model_viewer/assets/globe/clouds.png
new file mode 100644 (file)
index 0000000..6a34285
Binary files /dev/null and b/contrib/model_viewer/assets/globe/clouds.png differ
diff --git a/contrib/model_viewer/assets/globe/earth.jpg b/contrib/model_viewer/assets/globe/earth.jpg
new file mode 100644 (file)
index 0000000..53388c8
Binary files /dev/null and b/contrib/model_viewer/assets/globe/earth.jpg differ
diff --git a/contrib/model_viewer/assets/globe/elevation.jpg b/contrib/model_viewer/assets/globe/elevation.jpg
new file mode 100644 (file)
index 0000000..48737a0
Binary files /dev/null and b/contrib/model_viewer/assets/globe/elevation.jpg differ
diff --git a/contrib/model_viewer/assets/globe/lights.jpg b/contrib/model_viewer/assets/globe/lights.jpg
new file mode 100644 (file)
index 0000000..48dff8d
Binary files /dev/null and b/contrib/model_viewer/assets/globe/lights.jpg differ
diff --git a/contrib/model_viewer/assets/globe/seas.jpg b/contrib/model_viewer/assets/globe/seas.jpg
new file mode 100644 (file)
index 0000000..a078e66
Binary files /dev/null and b/contrib/model_viewer/assets/globe/seas.jpg differ
diff --git a/contrib/model_viewer/assets/ui/next.png b/contrib/model_viewer/assets/ui/next.png
new file mode 100644 (file)
index 0000000..32380f4
Binary files /dev/null and b/contrib/model_viewer/assets/ui/next.png differ
diff --git a/contrib/model_viewer/assets/ui/prev.png b/contrib/model_viewer/assets/ui/prev.png
new file mode 100644 (file)
index 0000000..9d35ace
Binary files /dev/null and b/contrib/model_viewer/assets/ui/prev.png differ
diff --git a/contrib/model_viewer/src/globe.nit b/contrib/model_viewer/src/globe.nit
new file mode 100644 (file)
index 0000000..9da1c59
--- /dev/null
@@ -0,0 +1,351 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Intro a custom model, material and graphics program to draw a globe
+module globe
+
+intrude import gamnit::depth # To access `Mesh::indices_c`
+
+# Number of vertices to create parallels, meridians are double of this
+#
+# The minimum should be 3 for an octahedron planet.
+fun n_parallels: Int do return 25
+
+redef class App
+
+       # Program for the graphic card
+       private var globe_program = new GlobeProgram
+
+       # Texture of the reflexive surface of the earth (with the seas in white)
+       private var texture_seas = new Texture("globe/seas.jpg")
+
+       # Texture of the surface of the earth
+       private var texture_earth = new Texture("globe/earth.jpg")
+
+       # Texture of the lights at night on earth
+       private var texture_night = new Texture("globe/lights.jpg")
+
+       # Elevation map of earth
+       private var texture_elevation = new Texture("globe/elevation.jpg")
+
+       # Texture of the clouds above the earth
+       private var texture_clouds = new Texture("globe/clouds.png")
+
+       redef fun on_create
+       do
+               super
+
+               # Compile globe_program
+               var program = app.globe_program
+               program.compile_and_link
+
+               # Catch any errors
+               var gamnit_error = program.error
+               assert gamnit_error == null else print_error gamnit_error
+       end
+end
+
+# Full model of a globe, with a surface, clouds layer and atmosphere
+class GlobeModel
+       super CompositeModel
+
+       redef fun load
+       do
+               leaves.add new LeafModel(
+                       new Mesh.uv_sphere(1.0, 2*n_parallels, n_parallels),
+                       new GlobeMaterial.surface)
+               leaves.add new LeafModel(
+                       new Mesh.uv_sphere(1.1, 2*n_parallels, n_parallels),
+                       new GlobeMaterial.clouds)
+               leaves.add new LeafModel(
+                       new Mesh.uv_sphere(1.2, 2*n_parallels, n_parallels),
+                       new GlobeMaterial.atmo)
+       end
+end
+
+# Parameterizable material to draw the 3 layers of the globe
+class GlobeMaterial
+       super Material
+
+       # Id of the texture for diffuse colors, if any
+       var texture_id: nullable Int
+
+       # Draw as a surface, using the elevation map and the night lights
+       var is_surface: Bool
+
+       # Ambient color
+       var color: Array[Float]
+
+       # Create and configure a material for the earth surface
+       init surface do init(0, true, [1.0, 1.0, 1.0, 1.0])
+
+       # Create and configure a material for the cloud layer
+       init clouds do init(4, false, [1.0, 1.0, 1.0, 0.25])
+
+       # Create and configure a material for the visible atmosphere
+       init atmo do init(null, false, [0.0, 0.8, 1.0, 0.05])
+
+       redef fun draw(actor, model)
+       do
+               var gl_error = glGetError
+               assert gl_error == gl_NO_ERROR else print gl_error
+
+               var mesh = model.mesh
+
+               var program = app.globe_program
+               program.use
+
+               # Set constant program values
+               program.use
+
+               # Bind textures
+               glActiveTexture gl_TEXTURE0
+               glBindTexture(gl_TEXTURE_2D, app.texture_earth.gl_texture)
+
+               glActiveTexture gl_TEXTURE1
+               glBindTexture(gl_TEXTURE_2D, app.texture_seas.gl_texture)
+
+               glActiveTexture gl_TEXTURE2
+               glBindTexture(gl_TEXTURE_2D, app.texture_night.gl_texture)
+
+               glActiveTexture gl_TEXTURE3
+               glBindTexture(gl_TEXTURE_2D, app.texture_elevation.gl_texture)
+
+               glActiveTexture gl_TEXTURE4
+               glBindTexture(gl_TEXTURE_2D, app.texture_clouds.gl_texture)
+
+               # Set samplers
+               program.tex_specular.uniform 1
+               program.tex_night.uniform 2
+               program.tex_displace.uniform 3
+
+               # Update camera view and light
+               var p = app.world_camera.position
+               program.camera.uniform(p.x, p.y, p.z)
+               program.mvp.uniform app.world_camera.mvp_matrix
+               program.light_center.uniform(app.light.position.x, app.light.position.y, app.light.position.z)
+
+               # Set attributes
+               program.coord.array_enabled = true
+               program.coord.array(mesh.vertices, 3)
+
+               program.tex_coord.array_enabled = true
+               program.tex_coord.array(mesh.texture_coords, 2)
+
+               program.normal.array_enabled = true
+               program.normal.array(mesh.normals, 3)
+
+               # Set uniforms
+               program.scale.uniform 1.0
+               program.rotation.uniform new Matrix.rotation(actor.rotation, 0.0, 1.0, 0.0)
+               program.translation.uniform(actor.center.x, -actor.center.y, actor.center.z, 0.0)
+               program.color.uniform(color[0], color[1], color[2], color[3])
+               program.is_surface.uniform is_surface
+
+               # Set the color texture?
+               var tex = texture_id
+               if tex == null then
+                       program.use_texture.uniform false
+               else
+                       program.use_texture.uniform true
+                       program.tex.uniform tex
+               end
+
+               # Execute draw, support only meshes with `indices`
+               glDrawElements(gl_TRIANGLES, mesh.indices.length, gl_UNSIGNED_SHORT, mesh.indices_c.native_array)
+
+               # Catch any errors
+               gl_error = glGetError
+               assert gl_error == gl_NO_ERROR else print gl_error
+       end
+end
+
+# Graphical program to draw a planet with Phong lighting
+class GlobeProgram
+       super GamnitProgramFromSource
+
+       redef var vertex_shader_source = """
+               // Vertex coordinates
+               attribute vec4 coord;
+
+               // Vertex color tint
+               uniform vec4 color;
+
+               // Vertex translation
+               uniform vec4 translation;
+
+               // Vertex scaling
+               uniform float scale;
+
+               // Vertex coordinates on textures
+               attribute vec2 tex_coord;
+
+               // Vertex normal
+               attribute vec3 normal;
+
+               // Model view projection matrix
+               uniform mat4 mvp;
+
+               // Model rotation
+               uniform mat4 rotation;
+
+               // Lights config
+               uniform vec3 light_center;
+
+               // Texture of surface elevation to displace vertices
+               uniform sampler2D tex_displace;
+
+               // Draw this as a planet surface?
+               uniform bool is_surface;
+
+               // Output for the fragment shader
+               varying vec4 v_color;
+               varying vec2 v_tex_coord;
+               varying vec3 v_normal;
+               varying vec4 v_light_center;
+
+               void main()
+               {
+                       v_color = color;
+                       v_tex_coord = tex_coord;
+                       v_normal = normalize(vec4(normal, 0.0) * rotation * mvp).xyz;
+                       v_light_center = vec4(light_center, 0.0) * mvp;
+
+                       // Apply displacement map
+                       float s = scale;
+                       if (is_surface)
+                               s += 0.05 * texture2D(tex_displace, tex_coord).r;
+
+                       gl_Position = (vec4(coord.xyz * s, 1.0) * rotation + translation) * mvp;
+
+               }
+               """ @ glsl_vertex_shader
+
+       redef var fragment_shader_source = """
+               precision mediump float;
+
+               // Input from the vertex shader
+               varying vec4 v_color;
+               varying vec2 v_tex_coord;
+               varying vec3 v_normal;
+               varying vec4 v_light_center;
+
+               // Coordinates of the camera
+               uniform vec3 camera;
+
+               // Does this object use a texture?
+               uniform bool use_texture;
+
+               // Texture to apply on this object
+               uniform sampler2D tex;
+
+               // Reflection map to apply to the Phong logic
+               uniform sampler2D tex_specular;
+
+               // Texture for the dark side of the earth
+               uniform sampler2D tex_night;
+
+               // Draw this as a planet surface?
+               uniform bool is_surface;
+
+               // Colors config
+               vec4 ambient_color = vec4(0.2, 0.2, 0.2, 1.0);
+               vec4 diffuse_color = vec4(1.0, 1.0, 1.0, 1.0);
+               vec4 specular_color = vec4(1.0, 1.0, 1.0, 1.0);
+
+               void main()
+               {
+                       // Lambert diffusion
+                       vec3 to_light = normalize(v_light_center.xyz);
+                       float lambert = max(dot(to_light, v_normal), 0.0);
+
+                       // Phong specular
+                       float specular = 0.0;
+                       if (lambert > 0.0) {
+                               vec3 to_camera = normalize(camera);
+                               vec3 normal = normalize(v_normal);
+                               vec3 light_reflect = reflect(to_light, normal);
+                               float spec_angle = max(dot(light_reflect, to_camera), 0.0);
+                               specular = pow(spec_angle, 16.0);
+
+                               if (is_surface)
+                                       specular *= texture2D(tex_specular, v_tex_coord).x;
+                               else specular *= 0.2;
+                       }
+
+                       if(use_texture) {
+                               gl_FragColor = v_color * texture2D(tex, v_tex_coord);
+                       } else {
+                               gl_FragColor = v_color;
+                       }
+
+                       gl_FragColor *= ambient_color + lambert * diffuse_color;
+                       gl_FragColor += specular * specular_color;
+
+                       if (is_surface && lambert < 0.2) {
+                               // Show city lights at night
+                               float p_night = (0.2 - lambert) * 5.0;
+                               gl_FragColor += p_night*texture2D(tex_night, v_tex_coord);
+                       }
+               }
+               """ @ glsl_fragment_shader
+
+       # Vertices coordinates
+       var coord = attributes["coord"].as(AttributeVec4) is lazy
+
+       # Color tint per vertex
+       var color = uniforms["color"].as(UniformVec4) is lazy
+
+       # Scaling per vertex
+       var scale = uniforms["scale"].as(UniformFloat) is lazy
+
+       # Coordinates on the textures, per vertex
+       var tex_coord = attributes["tex_coord"].as(AttributeVec2) is lazy
+
+       # Normal per vertex
+       var normal = attributes["normal"].as(AttributeVec3) is lazy
+
+       # Model view projection matrix
+       var mvp = uniforms["mvp"].as(UniformMat4) is lazy
+
+       # Should this program use the texture `tex`?
+       var use_texture = uniforms["use_texture"].as(UniformBool) is lazy
+
+       # Main visible texture unit
+       var tex = uniforms["tex"].as(UniformSampler2D) is lazy
+
+       # Texture unit for reflection effect
+       var tex_specular = uniforms["tex_specular"].as(UniformSampler2D) is lazy
+
+       # Texture of the earth at night
+       var tex_night = uniforms["tex_night"].as(UniformSampler2D) is lazy
+
+       # Texture with elevation data
+       var tex_displace = uniforms["tex_displace"].as(UniformSampler2D) is lazy
+
+       # Position of the camera
+       var camera = uniforms["camera"].as(UniformVec3) is lazy
+
+       # Execute this program to draw a planet surface?
+       var is_surface = uniforms["is_surface"].as(UniformBool) is lazy
+
+       # Translation applied to each vertex
+       var translation = uniforms["translation"].as(UniformVec4) is lazy
+
+       # Rotation matrix
+       var rotation = uniforms["rotation"].as(UniformMat4) is lazy
+
+       # Center position of the light
+       var light_center = uniforms["light_center"].as(UniformVec3) is lazy
+end
index dd1fa98..f147823 100644 (file)
@@ -24,6 +24,8 @@ end
 
 import gamnit::depth
 
+import globe
+
 redef class App
 
        # All available models
@@ -33,7 +35,8 @@ redef class App
                new LeafModel(new Mesh.uv_sphere(4.0, 32, 16), new NormalsMaterial),
                new Model("models/Tree_01.obj"),
                new Model("models/Oak_Fall_01.obj"),
-               new Model("models/Quandtum_BA-2_v1_1.obj")]
+               new Model("models/Quandtum_BA-2_v1_1.obj"),
+               new GlobeModel]
 
        # Index of the current model in `models`
        var model_index = 0
@@ -92,7 +95,7 @@ redef class App
                actor.center.z -= model.mesh.center.z
 
                var height = model.mesh.dimensions.y
-               world_camera.reset_height(height * 4.0)
+               world_camera.reset_height(height * 3.0)
 
                actors.clear
                actors.add actor
index b599a37..15eff41 100644 (file)
@@ -51,11 +51,6 @@ extern class NativeHeadTracker in "Java" `{ com.google.vrtoolkit.cardboard.senso
        # Stop tracking head movement
        fun stop_tracking in "Java" `{ self.stopTracking(); `}
 
-       # Apply correction to the gyroscope values
-       fun gyro_bias=(matrix: JavaFloatArray) in "Java" `{
-               self.setGyroBias(matrix);
-       `}
-
        # Enable finer analysis using the neck as center of movement
        fun neck_model_enabled=(value: Bool) in "Java" `{
                self.setNeckModelEnabled(value);
diff --git a/lib/gamnit/depth/cardboard.nit b/lib/gamnit/depth/cardboard.nit
new file mode 100644 (file)
index 0000000..ccecf15
--- /dev/null
@@ -0,0 +1,108 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Update the orientation of `world_camera` at each frame using the head position given by `android::cardboard`
+#
+# This module is Android specific.
+module cardboard
+
+import ::android::cardboard
+
+import depth
+intrude import cameras
+
+redef class EulerCamera
+       # Do not use `yaw` and `pitch`, the value will instead originate from the Cardboard API
+       redef var rotation_matrix = new Matrix.identity(4)
+
+       # Get the angle value from the `rotation_matrix`
+       redef fun pitch
+       do
+               var a = rotation_matrix[0, 1]
+               var b = rotation_matrix[1, 1]
+               return -atan2(a, b)
+       end
+
+       # Get the angle value from the `rotation_matrix`
+       redef fun yaw
+       do
+               var a = rotation_matrix[2, 0]
+               var b = rotation_matrix[2, 2]
+               return -atan2(a, b)
+       end
+end
+
+redef class App
+
+       # Cardboard's head tacker instance
+       private var head_tracker: nullable NativeHeadTracker = null
+
+       # Rotation matrix read from `head_tracker`, reusing the same structure as a buffer
+       private var java_rotation_matrix = new JavaFloatArray(16) is lazy
+
+       # Initialize and set `head_tracker`
+       fun initialize_head_tracker
+       do
+               # Initialize the Cardboard head orientation tracker service
+               var head_tracker = new NativeHeadTracker(app.native_activity)
+               head_tracker.neck_model_enabled = true
+               head_tracker.start_tracking
+               self.head_tracker = head_tracker
+
+               # Set a wide field of view
+               world_camera.field_of_view_y = 1.0
+       end
+
+       # Read the rotation matrix from Cardboard and update `world_camera`
+       private fun update_from_head_tracker
+       do
+               var head_tracker = head_tracker
+               if head_tracker == null then return
+
+               head_tracker.last_head_view(java_rotation_matrix, 0)
+
+               # Copy values from the Java array to our matrix
+               for y in [0..4[ do
+                       for x in [0..4[ do
+                               world_camera.rotation_matrix[y, x] = java_rotation_matrix[y*4+x]
+                       end
+               end
+       end
+
+       redef fun on_create
+       do
+               super
+               initialize_head_tracker
+       end
+
+       redef fun update(dt)
+       do
+               super
+               update_from_head_tracker
+       end
+
+       redef fun pause
+       do
+               super
+               var tracker = head_tracker
+               if tracker != null then tracker.stop_tracking
+       end
+
+       redef fun resume
+       do
+               super
+               var tracker = head_tracker
+               if tracker != null then tracker.start_tracking
+       end
+end
index e17b5af..c2328c6 100644 (file)
@@ -40,11 +40,11 @@ redef class App
                assert gamnit_error == null else print_error gamnit_error
        end
 
-       # Draw all element in `actors`
-       redef fun frame_core_draw(display)
-       do
-               super
+       redef fun frame_core_draw(display) do frame_core_depth display
 
+       # Draw all elements of `actors` and then call `frame_core_flat`
+       protected fun frame_core_depth(display: GamnitDisplay)
+       do
                # Update cameras on both our programs
                versatile_program.use
                versatile_program.mvp.uniform world_camera.mvp_matrix
@@ -57,5 +57,7 @@ redef class App
                                leaf.material.draw(actor, leaf)
                        end
                end
+
+               frame_core_flat display
        end
 end
index 40fe1fa..983b0fc 100644 (file)
@@ -212,10 +212,10 @@ class LambertProgram
                attribute vec4 coord;
 
                // Vertex translation
-               attribute vec4 translation;
+               uniform vec4 translation;
 
                // Vertex scaling
-               attribute float scale;
+               uniform float scale;
 
                // Vertex coordinates on textures
                attribute vec2 tex_coord;
@@ -349,13 +349,13 @@ class LambertProgram
        var camera = uniforms["camera"].as(UniformVec3) is lazy
 
        # Translation applied to each vertex
-       var translation = attributes["translation"].as(AttributeVec4) is lazy
+       var translation = uniforms["translation"].as(UniformVec4) is lazy
 
        # Rotation matrix
        var rotation = uniforms["rotation"].as(UniformMat4) is lazy
 
        # Scaling per vertex
-       var scale = attributes["scale"].as(AttributeFloat) is lazy
+       var scale = uniforms["scale"].as(UniformFloat) is lazy
 
        # Model view projection matrix
        var mvp = uniforms["mvp"].as(UniformMat4) is lazy
index 9cbc830..fe3f9df 100644 (file)
@@ -57,6 +57,9 @@ class Plane
        end
 
        redef var center = new Point3d[Float](0.0, 0.0, 0.0) is lazy
+
+       init do indices.add_all([0, 1, 2, 2, 1, 3])
+       # TODO use gl_TRIANGLE_FAN instead
 end
 
 # Cube, with 6 faces
@@ -98,5 +101,16 @@ class Cube
                return normals
        end
 
+       redef var texture_coords: Array[Float] is lazy do
+               var a = [0.0, 1.0]
+               var b = [1.0, 1.0]
+               var c = [0.0, 0.0]
+               var d = [1.0, 0.0]
+
+               var texture_coords = new Array[Float]
+               for v in [c, d, a, a, d, b] do for i in 6.times do texture_coords.add_all v
+               return texture_coords
+       end
+
        redef var center = new Point3d[Float](0.0, 0.0, 0.0) is lazy
 end
diff --git a/lib/gamnit/depth/stereoscopic_view.nit b/lib/gamnit/depth/stereoscopic_view.nit
new file mode 100644 (file)
index 0000000..2857e7d
--- /dev/null
@@ -0,0 +1,88 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Refine `EulerCamera` and `App::frame_core_draw` to get a stereoscopic view
+module stereoscopic_view
+
+import depth
+intrude import cameras
+
+redef class EulerCamera
+       redef var mvp_matrix = new Matrix.identity(4)
+
+       # Half of the distance between the eyes
+       var eye_separation: Float = 0.03125
+
+       # MVP matrix for the left eye
+       fun mvp_matrix_left: Matrix do return mvp_matrix_eye(eye_separation)
+
+       # MVP matrix for the right eye
+       fun mvp_matrix_right: Matrix do return mvp_matrix_eye(-eye_separation)
+
+       # Get an MVP matrix for an eye at `diff` world unit from the center
+       private fun mvp_matrix_eye(diff: Float): Matrix
+       do
+               var view = new Matrix.identity(4)
+
+               # Translate the world away from the camera
+               view.translate(-position.x/2.0, -position.y/2.0, -position.z/2.0)
+
+               # Rotate the camera, first by looking left or right, then up or down
+               view = view * rotation_matrix
+
+               # Apply eye transformation
+               var translation = new Matrix.identity(4)
+               translation.translate(diff, 0.0, 0.0)
+               view = view * translation
+
+               # Use a projection matrix with a depth
+               var projection = new Matrix.perspective(pi*field_of_view_y/2.0,
+                       display.aspect_ratio, near, far)
+
+               return view * projection
+       end
+end
+
+redef class GamnitDisplay
+
+       # With stereoscopic view, the aspect ratio (in each eye) is half of the screen
+       redef fun aspect_ratio do return super / 2.0
+end
+
+redef class App
+       redef fun frame_core_draw(display) do frame_core_stereoscopic display
+
+       # Split the screen in two, and call `frame_core_depth` for each eyes
+       protected fun frame_core_stereoscopic(display: GamnitDisplay)
+       do
+               var half_width = display.width / 2
+
+               # Left eye
+               glViewport(0, 0, half_width, display.height)
+               world_camera.mvp_matrix = world_camera.mvp_matrix_left
+               frame_core_depth display
+
+               # Right eye
+               glViewport(half_width, 0, half_width, display.height)
+               world_camera.mvp_matrix = world_camera.mvp_matrix_right
+               frame_core_depth display
+
+               # We reset the viewport for selection
+               glViewport(0, 0, display.width, display.height)
+
+               # Check for errors
+               var gl_error = glGetError
+               assert gl_error == gl_NO_ERROR else print gl_error
+       end
+end
diff --git a/lib/gamnit/depth/vr.nit b/lib/gamnit/depth/vr.nit
new file mode 100644 (file)
index 0000000..1c3a845
--- /dev/null
@@ -0,0 +1,19 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# VR support for gamnit depth, for Android only
+module vr
+
+import cardboard
+import stereoscopic_view
diff --git a/lib/gamnit/examples/globe/Makefile b/lib/gamnit/examples/globe/Makefile
deleted file mode 100644 (file)
index d18b689..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-NITC=../../../../bin/nitc
-NITLS=../../../../bin/nitls
-
-all: bin/globe
-
-bin/globe: $(shell ${NITLS} -M src/globe.nit linux) ${NITC}
-       ${NITC} src/globe.nit -m linux -o $@ -D n_parallels=100
-
-check: bin/globe
-       bin/globe
-
-# ---
-# Android
-
-android: bin/globe.apk
-bin/globe.apk: $(shell ${NITLS} -M src/globe.nit android) ${NITC} res/drawable-hdpi/icon.png assets/ld/earth.jpg
-       ${NITC} src/globe.nit -m android -o $@
-
-android-release: $(shell ${NITLS} -M src/globe.nit android) ${NITC} res/drawable-hdpi/icon.png assets/ld/earth.jpg
-       ${NITC} src/globe.nit -m android -o bin/globe.apk --release
-
-android-wear: $(shell ${NITLS} -M src/globe.nit android) ${NITC} res/drawable-hdpi/icon.png assets/ld/earth.jpg
-       ${NITC} src/globe.nit -m android -o bin/planet_wear.apk -D n_parallels=10
-
-res/drawable-hdpi/icon.png: art/icon.png
-       mkdir -p res/drawable-ldpi/ res/drawable-mdpi/ res/drawable-hdpi/ \
-               res/drawable-xhdpi/ res/drawable-xxhdpi/ res/drawable-xxxhdpi/
-       convert -resize 36x36   art/icon.png res/drawable-ldpi/icon.png
-       convert -resize 48x48   art/icon.png res/drawable-mdpi/icon.png
-       convert -resize 72x72   art/icon.png res/drawable-hdpi/icon.png
-       convert -resize 96x96   art/icon.png res/drawable-xhdpi/icon.png
-       convert -resize 144x144 art/icon.png res/drawable-xxhdpi/icon.png
-       convert -resize 192x192 art/icon.png res/drawable-xxxhdpi/icon.png
-
-assets/ld/earth.jpg:
-       mkdir -p assets/ld
-       convert -resize 2048x1024 assets/hd/earth.jpg assets/ld/earth.jpg
-       convert -resize 2048x1024 assets/hd/seas.jpg assets/ld/seas.jpg
-       convert -resize 2048x1024 assets/hd/clouds.png assets/ld/clouds.png
-       convert -resize 2048x1024 assets/hd/elevation.jpg assets/ld/elevation.jpg
-       convert -resize 2048x1024 assets/hd/lights.jpg assets/ld/lights.jpg
diff --git a/lib/gamnit/examples/globe/README b/lib/gamnit/examples/globe/README
deleted file mode 100644 (file)
index 0234f7f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-Sample gamnit app rendering the earth with elevated surface, cloud layer, city lights and Phong lighting.
-
-# Possible variations
-
-It would have been possible to achieve the same result with different approaches.
-They should be explored as they could provide better performances or be easier to understand.
-
-* Use a single set of vertices, normals and indices because we only need spheres.
-* Alternatively, use one program per sphere.
-
-# Art
-
-Images credit: NASA, Visible Earth
diff --git a/lib/gamnit/examples/globe/art/icon.png b/lib/gamnit/examples/globe/art/icon.png
deleted file mode 100644 (file)
index 71612a4..0000000
Binary files a/lib/gamnit/examples/globe/art/icon.png and /dev/null differ
diff --git a/lib/gamnit/examples/globe/art/icon.xcf b/lib/gamnit/examples/globe/art/icon.xcf
deleted file mode 100644 (file)
index efcf652..0000000
Binary files a/lib/gamnit/examples/globe/art/icon.xcf and /dev/null differ
diff --git a/lib/gamnit/examples/globe/assets/hd/clouds.png b/lib/gamnit/examples/globe/assets/hd/clouds.png
deleted file mode 100644 (file)
index c4319d7..0000000
Binary files a/lib/gamnit/examples/globe/assets/hd/clouds.png and /dev/null differ
diff --git a/lib/gamnit/examples/globe/assets/hd/earth.jpg b/lib/gamnit/examples/globe/assets/hd/earth.jpg
deleted file mode 100644 (file)
index 79f6f2c..0000000
Binary files a/lib/gamnit/examples/globe/assets/hd/earth.jpg and /dev/null differ
diff --git a/lib/gamnit/examples/globe/assets/hd/elevation.jpg b/lib/gamnit/examples/globe/assets/hd/elevation.jpg
deleted file mode 100644 (file)
index 3ec70c0..0000000
Binary files a/lib/gamnit/examples/globe/assets/hd/elevation.jpg and /dev/null differ
diff --git a/lib/gamnit/examples/globe/assets/hd/lights.jpg b/lib/gamnit/examples/globe/assets/hd/lights.jpg
deleted file mode 100644 (file)
index 240df35..0000000
Binary files a/lib/gamnit/examples/globe/assets/hd/lights.jpg and /dev/null differ
diff --git a/lib/gamnit/examples/globe/assets/hd/seas.jpg b/lib/gamnit/examples/globe/assets/hd/seas.jpg
deleted file mode 100644 (file)
index 52ad2ac..0000000
Binary files a/lib/gamnit/examples/globe/assets/hd/seas.jpg and /dev/null differ
diff --git a/lib/gamnit/examples/globe/org.nitlanguage.globe.txt b/lib/gamnit/examples/globe/org.nitlanguage.globe.txt
deleted file mode 100644 (file)
index 845e177..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-Categories:Nit,Multimedia
-License:Apache2
-Web Site:http://nitlanguage.org
-Source Code:http://nitlanguage.org/nit.git/tree/HEAD:/lib/gamnit/examples/globe
-Issue Tracker:https://github.com/nitlang/nit/issues
-
-Summary:Simple rotating globe of the earth
-Description:
-Non-interactive sample gamnit app rendering the earth with elevated surface, cloud layer, city lights and Phong lighting.
-.
diff --git a/lib/gamnit/examples/globe/package.ini b/lib/gamnit/examples/globe/package.ini
deleted file mode 100644 (file)
index b4e8861..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name=globe
-tags=example
-maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-license=Apache-2.0
-[upstream]
-browse=https://github.com/nitlang/nit/tree/master/lib/gamnit/examples/globe/
-git=https://github.com/nitlang/nit.git
-git.directory=lib/gamnit/examples/globe/
-homepage=http://nitlanguage.org
-issues=https://github.com/nitlang/nit/issues
-apk=http://nitlanguage.org/fdroid/apk/globe.apk
diff --git a/lib/gamnit/examples/globe/src/globe.nit b/lib/gamnit/examples/globe/src/globe.nit
deleted file mode 100644 (file)
index 570cb5d..0000000
+++ /dev/null
@@ -1,463 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Portable app using gamnit textures and programs with custom calls to OpenGL ES 2.0
-module globe is
-       app_name "gamnit Globe"
-       app_namespace "org.nitlanguage.globe"
-       app_version(1, 0, git_revision)
-
-       android_manifest_activity """android:screenOrientation="portrait""""
-       android_api_target 15
-end
-
-import realtime
-import matrix::projection
-
-import gamnit
-import gamnit::cameras
-import gamnit::limit_fps
-
-private import more_collections
-
-# Graphical program to draw a planet with Phong lighting
-class GlobeProgram
-       super GamnitProgramFromSource
-
-       redef var vertex_shader_source = """
-               // Vertex coordinates
-               attribute vec4 coord;
-
-               // Vertex color tint
-               attribute vec4 color;
-
-               // Vertex translation
-               attribute vec4 translation;
-
-               // Vertex scaling
-               attribute float scale;
-
-               // Vertex coordinates on textures
-               attribute vec2 tex_coord;
-
-               // Vertex normal
-               attribute vec3 normal;
-
-               // Model view projection matrix
-               uniform mat4 mvp;
-
-               // Texture of surface elevation to displace vertices
-               uniform sampler2D tex_displace;
-
-               // Draw this as a planet surface?
-               uniform bool is_surface;
-
-               // Output for the fragment shader
-               varying vec4 v_color;
-               varying vec2 v_tex_coord;
-               varying vec3 v_normal;
-
-               void main()
-               {
-                       // Pass varyings to the fragment shader
-                       v_color = color;
-                       v_tex_coord = tex_coord;
-                       v_normal = normal;
-
-                       // Apply bump map
-                       float s = scale;
-                       if (is_surface)
-                               s += 0.05 * texture2D(tex_displace, tex_coord).r;
-
-                       gl_Position = (vec4(coord.xyz * s, 1.0) + translation) * mvp;
-               }
-               """ @ glsl_vertex_shader
-
-       redef var fragment_shader_source = """
-               precision mediump float;
-
-               // Input from the vertex shader
-               varying vec4 v_color;
-               varying vec2 v_tex_coord;
-               varying vec3 v_normal;
-
-               // Coordinates of the camera
-               uniform vec3 camera;
-
-               // Does this object use a texture?
-               uniform bool use_texture;
-
-               // Texture to apply on this object
-               uniform sampler2D tex;
-
-               // Reflection map to apply the the phong logic
-               uniform sampler2D tex_shiny;
-
-               // Texture for the dark side of the earth
-               uniform sampler2D tex_night;
-
-               // Draw this as a planet surface?
-               uniform bool is_surface;
-
-               // Lights config
-               // TODO configure from outside the shader
-               vec3 light_dir = normalize(vec3(-1.0, 0.0, -1.0));
-               vec4 ambient_color = vec4(0.2, 0.2, 0.2, 1.0);
-               vec4 diffuse_color = vec4(1.0, 1.0, 1.0, 1.0);
-               vec4 specular_color = vec4(1.0, 1.0, 1.0, 1.0);
-
-               void main()
-               {
-                       if(use_texture) {
-                               gl_FragColor = v_color * texture2D(tex, v_tex_coord);
-                       } else {
-                               gl_FragColor = v_color;
-                       }
-
-                       // Lambert diffusion
-                       float lambert = max(dot(light_dir, v_normal), 0.0);
-
-                       // Phong specular
-                       float specular = 0.0;
-                       if (lambert > 0.0) {
-                               vec3 to_camera = normalize(camera);
-                               vec3 light_reflect = reflect(light_dir, v_normal);
-                               float specularAngle = max(dot(light_reflect, to_camera), 0.0);
-                               specular = pow(specularAngle, 16.0);
-
-                               if (is_surface)
-                                       specular *= texture2D(tex_shiny, v_tex_coord).x;
-                               else specular *= 0.2;
-                       }
-
-                       gl_FragColor *= ambient_color + lambert * diffuse_color;
-                       gl_FragColor += specular * specular_color;
-
-                       if (is_surface && lambert < 0.2) {
-                               // Show city lights at night
-                               float p_night = (0.2 - lambert) * 5.0;
-                               gl_FragColor += p_night*texture2D(tex_night, v_tex_coord);
-                       }
-               }
-               """ @ glsl_fragment_shader
-
-               # Vertices coordinates
-               var coord = attributes["coord"].as(AttributeVec4) is lazy
-
-               # Color tint per vertex
-               var color = attributes["color"].as(AttributeVec4) is lazy
-
-               # Scaling per vertex
-               var scale = attributes["scale"].as(AttributeFloat) is lazy
-
-               # Coordinates on the textures, per vertex
-               var tex_coord = attributes["tex_coord"].as(AttributeVec2) is lazy
-
-               # Normal per vertex
-               var normal = attributes["normal"].as(AttributeVec3) is lazy
-
-               # Model view projection matrix
-               var mvp = uniforms["mvp"].as(UniformMat4) is lazy
-
-               # Should this program use the texture `tex`?
-               var use_texture = uniforms["use_texture"].as(UniformBool) is lazy
-
-               # Main visible texture unit
-               var tex = uniforms["tex"].as(UniformSampler2D) is lazy
-
-               # Texture unit for reflection effect
-               var tex_shiny = uniforms["tex_shiny"].as(UniformSampler2D) is lazy
-
-               # Texture of the earth at night
-               var tex_night = uniforms["tex_night"].as(UniformSampler2D) is lazy
-
-               # Texture with elevation data
-               var tex_displace = uniforms["tex_displace"].as(UniformSampler2D) is lazy
-
-               # Position of the camera
-               var camera = uniforms["camera"].as(UniformVec3) is lazy
-
-               # Execute this program to draw a planet surface?
-               var is_surface = uniforms["is_surface"].as(UniformBool) is lazy
-end
-
-# Mesh with all information for drawing
-class Mesh
-
-       # Vertices coordinates
-       var vertices: Array[Float]
-
-       # Indices to draw triangles
-       var indices: Array[Int]
-
-       private var indices_c = new CUInt16Array.from(indices) is lazy
-
-       # Normals on each vertex
-       var normals: Array[Float]
-
-       # Coordinates on the texture per vertex
-       var texture_coords: Array[Float]
-
-       # Create an UV sphere of `radius` with `n_meridians` and `n_parallels`
-       init uv_sphere(radius: Float, n_meridians, n_parallels: Int)
-       do
-               var w = n_meridians
-               var h = n_parallels
-
-               var vertices = new Array[Float].with_capacity(w*h*3)
-               var texture_coords = new Array[Float].with_capacity(w*h*2)
-               var normals = new Array[Float].with_capacity(w*h*3)
-
-               # Build vertices
-               for m in [0..w[ do
-                       for p in [0..h[ do
-                               var u = m.to_f * 2.0 * pi / (w-1).to_f
-                               var v = p.to_f * pi / (h-1).to_f
-
-                               vertices.add radius * u.cos * v.sin
-                               vertices.add radius * v.cos
-                               vertices.add radius * u.sin * v.sin
-
-                               texture_coords.add (1.0 - m.to_f/(w-1).to_f)
-                               texture_coords.add(p.to_f/(h-1).to_f)
-
-                               normals.add u.cos * v.sin
-                               normals.add v.cos
-                               normals.add u.sin * v.sin
-                       end
-               end
-
-               # Build faces
-               var indices = new Array[Int].with_capacity((w-1)*(h-1)*6)
-               for m in [0..w-1[ do
-                       for p in [0..h-1[ do
-                               var a = m*h + p
-
-                               indices.add a
-                               indices.add(a+h)
-                               indices.add(a+1)
-
-                               indices.add(a+h)
-                               indices.add(a+h+1)
-                               indices.add(a+1)
-                       end
-               end
-
-               init(vertices, indices, normals, texture_coords)
-       end
-end
-
-# Number of vertices to create parallels, meridians are double of this
-#
-# The minimum should be 3 for an octahedron planet.
-fun n_parallels: Int do return 25
-
-redef class GamnitAssetTexture
-       # All images are either within the hd or ld folder
-       redef fun path do return app.definition / super
-end
-
-redef class App
-
-       # Earth
-       var planet = new Mesh.uv_sphere(2.0, 2*n_parallels, n_parallels)
-
-       # Cloud layer
-       var clouds = new Mesh.uv_sphere(2.08, 2*n_parallels, n_parallels)
-
-       # Visible atmosphere
-       var atmo = new Mesh.uv_sphere(2.16, 2*n_parallels, n_parallels)
-
-       # Program for the graphic card
-       var program = new GlobeProgram
-
-       private var definition: String is lazy do
-               var max_texture_size = glGetIntegerv(gl_MAX_TEXTURE_SIZE)
-
-               # HD textures max sizes reange from 2048 px to 5400 px
-               if max_texture_size < 5400 then
-                       return "ld"
-               else return "hd"
-       end
-
-       # Texture of the reflexive surface of the earth (with the seas in white)
-       var texture_seas = new Texture("seas.jpg")
-
-       # Texture of the surface of the earth
-       var texture_earth = new Texture("earth.jpg")
-
-       # Texture of the lights at night on earth
-       var texture_night = new Texture("lights.jpg")
-
-       # Elevation map of earth
-       var texture_elevation = new Texture("elevation.jpg")
-
-       # Texture of the clouds above the earth
-       var texture_clouds = new Texture("clouds.png")
-
-       # Camera for the only view
-       var camera: EulerCamera is lazy do
-               var camera = new EulerCamera(app.display.as(not null))
-               camera.move(0.0, 0.1, -5.0)
-               return camera
-       end
-
-       redef fun on_create
-       do
-               super
-
-               var display = display
-               assert display != null
-
-               var gl_error = glGetError
-               assert gl_error == gl_NO_ERROR else print gl_error
-
-               # Prepare program
-               var program = program
-               program.compile_and_link
-
-               var gamnit_error = program.error
-               assert gamnit_error == null else print_error gamnit_error
-
-               # Blend
-               gl.capabilities.blend.enable
-               glBlendFunc(gl_SRC_ALPHA, gl_ONE_MINUS_SRC_ALPHA)
-
-               gl.capabilities.depth_test.enable
-               glDepthFunc gl_LEQUAL
-               glDepthMask true
-
-               gl_error = glGetError
-               assert gl_error == gl_NO_ERROR else print gl_error
-
-               # Prepare to draw
-               for tex in all_root_textures do
-                       tex.load
-                       glTexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER, gl_LINEAR)
-                       glTexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MAG_FILTER, gl_LINEAR)
-
-                       gamnit_error = tex.error
-                       assert gamnit_error == null else print_error gamnit_error
-               end
-
-               gl_error = glGetError
-               assert gl_error == gl_NO_ERROR else print gl_error
-
-               program.use
-
-               glViewport(0, 0, display.width, display.height)
-               glClearColor(0.0, 0.02, 0.0, 1.0)
-
-               gl_error = glGetError
-               assert gl_error == gl_NO_ERROR else print gl_error
-
-               # Assign all textures to a unit
-               glActiveTexture gl_TEXTURE0
-               glBindTexture(gl_TEXTURE_2D, texture_earth.gl_texture)
-
-               glActiveTexture gl_TEXTURE1
-               glBindTexture(gl_TEXTURE_2D, texture_seas.gl_texture)
-
-               glActiveTexture gl_TEXTURE2
-               glBindTexture(gl_TEXTURE_2D, texture_night.gl_texture)
-
-               glActiveTexture gl_TEXTURE3
-               glBindTexture(gl_TEXTURE_2D, texture_elevation.gl_texture)
-
-               glActiveTexture gl_TEXTURE4
-               glBindTexture(gl_TEXTURE_2D, texture_clouds.gl_texture)
-
-               gl_error = glGetError
-               assert gl_error == gl_NO_ERROR else print gl_error
-
-               # Constant program values
-               program.coord.array_enabled = true
-               program.tex_coord.array_enabled = true
-               program.normal.array_enabled = true
-
-               program.scale.uniform 1.0
-
-               program.use_texture.uniform true
-
-               program.tex_shiny.uniform 1
-               program.tex_night.uniform 2
-               program.tex_displace.uniform 3
-
-               gl_error = glGetError
-               assert gl_error == gl_NO_ERROR else print gl_error
-       end
-
-       private var clock = new Clock
-
-       redef fun frame_core(display)
-       do
-               var t = clock.total.to_f/3.0 + 0.75*pi
-
-               var gl_error = glGetError
-               assert gl_error == gl_NO_ERROR else print gl_error
-
-               glClear(gl_COLOR_BUFFER_BIT | gl_DEPTH_BUFFER_BIT)
-               program.use
-
-               # Rotate world
-               # FIXME do this cleanly by moving the camera
-               var mvp = new Matrix.rotation(t, 0.0, 1.0, 0.0) * camera.mvp_matrix
-               program.mvp.uniform mvp
-               program.camera.uniform(-t.sin, -0.8, -t.cos)
-
-               # Planet
-               program.coord.array(planet.vertices, 3)
-               program.tex_coord.array(planet.texture_coords, 2)
-               program.normal.array(planet.normals, 3)
-               program.tex.uniform 0
-               program.use_texture.uniform true
-               program.color.uniform(1.0, 1.0, 1.0, 1.0)
-               program.is_surface.uniform true
-               glDrawElements(gl_TRIANGLES, planet.indices.length, gl_UNSIGNED_SHORT, planet.indices_c.native_array)
-
-               # Clouds
-               program.coord.array(clouds.vertices, 3)
-               program.tex_coord.array(clouds.texture_coords, 2)
-               program.normal.array(clouds.normals, 3)
-               program.tex.uniform 4
-               program.color.uniform(1.0, 1.0, 1.0, 0.5) # Half transparency
-               program.is_surface.uniform false
-               glDrawElements(gl_TRIANGLES, clouds.indices.length, gl_UNSIGNED_SHORT, clouds.indices_c.native_array)
-
-               # Atmo
-               program.coord.array(atmo.vertices, 3)
-               program.tex_coord.array(atmo.texture_coords, 2)
-               program.normal.array(atmo.normals, 3)
-               program.color.uniform(0.0, 0.8, 1.0, 0.02) # Blueish
-               program.is_surface.uniform false
-               program.use_texture.uniform false
-               glDrawElements(gl_TRIANGLES, atmo.indices.length, gl_UNSIGNED_SHORT, atmo.indices_c.native_array)
-               assert program.use_texture.is_active
-
-               display.flip
-
-               gl_error = glGetError
-               assert gl_error == gl_NO_ERROR else print gl_error
-       end
-
-       redef fun on_stop
-       do
-               # Clean up
-               program.delete
-
-               # Close gamnit
-               var display = display
-               if display != null then display.close
-       end
-end
index eaa5ba8..d415ded 100644 (file)
@@ -68,6 +68,10 @@ class Sprite
                glActiveTexture gl_TEXTURE0
                glBindTexture(gl_TEXTURE_2D, texture.root.gl_texture)
 
+               simple_2d_program.translation.array_enabled = false
+               simple_2d_program.color.array_enabled = false
+               simple_2d_program.scale.array_enabled = false
+
                simple_2d_program.translation.uniform(center.x, -center.y, center.z, 0.0)
                simple_2d_program.color.uniform(1.0, 1.0, 1.0, alpha)
                simple_2d_program.scale.uniform scale
@@ -179,8 +183,11 @@ redef class App
                assert gl_error == gl_NO_ERROR else print gl_error
        end
 
+       # Draw the whole screen, all `glDraw...` calls should be executed here
+       protected fun frame_core_draw(display: GamnitDisplay) do frame_core_flat display
+
        # Draw sprites in `sprites` and `ui_sprites`
-       protected fun frame_core_draw(display: GamnitDisplay)
+       protected fun frame_core_flat(display: GamnitDisplay)
        do
                simple_2d_program.use
 
diff --git a/lib/gamnit/keys.nit b/lib/gamnit/keys.nit
new file mode 100644 (file)
index 0000000..85e9e1e
--- /dev/null
@@ -0,0 +1,47 @@
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Simple service keeping track of which keys are currently pressed
+#
+# This service revolves around `app.pressed_keys`, a `Set` of the names of currently pressed keys.
+# As a `Set`, `app.pressed_keys` can be iterated and queried with `has`.
+#
+# Limitations: The keys names are platform dependent.
+module keys
+
+import mnit::input
+import gamnit
+
+redef class App
+       # Currently pressed keys
+       var pressed_keys = new Set[String] is lazy
+
+       # Register `event` to update `app.pressed_keys`
+       private fun register_key_event(event: KeyEvent)
+       do
+               var key = event.name
+               if event.is_down then
+                       app.pressed_keys.add key
+               else if app.pressed_keys.has(key) then
+                       app.pressed_keys.remove key
+               end
+       end
+
+       redef fun accept_event(event)
+       do
+               if event isa KeyEvent then register_key_event event
+
+               return super
+       end
+end