diff --git a/build/coverage/lcov-report/base.css b/build/coverage/lcov-report/base.css new file mode 100644 index 0000000..29737bc --- /dev/null +++ b/build/coverage/lcov-report/base.css @@ -0,0 +1,213 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.medium .chart { border:1px solid #f9cd0b; } +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } +/* light gray */ +span.cline-neutral { background: #eaeaea; } + +.cbranch-no { background: yellow !important; color: #111; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/build/coverage/lcov-report/build/game-lib.js.html b/build/coverage/lcov-report/build/game-lib.js.html new file mode 100644 index 0000000..a69c4c0 --- /dev/null +++ b/build/coverage/lcov-report/build/game-lib.js.html @@ -0,0 +1,14066 @@ + + + + Code coverage report for build/game-lib.js + + + + + + + +
+
+

+ all files / build/ game-lib.js +

+
+
+ 16.22% + Statements + 283/1745 +
+
+ 2.87% + Branches + 20/697 +
+
+ 2.05% + Functions + 3/146 +
+
+ 16.22% + Lines + 283/1745 +
+
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983 +984 +985 +986 +987 +988 +989 +990 +991 +992 +993 +994 +995 +996 +997 +998 +999 +1000 +1001 +1002 +1003 +1004 +1005 +1006 +1007 +1008 +1009 +1010 +1011 +1012 +1013 +1014 +1015 +1016 +1017 +1018 +1019 +1020 +1021 +1022 +1023 +1024 +1025 +1026 +1027 +1028 +1029 +1030 +1031 +1032 +1033 +1034 +1035 +1036 +1037 +1038 +1039 +1040 +1041 +1042 +1043 +1044 +1045 +1046 +1047 +1048 +1049 +1050 +1051 +1052 +1053 +1054 +1055 +1056 +1057 +1058 +1059 +1060 +1061 +1062 +1063 +1064 +1065 +1066 +1067 +1068 +1069 +1070 +1071 +1072 +1073 +1074 +1075 +1076 +1077 +1078 +1079 +1080 +1081 +1082 +1083 +1084 +1085 +1086 +1087 +1088 +1089 +1090 +1091 +1092 +1093 +1094 +1095 +1096 +1097 +1098 +1099 +1100 +1101 +1102 +1103 +1104 +1105 +1106 +1107 +1108 +1109 +1110 +1111 +1112 +1113 +1114 +1115 +1116 +1117 +1118 +1119 +1120 +1121 +1122 +1123 +1124 +1125 +1126 +1127 +1128 +1129 +1130 +1131 +1132 +1133 +1134 +1135 +1136 +1137 +1138 +1139 +1140 +1141 +1142 +1143 +1144 +1145 +1146 +1147 +1148 +1149 +1150 +1151 +1152 +1153 +1154 +1155 +1156 +1157 +1158 +1159 +1160 +1161 +1162 +1163 +1164 +1165 +1166 +1167 +1168 +1169 +1170 +1171 +1172 +1173 +1174 +1175 +1176 +1177 +1178 +1179 +1180 +1181 +1182 +1183 +1184 +1185 +1186 +1187 +1188 +1189 +1190 +1191 +1192 +1193 +1194 +1195 +1196 +1197 +1198 +1199 +1200 +1201 +1202 +1203 +1204 +1205 +1206 +1207 +1208 +1209 +1210 +1211 +1212 +1213 +1214 +1215 +1216 +1217 +1218 +1219 +1220 +1221 +1222 +1223 +1224 +1225 +1226 +1227 +1228 +1229 +1230 +1231 +1232 +1233 +1234 +1235 +1236 +1237 +1238 +1239 +1240 +1241 +1242 +1243 +1244 +1245 +1246 +1247 +1248 +1249 +1250 +1251 +1252 +1253 +1254 +1255 +1256 +1257 +1258 +1259 +1260 +1261 +1262 +1263 +1264 +1265 +1266 +1267 +1268 +1269 +1270 +1271 +1272 +1273 +1274 +1275 +1276 +1277 +1278 +1279 +1280 +1281 +1282 +1283 +1284 +1285 +1286 +1287 +1288 +1289 +1290 +1291 +1292 +1293 +1294 +1295 +1296 +1297 +1298 +1299 +1300 +1301 +1302 +1303 +1304 +1305 +1306 +1307 +1308 +1309 +1310 +1311 +1312 +1313 +1314 +1315 +1316 +1317 +1318 +1319 +1320 +1321 +1322 +1323 +1324 +1325 +1326 +1327 +1328 +1329 +1330 +1331 +1332 +1333 +1334 +1335 +1336 +1337 +1338 +1339 +1340 +1341 +1342 +1343 +1344 +1345 +1346 +1347 +1348 +1349 +1350 +1351 +1352 +1353 +1354 +1355 +1356 +1357 +1358 +1359 +1360 +1361 +1362 +1363 +1364 +1365 +1366 +1367 +1368 +1369 +1370 +1371 +1372 +1373 +1374 +1375 +1376 +1377 +1378 +1379 +1380 +1381 +1382 +1383 +1384 +1385 +1386 +1387 +1388 +1389 +1390 +1391 +1392 +1393 +1394 +1395 +1396 +1397 +1398 +1399 +1400 +1401 +1402 +1403 +1404 +1405 +1406 +1407 +1408 +1409 +1410 +1411 +1412 +1413 +1414 +1415 +1416 +1417 +1418 +1419 +1420 +1421 +1422 +1423 +1424 +1425 +1426 +1427 +1428 +1429 +1430 +1431 +1432 +1433 +1434 +1435 +1436 +1437 +1438 +1439 +1440 +1441 +1442 +1443 +1444 +1445 +1446 +1447 +1448 +1449 +1450 +1451 +1452 +1453 +1454 +1455 +1456 +1457 +1458 +1459 +1460 +1461 +1462 +1463 +1464 +1465 +1466 +1467 +1468 +1469 +1470 +1471 +1472 +1473 +1474 +1475 +1476 +1477 +1478 +1479 +1480 +1481 +1482 +1483 +1484 +1485 +1486 +1487 +1488 +1489 +1490 +1491 +1492 +1493 +1494 +1495 +1496 +1497 +1498 +1499 +1500 +1501 +1502 +1503 +1504 +1505 +1506 +1507 +1508 +1509 +1510 +1511 +1512 +1513 +1514 +1515 +1516 +1517 +1518 +1519 +1520 +1521 +1522 +1523 +1524 +1525 +1526 +1527 +1528 +1529 +1530 +1531 +1532 +1533 +1534 +1535 +1536 +1537 +1538 +1539 +1540 +1541 +1542 +1543 +1544 +1545 +1546 +1547 +1548 +1549 +1550 +1551 +1552 +1553 +1554 +1555 +1556 +1557 +1558 +1559 +1560 +1561 +1562 +1563 +1564 +1565 +1566 +1567 +1568 +1569 +1570 +1571 +1572 +1573 +1574 +1575 +1576 +1577 +1578 +1579 +1580 +1581 +1582 +1583 +1584 +1585 +1586 +1587 +1588 +1589 +1590 +1591 +1592 +1593 +1594 +1595 +1596 +1597 +1598 +1599 +1600 +1601 +1602 +1603 +1604 +1605 +1606 +1607 +1608 +1609 +1610 +1611 +1612 +1613 +1614 +1615 +1616 +1617 +1618 +1619 +1620 +1621 +1622 +1623 +1624 +1625 +1626 +1627 +1628 +1629 +1630 +1631 +1632 +1633 +1634 +1635 +1636 +1637 +1638 +1639 +1640 +1641 +1642 +1643 +1644 +1645 +1646 +1647 +1648 +1649 +1650 +1651 +1652 +1653 +1654 +1655 +1656 +1657 +1658 +1659 +1660 +1661 +1662 +1663 +1664 +1665 +1666 +1667 +1668 +1669 +1670 +1671 +1672 +1673 +1674 +1675 +1676 +1677 +1678 +1679 +1680 +1681 +1682 +1683 +1684 +1685 +1686 +1687 +1688 +1689 +1690 +1691 +1692 +1693 +1694 +1695 +1696 +1697 +1698 +1699 +1700 +1701 +1702 +1703 +1704 +1705 +1706 +1707 +1708 +1709 +1710 +1711 +1712 +1713 +1714 +1715 +1716 +1717 +1718 +1719 +1720 +1721 +1722 +1723 +1724 +1725 +1726 +1727 +1728 +1729 +1730 +1731 +1732 +1733 +1734 +1735 +1736 +1737 +1738 +1739 +1740 +1741 +1742 +1743 +1744 +1745 +1746 +1747 +1748 +1749 +1750 +1751 +1752 +1753 +1754 +1755 +1756 +1757 +1758 +1759 +1760 +1761 +1762 +1763 +1764 +1765 +1766 +1767 +1768 +1769 +1770 +1771 +1772 +1773 +1774 +1775 +1776 +1777 +1778 +1779 +1780 +1781 +1782 +1783 +1784 +1785 +1786 +1787 +1788 +1789 +1790 +1791 +1792 +1793 +1794 +1795 +1796 +1797 +1798 +1799 +1800 +1801 +1802 +1803 +1804 +1805 +1806 +1807 +1808 +1809 +1810 +1811 +1812 +1813 +1814 +1815 +1816 +1817 +1818 +1819 +1820 +1821 +1822 +1823 +1824 +1825 +1826 +1827 +1828 +1829 +1830 +1831 +1832 +1833 +1834 +1835 +1836 +1837 +1838 +1839 +1840 +1841 +1842 +1843 +1844 +1845 +1846 +1847 +1848 +1849 +1850 +1851 +1852 +1853 +1854 +1855 +1856 +1857 +1858 +1859 +1860 +1861 +1862 +1863 +1864 +1865 +1866 +1867 +1868 +1869 +1870 +1871 +1872 +1873 +1874 +1875 +1876 +1877 +1878 +1879 +1880 +1881 +1882 +1883 +1884 +1885 +1886 +1887 +1888 +1889 +1890 +1891 +1892 +1893 +1894 +1895 +1896 +1897 +1898 +1899 +1900 +1901 +1902 +1903 +1904 +1905 +1906 +1907 +1908 +1909 +1910 +1911 +1912 +1913 +1914 +1915 +1916 +1917 +1918 +1919 +1920 +1921 +1922 +1923 +1924 +1925 +1926 +1927 +1928 +1929 +1930 +1931 +1932 +1933 +1934 +1935 +1936 +1937 +1938 +1939 +1940 +1941 +1942 +1943 +1944 +1945 +1946 +1947 +1948 +1949 +1950 +1951 +1952 +1953 +1954 +1955 +1956 +1957 +1958 +1959 +1960 +1961 +1962 +1963 +1964 +1965 +1966 +1967 +1968 +1969 +1970 +1971 +1972 +1973 +1974 +1975 +1976 +1977 +1978 +1979 +1980 +1981 +1982 +1983 +1984 +1985 +1986 +1987 +1988 +1989 +1990 +1991 +1992 +1993 +1994 +1995 +1996 +1997 +1998 +1999 +2000 +2001 +2002 +2003 +2004 +2005 +2006 +2007 +2008 +2009 +2010 +2011 +2012 +2013 +2014 +2015 +2016 +2017 +2018 +2019 +2020 +2021 +2022 +2023 +2024 +2025 +2026 +2027 +2028 +2029 +2030 +2031 +2032 +2033 +2034 +2035 +2036 +2037 +2038 +2039 +2040 +2041 +2042 +2043 +2044 +2045 +2046 +2047 +2048 +2049 +2050 +2051 +2052 +2053 +2054 +2055 +2056 +2057 +2058 +2059 +2060 +2061 +2062 +2063 +2064 +2065 +2066 +2067 +2068 +2069 +2070 +2071 +2072 +2073 +2074 +2075 +2076 +2077 +2078 +2079 +2080 +2081 +2082 +2083 +2084 +2085 +2086 +2087 +2088 +2089 +2090 +2091 +2092 +2093 +2094 +2095 +2096 +2097 +2098 +2099 +2100 +2101 +2102 +2103 +2104 +2105 +2106 +2107 +2108 +2109 +2110 +2111 +2112 +2113 +2114 +2115 +2116 +2117 +2118 +2119 +2120 +2121 +2122 +2123 +2124 +2125 +2126 +2127 +2128 +2129 +2130 +2131 +2132 +2133 +2134 +2135 +2136 +2137 +2138 +2139 +2140 +2141 +2142 +2143 +2144 +2145 +2146 +2147 +2148 +2149 +2150 +2151 +2152 +2153 +2154 +2155 +2156 +2157 +2158 +2159 +2160 +2161 +2162 +2163 +2164 +2165 +2166 +2167 +2168 +2169 +2170 +2171 +2172 +2173 +2174 +2175 +2176 +2177 +2178 +2179 +2180 +2181 +2182 +2183 +2184 +2185 +2186 +2187 +2188 +2189 +2190 +2191 +2192 +2193 +2194 +2195 +2196 +2197 +2198 +2199 +2200 +2201 +2202 +2203 +2204 +2205 +2206 +2207 +2208 +2209 +2210 +2211 +2212 +2213 +2214 +2215 +2216 +2217 +2218 +2219 +2220 +2221 +2222 +2223 +2224 +2225 +2226 +2227 +2228 +2229 +2230 +2231 +2232 +2233 +2234 +2235 +2236 +2237 +2238 +2239 +2240 +2241 +2242 +2243 +2244 +2245 +2246 +2247 +2248 +2249 +2250 +2251 +2252 +2253 +2254 +2255 +2256 +2257 +2258 +2259 +2260 +2261 +2262 +2263 +2264 +2265 +2266 +2267 +2268 +2269 +2270 +2271 +2272 +2273 +2274 +2275 +2276 +2277 +2278 +2279 +2280 +2281 +2282 +2283 +2284 +2285 +2286 +2287 +2288 +2289 +2290 +2291 +2292 +2293 +2294 +2295 +2296 +2297 +2298 +2299 +2300 +2301 +2302 +2303 +2304 +2305 +2306 +2307 +2308 +2309 +2310 +2311 +2312 +2313 +2314 +2315 +2316 +2317 +2318 +2319 +2320 +2321 +2322 +2323 +2324 +2325 +2326 +2327 +2328 +2329 +2330 +2331 +2332 +2333 +2334 +2335 +2336 +2337 +2338 +2339 +2340 +2341 +2342 +2343 +2344 +2345 +2346 +2347 +2348 +2349 +2350 +2351 +2352 +2353 +2354 +2355 +2356 +2357 +2358 +2359 +2360 +2361 +2362 +2363 +2364 +2365 +2366 +2367 +2368 +2369 +2370 +2371 +2372 +2373 +2374 +2375 +2376 +2377 +2378 +2379 +2380 +2381 +2382 +2383 +2384 +2385 +2386 +2387 +2388 +2389 +2390 +2391 +2392 +2393 +2394 +2395 +2396 +2397 +2398 +2399 +2400 +2401 +2402 +2403 +2404 +2405 +2406 +2407 +2408 +2409 +2410 +2411 +2412 +2413 +2414 +2415 +2416 +2417 +2418 +2419 +2420 +2421 +2422 +2423 +2424 +2425 +2426 +2427 +2428 +2429 +2430 +2431 +2432 +2433 +2434 +2435 +2436 +2437 +2438 +2439 +2440 +2441 +2442 +2443 +2444 +2445 +2446 +2447 +2448 +2449 +2450 +2451 +2452 +2453 +2454 +2455 +2456 +2457 +2458 +2459 +2460 +2461 +2462 +2463 +2464 +2465 +2466 +2467 +2468 +2469 +2470 +2471 +2472 +2473 +2474 +2475 +2476 +2477 +2478 +2479 +2480 +2481 +2482 +2483 +2484 +2485 +2486 +2487 +2488 +2489 +2490 +2491 +2492 +2493 +2494 +2495 +2496 +2497 +2498 +2499 +2500 +2501 +2502 +2503 +2504 +2505 +2506 +2507 +2508 +2509 +2510 +2511 +2512 +2513 +2514 +2515 +2516 +2517 +2518 +2519 +2520 +2521 +2522 +2523 +2524 +2525 +2526 +2527 +2528 +2529 +2530 +2531 +2532 +2533 +2534 +2535 +2536 +2537 +2538 +2539 +2540 +2541 +2542 +2543 +2544 +2545 +2546 +2547 +2548 +2549 +2550 +2551 +2552 +2553 +2554 +2555 +2556 +2557 +2558 +2559 +2560 +2561 +2562 +2563 +2564 +2565 +2566 +2567 +2568 +2569 +2570 +2571 +2572 +2573 +2574 +2575 +2576 +2577 +2578 +2579 +2580 +2581 +2582 +2583 +2584 +2585 +2586 +2587 +2588 +2589 +2590 +2591 +2592 +2593 +2594 +2595 +2596 +2597 +2598 +2599 +2600 +2601 +2602 +2603 +2604 +2605 +2606 +2607 +2608 +2609 +2610 +2611 +2612 +2613 +2614 +2615 +2616 +2617 +2618 +2619 +2620 +2621 +2622 +2623 +2624 +2625 +2626 +2627 +2628 +2629 +2630 +2631 +2632 +2633 +2634 +2635 +2636 +2637 +2638 +2639 +2640 +2641 +2642 +2643 +2644 +2645 +2646 +2647 +2648 +2649 +2650 +2651 +2652 +2653 +2654 +2655 +2656 +2657 +2658 +2659 +2660 +2661 +2662 +2663 +2664 +2665 +2666 +2667 +2668 +2669 +2670 +2671 +2672 +2673 +2674 +2675 +2676 +2677 +2678 +2679 +2680 +2681 +2682 +2683 +2684 +2685 +2686 +2687 +2688 +2689 +2690 +2691 +2692 +2693 +2694 +2695 +2696 +2697 +2698 +2699 +2700 +2701 +2702 +2703 +2704 +2705 +2706 +2707 +2708 +2709 +2710 +2711 +2712 +2713 +2714 +2715 +2716 +2717 +2718 +2719 +2720 +2721 +2722 +2723 +2724 +2725 +2726 +2727 +2728 +2729 +2730 +2731 +2732 +2733 +2734 +2735 +2736 +2737 +2738 +2739 +2740 +2741 +2742 +2743 +2744 +2745 +2746 +2747 +2748 +2749 +2750 +2751 +2752 +2753 +2754 +2755 +2756 +2757 +2758 +2759 +2760 +2761 +2762 +2763 +2764 +2765 +2766 +2767 +2768 +2769 +2770 +2771 +2772 +2773 +2774 +2775 +2776 +2777 +2778 +2779 +2780 +2781 +2782 +2783 +2784 +2785 +2786 +2787 +2788 +2789 +2790 +2791 +2792 +2793 +2794 +2795 +2796 +2797 +2798 +2799 +2800 +2801 +2802 +2803 +2804 +2805 +2806 +2807 +2808 +2809 +2810 +2811 +2812 +2813 +2814 +2815 +2816 +2817 +2818 +2819 +2820 +2821 +2822 +2823 +2824 +2825 +2826 +2827 +2828 +2829 +2830 +2831 +2832 +2833 +2834 +2835 +2836 +2837 +2838 +2839 +2840 +2841 +2842 +2843 +2844 +2845 +2846 +2847 +2848 +2849 +2850 +2851 +2852 +2853 +2854 +2855 +2856 +2857 +2858 +2859 +2860 +2861 +2862 +2863 +2864 +2865 +2866 +2867 +2868 +2869 +2870 +2871 +2872 +2873 +2874 +2875 +2876 +2877 +2878 +2879 +2880 +2881 +2882 +2883 +2884 +2885 +2886 +2887 +2888 +2889 +2890 +2891 +2892 +2893 +2894 +2895 +2896 +2897 +2898 +2899 +2900 +2901 +2902 +2903 +2904 +2905 +2906 +2907 +2908 +2909 +2910 +2911 +2912 +2913 +2914 +2915 +2916 +2917 +2918 +2919 +2920 +2921 +2922 +2923 +2924 +2925 +2926 +2927 +2928 +2929 +2930 +2931 +2932 +2933 +2934 +2935 +2936 +2937 +2938 +2939 +2940 +2941 +2942 +2943 +2944 +2945 +2946 +2947 +2948 +2949 +2950 +2951 +2952 +2953 +2954 +2955 +2956 +2957 +2958 +2959 +2960 +2961 +2962 +2963 +2964 +2965 +2966 +2967 +2968 +2969 +2970 +2971 +2972 +2973 +2974 +2975 +2976 +2977 +2978 +2979 +2980 +2981 +2982 +2983 +2984 +2985 +2986 +2987 +2988 +2989 +2990 +2991 +2992 +2993 +2994 +2995 +2996 +2997 +2998 +2999 +3000 +3001 +3002 +3003 +3004 +3005 +3006 +3007 +3008 +3009 +3010 +3011 +3012 +3013 +3014 +3015 +3016 +3017 +3018 +3019 +3020 +3021 +3022 +3023 +3024 +3025 +3026 +3027 +3028 +3029 +3030 +3031 +3032 +3033 +3034 +3035 +3036 +3037 +3038 +3039 +3040 +3041 +3042 +3043 +3044 +3045 +3046 +3047 +3048 +3049 +3050 +3051 +3052 +3053 +3054 +3055 +3056 +3057 +3058 +3059 +3060 +3061 +3062 +3063 +3064 +3065 +3066 +3067 +3068 +3069 +3070 +3071 +3072 +3073 +3074 +3075 +3076 +3077 +3078 +3079 +3080 +3081 +3082 +3083 +3084 +3085 +3086 +3087 +3088 +3089 +3090 +3091 +3092 +3093 +3094 +3095 +3096 +3097 +3098 +3099 +3100 +3101 +3102 +3103 +3104 +3105 +3106 +3107 +3108 +3109 +3110 +3111 +3112 +3113 +3114 +3115 +3116 +3117 +3118 +3119 +3120 +3121 +3122 +3123 +3124 +3125 +3126 +3127 +3128 +3129 +3130 +3131 +3132 +3133 +3134 +3135 +3136 +3137 +3138 +3139 +3140 +3141 +3142 +3143 +3144 +3145 +3146 +3147 +3148 +3149 +3150 +3151 +3152 +3153 +3154 +3155 +3156 +3157 +3158 +3159 +3160 +3161 +3162 +3163 +3164 +3165 +3166 +3167 +3168 +3169 +3170 +3171 +3172 +3173 +3174 +3175 +3176 +3177 +3178 +3179 +3180 +3181 +3182 +3183 +3184 +3185 +3186 +3187 +3188 +3189 +3190 +3191 +3192 +3193 +3194 +3195 +3196 +3197 +3198 +3199 +3200 +3201 +3202 +3203 +3204 +3205 +3206 +3207 +3208 +3209 +3210 +3211 +3212 +3213 +3214 +3215 +3216 +3217 +3218 +3219 +3220 +3221 +3222 +3223 +3224 +3225 +3226 +3227 +3228 +3229 +3230 +3231 +3232 +3233 +3234 +3235 +3236 +3237 +3238 +3239 +3240 +3241 +3242 +3243 +3244 +3245 +3246 +3247 +3248 +3249 +3250 +3251 +3252 +3253 +3254 +3255 +3256 +3257 +3258 +3259 +3260 +3261 +3262 +3263 +3264 +3265 +3266 +3267 +3268 +3269 +3270 +3271 +3272 +3273 +3274 +3275 +3276 +3277 +3278 +3279 +3280 +3281 +3282 +3283 +3284 +3285 +3286 +3287 +3288 +3289 +3290 +3291 +3292 +3293 +3294 +3295 +3296 +3297 +3298 +3299 +3300 +3301 +3302 +3303 +3304 +3305 +3306 +3307 +3308 +3309 +3310 +3311 +3312 +3313 +3314 +3315 +3316 +3317 +3318 +3319 +3320 +3321 +3322 +3323 +3324 +3325 +3326 +3327 +3328 +3329 +3330 +3331 +3332 +3333 +3334 +3335 +3336 +3337 +3338 +3339 +3340 +3341 +3342 +3343 +3344 +3345 +3346 +3347 +3348 +3349 +3350 +3351 +3352 +3353 +3354 +3355 +3356 +3357 +3358 +3359 +3360 +3361 +3362 +3363 +3364 +3365 +3366 +3367 +3368 +3369 +3370 +3371 +3372 +3373 +3374 +3375 +3376 +3377 +3378 +3379 +3380 +3381 +3382 +3383 +3384 +3385 +3386 +3387 +3388 +3389 +3390 +3391 +3392 +3393 +3394 +3395 +3396 +3397 +3398 +3399 +3400 +3401 +3402 +3403 +3404 +3405 +3406 +3407 +3408 +3409 +3410 +3411 +3412 +3413 +3414 +3415 +3416 +3417 +3418 +3419 +3420 +3421 +3422 +3423 +3424 +3425 +3426 +3427 +3428 +3429 +3430 +3431 +3432 +3433 +3434 +3435 +3436 +3437 +3438 +3439 +3440 +3441 +3442 +3443 +3444 +3445 +3446 +3447 +3448 +3449 +3450 +3451 +3452 +3453 +3454 +3455 +3456 +3457 +3458 +3459 +3460 +3461 +3462 +3463 +3464 +3465 +3466 +3467 +3468 +3469 +3470 +3471 +3472 +3473 +3474 +3475 +3476 +3477 +3478 +3479 +3480 +3481 +3482 +3483 +3484 +3485 +3486 +3487 +3488 +3489 +3490 +3491 +3492 +3493 +3494 +3495 +3496 +3497 +3498 +3499 +3500 +3501 +3502 +3503 +3504 +3505 +3506 +3507 +3508 +3509 +3510 +3511 +3512 +3513 +3514 +3515 +3516 +3517 +3518 +3519 +3520 +3521 +3522 +3523 +3524 +3525 +3526 +3527 +3528 +3529 +3530 +3531 +3532 +3533 +3534 +3535 +3536 +3537 +3538 +3539 +3540 +3541 +3542 +3543 +3544 +3545 +3546 +3547 +3548 +3549 +3550 +3551 +3552 +3553 +3554 +3555 +3556 +3557 +3558 +3559 +3560 +3561 +3562 +3563 +3564 +3565 +3566 +3567 +3568 +3569 +3570 +3571 +3572 +3573 +3574 +3575 +3576 +3577 +3578 +3579 +3580 +3581 +3582 +3583 +3584 +3585 +3586 +3587 +3588 +3589 +3590 +3591 +3592 +3593 +3594 +3595 +3596 +3597 +3598 +3599 +3600 +3601 +3602 +3603 +3604 +3605 +3606 +3607 +3608 +3609 +3610 +3611 +3612 +3613 +3614 +3615 +3616 +3617 +3618 +3619 +3620 +3621 +3622 +3623 +3624 +3625 +3626 +3627 +3628 +3629 +3630 +3631 +3632 +3633 +3634 +3635 +3636 +3637 +3638 +3639 +3640 +3641 +3642 +3643 +3644 +3645 +3646 +3647 +3648 +3649 +3650 +3651 +3652 +3653 +3654 +3655 +3656 +3657 +3658 +3659 +3660 +3661 +3662 +3663 +3664 +3665 +3666 +3667 +3668 +3669 +3670 +3671 +3672 +3673 +3674 +3675 +3676 +3677 +3678 +3679 +3680 +3681 +3682 +3683 +3684 +3685 +3686 +3687 +3688 +3689 +3690 +3691 +3692 +3693 +3694 +3695 +3696 +3697 +3698 +3699 +3700 +3701 +3702 +3703 +3704 +3705 +3706 +3707 +3708 +3709 +3710 +3711 +3712 +3713 +3714 +3715 +3716 +3717 +3718 +3719 +3720 +3721 +3722 +3723 +3724 +3725 +3726 +3727 +3728 +3729 +3730 +3731 +3732 +3733 +3734 +3735 +3736 +3737 +3738 +3739 +3740 +3741 +3742 +3743 +3744 +3745 +3746 +3747 +3748 +3749 +3750 +3751 +3752 +3753 +3754 +3755 +3756 +3757 +3758 +3759 +3760 +3761 +3762 +3763 +3764 +3765 +3766 +3767 +3768 +3769 +3770 +3771 +3772 +3773 +3774 +3775 +3776 +3777 +3778 +3779 +3780 +3781 +3782 +3783 +3784 +3785 +3786 +3787 +3788 +3789 +3790 +3791 +3792 +3793 +3794 +3795 +3796 +3797 +3798 +3799 +3800 +3801 +3802 +3803 +3804 +3805 +3806 +3807 +3808 +3809 +3810 +3811 +3812 +3813 +3814 +3815 +3816 +3817 +3818 +3819 +3820 +3821 +3822 +3823 +3824 +3825 +3826 +3827 +3828 +3829 +3830 +3831 +3832 +3833 +3834 +3835 +3836 +3837 +3838 +3839 +3840 +3841 +3842 +3843 +3844 +3845 +3846 +3847 +3848 +3849 +3850 +3851 +3852 +3853 +3854 +3855 +3856 +3857 +3858 +3859 +3860 +3861 +3862 +3863 +3864 +3865 +3866 +3867 +3868 +3869 +3870 +3871 +3872 +3873 +3874 +3875 +3876 +3877 +3878 +3879 +3880 +3881 +3882 +3883 +3884 +3885 +3886 +3887 +3888 +3889 +3890 +3891 +3892 +3893 +3894 +3895 +3896 +3897 +3898 +3899 +3900 +3901 +3902 +3903 +3904 +3905 +3906 +3907 +3908 +3909 +3910 +3911 +3912 +3913 +3914 +3915 +3916 +3917 +3918 +3919 +3920 +3921 +3922 +3923 +3924 +3925 +3926 +3927 +3928 +3929 +3930 +3931 +3932 +3933 +3934 +3935 +3936 +3937 +3938 +3939 +3940 +3941 +3942 +3943 +3944 +3945 +3946 +3947 +3948 +3949 +3950 +3951 +3952 +3953 +3954 +3955 +3956 +3957 +3958 +3959 +3960 +3961 +3962 +3963 +3964 +3965 +3966 +3967 +3968 +3969 +3970 +3971 +3972 +3973 +3974 +3975 +3976 +3977 +3978 +3979 +3980 +3981 +3982 +3983 +3984 +3985 +3986 +3987 +3988 +3989 +3990 +3991 +3992 +3993 +3994 +3995 +3996 +3997 +3998 +3999 +4000 +4001 +4002 +4003 +4004 +4005 +4006 +4007 +4008 +4009 +4010 +4011 +4012 +4013 +4014 +4015 +4016 +4017 +4018 +4019 +4020 +4021 +4022 +4023 +4024 +4025 +4026 +4027 +4028 +4029 +4030 +4031 +4032 +4033 +4034 +4035 +4036 +4037 +4038 +4039 +4040 +4041 +4042 +4043 +4044 +4045 +4046 +4047 +4048 +4049 +4050 +4051 +4052 +4053 +4054 +4055 +4056 +4057 +4058 +4059 +4060 +4061 +4062 +4063 +4064 +4065 +4066 +4067 +4068 +4069 +4070 +4071 +4072 +4073 +4074 +4075 +4076 +4077 +4078 +4079 +4080 +4081 +4082 +4083 +4084 +4085 +4086 +4087 +4088 +4089 +4090 +4091 +4092 +4093 +4094 +4095 +4096 +4097 +4098 +4099 +4100 +4101 +4102 +4103 +4104 +4105 +4106 +4107 +4108 +4109 +4110 +4111 +4112 +4113 +4114 +4115 +4116 +4117 +4118 +4119 +4120 +4121 +4122 +4123 +4124 +4125 +4126 +4127 +4128 +4129 +4130 +4131 +4132 +4133 +4134 +4135 +4136 +4137 +4138 +4139 +4140 +4141 +4142 +4143 +4144 +4145 +4146 +4147 +4148 +4149 +4150 +4151 +4152 +4153 +4154 +4155 +4156 +4157 +4158 +4159 +4160 +4161 +4162 +4163 +4164 +4165 +4166 +4167 +4168 +4169 +4170 +4171 +4172 +4173 +4174 +4175 +4176 +4177 +4178 +4179 +4180 +4181 +4182 +4183 +4184 +4185 +4186 +4187 +4188 +4189 +4190 +4191 +4192 +4193 +4194 +4195 +4196 +4197 +4198 +4199 +4200 +4201 +4202 +4203 +4204 +4205 +4206 +4207 +4208 +4209 +4210 +4211 +4212 +4213 +4214 +4215 +4216 +4217 +4218 +4219 +4220 +4221 +4222 +4223 +4224 +4225 +4226 +4227 +4228 +4229 +4230 +4231 +4232 +4233 +4234 +4235 +4236 +4237 +4238 +4239 +4240 +4241 +4242 +4243 +4244 +4245 +4246 +4247 +4248 +4249 +4250 +4251 +4252 +4253 +4254 +4255 +4256 +4257 +4258 +4259 +4260 +4261 +4262 +4263 +4264 +4265 +4266 +4267 +4268 +4269 +4270 +4271 +4272 +4273 +4274 +4275 +4276 +4277 +4278 +4279 +4280 +4281 +4282 +4283 +4284 +4285 +4286 +4287 +4288 +4289 +4290 +4291 +4292 +4293 +4294 +4295 +4296 +4297 +4298 +4299 +4300 +4301 +4302 +4303 +4304 +4305 +4306 +4307 +4308 +4309 +4310 +4311 +4312 +4313 +4314 +4315 +4316 +4317 +4318 +4319 +4320 +4321 +4322 +4323 +4324 +4325 +4326 +4327 +4328 +4329 +4330 +4331 +4332 +4333 +4334 +4335 +4336 +4337 +4338 +4339 +4340 +4341 +4342 +4343 +4344 +4345 +4346 +4347 +4348 +4349 +4350 +4351 +4352 +4353 +4354 +4355 +4356 +4357 +4358 +4359 +4360 +4361 +4362 +4363 +4364 +4365 +4366 +4367 +4368 +4369 +4370 +4371 +4372 +4373 +4374 +4375 +4376 +4377 +4378 +4379 +4380 +4381 +4382 +4383 +4384 +4385 +4386 +4387 +4388 +4389 +4390 +4391 +4392 +4393 +4394 +4395 +4396 +4397 +4398 +4399 +4400 +4401 +4402 +4403 +4404 +4405 +4406 +4407 +4408 +4409 +4410 +4411 +4412 +4413 +4414 +4415 +4416 +4417 +4418 +4419 +4420 +4421 +4422 +4423 +4424 +4425 +4426 +4427 +4428 +4429 +4430 +4431 +4432 +4433 +4434 +4435 +4436 +4437 +4438 +4439 +4440 +4441 +4442 +4443 +4444 +4445 +4446 +4447 +4448 +4449 +4450 +4451 +4452 +4453 +4454 +4455 +4456 +4457 +4458 +4459 +4460 +4461 +4462 +4463 +4464 +4465 +4466 +4467 +4468 +4469 +4470 +4471 +4472 +4473 +4474 +4475 +4476 +4477 +4478 +4479 +4480 +4481 +4482 +4483 +4484 +4485 +4486 +4487 +4488 +4489 +4490 +4491 +4492 +4493 +4494 +4495 +4496 +4497 +4498 +4499 +4500 +4501 +4502 +4503 +4504 +4505 +4506 +4507 +4508 +4509 +4510 +4511 +4512 +4513 +4514 +4515 +4516 +4517 +4518 +4519 +4520 +4521 +4522 +4523 +4524 +4525 +4526 +4527 +4528 +4529 +4530 +4531 +4532 +4533 +4534 +4535 +4536 +4537 +4538 +4539 +4540 +4541 +4542 +4543 +4544 +4545 +4546 +4547 +4548 +4549 +4550 +4551 +4552 +4553 +4554 +4555 +4556 +4557 +4558 +4559 +4560 +4561 +4562 +4563 +4564 +4565 +4566 +4567 +4568 +4569 +4570 +4571 +4572 +4573 +4574 +4575 +4576 +4577 +4578 +4579 +4580 +4581 +4582 +4583 +4584 +4585 +4586 +4587 +4588 +4589 +4590 +4591 +4592 +4593 +4594 +4595 +4596 +4597 +4598 +4599 +4600 +4601 +4602 +4603 +4604 +4605 +4606 +4607 +4608 +4609 +4610 +4611 +4612 +4613 +4614 +4615 +4616 +4617 +4618 +4619 +4620 +4621 +4622 +4623 +4624 +4625 +4626 +4627 +4628 +4629 +4630 +4631 +4632 +4633 +4634 +4635 +4636 +4637 +4638 +4639 +4640 +4641 +4642 +4643 +4644 +4645 +4646 +4647 +4648 +4649 +4650 +4651 +4652 +4653 +4654 +4655 +4656 +4657 +4658 +4659 +4660 +4661 +4662 +4663 +4664 +4665 +4666 +4667 +4668 + +  +  + + +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  + + + +  + +  +  + +  + + +  + +  + + +  + +  + + +  + +  + + +  + +  + + +  + +  + + +  + +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + + + +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  + +  +  +  +  +  +  +  + + + +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  + +  +  +  +  +  + +  +  +  +  +  + +  +  +  +  +  +  +  + +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + + + +  +  +  +  +  + + + +  +  +  +  +  + + + + + +  +  +  +  +  + + + + + + + + + + + +  +  +  +  +  + + + + + +  +  +  +  +  + + + + + + + + +  +  +  +  +  + + + +  +  +  +  +  + + +  +  +  +  +  + + + + + + + + + + + +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  + +  +  +  +  +  + +  +  +  +  +  + +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + + +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + + +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  + + + + +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + + + + + + +  +  +  +  +  + + + + + + + + +  +  +  +  +  + + + +  +  +  +  +  + + + + + + +  +  +  +  +  + + + + + + + + +  +  +  +  +  + + + + + + + + +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  + +  +  +  +  +  +  + +  + + + +  + + +  +  + + +  +  + + +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  + +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  + +  +  +  +  +  +  + +  +  +  +  +  +  + +  +  +  + +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  + + + + +  + +  +  +  + +  +  +  + +  +  +  + +  +  +  +  + +  +  +  +  +  +  + +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  + +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  + +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + + + 
Iif (typeof GameLib == 'undefined') {
+    function GameLib() {}
+}
+ 
+Eif (typeof GameLib.D3 == 'undefined') {
+    GameLib.D3 = function(){};
+}
+/**
+ * BoneWeight object - associates a vertex to a bone with some weight
+ * @param boneIndex int
+ * @param weight float
+ * @constructor
+ */
+GameLib.D3.BoneWeight = function(
+    boneIndex,
+    weight
+) {
+    this.boneIndex = boneIndex;
+    this.weight = weight;
+};
+/**
+ * Bone Superset
+ * @param id
+ * @param name string
+ * @param boneId
+ * @param childBoneIds
+ * @param parentBoneId
+ * @param quaternion
+ * @param position
+ * @param rotation
+ * @param scale GameLib.D3.Vector3
+ * @param up
+ * @constructor
+ */
+GameLib.D3.Bone = function(
+    id,
+    boneId,
+    name,
+    childBoneIds,
+    parentBoneId,
+    quaternion,
+    position,
+    rotation,
+    scale,
+    up
+) {
+    this.id = id;
+    this.name = name;
+    this.boneId = boneId;
+ 
+    Iif (typeof childBoneIds == 'undefined') {
+        childBoneIds = [];
+    }
+    this.childBoneIds = childBoneIds;
+ 
+    Eif (typeof parentBoneId == 'undefined') {
+        parentBoneId = null;
+    }
+    this.parentBoneId = parentBoneId;
+ 
+    Eif (typeof quaternion == 'undefined') {
+        quaternion = new GameLib.D3.Vector4();
+    }
+    this.quaternion = quaternion;
+ 
+    Eif (typeof position == 'undefined') {
+        position = new GameLib.D3.Vector3(0,0,0);
+    }
+    this.position = position;
+ 
+    Eif (typeof rotation == 'undefined') {
+        rotation = new GameLib.D3.Vector3(0,0,0);
+    }
+    this.rotation = rotation;
+ 
+    Eif (typeof scale == 'undefined') {
+        scale = new GameLib.D3.Vector3(1,1,1);
+    }
+    this.scale = scale;
+ 
+    Eif (typeof up == 'undefined') {
+        up = new GameLib.D3.Vector3(0,1,0);
+    }
+    this.up = up;
+};
+/**
+ * Physics Broadphase Superset
+ * @param id
+ * @param name String
+ * @param broadphaseType Number
+ * @param engine GameLib.D3.Engine
+ * @param createInstance Boolean
+ * @constructor
+ */
+GameLib.D3.Broadphase = function(
+    id,
+    name,
+    broadphaseType,
+    engine,
+    createInstance
+) {
+    this.id = id;
+ 
+    if (typeof name == 'undefined') {
+        name = 'broadphase-' + broadphaseType;
+    }
+    this.name = name;
+ 
+    if (typeof broadphaseType == 'undefined') {
+        broadphaseType = GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE;
+    }
+    this.broadphaseType = broadphaseType;
+ 
+    if (typeof engine == 'undefined') {
+        engine = null;
+    }
+    this.engine = engine;
+ 
+    this.instance = null;
+ 
+    if (createInstance) {
+        this.createInstance();
+    }
+};
+ 
+/**
+ * Creates a custom Broadphase instance based on the engine type
+ */
+GameLib.D3.Broadphase.prototype.createInstance = function() {
+ 
+    if (!(this.engine instanceof GameLib.D3.Engine)) {
+        console.warn('No Engine');
+        throw new Error('No Engine');
+    }
+ 
+    this.engine.isNotCannonThrow();
+ 
+    var instance = null;
+ 
+    if (this.broadphaseType == GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE) {
+        instance = new this.engine.instance.NaiveBroadphase();
+    } else if (this.broadphaseType == GameLib.D3.Broadphase.BROADPHASE_TYPE_GRID) {
+        instance = new this.engine.instance.GridBroadphase();
+    } else if (this.broadphaseType == GameLib.D3.Broadphase.BROADPHASE_TYPE_SAP) {
+        instance = new this.engine.instance.SAPBroardphase();
+    } else {
+        console.warn('Unsupported broadphase type: ' + this.broadphaseType);
+        throw new Error('Unsupported broadphase type: ' + this.broadphaseType);
+    }
+ 
+    this.instance = instance;
+ 
+    return instance;
+};
+ 
+/**
+ * Broadphase Types
+ * @type {number}
+ */
+GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE = 0x1;
+GameLib.D3.Broadphase.BROADPHASE_TYPE_GRID = 0x2;
+GameLib.D3.Broadphase.BROADPHASE_TYPE_SAP = 0x3;
+/**
+ * Color Superset
+ * @param r
+ * @param g
+ * @param b
+ * @param a
+ * @constructor
+ */
+GameLib.D3.Color = function(r, g, b, a) {
+    this.r = r;
+    this.g = g;
+    this.b = b;
+    this.a = a;
+};
+/**
+ * Engine Superset
+ * @param engineType
+ * @param instance {CANNON | Ammo | Goblin}
+ * @constructor
+ */
+GameLib.D3.Engine = function(
+    engineType,
+    instance
+) {
+    this.engineType = engineType;
+    this.instance = instance;
+};
+ 
+/**
+ * True if CANNON physics
+ * @returns {boolean}
+ */
+GameLib.D3.Engine.prototype.isCannon = function() {
+    return (this.engineType == GameLib.D3.Engine.ENGINE_TYPE_CANNON)
+};
+ 
+/**
+ * Logs a warning and throws an error if not cannon
+ */
+GameLib.D3.Engine.prototype.isNotCannonThrow = function() {
+    if (this.engineType != GameLib.D3.Engine.ENGINE_TYPE_CANNON) {
+        console.warn('Only CANNON supported for this function');
+        throw new Error('Only CANNON supported for this function');
+    }
+};
+ 
+/**
+ * True if Ammo physics
+ * @returns {boolean}
+ */
+GameLib.D3.Engine.prototype.isAmmo = function() {
+    return (this.engineType == GameLib.D3.Engine.ENGINE_TYPE_AMMO)
+};
+ 
+/**
+ * True if Goblin physics
+ * @returns {boolean}
+ */
+GameLib.D3.Engine.prototype.isGoblin = function() {
+    return (this.engineType == GameLib.D3.Engine.ENGINE_TYPE_GOBLIN)
+};
+ 
+/**
+ * Physics GameLib.D3.Engine Types
+ * @type {number}
+ */
+GameLib.D3.Engine.ENGINE_TYPE_CANNON = 0x1;
+GameLib.D3.Engine.ENGINE_TYPE_AMMO = 0x2;
+GameLib.D3.Engine.ENGINE_TYPE_GOBLIN = 0x3;
+/**
+ * Fly Controls
+ * @param camera
+ * @param THREE
+ * @param canvas
+ * @constructor
+ */
+GameLib.D3.FlyControls = function(
+    camera,
+    THREE,
+    canvas
+) {
+    this.flySpeed = 100;
+ 
+    this.canvas = canvas;
+ 
+    this.THREE = THREE;
+ 
+    this.yaw = 0;
+    this.pitch = 0;
+    this.canRotate = false;
+ 
+    this.moveForward = false;
+    this.moveBackward = false;
+    this.moveLeft = false;
+    this.moveRight = false;
+    this.moveUp = false;
+    this.moveDown = false;
+ 
+    this.mouseUpCallback = this.onMouseUp.bind(this);
+    this.mouseDownCallback = this.onMouseDown.bind(this);
+    this.mouseMoveCallback = this.onMouseMove.bind(this);
+    this.mouseWheelCallback = this.onMouseWheel.bind(this);
+    this.keyDownCallback = this.onKeyDown.bind(this);
+    this.keyUpCallback = this.onKeyUp.bind(this);
+ 
+    this.camera = camera;
+ 
+    this.canvas.addEventListener('keydown', this.keyDownCallback, false);
+    this.canvas.addEventListener('keyup', this.keyUpCallback, false);
+    this.canvas.addEventListener('mousedown', this.mouseDownCallback, false);
+    this.canvas.addEventListener('mouseup', this.mouseUpCallback, false);
+    this.canvas.addEventListener('mousewheel', this.mouseWheelCallback, false);
+ 
+    this.havePointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
+    this.element = document.body;
+ 
+    if (this.havePointerLock) {
+        this.element.requestPointerLock = this.element.requestPointerLock || this.element.mozRequestPointerLock || this.element.webkitRequestPointerLock;
+        document.exitPointerLock = document.exitPointerLock || document.mozExitPointerLock || document.webkitExitPointerLock;
+    }
+};
+ 
+/**
+ * Go forward / backward on mouse wheel
+ * @param event
+ */
+GameLib.D3.FlyControls.prototype.onMouseWheel = function(event) {
+    this.moveForward = true;
+    this.applyTranslation(event.wheelDelta * 0.001);
+    event.preventDefault();
+    this.moveForward = false;
+};
+ 
+/**
+ * Start rotating the camera on mouse middle button down
+ * @param event
+ */
+GameLib.D3.FlyControls.prototype.onMouseDown = function(event) {
+    if (event.button == 1) {
+        this.canRotate = true;
+        this.canvas.addEventListener('mousemove', this.mouseMoveCallback, false);
+    }
+};
+ 
+/**
+ * Stop rotating on middle mouse button down
+ * @param event
+ */
+GameLib.D3.FlyControls.prototype.onMouseUp = function(event) {
+    if (event.button == 1) {
+        this.canRotate = false;
+        this.canvas.removeEventListener('mousemove', this.mouseMoveCallback);
+    }
+};
+ 
+/**
+ * Apply current yaw and pitch to camera
+ */
+GameLib.D3.FlyControls.prototype.applyRotation = function() {
+    this.camera.rotation.set(this.pitch, this.yaw, 0, "YXZ");
+};
+ 
+/**
+ * Apply current position to camera
+ * @param deltaTime
+ */
+GameLib.D3.FlyControls.prototype.applyTranslation = function(deltaTime) {
+    var direction = new this.THREE.Vector3(0, 0, -1);
+    var rotation = new this.THREE.Euler(0, 0, 0, "YXZ");
+    rotation.set(this.pitch, this.yaw, 0, "YXZ");
+ 
+    direction = direction.applyEuler(rotation);
+ 
+    var forward = direction.normalize();
+    var right = forward.cross(new this.THREE.Vector3(0, 1, 0));
+ 
+    if(this.moveForward) {
+ 
+        this.camera.position.x += forward.x * (deltaTime * this.flySpeed);
+        this.camera.position.y += forward.y * (deltaTime * this.flySpeed);
+        this.camera.position.z += forward.z * (deltaTime * this.flySpeed);
+ 
+    } else if(this.moveBackward) {
+ 
+        this.camera.position.x -= forward.x * (deltaTime * this.flySpeed);
+        this.camera.position.y -= forward.y * (deltaTime * this.flySpeed);
+        this.camera.position.z -= forward.z * (deltaTime * this.flySpeed);
+    }
+ 
+    if(this.moveLeft) {
+ 
+        this.camera.position.x -= right.x * (deltaTime * this.flySpeed);
+        this.camera.position.y -= right.y * (deltaTime * this.flySpeed);
+        this.camera.position.z -= right.z * (deltaTime * this.flySpeed);
+ 
+    } else if(this.moveRight) {
+ 
+        this.camera.position.x += right.x * (deltaTime * this.flySpeed);
+        this.camera.position.y += right.y * (deltaTime * this.flySpeed);
+        this.camera.position.z += right.z * (deltaTime * this.flySpeed);
+    }
+ 
+    if(this.moveUp) {
+ 
+        this.camera.position.y += (deltaTime * this.flySpeed);
+ 
+    } else if(this.moveDown) {
+ 
+        this.camera.position.y -= (deltaTime * this.flySpeed);
+ 
+    }
+};
+ 
+/**
+ * This update function should be called from the animation function in order to apply the 'frame rate independent'
+ * movement to the camera
+ * @param deltaTime
+ */
+GameLib.D3.FlyControls.prototype.update = function(deltaTime) {
+    this.applyRotation();
+    this.applyTranslation(deltaTime);
+};
+ 
+/**
+ * Rotate on mouse move
+ * @param event
+ */
+GameLib.D3.FlyControls.prototype.onMouseMove = function ( event ) {
+    if (this.canRotate) {
+        var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
+        var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
+ 
+        this.yaw -= movementX * 0.002;
+        this.pitch -= movementY * 0.002;
+    }
+};
+ 
+/**
+ * Keyboard controls
+ * @param event
+ */
+GameLib.D3.FlyControls.prototype.onKeyDown = function ( event ) {
+    switch ( event.keyCode ) {
+ 
+        case 87: // w
+            this.moveForward = true;
+            break;
+ 
+        case 65: // a
+            this.moveLeft = true;
+            break;
+ 
+        case 83: // s
+            this.moveBackward = true;
+            break;
+ 
+        case 68: // d
+            this.moveRight = true;
+            break;
+ 
+        case 104: // keypad up arrow
+            this.moveUp = true;
+            break;
+ 
+        case 98: // keypad down arrow
+            this.moveDown = true;
+            break;
+    }
+};
+ 
+/**
+ * Keyboard controls
+ * @param event
+ */
+GameLib.D3.FlyControls.prototype.onKeyUp = function ( event ) {
+    switch ( event.keyCode ) {
+ 
+        case 38: // up
+        case 87: // w
+            this.moveForward = false;
+            break;
+ 
+        case 37: // left
+        case 65: // a
+            this.moveLeft = false;
+            break;
+ 
+        case 40: // down
+        case 83: // s
+            this.moveBackward = false;
+            break;
+ 
+        case 39: // right
+        case 68: // d
+            this.moveRight = false;
+            break;
+ 
+        case 104: // keypad up arrow
+            this.moveUp = false;
+            break;
+ 
+        case 98: // keypad down arrow
+            this.moveDown = false;
+            break;
+    }
+};
+GameLib.D3.Game = function (
+ 
+) {
+    this.scenes = {};
+    this.physicsWorlds = [];
+    this.sceneToPhysicsWorldsMap = {};
+};
+ 
+GameLib.D3.Game.prototype.AddScene = function(
+    scene
+) {
+    this.scenes[scene.name] = scene;
+};
+ 
+GameLib.D3.Game.prototype.AddPhysicsWorld = function(
+    physicsWorld
+) {
+    this.physicsWorlds.push(physicsWorld);
+};
+ 
+GameLib.D3.Game.prototype.LinkPhysicsWorldToScene = function(
+    physicsWorld,
+    scene
+) {
+    this.sceneToPhysicsWorldsMap[scene.name] = this.sceneToPhysicsWorldsMap[scene.name] || [];
+    this.sceneToPhysicsWorldsMap[scene.name].push(physicsWorld);
+};
+ 
+GameLib.D3.Game.prototype.GetPhysicsWorldsForScene = function (
+    scene
+) {
+    return this.sceneToPhysicsWorldsMap[scene.name];
+};
+ 
+GameLib.D3.Game.prototype.ProcessPhysics = function (
+    timestep
+) {
+    for(var s in this.sceneToPhysicsWorldsMap) {
+ 
+        var physicsWorldArray = this.sceneToPhysicsWorldsMap[s];
+        var scene = this.scenes[s];
+ 
+        if(scene && physicsWorldArray) {
+ 
+            for(var i = 0, l = physicsWorldArray.length; i < l; i++) {
+ 
+                var physicsWorld = physicsWorldArray[i];
+                physicsWorld.Step(timestep);
+ 
+                for(var p in physicsWorld.linkedPairs) {
+                    var pair = physicsWorld.linkedPairs[p];
+                    var mesh = pair.threeMesh;
+                    var body = pair.physicsBody;
+ 
+                    if(mesh) {
+                        if(physicsWorld.engineType === GameLib.D3.Physics.TYPE_CANNON) {
+ 
+                            var quaternion = new THREE.Quaternion();
+                            quaternion.copy(body.rigidBodyInstance.quaternion);
+ 
+                            var quaternionCopy = quaternion.clone();
+ 
+                            var position = new THREE.Vector3();
+                            position.copy(body.rigidBodyInstance.position);
+ 
+                            if(mesh.permutate) {
+ 
+                                if(mesh.permutate.offset) {
+                                    if(mesh.permutate.offset.quaternion) {
+                                        var offsetQuaternion = new THREE.Quaternion();
+                                        offsetQuaternion.copy(mesh.permutate.offset.quaternion);
+                                        quaternion = quaternion.multiply(offsetQuaternion).normalize();
+                                    }
+ 
+                                    if(mesh.permutate.offset.position) {
+                                        var offsetPosition = new THREE.Vector3();
+                                        offsetPosition.copy(mesh.permutate.offset.position);
+                                        //position = position.add(offsetPosition);
+                                        position = position.add(offsetPosition.applyQuaternion(quaternionCopy));
+                                    }
+                                }
+                            }
+ 
+                            mesh.position.copy(position);
+                            mesh.quaternion.copy(quaternion);
+                        }
+                    }
+                }
+            }
+        }
+ 
+    }
+};
+ 
+GameLib.D3.Game.prototype.LinkPair = function (
+    threeMesh,
+    physicsBody,
+    physicsWorld
+) {
+    physicsWorld.linkedPairs = physicsWorld.linkedPairs || [];
+ 
+    physicsWorld.linkedPairs.push({
+        threeMesh : threeMesh,
+        physicsBody : physicsBody
+    });
+};
+/**
+ *
+ * @param sizeX Number
+ * @param sizeY Number
+ * @param matrix matrix 2D Array with height data (Column Major)
+ * @constructor
+ */
+GameLib.D3.Heightmap = function(
+    sizeX,
+    sizeY,
+    matrix
+) {
+    if (typeof sizeX == 'undefined') {
+        sizeX = 0;
+    }
+    this.sizeX = sizeX;
+ 
+    if (typeof sizeY == 'undefined') {
+        sizeY = 0;
+    }
+    this.sizeY = sizeY;
+ 
+    if (typeof matrix == 'undefined') {
+        matrix = [];
+    }
+    this.matrix = matrix;
+};
+ 
+GameLib.D3.Heightmap.prototype.generateThreeMeshFromHeightField = function(
+    THREE,
+    heightFieldShape,
+    engine
+) {
+    var geometry = new THREE.Geometry();
+ 
+    var v0 = new this.physics.CANNON.Vec3();
+    var v1 = new this.physics.CANNON.Vec3();
+    var v2 = new this.physics.CANNON.Vec3();
+ 
+    var shape = heightFieldShape;
+    for (var xi = 0; xi < shape.data.length - 1; xi++) {
+        for (var yi = 0; yi < shape.data[xi].length - 1; yi++) {
+            for (var k = 0; k < 2; k++) {
+                shape.getConvexTrianglePillar(xi, yi, k===0);
+                v0.copy(shape.pillarConvex.vertices[0]);
+                v1.copy(shape.pillarConvex.vertices[1]);
+                v2.copy(shape.pillarConvex.vertices[2]);
+                v0.vadd(shape.pillarOffset, v0);
+                v1.vadd(shape.pillarOffset, v1);
+                v2.vadd(shape.pillarOffset, v2);
+                geometry.vertices.push(
+                    new THREE.Vector3(v0.x, v0.y, v0.z),
+                    new THREE.Vector3(v1.x, v1.y, v1.z),
+                    new THREE.Vector3(v2.x, v2.y, v2.z)
+                );
+                var i = geometry.vertices.length - 3;
+                geometry.faces.push(new THREE.Face3(i, i+1, i+2));
+            }
+        }
+    }
+    geometry.computeBoundingSphere();
+    geometry.computeFaceNormals();
+ 
+    return new THREE.Mesh(geometry, new THREE.MeshNormalMaterial({ wireframe : false, shading : THREE.SmoothShading }));
+};
+ 
+ 
+GameLib.D3.Heightmap.prototype.generateHeightmapDataFromImage = function (
+    imagePath,
+    callback    // receives HeightmapData instance as the first argument
+) {
+    var img = new Image();
+ 
+    img.onload = function () {
+ 
+        var canvas = document.createElement('canvas');
+        canvas.width = img.width;
+        canvas.height = img.height;
+ 
+        var context = canvas.getContext('2d');
+        context.drawImage(img, 0, 0);
+ 
+        var imgd = context.getImageData(0, 0, img.width, img.height);
+        var pixels = imgd.data;
+ 
+        var heightList = [];
+        for (var i = 0, n = pixels.length; i < n; i += (4)) {
+            heightList.push(pixels[i]);
+        }
+ 
+        var matrix = [];
+        var sizeX = img.width,
+            sizeY = img.height;
+ 
+        for (var i = 0; i < sizeX; i++) {
+            matrix.push([]);
+            for (var j = 0; j < sizeY; j++) {
+                var height = (heightList[(sizeX - i) + j * sizeY] / 255) * 15;
+                matrix[i].push(height);
+            }
+        }
+ 
+ 
+        // todo: delete canvas here
+ 
+        callback(new GameLib.D3.HeightmapData(sizeX, sizeY, matrix));
+    };
+ 
+    img.src = imagePath;
+};
+/**
+ * Image
+ * @param id
+ * @param textureLink
+ * @param filename
+ * @param size
+ * @param contentType
+ * @constructor
+ */
+GameLib.D3.Image = function(
+    id,
+    textureLink,
+    filename,
+    size,
+    contentType
+) {
+    this.id = id;
+ 
+    this.filename = filename;
+ 
+    this.textureLink = textureLink;
+ 
+    if (typeof size == 'undefined') {
+        size = 0;
+    }
+    this.size = size;
+ 
+    if (typeof contentType == 'undefined') {
+ 
+        contentType = 'application/octet-stream';
+ 
+        if (this.filename.match(/(png)$/i)) {
+            contentType = 'image/png';
+        }
+ 
+        if (this.filename.match(/(jpg|jpeg)$/i)) {
+            contentType = 'image/jpeg';
+        }
+ 
+        if (this.filename.match(/(gif)$/i)) {
+            contentType = 'image/gif';
+        }
+    }
+    this.contentType = contentType;
+};
+/**
+ * Light Superset
+ * @param id
+ * @param lightType
+ * @param name
+ * @param color
+ * @param intensity
+ * @param position
+ * @param targetPosition
+ * @param quaternion
+ * @param rotation
+ * @param scale
+ * @param distance
+ * @param decay
+ * @param power
+ * @param angle
+ * @param penumbra
+ * @constructor
+ */
+GameLib.D3.Light = function(
+    id,
+    lightType,
+    name,
+    color,
+    intensity,
+    position,
+    targetPosition,
+    quaternion,
+    rotation,
+    scale,
+    distance,
+    decay,
+    power,
+    angle,
+    penumbra
+) {
+    this.id = id;
+    this.lightType = lightType;
+    this.name = name;
+    this.color = color;
+    this.intensity = intensity;
+ 
+    if (typeof position == 'undefined') {
+        position = new GameLib.D3.Vector3(0,0,0);
+    }
+    this.position = position;
+ 
+    if (typeof targetPosition == 'undefined') {
+        targetPosition = new GameLib.D3.Vector3(0,0,0);
+    }
+    this.targetPosition = targetPosition;
+ 
+    if (typeof quaternion == 'undefined'){
+        quaternion = new GameLib.D3.Vector4();
+    }
+    this.quaternion = quaternion;
+ 
+    if (typeof rotation == 'undefined'){
+        rotation = new GameLib.D3.Vector3(0,0,0);
+    }
+    this.rotation = rotation;
+ 
+    if (typeof scale == 'undefined'){
+        scale = new GameLib.D3.Vector3(1,1,1);
+    }
+    this.scale = scale;
+ 
+    if (typeof distance == 'undefined'){
+        distance = 0;
+    }
+    this.distance = distance;
+ 
+    if (typeof decay == 'undefined'){
+        decay = 1;
+    }
+    this.decay = decay;
+ 
+    if (typeof power == 'undefined'){
+        power = 4 * Math.PI;
+    }
+    this.power = power;
+ 
+    if (typeof angle == 'undefined'){
+        angle = Math.PI / 3;
+    }
+    this.angle = angle;
+ 
+    if (typeof penumbra == 'undefined'){
+        penumbra = 0;
+    }
+    this.penumbra = penumbra;
+};
+/**
+ * Material Superset
+ * @param id
+ * @param name
+ * @param materialType
+ * @param opacity
+ * @param side
+ * @param transparent
+ * @param maps
+ * @param specular
+ * @param lightMapIntensity
+ * @param aoMapIntensity
+ * @param color
+ * @param emissive
+ * @param emissiveIntensity
+ * @param combine
+ * @param shininess
+ * @param reflectivity
+ * @param refractionRatio
+ * @param fog
+ * @param wireframe
+ * @param wireframeLineWidth
+ * @param wireframeLineCap
+ * @param wireframeLineJoin
+ * @param vertexColors
+ * @param skinning
+ * @param morphTargets
+ * @param morphNormals
+ * @param lineWidth
+ * @param lineCap
+ * @param lineJoin
+ * @param dashSize
+ * @param gapWidth
+ * @param blending
+ * @param blendSrc
+ * @param blendDst
+ * @param blendEquation
+ * @param depthTest
+ * @param depthFunc
+ * @param depthWrite
+ * @param polygonOffset
+ * @param polygonOffsetFactor
+ * @param polygonOffsetUnits
+ * @param alphaTest
+ * @param clippingPlanes
+ * @param clipShadows
+ * @param visible
+ * @param overdraw
+ * @param shading
+ * @param bumpScale
+ * @param normalScale
+ * @param displacementScale
+ * @param displacementBias
+ * @param roughness
+ * @param metalness
+ * @param pointSize
+ * @param pointSizeAttenuation
+ * @param spriteRotation
+ * @param envMapIntensity
+ * @constructor
+ */
+GameLib.D3.Material = function(
+    id,
+    name,
+    materialType,
+    opacity,
+    side,
+    transparent,
+    maps,
+    specular,
+    lightMapIntensity,
+    aoMapIntensity,
+    color,
+    emissive,
+    emissiveIntensity,
+    combine,
+    shininess,
+    reflectivity,
+    refractionRatio,
+    fog,
+    wireframe,
+    wireframeLineWidth,
+    wireframeLineCap,
+    wireframeLineJoin,
+    vertexColors,
+    skinning,
+    morphTargets,
+    morphNormals,
+    lineWidth,
+    lineCap,
+    lineJoin,
+    dashSize,
+    gapWidth,
+    blending,
+    blendSrc,
+    blendDst,
+    blendEquation,
+    depthTest,
+    depthFunc,
+    depthWrite,
+    polygonOffset,
+    polygonOffsetFactor,
+    polygonOffsetUnits,
+    alphaTest,
+    clippingPlanes,
+    clipShadows,
+    visible,
+    overdraw,
+    shading,
+    bumpScale,
+    normalScale,
+    displacementScale,
+    displacementBias,
+    roughness,
+    metalness,
+    pointSize,
+    pointSizeAttenuation,
+    spriteRotation,
+    envMapIntensity
+) {
+    this.id = id;
+    this.name = name;
+    if (typeof materialType == 'undefined') {
+        materialType = GameLib.D3.Material.TYPE_MESH_STANDARD;
+    }
+    this.materialType = materialType;
+ 
+    if (typeof opacity == 'undefined') {
+        opacity = 1.0;
+    }
+    this.opacity = opacity;
+ 
+    if (typeof side == 'undefined') {
+        side = GameLib.D3.Material.TYPE_FRONT_SIDE;
+    }
+    this.side = side;
+ 
+    if (typeof transparent == 'undefined') {
+        transparent = false;
+    }
+    this.transparent = transparent;
+ 
+    if (typeof maps == 'undefined') {
+        maps = {
+            alpha: null,
+            ao: null,
+            bump: null,
+            diffuse: null,
+            displacement: null,
+            emissive: null,
+            environment: null,
+            light: null,
+            metalness: null,
+            normal: null,
+            roughness: null,
+            specular: null
+        };
+    }
+    this.maps = maps;
+ 
+    if (typeof specular == 'undefined') {
+        specular = new GameLib.D3.Color(0.06, 0.06, 0.06, 0.06);
+    }
+    this.specular = specular;
+ 
+    if (typeof lightMapIntensity == 'undefined') {
+        lightMapIntensity = 1;
+    }
+    this.lightMapIntensity = lightMapIntensity;
+ 
+    if (typeof aoMapIntensity == 'undefined') {
+        aoMapIntensity = 1;
+    }
+    this.aoMapIntensity = aoMapIntensity;
+ 
+    if (typeof color == 'undefined') {
+        color = new GameLib.D3.Color(1, 1, 1, 1)
+    }
+    this.color = color;
+ 
+    if (typeof emissive == 'undefined') {
+        emissive = new GameLib.D3.Color(0, 0, 0, 0);
+    }
+    this.emissive = emissive;
+ 
+    if (typeof emissiveIntensity == 'undefined') {
+        emissiveIntensity = 1;
+    }
+    this.emissiveIntensity = emissiveIntensity;
+ 
+    if (typeof combine == 'undefined') {
+        combine = GameLib.D3.Material.TYPE_MULTIPLY_OPERATION;
+    }
+    this.combine = combine;
+ 
+    if (typeof shininess == 'undefined') {
+        shininess = 30;
+    }
+    this.shininess = shininess;
+ 
+    if (typeof reflectivity == 'undefined') {
+        reflectivity = 1;
+    }
+    this.reflectivity = reflectivity;
+ 
+    if (typeof refractionRatio == 'undefined') {
+        refractionRatio = 0.98;
+    }
+    this.refractionRatio = refractionRatio;
+ 
+    if (typeof fog == 'undefined') {
+        fog = true;
+    }
+    this.fog = fog;
+ 
+    if (typeof wireframe == 'undefined') {
+        wireframe = false;
+    }
+    this.wireframe = wireframe;
+ 
+    if (typeof wireframeLineWidth == 'undefined') {
+        wireframeLineWidth = 1;
+    }
+    this.wireframeLineWidth = wireframeLineWidth;
+ 
+    if (typeof wireframeLineCap == 'undefined') {
+        wireframeLineCap = 'round';
+    }
+    this.wireframeLineCap = wireframeLineCap;
+ 
+    if (typeof wireframeLineJoin == 'undefined') {
+        wireframeLineJoin = 'round';
+    }
+    this.wireframeLineJoin = wireframeLineJoin;
+ 
+    if (typeof vertexColors == 'undefined') {
+        vertexColors = GameLib.D3.Material.TYPE_NO_COLORS;
+    }
+    this.vertexColors = vertexColors;
+ 
+    if (typeof skinning == 'undefined') {
+        skinning = false;
+    }
+    this.skinning = skinning;
+ 
+    if (typeof morphTargets == 'undefined') {
+        morphTargets = false;
+    }
+    this.morphTargets = morphTargets;
+ 
+    if (typeof morphNormals == 'undefined') {
+        morphNormals = false;
+    }
+    this.morphNormals = morphNormals;
+ 
+    if (typeof overdraw == 'undefined') {
+        overdraw = 0;
+    }
+    this.overdraw = overdraw;
+ 
+    if (typeof lineWidth == 'undefined') {
+        lineWidth = 1;
+    }
+    this.lineWidth = lineWidth;
+ 
+    if (typeof lineCap == 'undefined') {
+        lineCap = 'round';
+    }
+    this.lineCap = lineCap;
+ 
+    if (typeof lineJoin == 'undefined') {
+        lineJoin = 'round';
+    }
+    this.lineJoin = lineJoin;
+ 
+    if (typeof dashSize == 'undefined') {
+        dashSize = 3;
+    }
+    this.dashSize = dashSize;
+ 
+    if (typeof gapWidth == 'undefined') {
+        gapWidth = 1;
+    }
+    this.gapWidth = gapWidth;
+ 
+    if (typeof blending == 'undefined') {
+        blending = GameLib.D3.Material.TYPE_NORMAL_BLENDING;
+    }
+    this.blending = blending;
+ 
+    if (typeof blendSrc == 'undefined') {
+        blendSrc = GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR;
+    }
+    this.blendSrc = blendSrc;
+ 
+    if (typeof blendDst == 'undefined') {
+        blendDst = GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR;
+    }
+    this.blendDst = blendDst;
+ 
+    if (typeof blendEquation == 'undefined') {
+        blendEquation = GameLib.D3.Material.TYPE_ADD_EQUATION;
+    }
+    this.blendEquation = blendEquation;
+ 
+    if (typeof depthTest == 'undefined') {
+        depthTest = true;
+    }
+    this.depthTest = depthTest;
+ 
+    if (typeof depthFunc == 'undefined') {
+        depthFunc = GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH;
+    }
+    this.depthFunc = depthFunc;
+ 
+    if (typeof depthWrite == 'undefined') {
+        depthWrite = true;
+    }
+    this.depthWrite = depthWrite;
+ 
+    if (typeof polygonOffset == 'undefined') {
+        polygonOffset = false;
+    }
+    this.polygonOffset = polygonOffset;
+ 
+    if (typeof polygonOffsetFactor == 'undefined') {
+        polygonOffsetFactor = 1;
+    }
+    this.polygonOffsetFactor = polygonOffsetFactor;
+ 
+    if (typeof polygonOffsetUnits == 'undefined') {
+        polygonOffsetUnits = 1;
+    }
+    this.polygonOffsetUnits = polygonOffsetUnits;
+ 
+    if (typeof alphaTest == 'undefined') {
+        alphaTest = 0;
+    }
+    this.alphaTest = alphaTest;
+ 
+    if (typeof clippingPlanes == 'undefined') {
+        clippingPlanes = [];
+    }
+    this.clippingPlanes = clippingPlanes;
+ 
+    if (typeof clipShadows == 'undefined') {
+        clipShadows = false;
+    }
+    this.clipShadows = clipShadows;
+ 
+    if (typeof visible == 'undefined') {
+        visible = true;
+    }
+    this.visible = visible;
+ 
+    if (typeof shading == 'undefined') {
+        shading = GameLib.D3.Material.TYPE_FLAT_SHADING;
+    }
+    this.shading = shading;
+ 
+    if (typeof bumpScale == 'undefined') {
+        bumpScale = 1;
+    }
+    this.bumpScale = bumpScale;
+ 
+    if (typeof normalScale == 'undefined') {
+        normalScale = 1;
+    }
+    this.normalScale = normalScale;
+ 
+    if (typeof displacementScale == 'undefined') {
+        displacementScale = 1;
+    }
+    this.displacementScale = displacementScale;
+ 
+    if (typeof displacementBias == 'undefined') {
+        displacementBias = 0;
+    }
+    this.displacementBias = displacementBias;
+ 
+    if (typeof roughness == 'undefined') {
+        roughness = 0.5;
+    }
+    this.roughness = roughness;
+ 
+    if (typeof metalness == 'undefined') {
+        metalness = 0.5;
+    }
+    this.metalness = metalness;
+ 
+    if (typeof pointSize == 'undefined') {
+        pointSize = 1;
+    }
+    this.pointSize = pointSize;
+ 
+    if (typeof pointSizeAttenuation == 'undefined') {
+        pointSizeAttenuation = true;
+    }
+    this.pointSizeAttenuation = pointSizeAttenuation;
+ 
+    if (typeof spriteRotation == 'undefined') {
+        spriteRotation = 0;
+    }
+    this.spriteRotation = spriteRotation;
+ 
+    if (typeof envMapIntensity == 'undefined') {
+        envMapIntensity = 1.0;
+    }
+    this.envMapIntensity = envMapIntensity;
+ 
+};
+ 
+/**
+ * Combine Method
+ * @type {number}
+ */
+GameLib.D3.Material.TYPE_MULTIPLY_OPERATION = 0;
+GameLib.D3.Material.TYPE_MIX_OPERATION = 1;
+GameLib.D3.Material.TYPE_ADD_OPERATION = 2;
+ 
+/**
+ * Vertex Color Mode
+ * @type {number}
+ */
+GameLib.D3.Material.TYPE_NO_COLORS = 0;
+GameLib.D3.Material.TYPE_FACE_COLORS = 1;
+GameLib.D3.Material.TYPE_VERTEX_COLORS = 2;
+ 
+/**
+ * Blending Mode
+ * @type {number}
+ */
+GameLib.D3.Material.TYPE_NORMAL_BLENDING = 1;
+GameLib.D3.Material.TYPE_ADDITIVE_BLENDING = 2;
+GameLib.D3.Material.TYPE_SUBTRACTIVE_BLENDING = 3;
+GameLib.D3.Material.TYPE_MULTIPLY_BLENDING = 4;
+GameLib.D3.Material.TYPE_CUSTOM_BLENDING = 5;
+ 
+/**
+ * Blend Source and Destination
+ * @type {number}
+ */
+GameLib.D3.Material.TYPE_ZERO_FACTOR = 200;
+GameLib.D3.Material.TYPE_ONE_FACTOR = 201;
+GameLib.D3.Material.TYPE_SRC_COLOR_FACTOR = 202;
+GameLib.D3.Material.TYPE_ONE_MINUS_SRC_COLOR_FACTOR = 203;
+GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR = 204;
+GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR = 205;
+GameLib.D3.Material.TYPE_DST_ALPHA_FACTOR = 206;
+GameLib.D3.Material.TYPE_ONE_MINUS_DST_ALPHA_FACTOR = 207;
+GameLib.D3.Material.TYPE_DST_COLOR_FACTOR = 208;
+GameLib.D3.Material.TYPE_ONE_MINUS_DST_COLOR_FACTOR = 209;
+GameLib.D3.Material.TYPE_SRC_ALPHA_SATURATE_FACTOR = 210;
+ 
+/**
+ * Blend Operation
+ * @type {number}
+ */
+GameLib.D3.Material.TYPE_ADD_EQUATION = 100;
+GameLib.D3.Material.TYPE_SUBTRACT_EQUATION = 101;
+GameLib.D3.Material.TYPE_REVERSE_SUBTRACT_EQUATION = 102;
+GameLib.D3.Material.TYPE_MIN_EQUATION = 103;
+GameLib.D3.Material.TYPE_MAX_EQUATION = 104;
+ 
+/**
+ * Depth Function
+ * @type {number}
+ */
+GameLib.D3.Material.TYPE_NEVER_DEPTH = 0;
+GameLib.D3.Material.TYPE_ALWAYS_DEPTH = 1;
+GameLib.D3.Material.TYPE_LESS_DEPTH = 2;
+GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH = 3;
+GameLib.D3.Material.TYPE_EQUAL_DEPTH = 4;
+GameLib.D3.Material.TYPE_GREATER_EQUAL_DEPTH = 5;
+GameLib.D3.Material.TYPE_GREATER_DEPTH = 6;
+GameLib.D3.Material.TYPE_NOT_EQUAL_DEPTH = 7;
+ 
+/**
+ * Culling Mode
+ * @type {number}
+ */
+GameLib.D3.Material.TYPE_FRONT_SIDE = 0;
+GameLib.D3.Material.TYPE_BACK_SIDE = 1;
+GameLib.D3.Material.TYPE_DOUBLE_SIDE = 2;
+ 
+/**
+ * Shading Type
+ * @type {number}
+ */
+GameLib.D3.Material.TYPE_FLAT_SHADING = 1;
+GameLib.D3.Material.TYPE_SMOOTH_SHADING = 2;
+ 
+/**
+ * Material Type
+ * @type {string}
+ */
+GameLib.D3.Material.TYPE_LINE_BASIC    = "LineBasicMaterial";
+GameLib.D3.Material.TYPE_LINE_DASHED   = "LineDashedMaterial";
+GameLib.D3.Material.TYPE_MESH_BASIC    = "MeshBasicMaterial";
+GameLib.D3.Material.TYPE_MESH_DEPTH    = "MeshDepthMaterial";
+GameLib.D3.Material.TYPE_MESH_LAMBERT  = "MeshLambertMaterial";
+GameLib.D3.Material.TYPE_MESH_NORMAL   = "MeshNormalMaterial";
+GameLib.D3.Material.TYPE_MESH_PHONG    = "MeshPhongMaterial";
+GameLib.D3.Material.TYPE_MESH_STANDARD = "MeshStandardMaterial";
+GameLib.D3.Material.TYPE_POINTS        = "PointsMaterial";
+GameLib.D3.Material.TYPE_SPRITE        = "SpriteMaterial";
+GameLib.D3.Material.TYPE_MULTI_MATERIAL= "MultiMaterial";
+ 
+/**
+ * Creates a THREE.Material from a GameLib.D3.Material
+ * @param blenderMaterial GameLib.D3.Material
+ * @param THREE THREE.js
+ */
+GameLib.D3.prototype.createThreeMaterial = function(blenderMaterial, THREE) {
+ 
+    var defer = this.Q.defer();
+ 
+    var threeMaterial = null;
+ 
+    var blenderMaps = [];
+ 
+    if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_STANDARD) {
+ 
+        threeMaterial = new THREE.MeshStandardMaterial({
+            name: blenderMaterial.name,
+            opacity: blenderMaterial.opacity,
+            transparent: blenderMaterial.transparent,
+            blending: blenderMaterial.blending,
+            blendSrc: blenderMaterial.blendSrc,
+            blendDst: blenderMaterial.blendDst,
+            blendEquation: blenderMaterial.blendEquation,
+            depthTest: blenderMaterial.depthTest,
+            depthFunc: blenderMaterial.depthFunc,
+            depthWrite: blenderMaterial.depthWrite,
+            polygonOffset: blenderMaterial.polygonOffset,
+            polygonOffsetFactor: blenderMaterial.polygonOffsetFactor,
+            polygonOffsetUnits: blenderMaterial.polygonOffsetUnits,
+            alphaTest: blenderMaterial.alphaTest,
+            clippingPlanes: blenderMaterial.clippingPlanes,
+            clipShadows: blenderMaterial.clipShadows,
+            overdraw: blenderMaterial.overdraw,
+            visible: blenderMaterial.visible,
+            side: blenderMaterial.side,
+            color: new THREE.Color(
+                blenderMaterial.color.r,
+                blenderMaterial.color.g,
+                blenderMaterial.color.b
+            ),
+            roughness: blenderMaterial.roughness,
+            metalness: blenderMaterial.metalness,
+            lightMapIntensity: blenderMaterial.lightMapIntensity,
+            aoMapIntensity: blenderMaterial.aoMapIntensity,
+            emissive: new THREE.Color(
+                blenderMaterial.emissive.r,
+                blenderMaterial.emissive.g,
+                blenderMaterial.emissive.b
+            ),
+            emissiveIntensity: blenderMaterial.emissiveIntensity,
+            bumpScale: blenderMaterial.bumpScale,
+            normalScale: blenderMaterial.normalScale,
+            displacementScale: blenderMaterial.displacementScale,
+            refractionRatio: blenderMaterial.refractionRatio,
+            fog: blenderMaterial.fog,
+            shading: blenderMaterial.shading,
+            wireframe: blenderMaterial.wireframe,
+            wireframeLinewidth: blenderMaterial.wireframeLineWidth,
+            wireframeLinecap: blenderMaterial.wireframeLineCap,
+            wireframeLinejoin: blenderMaterial.wireframeLineJoin,
+            vertexColors: blenderMaterial.vertexColors,
+            skinning: blenderMaterial.skinning,
+            morphTargets: blenderMaterial.morphTargets,
+            morphNormals: blenderMaterial.morphNormals
+        });
+ 
+        blenderMaps.push(
+            'diffuse',
+            'light',
+            'ao',
+            'emissive',
+            'bump',
+            'normal',
+            'displacement',
+            'roughness',
+            'metalness',
+            'alpha',
+            'environment'
+        );
+    } else if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_PHONG) {
+ 
+        threeMaterial = new THREE.MeshPhongMaterial({
+            name: blenderMaterial.name,
+            opacity: blenderMaterial.opacity,
+            transparent: blenderMaterial.transparent,
+            blending: blenderMaterial.blending,
+            blendSrc: blenderMaterial.blendSrc,
+            blendDst: blenderMaterial.blendDst,
+            blendEquation: blenderMaterial.blendEquation,
+            depthTest: blenderMaterial.depthTest,
+            depthFunc: blenderMaterial.depthFunc,
+            depthWrite: blenderMaterial.depthWrite,
+            polygonOffset: blenderMaterial.polygonOffset,
+            polygonOffsetFactor: blenderMaterial.polygonOffsetFactor,
+            polygonOffsetUnits: blenderMaterial.polygonOffsetUnits,
+            alphaTest: blenderMaterial.alphaTest,
+            clippingPlanes: blenderMaterial.clippingPlanes,
+            clipShadows: blenderMaterial.clipShadows,
+            overdraw: blenderMaterial.overdraw,
+            visible: blenderMaterial.visible,
+            side: blenderMaterial.side,
+            color: new THREE.Color(
+                blenderMaterial.color.r,
+                blenderMaterial.color.g,
+                blenderMaterial.color.b
+            ),
+            specular: new THREE.Color(
+                blenderMaterial.specular.r,
+                blenderMaterial.specular.g,
+                blenderMaterial.specular.b
+            ),
+            shininess: blenderMaterial.shininess,
+            lightMapIntensity: blenderMaterial.lightMapIntensity,
+            aoMapIntensity: blenderMaterial.aoMapIntensity,
+            emissive: new THREE.Color(
+                blenderMaterial.emissive.r,
+                blenderMaterial.emissive.g,
+                blenderMaterial.emissive.b
+            ),
+            emissiveIntensity: blenderMaterial.emissiveIntensity,
+            bumpScale: blenderMaterial.bumpScale,
+            normalScale: blenderMaterial.normalScale,
+            displacementScale: blenderMaterial.displacementScale,
+            combine: blenderMaterial.combine,
+            refractionRatio: blenderMaterial.refractionRatio,
+            fog: blenderMaterial.fog,
+            shading: blenderMaterial.shading,
+            wireframe: blenderMaterial.wireframe,
+            wireframeLinewidth: blenderMaterial.wireframeLineWidth,
+            wireframeLinecap: blenderMaterial.wireframeLineCap,
+            wireframeLinejoin: blenderMaterial.wireframeLineJoin,
+            vertexColors: blenderMaterial.vertexColors,
+            skinning: blenderMaterial.skinning,
+            morphTargets: blenderMaterial.morphTargets,
+            morphNormals: blenderMaterial.morphNormals
+        });
+ 
+        blenderMaps.push(
+            'diffuse',
+            'light',
+            'ao',
+            'emissive',
+            'bump',
+            'normal',
+            'displacement',
+            'specular',
+            'alpha',
+            'environment'
+        );
+ 
+    } else {
+        console.log("material type is not implemented yet: " + blenderMaterial.materialType + " - material indexes could be screwed up");
+    }
+ 
+    if (blenderMaps.length > 0) {
+        var textureMaps = this.loadMaps(blenderMaterial, blenderMaps, threeMaterial);
+        Q.all(textureMaps).then(
+            function(){
+                defer.resolve(threeMaterial);
+            }
+        ).catch(
+            function(error){
+                console.log(error);
+                defer.reject(error);
+            }
+        )
+    } else {
+        defer.resolve(threeMaterial);
+    }
+ 
+    return defer.promise;
+};
+/**
+ * Matrix 3 Maths
+ * @param row0 GameLib.D3.Vector3
+ * @param row1 GameLib.D3.Vector3
+ * @param row2 GameLib.D3.Vector3
+ * @constructor
+ */
+GameLib.D3.Matrix3 = function(
+    row0,
+    row1,
+    row2
+) {
+    this.identity();
+ 
+    if (row0) {
+        this.rows[0] = row0;
+    }
+ 
+    if (row1) {
+        this.rows[1] = row1;
+    }
+ 
+    if (row2) {
+        this.rows[2] = row2;
+    }
+};
+ 
+/**
+ * Set matrix to identity
+ */
+GameLib.D3.Matrix3.prototype.identity = function () {
+    this.rows = [
+        new GameLib.D3.Vector4(1, 0, 0),
+        new GameLib.D3.Vector4(0, 1, 0),
+        new GameLib.D3.Vector4(0, 0, 1)
+    ];
+};
+GameLib.D3.Matrix4 = function(
+    row0,
+    row1,
+    row2,
+    row3
+) {
+ 
+    this.identity();
+ 
+    if (row0) {
+        this.rows[0] = row0;
+    }
+ 
+    if (row1) {
+        this.rows[1] = row1;
+    }
+ 
+    if (row2) {
+        this.rows[2] = row2;
+    }
+ 
+    if (row3) {
+        this.rows[3] = row3;
+    }
+};
+ 
+GameLib.D3.Matrix4.prototype.rotationMatrixX = function (radians) {
+    this.identity();
+    this.rows[1] = new GameLib.D3.Vector4(0, Math.cos(radians), -1 * Math.sin(radians), 0);
+    this.rows[2] = new GameLib.D3.Vector4(0, Math.sin(radians), Math.cos(radians), 0);
+    return this;
+};
+ 
+GameLib.D3.Matrix4.prototype.rotationMatrixY = function (radians) {
+    this.identity();
+    this.rows[0] = new GameLib.D3.Vector4(
+        Math.cos(radians),
+        0,
+        Math.sin(radians),
+        0
+    );
+    this.rows[2] = new GameLib.D3.Vector4(
+        -1 * Math.sin(radians),
+        0,
+        Math.cos(radians),
+        0
+    );
+    return this;
+};
+ 
+GameLib.D3.Matrix4.prototype.rotationMatrixZ = function (radians) {
+    this.identity();
+    this.rows[0] = new GameLib.D3.Vector4(Math.cos(radians), -1 * Math.sin(radians), 0, 0);
+    this.rows[1] = new GameLib.D3.Vector4(Math.sin(radians), Math.cos(radians), 0, 0);
+    return this;
+};
+ 
+GameLib.D3.Matrix4.prototype.rotateX = function (radians, point) {
+    this.identity();
+    this.rotationMatrixX(radians);
+    return this.multiply(point);
+};
+ 
+GameLib.D3.Matrix4.prototype.rotateY = function (radians, point) {
+    this.identity();
+    this.rotationMatrixY(radians);
+    return this.multiply(point);
+};
+ 
+GameLib.D3.Matrix4.prototype.rotateZ = function (radians, point) {
+    this.identity();
+    this.rotationMatrixZ(radians);
+    return this.multiply(point);
+};
+ 
+GameLib.D3.Matrix4.prototype.multiply = function (mvp) {
+    if (mvp instanceof GameLib.D3.Vector4) {
+        return new GameLib.D3.Vector4(
+            this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z + this.rows[0].w * mvp.w,
+            this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z + this.rows[1].w * mvp.w,
+            this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z + this.rows[2].w * mvp.w,
+            this.rows[3].x * mvp.x + this.rows[3].y * mvp.y + this.rows[3].z * mvp.z + this.rows[3].w * mvp.w
+        );
+    } else if (mvp instanceof GameLib.D3.Vector3) {
+        return new GameLib.D3.Vector3(
+            this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z,
+            this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z,
+            this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z
+        );
+    }
+};
+ 
+GameLib.D3.Matrix4.prototype.identity = function () {
+    this.rows = [
+        new GameLib.D3.Vector4(1, 0, 0, 0),
+        new GameLib.D3.Vector4(0, 1, 0, 0),
+        new GameLib.D3.Vector4(0, 0, 1, 0),
+        new GameLib.D3.Vector4(0, 0, 0, 1)
+    ];
+};
+ 
+GameLib.D3.Matrix4.prototype.lookAt = function (position, target, up) {
+ 
+    var pv = new GameLib.D3.Vector3(position.x, position.y, position.z);
+ 
+    var z = pv.subtract(target).normalize();
+ 
+    if (z.squared() === 0) {
+        z.z = 1;
+    }
+ 
+    var x = up.cross(z).normalize();
+ 
+    if (x.squared() === 0) {
+        z.x += 0.0001;
+        x = up.cross(z).normalize();
+    }
+ 
+    var y = z.cross(x);
+ 
+    this.rows[0].x = x.x;
+    this.rows[0].y = x.y;
+    this.rows[0].z = x.z;
+ 
+    this.rows[1].x = y.x;
+    this.rows[1].y = y.y;
+    this.rows[1].z = y.z;
+ 
+    this.rows[2].x = z.x;
+    this.rows[2].y = z.y;
+    this.rows[2].z = z.z;
+ 
+    return this;
+ 
+    // te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
+    // te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
+    // te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
+ 
+ 
+    // var matrix4 = new Matrix4();
+    //
+    // matrix4.rows[0] = side.negative();
+    // matrix4.rows[1] = _up;
+    // matrix4.rows[2] = forward;
+ 
+    //
+    // matrix4.setColumn(0, side.negative());
+    // matrix4.setColumn(1, _up);
+    // matrix4.setColumn(2, forward);
+ 
+    //return matrix4;
+ 
+    // return new Matrix4(
+    //     new Vector4(
+    //         side.x,
+    //         side.y,
+    //         side.z,
+    //         side.negative().dot(position)
+    //     ),
+    //     new Vector4(
+    //         _up.x,
+    //         _up.y,
+    //         _up.z,
+    //         _up.negative().dot(position)
+    //     ),
+    //     new Vector4(
+    //         forward.negative().x,
+    //         forward.negative().y,
+    //         forward.negative().z,
+    //         forward.dot(position)
+    //     )
+    // )
+};
+ 
+/**
+ * Mesh Superset
+ * @param id
+ * @param path
+ * @param name
+ * @param meshType
+ * @param vertices
+ * @param faces
+ * @param skeleton
+ * @param faceVertexUvs
+ * @param skinIndices
+ * @param skinWeights
+ * @param materials
+ * @param position
+ * @param quaternion
+ * @param rotation
+ * @param scale
+ * @param up
+ * @param physics
+ * @param parentMeshId
+ * @param parentSceneId
+ * @param rawData
+ * @constructor
+ */
+GameLib.D3.Mesh = function(
+    id,
+    path,
+    name,
+    meshType,
+    vertices,
+    faces,
+    skeleton,
+    faceVertexUvs,
+    skinIndices,
+    skinWeights,
+    materials,
+    position,
+    quaternion,
+    rotation,
+    scale,
+    up,
+    physics,
+    parentMeshId,
+    parentSceneId,
+    rawData
+) {
+    this.id = id;
+    this.path = path;
+    this.name = name;
+    this.meshType = meshType;
+    this.vertices = vertices;
+    this.faces = faces;
+ 
+    if (typeof skeleton == 'undefined') {
+        skeleton = null;
+    }
+    this.skeleton = skeleton;
+ 
+    if (typeof faceVertexUvs == 'undefined') {
+        faceVertexUvs = [];
+    }
+    this.faceVertexUvs = faceVertexUvs;
+ 
+    if (typeof skinIndices == 'undefined') {
+        skinIndices = [];
+    }
+    this.skinIndices = skinIndices;
+ 
+    if (typeof skinWeights == 'undefined') {
+        skinWeights = [];
+    }
+    this.skinWeights = skinWeights;
+ 
+    if (typeof materials == 'undefined') {
+        materials = [];
+    }
+    this.materials = materials;
+ 
+    if (typeof position == 'undefined') {
+        position = new GameLib.D3.Vector3(0,0,0);
+    }
+    this.position = position;
+ 
+    if (typeof quaternion == 'undefined') {
+        new GameLib.D3.Vector4();
+    }
+    this.quaternion = quaternion;
+ 
+    if (typeof rotation == 'undefined') {
+        rotation = new GameLib.D3.Vector3(0,0,0);
+    }
+    this.rotation = rotation;
+ 
+    if (typeof scale == 'undefined') {
+        scale = new GameLib.D3.Vector3(1,1,1);
+    }
+    this.scale = scale;
+ 
+    if (typeof up == 'undefined') {
+        up = new GameLib.D3.Vector3(0,1,0);
+    }
+    this.up = up;
+ 
+    this.physics = physics;
+ 
+    this.parentMeshId = parentMeshId;
+ 
+    this.parentSceneId = parentSceneId;
+ 
+    this.rawData = null;// rawData;
+};
+ 
+ 
+/**
+ * Mesh Type
+ * @type {number}
+ */
+GameLib.D3.Mesh.TYPE_NORMAL = 0;
+GameLib.D3.Mesh.TYPE_SKINNED = 1;
+ 
+ 
+/**
+ * Creates a THREE Mesh from GameLib.D3.Mesh
+ * @param gameLibMesh
+ * @param threeGeometry
+ * @param threeMaterial
+ * @returns {*}
+ */
+GameLib.D3.prototype.createThreeMesh = function(gameLibMesh, threeGeometry, threeMaterial) {
+ 
+    var threeMesh = null;
+ 
+    if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_NORMAL) {
+        threeMesh = new this.THREE.Mesh(threeGeometry, threeMaterial);
+    }
+ 
+    if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_SKINNED) {
+ 
+        var bones = gameLibMesh.skeleton.bones;
+ 
+        var skinIndices = gameLibMesh.skinIndices;
+ 
+        var skinWeights = gameLibMesh.skinWeights;
+ 
+        var threeBones = [];
+ 
+        for (var bi = 0; bi < bones.length; bi++) {
+ 
+            var bone = new this.THREE.Bone();
+ 
+            bone.name = bones[bi].name;
+ 
+            bone.position.x = bones[bi].position.x;
+            bone.position.y = bones[bi].position.y;
+            bone.position.z = bones[bi].position.z;
+ 
+            bone.rotation.x = bones[bi].rotation.x;
+            bone.rotation.y = bones[bi].rotation.y;
+            bone.rotation.z = bones[bi].rotation.z;
+ 
+            bone.quaternion.x = bones[bi].quaternion.x;
+            bone.quaternion.y = bones[bi].quaternion.y;
+            bone.quaternion.z = bones[bi].quaternion.z;
+            bone.quaternion.w = bones[bi].quaternion.w;
+ 
+            bone.scale.x = bones[bi].scale.x;
+            bone.scale.y = bones[bi].scale.y;
+            bone.scale.z = bones[bi].scale.z;
+ 
+            bone.up.x = bones[bi].up.x;
+            bone.up.y = bones[bi].up.y;
+            bone.up.z = bones[bi].up.z;
+ 
+            threeBones.push(bone);
+        }
+ 
+        /**
+         * Setup the bone relationships
+         */
+        for (var br = 0; br < bones.length; br++) {
+            for (var cbi = 0; cbi < bones[br].childBoneIds.length; cbi++) {
+                threeBones[br].add(threeBones[bones[br].childBoneIds[cbi]]);
+            }
+        }
+ 
+        /**
+         * Setup bones (indexes)
+         */
+        for (var si = 0; si < skinIndices.length; si++) {
+            threeGeometry.skinIndices.push(
+                new this.THREE.Vector4(
+                    skinIndices[si].x,
+                    skinIndices[si].y,
+                    skinIndices[si].z,
+                    skinIndices[si].w
+                )
+            );
+        }
+ 
+        /**
+         * Setup bones (weights)
+         */
+        for (var sw = 0; sw < skinWeights.length; sw++) {
+            threeGeometry.skinWeights.push(
+                new this.THREE.Vector4(
+                    skinWeights[sw].x,
+                    skinWeights[sw].y,
+                    skinWeights[sw].z,
+                    skinWeights[sw].w
+                )
+            );
+        }
+ 
+        threeMesh = new this.THREE.SkinnedMesh(threeGeometry, threeMaterial);
+ 
+        var skeleton = new this.THREE.Skeleton(threeBones);
+ 
+        skeleton.useVertexTexture = gameLibMesh.skeleton.useVertexTexture;
+ 
+        for (var i = 0; i < bones.length; i++) {
+            if (bones[i].parentBoneId === null) {
+                threeMesh.add(threeBones[i]);
+                break;
+            }
+        }
+ 
+        threeMesh.bind(skeleton);
+ 
+        threeMesh.pose();
+ 
+        threeMesh.skeleton.skeletonHelper = new this.THREE.SkeletonHelper(threeMesh);
+        threeMesh.skeleton.skeletonHelper.material.linewidth = 5;
+    }
+ 
+    if (threeMesh == null) {
+        console.log('cannot handle meshes of type ' + gameLibMesh.meshType + ' yet.');
+    }
+ 
+    gameLibMesh.threeMeshId = threeMesh.id;
+ 
+    return threeMesh;
+};
+ 
+GameLib.D3.prototype.invertWindingOrder = function(triangles) {
+ 
+    for (var i = 0; i < triangles.length; i++) {
+        var v1 = triangles[i].v1;
+        triangles[i].v1 = triangles[i].v2;
+        triangles[i].v2 = v1;
+ 
+        var backupUV = triangles[i].triangle.v1uv;
+        triangles[i].triangle.v1uv = triangles[i].triangle.v2uv;
+        triangles[i].triangle.v2uv = backupUV;
+    }
+ 
+    return triangles;
+};
+ 
+/**
+ * This function resets a the winding order of a mesh from a reference point V (the average center of the mesh)
+ */
+GameLib.D3.prototype.resetWindingOrder = function(faces, vertices) {
+ 
+    var vertexList = new GameLib.D3.Vector3.Points();
+ 
+    for (var v = 0; v < vertices.length; v++) {
+        vertexList.add(new GameLib.D3.Vector3(
+            vertices[v].position.x,
+            vertices[v].position.y,
+            vertices[v].position.z
+        ));
+    }
+ 
+    var V = vertexList.average();
+ 
+    var triangles = [];
+ 
+    for (var s = 0; s < faces.length; s += 3) {
+ 
+        var v0 = faces[s];
+        var v1 = faces[s+1];
+        var v2 = faces[s+2];
+ 
+        triangles.push(
+            {
+                v0 : v0,
+                v1 : v1,
+                v2 : v2,
+                edges : [
+                    {v0: v0, v1: v1},
+                    {v0: v1, v1: v2},
+                    {v0: v2, v1: v0}
+                ],
+                winding : 0,
+                edgeIndex : -1,
+                processed : false
+            }
+        );
+    }
+ 
+    for (var i = 0; i < triangles.length; i++) {
+        if (
+            GameLib.D3.Vector3.clockwise(
+                vertices[triangles[i].v0].position,
+                vertices[triangles[i].v1].position,
+                vertices[triangles[i].v2].position,
+                V
+            )
+        ) {
+            console.log('clockwise');
+            var bv1 = triangles[i].v1;
+            triangles[i].v1 = triangles[i].v2;
+            triangles[i].v2 = bv1;
+        } else {
+            console.log('not clockwise');
+        }
+    }
+ 
+    return triangles;
+};
+ 
+/**
+ * This function resets the winding order for triangles in faces, given an initial triangle and orientation edge
+ * used pseudocode from
+ * http://stackoverflow.com/questions/17036970/how-to-correct-winding-of-triangles-to-counter-clockwise-direction-of-a-3d-mesh
+ *  We need to use a graph traversal algorithm,
+ *  lets assume we have method that returns neighbor of triangle on given edge
+ *
+ *      neighbor_on_egde( next_tria, edge )
+ *
+ *  to_process = set of pairs triangle and orientation edge, initial state is one good oriented triangle with any edge on it
+ *  processed = set of processed triangles; initial empty
+ *
+ *  while to_process is not empty:
+ *      next_tria, orientation_edge = to_process.pop()
+ *      add next_tria in processed
+ *      if next_tria is not opposite oriented than orientation_edge:
+ *          change next_tria (ABC) orientation  (B<->C)
+ *      for each edge (AB) in next_tria:
+ *          neighbor_tria = neighbor_on_egde( next_tria, edge )
+ *          if neighbor_tria exists and neighbor_tria not in processed:
+ *              to_process add (neighbor_tria, edge opposite oriented (BA))
+ * @param faces GameLib.D3.TriangleFace[]
+ * @param orientationEdge GameLib.D3.Vector2
+ * @returns {Array}
+ */
+GameLib.D3.fixWindingOrder = function(faces, orientationEdge) {
+ 
+    /**
+     * Checks if a TriangleFace belonging to a TriangleEdge has already been processed
+     * @param processed TriangleEdge[]
+     * @param triangle TriangleFace
+     * @returns {boolean}
+     */
+    function inProcessed(processed, triangle) {
+ 
+        for (var i = 0; i < processed.length; i++) {
+            if (processed[i].triangle.equals(triangle)) {
+                return true;
+            }
+        }
+ 
+        return false;
+    }
+ 
+    /**
+     * Returns a neighbouring triangle on a specific edge - preserving the edge orientation
+     * @param edge GameLib.D3.Vector2
+     * @param faces GameLib.D3.TriangleFace[]
+     * @param currentTriangle
+     * @returns {*}
+     */
+    function neighbourOnEdge(edge, faces, currentTriangle) {
+ 
+        for (var i = 0; i < faces.length; i++) {
+            if (
+                (faces[i].v0 == edge.x && faces[i].v1 == edge.y) ||
+                (faces[i].v1 == edge.x && faces[i].v2 == edge.y) ||
+                (faces[i].v2 == edge.x && faces[i].v0 == edge.y) ||
+                (faces[i].v0 == edge.y && faces[i].v1 == edge.x) ||
+                (faces[i].v1 == edge.y && faces[i].v2 == edge.x) ||
+                (faces[i].v2 == edge.y && faces[i].v0 == edge.x)
+            ) {
+ 
+                var triangle = new GameLib.D3.TriangleFace(
+                    faces[i].v0,
+                    faces[i].v1,
+                    faces[i].v2,
+                    faces[i].materialIndex,
+                    faces[i].v0uv,
+                    faces[i].v1uv,
+                    faces[i].v2uv
+                );
+ 
+                if (triangle.equals(currentTriangle)) {
+                    continue;
+                }
+ 
+                return new GameLib.D3.TriangleEdge(
+                    triangle,
+                    edge
+                );
+            }
+        }
+ 
+        return null;
+    }
+ 
+    var toProcess = [
+        new GameLib.D3.TriangleEdge(
+            new GameLib.D3.TriangleFace(
+                faces[0].v0,
+                faces[0].v1,
+                faces[0].v2,
+                faces[0].materialIndex,
+                faces[0].v0uv,
+                faces[0].v1uv,
+                faces[0].v2uv
+            ),
+            orientationEdge
+        )
+    ];
+ 
+    var processed = [];
+ 
+    while (toProcess.length > 0) {
+ 
+        var triangleEdge = toProcess.pop();
+ 
+        /**
+         * If edge is the same orientation (i.e. the edge order is the same as the given triangle edge) it needs to be reversed
+         * to have the same winding order)
+         */
+        if (
+            (triangleEdge.triangle.v0 == triangleEdge.edge.x &&
+            triangleEdge.triangle.v1 == triangleEdge.edge.y) ||
+            (triangleEdge.triangle.v1 == triangleEdge.edge.x &&
+            triangleEdge.triangle.v2 == triangleEdge.edge.y) ||
+            (triangleEdge.triangle.v2 == triangleEdge.edge.x &&
+            triangleEdge.triangle.v0 == triangleEdge.edge.y)
+        ) {
+            var backupV = triangleEdge.triangle.v1;
+            triangleEdge.triangle.v1 = triangleEdge.triangle.v2;
+            triangleEdge.triangle.v2 = backupV;
+ 
+            var backupUV = triangleEdge.triangle.v1uv;
+            triangleEdge.triangle.v1uv = triangleEdge.triangle.v2uv;
+            triangleEdge.triangle.v2uv = backupUV;
+        }
+ 
+        processed.push(triangleEdge);
+ 
+        var edges = [
+            new GameLib.D3.Vector2(
+                triangleEdge.triangle.v0,
+                triangleEdge.triangle.v1
+            ),
+            new GameLib.D3.Vector2(
+                triangleEdge.triangle.v1,
+                triangleEdge.triangle.v2
+            ),
+            new GameLib.D3.Vector2(
+                triangleEdge.triangle.v2,
+                triangleEdge.triangle.v0
+            )
+        ];
+ 
+        for (var j = 0; j < edges.length; j++) {
+            var neighbour = neighbourOnEdge(edges[j], faces, triangleEdge.triangle);
+            if (neighbour && !inProcessed(processed, neighbour.triangle)) {
+                toProcess.push(neighbour);
+            }
+        }
+    }
+ 
+    /**
+     * In processed - we will have some duplicates - only add the unique ones
+     * @type {Array}
+     */
+    var triangles = [];
+    for (var i = 0; i < processed.length; i++) {
+        var found = false;
+        for (var k = 0; k < triangles.length; k++) {
+            if (triangles[k].equals(processed[i].triangle)){
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            triangles.push(processed[i].triangle);
+        }
+    }
+ 
+    return triangles;
+};
+ 
+/**
+ * This is a work-around function to fix polys which don't triangulate because
+ * they could lie on Z-plane (XZ or YZ)) - we translate the poly to the origin, systematically rotate the poly around
+ * Z then Y axis
+ * @param verticesFlat []
+ * @param grain is the amount to systematically rotate the poly by - a finer grain means a more accurate maximum XY
+ * @return []
+ */
+GameLib.D3.fixPolyZPlane = function(verticesFlat, grain) {
+ 
+    if ((verticesFlat.length % 3) != 0 && !(verticesFlat.length > 9)) {
+        console.log("The vertices are not in the right length : " + verticesFlat.length);
+    }
+ 
+    var vertices = [];
+ 
+    var points = new GameLib.D3.Vector4.Points();
+ 
+    for (var i = 0; i < verticesFlat.length; i += 3) {
+        points.add(new GameLib.D3.Vector3(
+            verticesFlat[i],
+            verticesFlat[i + 1],
+            verticesFlat[i + 2]
+        ));
+    }
+ 
+    points.toOrigin();
+ 
+    points.maximizeXDistance(grain);
+ 
+    points.maximizeYDistance(grain);
+ 
+    for (i = 0; i < points.vectors.length; i++) {
+        vertices.push(
+            [
+                points.vectors[i].x,
+                points.vectors[i].y
+            ]
+        );
+    }
+ 
+    return vertices;
+};
+/**
+ * Physics SuperSet Namespace Object
+ * @param id
+ * @param name
+ * @param engine GameLib.D3.Engine
+ * @param worlds
+ * @returns {{World: World}}
+ * @constructor
+ */
+GameLib.D3.Physics = function(
+    id,
+    name,
+    engine,
+    worlds
+) {
+    this.id = id;
+    this.name = name;
+    this.engine = engine;
+ 
+    if (typeof worlds == 'undefined') {
+        worlds = [];
+    }
+    this.worlds = worlds;
+};
+ 
+ 
+/**
+ * Solver Types
+ * @type {number}
+ */
+GameLib.D3.Physics.SPLIT_SOLVER = 0x1;
+GameLib.D3.Physics.GS_SOLVER = 0x2;
+/**
+ * Contains a Poly vertex data structure
+ * @param localIndex
+ * @param mvertIndex
+ * @param uv GameLib.D3.Vector2
+ * @param materialIndex
+ * @param edgeIndex
+ * @constructor
+ */
+GameLib.D3.PolyVertex = function(
+    localIndex,
+    mvertIndex,
+    uv,
+    materialIndex,
+    edgeIndex
+) {
+    this.localIndex = localIndex;
+    this.mvertIndex = mvertIndex;
+    this.uv = uv;
+    this.materialIndex = materialIndex;
+    this.edgeIndex = edgeIndex;
+};
+ 
+/**
+ * Clone a PolyVertex
+ * @returns {GameLib.D3.PolyVertex}
+ */
+GameLib.D3.PolyVertex.prototype.clone = function() {
+    return new GameLib.D3.PolyVertex(
+        this.localIndex,
+        this.mvertIndex,
+        this.uv.copy(),
+        this.materialIndex,
+        this.edgeIndex
+    )
+};
+/**
+ * Physics Raycast Vehicle Superset
+ * TODO: body + wheels[]
+ * @constructor
+ */
+GameLib.D3.RaycastVehicle = function(
+) {
+    this.vehicleObject = null;
+};
+ 
+GameLib.D3.RaycastVehicle.prototype.GetWheelInfo = function(
+ 
+) {
+    // note: need a way to determine which engine we are currently using
+    return this.vehicleObject.wheelInfos;
+};
+ 
+/**
+ * Physics Rigid Body Vehicle Superset
+ * TODO: body + wheels[]
+ * @constructor
+ */
+GameLib.D3.RigidVehicle = function(
+) {
+    this.vehicleObject = null;
+};
+ 
+GameLib.D3.RigidVehicle.prototype.GetWheelInfo = function(
+ 
+) {
+    // note: need a way to determine which engine we are currently using
+    return this.vehicleObject.wheelBodies;
+};
+ 
+/**
+ * RigidBody Superset
+ * @param mass
+ * @param friction
+ * @param position
+ * @param quaternion
+ * @param velocity
+ * @param angularVelocity
+ * @param linearDamping
+ * @param angularDamping
+ * @param allowSleep
+ * @param sleepSpeedLimit
+ * @param sleepTimeLimit
+ * @param collisionFilterGroup
+ * @param collisionFilterMask
+ * @param fixedRotation
+ * @param shape
+ * @returns {GameLib.D3.Physics.RigidBody}
+ * @constructor
+ */
+GameLib.D3.RigidBody = function(
+    mass,
+    friction,
+    position,
+    quaternion,
+    velocity,
+    angularVelocity,
+    linearDamping,
+    angularDamping,
+    allowSleep,
+    sleepSpeedLimit,
+    sleepTimeLimit,
+    collisionFilterGroup,
+    collisionFilterMask,
+    fixedRotation,
+    shape
+) {
+ 
+    this.position = position || new GameLib.D3.Vector3();
+    this.velocity = velocity || new GameLib.D3.Vector3();
+    this.angularVelocity = angularVelocity || new GameLib.D3.Vector3();
+    this.quaternion = quaternion || new GameLib.D3.Vector4(0, 0, 0, 1);
+    this.mass = typeof mass == "undefined" ? 0 : mass;
+    this.friction = typeof friction == "undefined" ? 5 : friction;
+    this.linearDamping = typeof linearDamping == "undefined" ? 0.01 : linearDamping;
+    this.angularDamping = typeof angularDamping == "undefined" ? 0.01 : angularDamping;
+    this.allowSleep = typeof allowSleep == "undefined" ? true : allowSleep;
+    this.sleepSpeedLimit = typeof sleepSpeedLimit == "undefined" ? 0.1 : sleepSpeedLimit;
+    this.sleepTimeLimit = typeof sleepTimeLimit == "undefined" ? 1.0 : sleepTimeLimit;
+    this.collisionFilterGroup = typeof collisionFilterGroup == "undefined" ? 1 : collisionFilterGroup;
+    this.collisionFilterMask = typeof collisionFilterMask == "undefined" ? 1 : collisionFilterMask;
+    this.fixedRotation = typeof fixedRotation == "undefined" ? false : fixedRotation;
+    this.shape = typeof shape == "undefined" ? null : shape;
+ 
+    this.rigidBodyInstance = this.createRigidBodyInstance();
+};
+ 
+/**
+ *
+ * @returns {*}
+ */
+GameLib.D3.RigidBody.prototype.createRigidBodyInstance = function() {
+ 
+    var rigidBody = null;
+ 
+    // Create the bodyObject
+    if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+        rigidBody = new this.physics.CANNON.Body(
+            {
+                mass: mass,
+                friction: friction,
+                position: new this.physics.CANNON.Vec3(position.x, position.y, position.z),
+                velocity: new this.physics.CANNON.Vec3(velocity.x, velocity.y, velocity.z),
+                quaternion: new this.physics.CANNON.Quaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w),
+                angularVelocity: new this.physics.CANNON.Vec3(angularVelocity.x, angularVelocity.y, angularVelocity.z),
+                linearDamping: linearDamping,
+                angularDamping: angularDamping,
+                allowSleep: allowSleep,
+                sleepSpeedLimit: sleepSpeedLimit,
+                sleepTimeLimit: sleepTimeLimit,
+                collisionFilterGroup: collisionFilterGroup,
+                collisionFilterMask: collisionFilterMask,
+                fixedRotation: fixedRotation,
+                shape: shape
+            }
+        );
+ 
+    }
+ 
+    return rigidBody;
+};
+ 
+ 
+/**
+ * Scenes are objects putting meshes into 'world space'
+ * @param id
+ * @param path String
+ * @param name String
+ * @param meshes GameLib.D3.Mesh[]
+ * @param quaternion
+ * @param position
+ * @param rotation
+ * @param scale
+ * @param parentSceneId
+ * @param lights
+ * @constructor
+ */
+GameLib.D3.Scene = function(
+    id,
+    path,
+    name,
+    meshes,
+    quaternion,
+    position,
+    rotation,
+    scale,
+    parentSceneId,
+    lights,
+    physics
+) {
+    this.id = id;
+    this.path = path;
+    this.name = name;
+    if (this.name.trim() == "") {
+        this.name = 'unnamed';
+    }
+    this.meshes = meshes;
+ 
+    if (typeof quaternion == 'undefined') {
+        quaternion = new GameLib.D3.Vector4();
+    }
+    this.quaternion = quaternion;
+ 
+    if (typeof position == 'undefined') {
+        position = new GameLib.D3.Vector3(0,0,0);
+    }
+    this.position = position;
+ 
+    if (typeof rotation == 'undefined') {
+        rotation = new GameLib.D3.Vector3(0,0,0);
+    }
+    this.rotation = rotation;
+ 
+    if (typeof scale == 'undefined') {
+        scale = new GameLib.D3.Vector3(1,1,1);
+    }
+    this.scale = scale;
+ 
+    if (typeof parentSceneId == 'undefined') {
+        parentSceneId = null;
+    }
+    this.parentSceneId = parentSceneId;
+ 
+    if (typeof lights == 'undefined') {
+        lights = [];
+    }
+    this.lights = lights;
+ 
+    if (typeof physics == 'undefined') {
+        physics = [];
+    }
+    this.physics = physics;
+};
+ 
+/**
+ * Loads a scene directly from the API
+ * @param sceneName
+ * @param onLoaded callback
+ */
+GameLib.D3.prototype.loadSceneFromApi = function(scene, onLoaded) {
+ 
+    /**
+     * First check if this is a client or server side request
+     */
+    if (typeof XMLHttpRequest == 'undefined') {
+        console.warn('implement server side loading from API here');
+        return onLoaded(null, new Error('not implemented'));
+    }
+ 
+    var xhr = new XMLHttpRequest();
+    xhr.open(
+        'GET',
+        this.apiUrl + '/scene/load' + scene.path + '/' + scene.name
+    );
+ 
+    xhr.onreadystatechange = function(xhr, gameLibD3) {
+        return function() {
+            if (xhr.readyState == 4) {
+ 
+                var response = JSON.parse(xhr.responseText);
+ 
+                if (!response.scene || response.scene.length == 0) {
+                    return onLoaded(null, null, new Error('Could not load scene'));
+                }
+ 
+                var scene = response.scene[0];
+ 
+                var physics3ds = [];
+ 
+                if (scene.physics && scene.physics.length > 0) {
+ 
+                    for (var p = 0; p < scene.physics.length; p++) {
+ 
+                        var physics = scene.physics[p];
+ 
+                        var physics3d = new GameLib.D3.Physics(
+                            physics.id,
+                            physics.name,
+                            physics.engineType,
+                            gameLibD3.CANNON,
+                            null,
+                            null
+                        );
+ 
+                        var worlds3d = [];
+ 
+                        for (var w = 0; w < physics.worlds.length; w++) {
+ 
+                            var world = physics.worlds[w];
+ 
+                            var broadphase = world.broadphase;
+ 
+                            var broadphase3d = new GameLib.D3.Physics.Broadphase(
+                                broadphase.id,
+                                broadphase.name,
+                                broadphase.broadphaseType
+                            );
+ 
+                            var solver = world.solver;
+ 
+                            var solver3d = new GameLib.D3.Physics.Solver(
+                                solver.id,
+                                solver.name,
+                                solver.solverType,
+                                solver.iterations,
+                                solver.tolerance
+                            );
+ 
+                            var bodies = world.rigidBodies;
+ 
+                            var bodies3d = [];
+ 
+                            for (var b = 0; b < bodies.length; b++) {
+ 
+                                var body = bodies[b];
+ 
+                                //TODO: add all body properties here
+                                var body3d = new GameLib.D3.Physics.RigidBody(
+                                    body.id,
+                                    body.name
+                                );
+ 
+                                bodies3d.push(body3d);
+                            }
+ 
+                            var world3d = new GameLib.D3.Physics.World(
+                                null,
+                                world.name,
+                                physics3d,
+                                new GameLib.D3.Vector3(
+                                    world.gravity.x,
+                                    world.gravity.y,
+                                    world.gravity.z
+                                ),
+                                broadphase3d,
+                                solver3d,
+                                bodies3d
+                            );
+ 
+                            worlds3d.push(world3d);
+                        }
+ 
+                        physics3ds.push(physics3d);
+                    }
+                }
+ 
+                var lights3d = [];
+ 
+                for (var l = 0; l < scene.lights.length; l++) {
+ 
+                    var light = scene.lights[l];
+ 
+                    var light3d = new GameLib.D3.Light(
+                        light.id,
+                        light.lightType,
+                        light.name,
+                        new GameLib.D3.Color(
+                            light.color.r,
+                            light.color.g,
+                            light.color.b,
+                            light.color.a
+                        ),
+                        light.intensity,
+                        new GameLib.D3.Vector3(
+                            light.position.x,
+                            light.position.y,
+                            light.position.z
+                        ),
+                        new GameLib.D3.Vector3(
+                            light.targetPosition.x,
+                            light.targetPosition.y,
+                            light.targetPosition.z
+                        ),
+                        new GameLib.D3.Vector4(
+                            light.quaternion.x,
+                            light.quaternion.y,
+                            light.quaternion.z,
+                            light.quaternion.w
+                        ),
+                        new GameLib.D3.Vector3(
+                            light.rotation.x,
+                            light.rotation.y,
+                            light.rotation.z
+                        ),
+                        new GameLib.D3.Vector3(
+                            light.scale.x,
+                            light.scale.y,
+                            light.scale.z
+                        ),
+                        light.distance,
+                        light.decay,
+                        light.power,
+                        light.angle,
+                        light.penumbra
+                    );
+ 
+                    lights3d.push(light3d);
+                };
+ 
+                var scene3d = new GameLib.D3.Scene(
+                    scene._id || scene.id,
+                    scene.path,
+                    scene.name,
+                    scene.meshes,
+                    new GameLib.D3.Vector4(
+                        scene.quaternion.x,
+                        scene.quaternion.y,
+                        scene.quaternion.z,
+                        scene.quaternion.w
+                    ),
+                    new GameLib.D3.Vector3(
+                        scene.position.x,
+                        scene.position.y,
+                        scene.position.z
+                    ),
+                    new GameLib.D3.Vector3(
+                        scene.rotation.x,
+                        scene.rotation.y,
+                        scene.rotation.z
+                    ),
+                    new GameLib.D3.Vector3(
+                        scene.scale.x,
+                        scene.scale.y,
+                        scene.scale.z
+                    ),
+                    scene.parentSceneId,
+                    lights3d,
+                    physics3ds
+                );
+ 
+                gameLibD3.loadScene(scene3d, onLoaded, false);
+            }
+        }
+    }(xhr, this);
+ 
+    xhr.send();
+};
+ 
+ 
+/**
+ * Loads a GameLib.D3.Scene object into a ThreeJS Scene object
+ * @param gameLibScene GameLib.D3.Scene
+ * @param onLoaded callback when all meshes have loaded
+ * @param computeNormals set to true to compute new face and vertex normals during load
+ */
+GameLib.D3.prototype.loadScene = function(gameLibScene, onLoaded, computeNormals) {
+ 
+    console.log("loading scene " + gameLibScene.name);
+ 
+    this.path = gameLibScene.path;
+ 
+    var meshQ = [];
+ 
+    for (var m = 0; m < gameLibScene.meshes.length; m++) {
+ 
+        var mesh = gameLibScene.meshes[m];
+ 
+        console.log("loading mesh " + mesh.name);
+ 
+        var geometry = new this.THREE.Geometry();
+ 
+        var vertices = mesh.vertices;
+ 
+        var faces = mesh.faces;
+ 
+        var faceVertexUvs = mesh.faceVertexUvs;
+ 
+        var materials = mesh.materials;
+ 
+        /**
+         * Setup vertices
+         */
+        for (var v = 0; v < vertices.length; v++) {
+            geometry.vertices.push(
+                new this.THREE.Vector3(
+                    vertices[v].position.x,
+                    vertices[v].position.y,
+                    vertices[v].position.z
+                )
+            )
+        }
+ 
+        /**
+         * Setup faces
+         */
+        for (var f = 0; f < faces.length; f++) {
+ 
+            var face = new this.THREE.Face3(
+                faces[f].v0,
+                faces[f].v1,
+                faces[f].v2,
+                new this.THREE.Vector3(
+                    faces[f].normal.x,
+                    faces[f].normal.y,
+                    faces[f].normal.z
+                ),
+                new this.THREE.Color(
+                    faces[f].color.r,
+                    faces[f].color.g,
+                    faces[f].color.b
+                ),
+                faces[f].materialIndex
+            );
+ 
+            face.vertexColors = [
+                new this.THREE.Color(
+                    faces[f].vertexColors[0].r,
+                    faces[f].vertexColors[0].g,
+                    faces[f].vertexColors[0].b
+                ),
+                new this.THREE.Color(
+                    faces[f].vertexColors[1].r,
+                    faces[f].vertexColors[1].g,
+                    faces[f].vertexColors[1].b
+                ),
+                new this.THREE.Color(
+                    faces[f].vertexColors[2].r,
+                    faces[f].vertexColors[2].g,
+                    faces[f].vertexColors[2].b
+                )
+            ];
+ 
+            face.normal = new this.THREE.Vector3(
+                faces[f].normal.x,
+                faces[f].normal.y,
+                faces[f].normal.z
+            );
+ 
+            face.vertexNormals = [
+                new this.THREE.Vector3(
+                    faces[f].vertexNormals[0].x,
+                    faces[f].vertexNormals[0].y,
+                    faces[f].vertexNormals[0].z
+                ),
+                new this.THREE.Vector3(
+                    faces[f].vertexNormals[1].x,
+                    faces[f].vertexNormals[1].y,
+                    faces[f].vertexNormals[1].z
+                ),
+                new this.THREE.Vector3(
+                    faces[f].vertexNormals[2].x,
+                    faces[f].vertexNormals[2].y,
+                    faces[f].vertexNormals[2].z
+                )
+            ];
+ 
+            geometry.faces.push(face);
+        }
+ 
+        geometry.faceVertexUvs = [];
+ 
+        /**
+         * Setup face UVs
+         */
+        for (var fm = 0; fm < faceVertexUvs.length; fm++) {
+ 
+            var faceMaterialVertexUvs = faceVertexUvs[fm];
+ 
+            geometry.faceVertexUvs[fm] = [];
+ 
+            for (var fuv = 0; fuv < faceMaterialVertexUvs.length; fuv++) {
+                geometry.faceVertexUvs[fm][fuv] = [];
+                geometry.faceVertexUvs[fm][fuv].push(
+                    new this.THREE.Vector2(
+                        faceMaterialVertexUvs[fuv][0].x,
+                        faceMaterialVertexUvs[fuv][0].y
+                    ),
+                    new this.THREE.Vector2(
+                        faceMaterialVertexUvs[fuv][1].x,
+                        faceMaterialVertexUvs[fuv][1].y
+                    ),
+                    new this.THREE.Vector2(
+                        faceMaterialVertexUvs[fuv][2].x,
+                        faceMaterialVertexUvs[fuv][2].y
+                    )
+                );
+            }
+        }
+ 
+        /**
+         * Re-calculate normals (if we have to)
+         * @type {Array}
+         */
+        if (computeNormals) {
+            geometry.computeFaceNormals();
+            geometry.computeVertexNormals();
+        }
+ 
+        var threeMaterialLoaders = [];
+ 
+        /**
+         * Setup materials
+         */
+        for (var mi = 0; mi < materials.length; mi++) {
+            threeMaterialLoaders.push(this.createThreeMaterial(materials[mi]));
+        }
+ 
+        var result = this.Q.all(threeMaterialLoaders).then(
+            function(gl3d, mesh, geometry) {
+                return function(materials) {
+ 
+                    console.log("loaded material : " + materials[0].name);
+ 
+                    /**
+                     * We don't support MultiMaterial atm - it doesn't work with raycasting
+                     */
+                    var material = materials[0];
+ 
+                    var threeMesh = gl3d.createThreeMesh(mesh, geometry, material);
+                    threeMesh.name = mesh.name;
+ 
+                    threeMesh.position.x = mesh.position.x;
+                    threeMesh.position.y = mesh.position.y;
+                    threeMesh.position.z = mesh.position.z;
+ 
+                    threeMesh.rotation.x = mesh.rotation.x;
+                    threeMesh.rotation.y = mesh.rotation.y;
+                    threeMesh.rotation.z = mesh.rotation.z;
+ 
+                    threeMesh.scale.x = mesh.scale.x;
+                    threeMesh.scale.y = mesh.scale.y;
+                    threeMesh.scale.z = mesh.scale.z;
+ 
+                    threeMesh.quaternion.x = mesh.quaternion.x;
+                    threeMesh.quaternion.y = mesh.quaternion.y;
+                    threeMesh.quaternion.z = mesh.quaternion.z;
+                    threeMesh.quaternion.w = mesh.quaternion.w;
+ 
+                    return threeMesh;
+                };
+            }(this, mesh, geometry)
+        ).catch(function(error){
+            console.log(error);
+        });
+ 
+        meshQ.push(result);
+    }
+ 
+    this.Q.all(meshQ).then(function(threeMeshes){
+        console.log("all meshes have loaded");
+        if (typeof onLoaded != 'undefined') {
+ 
+            var threeLights = [];
+ 
+            for (var sli = 0; sli < gameLibScene.lights.length; sli++) {
+ 
+                var blenderLight = gameLibScene.lights[sli];
+ 
+                var light = null;
+ 
+                if (blenderLight.lightType == 'AmbientLight') {
+                    light = new this.THREE.AmbientLight(blenderLight.color, blenderLight.intensity);
+                }
+ 
+                if (blenderLight.lightType == 'DirectionalLight') {
+                    light = new this.THREE.DirectionalLight(blenderLight.color, blenderLight.intensity);
+                }
+ 
+                if (blenderLight.lightType == 'PointLight') {
+                    light = new this.THREE.PointLight(blenderLight.color, blenderLight.intensity);
+                    light.distance = blenderLight.distance;
+                    light.decay = blenderLight.decay;
+                }
+ 
+                if (blenderLight.lightType == 'SpotLight') {
+                    light = new this.THREE.SpotLight(blenderLight.color, blenderLight.intensity);
+                    light.distance = blenderLight.distance;
+                    light.angle = blenderLight.angle;
+                    light.penumbra = blenderLight.penumbra;
+                    light.decay = blenderLight.decay;
+                }
+ 
+                light.position.x = blenderLight.position.x;
+                light.position.y = blenderLight.position.y;
+                light.position.z = blenderLight.position.z;
+ 
+                light.rotation.x = blenderLight.rotation.x;
+                light.rotation.y = blenderLight.rotation.y;
+                light.rotation.z = blenderLight.rotation.z;
+ 
+                // light.scale.x = blenderLight.scale.x;
+                // light.scale.y = blenderLight.scale.y;
+                // light.scale.z = blenderLight.scale.z;
+ 
+                if (light == null) {
+                    console.warn('Does not support lights of type :' + blenderLight.lightType + ', not imported');
+                } else {
+                    light.name = blenderLight.name;
+                    threeLights.push(light);
+                }
+            }
+ 
+            var threeScene = new this.THREE.Scene();
+ 
+            threeScene.name = gameLibScene.name;
+ 
+            threeScene.position.x = gameLibScene.position.x;
+            threeScene.position.y = gameLibScene.position.y;
+            threeScene.position.z = gameLibScene.position.z;
+ 
+            threeScene.rotation.x = gameLibScene.rotation.x;
+            threeScene.rotation.y = gameLibScene.rotation.y;
+            threeScene.rotation.z = gameLibScene.rotation.z;
+ 
+            threeScene.scale.x = gameLibScene.scale.x;
+            threeScene.scale.y = gameLibScene.scale.y;
+            threeScene.scale.z = gameLibScene.scale.z;
+ 
+            threeScene.quaternion.x = gameLibScene.quaternion.x;
+            threeScene.quaternion.y = gameLibScene.quaternion.y;
+            threeScene.quaternion.z = gameLibScene.quaternion.z;
+            threeScene.quaternion.w = gameLibScene.quaternion.w;
+ 
+            for (var m = 0; m < threeMeshes.length; m++) {
+                threeScene.add(threeMeshes[m]);
+            }
+ 
+            for (var l = 0; l < threeLights.length; l++) {
+                threeScene.add(threeLights[l]);
+            }
+ 
+            onLoaded(
+                gameLibScene,
+                {
+                    scene: threeScene,
+                    lights: threeLights,
+                    meshes: threeMeshes
+                }
+            );
+        }
+    }.bind(this)).catch(function(error){
+        console.log(error);
+    });
+};
+/**
+ * Physics Shape Superset
+ * @constructor
+ */
+GameLib.D3.Physics.Shape = function(
+    shapeObject,     // Physics engine specific
+    shapeType
+) {
+    this.shapeObject = shapeObject;
+    this.shapeType = shapeType;
+    this.scale = new GameLib.D3.Vector3(1, 1, 1);
+};
+ 
+GameLib.D3.Physics.SHAPE_TYPE_SPHERE        = 1;
+GameLib.D3.Physics.SHAPE_TYPE_BOX           = 2;
+GameLib.D3.Physics.SHAPE_TYPE_TRIMESH       = 3;
+GameLib.D3.Physics.SHAPE_TYPE_CYLINDER      = 4;
+ 
+ 
+GameLib.D3.Physics.Shape.prototype.Update = function() {
+    if(this.physics.engineType === GameLib.D3.Physics.TYPE_CANNON) {
+        if(this.shapeType === GameLib.D3.Physics.SHAPE_TYPE_TRIMESH) {
+            this.shapeObject.setScale(
+                new this.physics.CANNON.Vec3(
+                    this.scale.x,
+                    this.scale.y,
+                    this.scale.z
+                )
+            );
+            this.shapeObject.updateAABB();
+            this.shapeObject.updateNormals();
+            this.shapeObject.updateEdges();
+            this.shapeObject.updateBoundingSphereRadius();
+            this.shapeObject.updateTree();
+        }
+    }
+};
+ 
+/**
+ * Skeleton Superset
+ * @param id
+ * @param bones GameLib.D3.Bone
+ * @param boneInverses
+ * @param useVertexTexture
+ * @param boneTextureWidth
+ * @param boneTextureHeight
+ * @param boneMatrices
+ * @param boneTexture
+ * @constructor
+ */
+GameLib.D3.Skeleton = function(
+    id,
+    bones,
+    boneInverses,
+    useVertexTexture,
+    boneTextureWidth,
+    boneTextureHeight,
+    boneMatrices,
+    boneTexture
+) {
+    this.id = id;
+ 
+    this.bones = bones;
+ 
+    /**
+     * An array of Matrix4s that represent the inverse of the matrixWorld of the individual bones.
+     * @type GameLib.D3.Matrix4[]
+     */
+    if (typeof boneInverses == 'undefined') {
+        boneInverses = [];
+    }
+    this.boneInverses = boneInverses;
+ 
+    /**
+     * Use a vertex texture in the shader - allows for more than 4 bones per vertex, not supported by all devices
+     * @type {boolean}
+     */
+    if (typeof useVertexTexture == 'undefined') {
+        useVertexTexture = false;
+    }
+    this.useVertexTexture = useVertexTexture;
+ 
+    if (this.useVertexTexture == true) {
+        console.warn('support for vertex texture bones is not supported yet - something could break somewhere');
+    }
+ 
+    if (typeof boneTextureWidth == 'undefined') {
+        boneTextureWidth = 0;
+    }
+    this.boneTextureWidth = boneTextureWidth;
+ 
+    if (typeof boneTextureHeight == 'undefined') {
+        boneTextureHeight = 0;
+    }
+    this.boneTextureHeight = boneTextureHeight;
+ 
+    if (typeof boneMatrices == 'undefined') {
+        boneMatrices = [];
+    }
+    this.boneMatrices = boneMatrices;
+ 
+    if (typeof boneTexture == 'undefined') {
+        boneTexture = [];
+    }
+    this.boneTexture = boneTexture;
+};
+ 
+ 
+GameLib.D3.SkyBox = function (
+ 
+) {
+    this.id = null;
+    this.texturesFolder = null;
+};
+ 
+GameLib.D3.SkyBox.prototype.Load = function (
+    texturesFolder
+) {
+    this.texturesFolder = texturesFolder;
+    this.textures = [];
+    this.materials = [];
+    this.mesh = {};
+    this.scene = new THREE.Scene();
+    this.textureCube = null;
+ 
+    var textureLoader = new THREE.TextureLoader();
+ 
+    // this textures are used to display the skybox
+    this.textures.push(textureLoader.load(this.texturesFolder + "px.png"));
+    this.textures.push(textureLoader.load(this.texturesFolder + "nx.png"));
+    this.textures.push(textureLoader.load(this.texturesFolder + "py.png"));
+    this.textures.push(textureLoader.load(this.texturesFolder + "ny.png"));
+    this.textures.push(textureLoader.load(this.texturesFolder + "pz.png"));
+    this.textures.push(textureLoader.load(this.texturesFolder + "nz.png"));
+ 
+    // assign textures to each cube face
+    for (var i = 0; i < 6; i ++) {
+        this.materials.push(new THREE.MeshBasicMaterial({ map: this.textures[i] }));
+    }
+ 
+    // create cube geometry
+    this.mesh = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), new THREE.MeshFaceMaterial(this.materials));
+    this.mesh.applyMatrix(new THREE.Matrix4().makeScale(1, 1, -1));
+    this.scene.add(this.mesh);
+ 
+    // Load env textureCube
+    // this is used for reflections on meshes
+    // mesh.material.envMap = this.textureCube;
+    this.textureCube = new THREE.CubeTextureLoader().load([
+        this.texturesFolder + "px.png", this.texturesFolder + "nx.png",
+        this.texturesFolder + "py.png", this.texturesFolder + "ny.png",
+        this.texturesFolder + "pz.png", this.texturesFolder + "nz.png"
+    ]);
+};
+ 
+GameLib.D3.SkyBox.prototype.Render = function (
+    threeRenderer,
+    threeCamera
+) {
+    var cameraPosition = new THREE.Vector3(threeCamera.position.x, threeCamera.position.y, threeCamera.position.z);
+ 
+    threeCamera.position.set(0, 0, 0);
+ 
+    var gl = threeRenderer.context;
+ 
+    gl.disable(gl.DEPTH_TEST);
+ 
+    threeRenderer.render(this.scene, threeCamera);
+ 
+    gl.enable(gl.DEPTH_TEST);
+ 
+    threeCamera.position.copy(cameraPosition);
+};
+ 
+/**
+ * Physics Solver Superset
+ * @param id
+ * @param name
+ * @param solverType
+ * @param iterations
+ * @param tolerance
+ * @constructor
+ */
+GameLib.D3.Physics.Solver = function(
+    id,
+    name,
+    solverType,
+    iterations,
+    tolerance
+) {
+    this.id = id;
+    if (typeof name == 'undefined') {
+        if (solverType == GameLib.D3.Physics.SPLIT_SOLVER) {
+            name = 'split solver';
+        } else if (solverType == GameLib.D3.Physics.GS_SOLVER) {
+            name = 'gs solver';
+        } else {
+            name = 'unknown solver';
+        }
+    }
+    this.name = name;
+    this.solverType = solverType;
+    this.iterations = iterations;
+    this.tolerance = tolerance;
+};
+ 
+/**
+ * Solver Types
+ * @type {number}
+ */
+GameLib.D3.Physics.SPLIT_SOLVER = 0x1;
+GameLib.D3.Physics.GS_SOLVER = 0x2;
+ 
+/**
+ * Texture Superset
+ * @param id
+ * @param name
+ * @param image
+ * @param wrapS
+ * @param wrapT
+ * @param repeat
+ * @param data
+ * @param format
+ * @param mapping
+ * @param magFilter
+ * @param minFilter
+ * @param textureType
+ * @param anisotropy
+ * @param offset
+ * @param generateMipmaps
+ * @param flipY
+ * @param mipmaps
+ * @param unpackAlignment
+ * @param premultiplyAlpha
+ * @param encoding
+ * @constructor
+ */
+GameLib.D3.Texture = function(
+    id,
+    name,
+    image,
+    wrapS,
+    wrapT,
+    repeat,
+    data,
+    format,
+    mapping,
+    magFilter,
+    minFilter,
+    textureType,
+    anisotropy,
+    offset,
+    generateMipmaps,
+    flipY,
+    mipmaps,
+    unpackAlignment,
+    premultiplyAlpha,
+    encoding
+) {
+    this.id = id;
+    this.name = name;
+    this.image = image;
+ 
+    if (typeof wrapS == 'undefined') {
+        wrapS = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING;
+    }
+    this.wrapS = wrapS;
+ 
+    if (typeof wrapT == 'undefined') {
+        wrapT = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING;
+    }
+    this.wrapT = wrapT;
+ 
+    if (typeof repeat == 'undefined') {
+        repeat = new GameLib.D3.Vector2(1, 1);
+    }
+    this.repeat = repeat;
+ 
+    if (typeof data == 'undefined') {
+        data = null;
+    }
+    this.data = data;
+ 
+    if (typeof format == 'undefined') {
+        format = GameLib.D3.Texture.TYPE_RGBA_FORMAT;
+    }
+    this.format = format;
+ 
+    if (typeof mapping == 'undefined') {
+        mapping = GameLib.D3.Texture.TYPE_UV_MAPPING;
+    }
+    this.mapping = mapping;
+ 
+    if (typeof magFilter == 'undefined') {
+        magFilter = GameLib.D3.Texture.TYPE_LINEAR_FILTER;
+    }
+    this.magFilter = magFilter;
+ 
+    if (typeof minFilter == 'undefined') {
+        minFilter = GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER;
+    }
+    this.minFilter = minFilter;
+ 
+    if (typeof textureType == 'undefined') {
+        textureType = GameLib.D3.Texture.TYPE_UNSIGNED_BYTE;
+    }
+    this.textureType = textureType;
+ 
+    if (typeof anisotropy == 'undefined') {
+        anisotropy = 1;
+    }
+    this.anisotropy = anisotropy;
+ 
+    if (typeof offset == 'undefined') {
+        offset = new GameLib.D3.Vector2(0, 0);
+    }
+    this.offset = offset;
+ 
+    if (typeof generateMipmaps == 'undefined') {
+        generateMipmaps = true;
+    }
+    this.generateMipmaps = generateMipmaps;
+ 
+    if (typeof flipY == 'undefined') {
+        flipY = true;
+    }
+    this.flipY = flipY;
+ 
+    if (typeof mipmaps == 'undefined') {
+        mipmaps = [];
+    }
+    this.mipmaps = mipmaps;
+ 
+    if (typeof unpackAlignment == 'undefined') {
+        unpackAlignment = 4;
+    }
+    this.unpackAlignment = unpackAlignment;
+ 
+    if (typeof premultiplyAlpha == 'undefined') {
+        premultiplyAlpha = false;
+    }
+    this.premultiplyAlpha = premultiplyAlpha;
+ 
+    if (typeof encoding == 'undefined') {
+        encoding = GameLib.D3.Texture.TYPE_LINEAR_ENCODING;
+    }
+    this.encoding = encoding;
+};
+ 
+/**
+ * Texture Formats
+ * @type {number}
+ */
+GameLib.D3.Texture.TYPE_ALPHA_FORMAT = 1019;
+GameLib.D3.Texture.TYPE_RGB_FORMAT = 1020;
+GameLib.D3.Texture.TYPE_RGBA_FORMAT = 1021;
+GameLib.D3.Texture.TYPE_LUMINANCE_FORMAT = 1022;
+GameLib.D3.Texture.TYPE_LUMINANCE_ALPHA_FORMAT = 1023;
+GameLib.D3.Texture.TYPE_DEPTH_FORMAT = 1026;
+ 
+/**
+ * Mapping modes
+ * @type {number}
+ */
+GameLib.D3.Texture.TYPE_UV_MAPPING = 300;
+GameLib.D3.Texture.TYPE_CUBE_REFLECTION_MAPPING = 301;
+GameLib.D3.Texture.TYPE_CUBE_REFRACTION_MAPPING = 302;
+GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFLECTION_MAPPING = 303;
+GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFRACTION_MAPPING = 304;
+GameLib.D3.Texture.TYPE_SPHERICAL_REFLECTION_MAPPING = 305;
+GameLib.D3.Texture.TYPE_CUBE_UV_REFLECTION_MAPPING = 306;
+GameLib.D3.Texture.TYPE_CUBE_UV_REFRACTION_MAPPING = 307;
+ 
+/**
+ * Wrapping Modes
+ * @type {number}
+ */
+GameLib.D3.Texture.TYPE_REPEAT_WRAPPING = 1000;
+GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING = 1001;
+GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING = 1002;
+ 
+/**
+ * Mipmap Filters
+ * @type {number}
+ */
+GameLib.D3.Texture.TYPE_NEAREST_FILTER = 1003;
+GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER = 1004;
+GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER = 1005;
+GameLib.D3.Texture.TYPE_LINEAR_FILTER = 1006;
+GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER = 1007;
+GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER = 1008;
+ 
+/**
+ * Texture Data Types
+ * @type {number}
+ */
+GameLib.D3.Texture.TYPE_UNSIGNED_BYTE = 1009;
+GameLib.D3.Texture.TYPE_BYTE = 1010;
+GameLib.D3.Texture.TYPE_SHORT = 1011;
+GameLib.D3.Texture.TYPE_UNSIGNED_SHORT = 1012;
+GameLib.D3.Texture.TYPE_INT = 1013;
+GameLib.D3.Texture.TYPE_UNSIGNED_INT = 1014;
+GameLib.D3.Texture.TYPE_FLOAT = 1015;
+GameLib.D3.Texture.TYPE_HALF_FLOAT = 1025;
+ 
+/**
+ * Encoding Modes
+ * @type {number}
+ */
+GameLib.D3.Texture.TYPE_LINEAR_ENCODING = 3000; // NO ENCODING AT ALL.
+GameLib.D3.Texture.TYPE_SRGB_ENCODING = 3001;
+GameLib.D3.Texture.TYPE_GAMMA_ENCODING = 3007; // USES GAMMA_FACTOR, FOR BACKWARDS COMPATIBILITY WITH WEBGLRENDERER.GAMMAINPUT/GAMMAOUTPUT
+GameLib.D3.Texture.TYPE_RGBE_ENCODING = 3002; // AKA RADIANCE.
+GameLib.D3.Texture.TYPE_LOG_LUV_ENCODING = 3003;
+GameLib.D3.Texture.TYPE_RGBM7_ENCODING = 3004;
+GameLib.D3.Texture.TYPE_RGBM16_ENCODING = 3005;
+GameLib.D3.Texture.TYPE_RGBD_ENCODING = 3006; // MAXRANGE IS 256.
+ 
+ 
+ 
+/**
+ * Defers loading of an image and resolves once image is loaded
+ * @param gameLibTexture
+ * @param threeMaterial
+ * @param threeMaterialMapType
+ * @returns {Promise}
+ */
+GameLib.D3.prototype.loadMap = function(gameLibTexture, threeMaterial, threeMaterialMapType) {
+ 
+    var q = this.Q.defer();
+ 
+    var imagePath = null;
+ 
+    if (gameLibTexture && gameLibTexture.image && gameLibTexture.image.filename) {
+        /**
+         * Else, load from upload source
+         */
+        imagePath = this.editorUrl + '/uploads' + this.path + '/' + gameLibTexture.image.filename;
+    }
+ 
+    if (imagePath) {
+ 
+        this.textureLoader.crossOrigin = '';
+ 
+        this.textureLoader.load(
+            imagePath,
+            function(texture) {
+                /**
+                 * onLoad
+                 */
+                threeMaterial[threeMaterialMapType] = texture;
+                threeMaterial[threeMaterialMapType].name = gameLibTexture.name;
+                threeMaterial[threeMaterialMapType].anisotropy = gameLibTexture.anisotropy;
+                threeMaterial[threeMaterialMapType].encoding = gameLibTexture.encoding;
+                threeMaterial[threeMaterialMapType].flipY = gameLibTexture.flipY;
+                /**
+                 * We don't restore the format since this changing from OS to OS and breaks the implementation sometimes
+                 */
+                threeMaterial[threeMaterialMapType].generateMipmaps = gameLibTexture.generateMipmaps;
+                threeMaterial[threeMaterialMapType].magFilter = gameLibTexture.magFilter;
+                threeMaterial[threeMaterialMapType].minFilter = gameLibTexture.minFilter;
+                threeMaterial[threeMaterialMapType].mapping = gameLibTexture.mapping;
+                threeMaterial[threeMaterialMapType].mipmaps = gameLibTexture.mipmaps;
+                threeMaterial[threeMaterialMapType].offset = new this.THREE.Vector2(
+                    gameLibTexture.offset.x,
+                    gameLibTexture.offset.y
+                );
+                threeMaterial[threeMaterialMapType].premultiplyAlpha = gameLibTexture.premultiplyAlpha;
+                threeMaterial[threeMaterialMapType].textureType = gameLibTexture.textureType;
+                threeMaterial[threeMaterialMapType].wrapS = gameLibTexture.wrapS;
+                threeMaterial[threeMaterialMapType].wrapT = gameLibTexture.wrapT;
+                threeMaterial[threeMaterialMapType].unpackAlignment = gameLibTexture.unpackAlignment;
+                threeMaterial.needsUpdate = true;
+                q.resolve(true);
+            },
+            function(xhr) {
+                /**
+                 * onProgress
+                 */
+                if (this.editor) {
+                    this.editor.setServerStatus(Math.round(xhr.loaded / xhr.total * 100) + '% complete', 'success');
+                }
+            },
+            function(error) {
+                /**
+                 * onError
+                 */
+                console.log("an error occurred while trying to load the image : " + imagePath);
+                q.resolve(null);
+            }
+        );
+ 
+    } else {
+        q.resolve(null);
+    }
+ 
+    return q.promise;
+};
+ 
+ 
+/**
+ * Returns an array of image loading Promises
+ * @param blenderMaterial
+ * @param blenderMaps
+ * @param threeMaterial
+ * @returns Q[]
+ */
+GameLib.D3.prototype.loadMaps = function(blenderMaterial, blenderMaps, threeMaterial) {
+ 
+    var textureMaps = [];
+ 
+    for (var ti = 0; ti < blenderMaps.length; ti++) {
+ 
+        var map = blenderMaps[ti];
+ 
+        if (blenderMaterial.maps.hasOwnProperty(map)) {
+ 
+            var blenderTexture = blenderMaterial.maps[map];
+ 
+            if (
+                blenderTexture &&
+                blenderTexture.image &&
+                blenderTexture.image.filename
+            ) {
+ 
+                var threeMap = null;
+ 
+                if (map == 'alpha') {
+                    threeMap = 'alhpaMap';
+                }
+ 
+                if (map == 'ao') {
+                    threeMap = 'aoMap';
+                }
+ 
+                if (map == 'bump') {
+                    threeMap = 'bumpMap';
+                }
+ 
+                if (map == 'displacement') {
+                    threeMap = 'displacementMap';
+                }
+ 
+                if (map == 'emissive') {
+                    threeMap = 'emissiveMap';
+                }
+ 
+                if (map == 'environment') {
+                    threeMap = 'envMap';
+                }
+ 
+                if (map == 'light') {
+                    threeMap = 'lightMap';
+                }
+ 
+                if (map == 'specular') {
+                    threeMap = 'specularMap';
+                }
+ 
+                if (map == 'diffuse') {
+                    threeMap = 'map';
+                }
+ 
+                if (map == 'roughness') {
+                    threeMap = 'roughnessMap';
+                }
+ 
+                if (map == 'metalness') {
+                    threeMap = 'metalnessMap';
+                }
+ 
+                if (threeMap == null) {
+                    console.warn("unsupported map type : " + map);
+                }
+ 
+                textureMaps.push(this.loadMap(blenderMaterial.maps[map], threeMaterial, threeMap));
+            }
+        }
+    }
+ 
+    return textureMaps;
+};
+ 
+/**
+ * TriangleEdge
+ * @param triangle
+ * @param edge
+ * @constructor
+ */
+GameLib.D3.TriangleEdge = function(
+    triangle,
+    edge
+) {
+    this.triangle = triangle;
+    this.edge = edge;
+};
+/**
+ * TriangleFace
+ * @param v0
+ * @param v1
+ * @param v2
+ * @param materialIndex
+ * @param v0uv
+ * @param v1uv
+ * @param v2uv
+ * @param color
+ * @param vertexColors
+ * @param vertexNormals
+ * @param normal
+ * @constructor
+ */
+GameLib.D3.TriangleFace = function(
+    v0,
+    v1,
+    v2,
+    materialIndex,
+    v0uv,
+    v1uv,
+    v2uv,
+    color,
+    vertexColors,
+    vertexNormals,
+    normal
+) {
+    this.v0 = v0;
+    this.v1 = v1;
+    this.v2 = v2;
+    this.materialIndex = materialIndex;
+    this.v0uv = v0uv;
+    this.v1uv = v1uv;
+    this.v2uv = v2uv;
+    if (!color) {
+        color = new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff);
+    }
+    this.color = color;
+ 
+    if (!vertexColors) {
+        vertexColors = [
+            new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff),
+            new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff),
+            new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff)
+        ];
+    }
+    this.vertexColors = vertexColors;
+ 
+    if (!vertexNormals) {
+        vertexNormals = [
+            new GameLib.D3.Vector3(),
+            new GameLib.D3.Vector3(),
+            new GameLib.D3.Vector3()
+        ]
+    }
+    this.vertexNormals = vertexNormals;
+ 
+    if (!normal) {
+        normal = new GameLib.D3.Vector3(0);
+    }
+ 
+    this.normal = normal;
+};
+ 
+/**
+ * Clone a TriangleFace
+ * @returns {GameLib.D3.TriangleFace}
+ */
+GameLib.D3.TriangleFace.prototype.clone = function(){
+    return new GameLib.D3.TriangleFace(
+        this.v0,
+        this.v1,
+        this.v2,
+        this.materialIndex,
+        this.v0uv.copy(),
+        this.v1uv.copy(),
+        this.v2uv.copy()
+    );
+};
+ 
+/**
+ * Returns true if two triangles are equal (their vertex indices match in some order)
+ * @param triangle
+ * @returns {boolean}
+ */
+GameLib.D3.TriangleFace.prototype.equals = function(triangle) {
+    return !!(
+    (
+        (this.v0 == triangle.v0) &&
+        (this.v1 == triangle.v1) &&
+        (this.v2 == triangle.v2)
+    )
+    ||
+    (
+        (this.v0 == triangle.v0) &&
+        (this.v1 == triangle.v2) &&
+        (this.v2 == triangle.v1)
+    )
+    ||
+    (
+        (this.v0 == triangle.v1) &&
+        (this.v1 == triangle.v0) &&
+        (this.v2 == triangle.v2)
+    )
+    ||
+    (
+        (this.v0 == triangle.v1) &&
+        (this.v1 == triangle.v2) &&
+        (this.v2 == triangle.v0)
+    )
+    ||
+    (
+        (this.v0 == triangle.v2) &&
+        (this.v1 == triangle.v0) &&
+        (this.v2 == triangle.v1)
+    )
+    ||
+    (
+        (this.v0 == triangle.v2) &&
+        (this.v1 == triangle.v1) &&
+        (this.v2 == triangle.v0)
+    ));
+};
+ 
+ 
+GameLib.D3.Vector2 = function(x, y) {
+ 
+    this.x = 0;
+    this.y = 0;
+ 
+    if (x) {
+        this.x = x;
+    }
+ 
+    if (y) {
+        this.y = y;
+    }
+};
+ 
+GameLib.D3.Vector2.prototype.copy = function() {
+    return new GameLib.D3.Vector2(
+        this.x,
+        this.y
+    );
+};
+ 
+GameLib.D3.Vector2.prototype.equals = function(v) {
+    return !!(((this.x == v.x) &&
+    (this.y == v.y)) ||
+    ((this.y == v.x) &&
+    (this.x == v.y)));
+};
+ 
+GameLib.D3.Vector3 = function(x, y, z) {
+ 
+    this.x = 0;
+    this.y = 0;
+    this.z = 0;
+ 
+    if (x) {
+        this.x = x;
+    }
+ 
+    if (y) {
+        this.y = y;
+    }
+ 
+    if (z) {
+        this.z = z;
+    }
+};
+ 
+GameLib.D3.Vector3.prototype.subtract = function (v) {
+ 
+    if (v instanceof GameLib.D3.Vector3) {
+        this.x -= v.x;
+        this.y -= v.y;
+        this.z -= v.z;
+    }
+ 
+    if (v instanceof GameLib.D3.Vector4) {
+        console.warn("trying to subtract vector of bigger length (4 vs 3))");
+    }
+ 
+    return this;
+};
+ 
+GameLib.D3.Vector3.prototype.cross = function (v) {
+    return new GameLib.D3.Vector3(
+        this.y * v.z - this.z * v.y,
+        this.z * v.x - this.x * v.z,
+        this.x * v.y - this.y * v.x
+    );
+};
+ 
+GameLib.D3.Vector3.prototype.negative = function () {
+    this.x *= -1;
+    this.y *= -1;
+    this.z *= -1;
+    return this;
+};
+ 
+GameLib.D3.Vector3.clockwise = function (u, v, w, viewPoint) {
+ 
+    var normal = GameLib.D3.Vector3.normal(u, v, w);
+ 
+    var uv = u.copy();
+ 
+    var winding = normal.dot(uv.subtract(viewPoint));
+ 
+    return (winding > 0);
+};
+ 
+GameLib.D3.Vector3.normal = function (u, v, w) {
+    var vv = v.copy();
+    var wv = w.copy();
+    return vv.subtract(u).cross(wv.subtract(u));
+};
+ 
+GameLib.D3.Vector3.prototype.lookAt = function (at, up) {
+ 
+    var lookAtMatrix = GameLib.D3.Matrix4.lookAt(this, at, up);
+ 
+    this.multiply(lookAtMatrix);
+};
+ 
+GameLib.D3.Vector3.prototype.translate = function (v) {
+    this.x += v.x;
+    this.y += v.y;
+    this.z += v.z;
+    return this;
+};
+ 
+GameLib.D3.Vector3.prototype.squared = function () {
+    return this.x * this.x + this.y * this.y + this.z * this.z;
+};
+ 
+GameLib.D3.Vector3.prototype.copy = function () {
+    return new GameLib.D3.Vector3(
+        this.x,
+        this.y,
+        this.z
+    );
+};
+ 
+GameLib.D3.Vector3.prototype.multiply = function (s) {
+    if (s instanceof GameLib.D3.Vector3) {
+        this.x *= s.x;
+        this.y *= s.y;
+        this.z *= s.z;
+    } else if (s instanceof GameLib.D3.Matrix4) {
+        var x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z;
+        var y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z;
+        var z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z;
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    } else {
+        console.log("functionality not implemented - please do this");
+        throw new Error("not implemented");
+    }
+    return this;
+};
+ 
+ 
+GameLib.D3.Vector3.prototype.dot = function (v) {
+    return (this.x * v.x) + (this.y * v.y) + (this.z * v.z);
+};
+ 
+GameLib.D3.Vector3.prototype.normalize = function () {
+ 
+    var EPSILON = 0.000001;
+ 
+    var v2 = this.squared();
+ 
+    if (v2 < EPSILON) {
+        return this; //do nothing for zero vector
+    }
+ 
+    var invLength = 1 / Math.sqrt(v2);
+ 
+    this.x *= invLength;
+    this.y *= invLength;
+    this.z *= invLength;
+ 
+    return this;
+};
+ 
+GameLib.D3.Vector4 = function(x, y, z, w) {
+ 
+    this.x = 0;
+    this.y = 0;
+    this.z = 0;
+    this.w = 0;
+ 
+    Iif (x) {
+        this.x = x;
+    }
+ 
+    Iif (y) {
+        this.y = y;
+    }
+ 
+    Iif (z) {
+        this.z = z;
+    }
+ 
+    Iif (w) {
+        this.w = w;
+    }
+};
+ 
+GameLib.D3.Vector4.prototype.translate = function (v) {
+    this.x += v.x;
+    this.y += v.y;
+    this.z += v.z;
+    return this;
+};
+ 
+GameLib.D3.Vector4.prototype.copy = function () {
+    return new GameLib.D3.Vector4(
+        this.x,
+        this.y,
+        this.z,
+        this.w
+    );
+};
+ 
+GameLib.D3.Vector4.prototype.multiply = function (s) {
+    if (s instanceof GameLib.D3.Vector3) {
+        this.x *= s.x;
+        this.y *= s.y;
+        this.z *= s.z;
+    } else if (s instanceof GameLib.D3.Matrix4) {
+        var x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z + s.rows[0].w * this.w;
+        var y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z + s.rows[1].w * this.w;
+        var z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z + s.rows[2].w * this.w;
+        var w = s.rows[3].x * this.x + s.rows[3].y * this.y + s.rows[3].z * this.z + s.rows[3].w * this.w;
+        this.x = x;
+        this.y = y;
+        this.z = z;
+        this.w = w;
+    } else {
+        console.log("functionality not implemented - please do this");
+        throw new Error("not implemented");
+    }
+};
+ 
+ 
+GameLib.D3.Vector4.prototype.normalize = function () {
+ 
+    // note - leave w untouched
+    var EPSILON = 0.000001;
+ 
+    var v2 = this.x * this.x + this.y * this.y + this.z * this.z;
+ 
+    if (v2 < EPSILON) {
+        return this; //do nothing for zero vector
+    }
+ 
+    var invLength = 1 / Math.sqrt(v2);
+ 
+    this.x *= invLength;
+    this.y *= invLength;
+    this.z *= invLength;
+ 
+    return this;
+};
+ 
+GameLib.D3.Vector4.prototype.subtract = function (v) {
+ 
+    if (v instanceof GameLib.D3.Vector3) {
+        this.x -= v.x;
+        this.y -= v.y;
+        this.z -= v.z;
+    }
+ 
+    if (v instanceof GameLib.D3.Vector4) {
+        this.x -= v.x;
+        this.y -= v.y;
+        this.z -= v.z;
+        this.w -= v.w;
+    }
+ 
+    return this;
+};
+ 
+GameLib.D3.Vector4.Points = function () {
+    this.vectors = [];
+};
+ 
+GameLib.D3.Vector4.Points.prototype.add = function (vector) {
+ 
+    if (vector instanceof GameLib.D3.Vector3) {
+        vector = new GameLib.D3.Vector4(
+            vector.x,
+            vector.y,
+            vector.z,
+            1
+        )
+    }
+ 
+    if (!vector instanceof GameLib.D3.Vector4) {
+        console.warn("Vector needs to be of type Vector4");
+        throw new Error("Vector needs to be of type Vector4");
+    }
+ 
+    this.vectors.push(vector);
+ 
+    return this;
+};
+ 
+GameLib.D3.Vector4.Points.prototype.copy = function () {
+ 
+    var vectors = [];
+ 
+    for (var i = 0; i < this.vectors.length; i++) {
+        vectors.push(this.vectors[i].copy());
+    }
+ 
+    return vectors;
+};
+ 
+GameLib.D3.Vector4.Points.prototype.maximizeXDistance = function (grain) {
+ 
+//    console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2));
+ 
+    var multiplier = 0;
+ 
+    var rotationMatrixY = new GameLib.D3.Matrix4().rotationMatrixY(grain);
+ 
+    var totalRadians = 0;
+ 
+    var backupVectors = this.copy();
+ 
+    var maxXDistance = 0;
+ 
+    for (var i = 0; i < Math.PI * 2; i += grain) {
+ 
+        multiplier++;
+ 
+        for (var j = 0; j < this.vectors.length; j++) {
+            this.vectors[j] = rotationMatrixY.multiply(this.vectors[j]);
+        }
+ 
+        var distances = this.distances();
+ 
+        if (distances.x > maxXDistance) {
+ 
+            maxXDistance = distances.x;
+            totalRadians = multiplier * grain;
+        }
+    }
+ 
+    this.vectors = backupVectors;
+ 
+//    console.log("distance: " + maxXDistance + " radians : " + totalRadians);
+ 
+    var maxRotationMatrix = new GameLib.D3.Matrix4().rotationMatrixY(totalRadians);
+ 
+    for (var k = 0; k < this.vectors.length; k++) {
+        this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]);
+    }
+ 
+//    console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2));
+ 
+};
+ 
+GameLib.D3.Vector4.Points.prototype.maximizeYDistance = function (grain) {
+ 
+//    console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2));
+ 
+    var multiplier = 0;
+ 
+    var rotationMatrixX = new GameLib.D3.Matrix4().rotationMatrixX(grain);
+ 
+    var totalRadians = 0;
+ 
+    var backupVectors = this.copy();
+ 
+    var maxYDistance = 0;
+ 
+    for (var i = 0; i < Math.PI * 2; i += grain) {
+ 
+        multiplier++;
+ 
+        for (var j = 0; j < this.vectors.length; j++) {
+            this.vectors[j] = rotationMatrixX.multiply(this.vectors[j]);
+        }
+ 
+        var distances = this.distances();
+ 
+        if (distances.y > maxYDistance) {
+            maxYDistance = distances.y;
+            totalRadians = multiplier * grain;
+        }
+    }
+ 
+    this.vectors = backupVectors;
+ 
+//    console.log("distance: " + maxYDistance + " radians : " + totalRadians);
+ 
+    var maxRotationMatrix = new GameLib.D3.Matrix4().rotationMatrixX(totalRadians);
+ 
+    for (var k = 0; k < this.vectors.length; k++) {
+        this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]);
+    }
+ 
+//    console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2));
+ 
+};
+ 
+ 
+GameLib.D3.Vector4.Points.prototype.lookAt = function (at, up) {
+ 
+    var polyCenter = this.average();
+ 
+    console.log("poly center : " + JSON.stringify(polyCenter));
+ 
+    var lookAtMatrix = new GameLib.D3.Matrix4().lookAt(polyCenter, at, up);
+ 
+    lookAtMatrix.rows[0] = new GameLib.D3.Vector4(1, 0, 0, 0);
+    lookAtMatrix.rows[1] = new GameLib.D3.Vector4(0, 0, 1, 0);
+    lookAtMatrix.rows[2] = new GameLib.D3.Vector4(0, 1, 0, 0);
+ 
+    console.log("look at matrix : " + JSON.stringify(lookAtMatrix, null, 2));
+ 
+    for (var i = 0; i < this.vectors.length; i++) {
+        console.log("vector " + i + " (before): " + JSON.stringify(this.vectors[i]));
+        this.vectors[i] = lookAtMatrix.multiply(this.vectors[i]);
+        console.log("vector " + i + " (after) : " + JSON.stringify(this.vectors[i]));
+    }
+};
+ 
+GameLib.D3.Vector4.Points.prototype.distances = function () {
+ 
+    var minX = this.vectors[0].x;
+    var minY = this.vectors[0].y;
+    var minZ = this.vectors[0].z;
+ 
+    var maxX = this.vectors[0].x;
+    var maxY = this.vectors[0].y;
+    var maxZ = this.vectors[0].z;
+ 
+    for (var i = 0; i < this.vectors.length; i++) {
+        if (this.vectors[i].x < minX) {
+            minX = this.vectors[i].x;
+        }
+        if (this.vectors[i].y < minY) {
+            minY = this.vectors[i].y;
+        }
+        if (this.vectors[i].z < minZ) {
+            minZ = this.vectors[i].z;
+        }
+ 
+        if (this.vectors[i].x > maxX) {
+            maxX = this.vectors[i].x;
+        }
+        if (this.vectors[i].y > maxY) {
+            maxY = this.vectors[i].y;
+        }
+        if (this.vectors[i].z > maxZ) {
+            maxZ = this.vectors[i].z;
+        }
+    }
+ 
+    return new GameLib.D3.Vector3(
+        Math.abs(maxX - minX),
+        Math.abs(maxY - minY),
+        Math.abs(maxY - minZ)
+    )
+};
+ 
+GameLib.D3.Vector4.Points.prototype.average = function () {
+    var averageX = 0;
+    var averageY = 0;
+    var averageZ = 0;
+ 
+    for (var i = 0; i < this.vectors.length; i++) {
+        averageX += this.vectors[i].x;
+        averageY += this.vectors[i].y;
+        averageZ += this.vectors[i].z;
+    }
+ 
+    return new GameLib.D3.Vector3(
+        averageX / this.vectors.length,
+        averageY / this.vectors.length,
+        averageZ / this.vectors.length
+    );
+};
+ 
+GameLib.D3.Vector4.Points.prototype.negative = function () {
+ 
+    for (var i = 0; i < this.vectors.length; i++) {
+        this.vectors[i].x *= -1;
+        this.vectors[i].y *= -1;
+        this.vectors[i].z *= -1;
+    }
+ 
+    return this;
+};
+ 
+ 
+GameLib.D3.Vector4.Points.prototype.toOrigin = function () {
+ 
+    var distanceFromOrigin = this.average().negative();
+ 
+    for (var i = 0; i < this.vectors.length; i++) {
+        this.vectors[i].translate(distanceFromOrigin);
+    }
+};
+ 
+/**
+ * The normal gets assigned when the face calculates its normal
+ * @param position
+ * @param boneWeights GameLib.D3.BoneWeight[]
+ * @constructor
+ */
+GameLib.D3.Vertex = function(
+    position,
+    boneWeights
+) {
+    this.position = position;
+    this.boneWeights = boneWeights;
+};
+/**
+ * World SuperSet - contains the custom world instance
+ * @param id
+ * @param name
+ * @param engine
+ * @param gravity
+ * @param broadphase
+ * @param solver
+ * @param rigidBodies
+ * @constructor
+ */
+GameLib.D3.World = function(
+    id,
+    name,
+    engine,
+    gravity,
+    broadphase,
+    solver,
+    rigidBodies
+) {
+ 
+    this.id = id;
+ 
+    this.name = name;
+ 
+    if (typeof gravity == 'undefined') {
+        gravity = new GameLib.D3.Vector3(0, -9.81, 0);
+    }
+    this.gravity = gravity;
+ 
+    if (typeof broadphase == 'undefined') {
+        broadphase = new GameLib.D3.Physics.Broadphase(
+            null,
+            'broadPhaseNaive',
+            GameLib.D3.Physics.BROADPHASE_TYPE_NAIVE
+        );
+    }
+    this.broadphase = broadphase;
+ 
+    if (typeof solver == 'undefined') {
+        solver = new GameLib.D3.Physics.Solver(
+            null,
+            'GSSolver',
+            GameLib.D3.Physics.GS_SOLVER
+        );
+    }
+    this.solver = solver;
+ 
+    if (typeof rigidBodies == 'undefined') {
+        rigidBodies = [];
+    }
+    this.rigidBodies = rigidBodies;
+ 
+    this.engine = null;
+ 
+    this.worldInstance = null;
+ 
+    /**
+     * We only set the physics property if we pass it in the constructor,
+     * because we don't always want the physics object (ex. when we store this world to the API - we also don't then
+     * want to store the custom worlds - we want to generate them after loading from API)
+     */
+    if (engine) {
+        this.engine = engine;
+        this.worldInstance = this.createWorldInstance();
+    }
+};
+ 
+ 
+GameLib.D3.World.prototype.createWorldInstance = function() {
+ 
+    this.engine.isNotCannonThrow();
+ 
+    var customWorld = new this.engine.instance.World();
+ 
+    var cannonBroadphase = null;
+ 
+ 
+    customWorld.broadphase = cannonBroadphase;
+ 
+    var cannonSolver = null;
+ 
+    if (this.solver.solverType == GameLib.D3.Physics.SPLIT_SOLVER) {
+        cannonSolver = new this.engine.instance.SplitSolver();
+    } else if (this.solver.solverType == GameLib.D3.Physics.GS_SOLVER) {
+        cannonSolver = new this.engine.instance.GSSolver();
+        cannonSolver.iterations = this.solver.iterations;
+    }
+ 
+    customWorld.solver = cannonSolver;
+ 
+    customWorld.gravity.x = this.gravity.x;
+    customWorld.gravity.y = this.gravity.y;
+    customWorld.gravity.z = this.gravity.z;
+ 
+    for (var b = 0; b < this.rigidBodies.length; b++) {
+ 
+        var customBody = this.createCustomBody(this.rigidBodies[b]);
+ 
+        //customWorld.AddRigidBody();
+    }
+ 
+    customWorld.name = this.name;
+ 
+    return customWorld;
+};
+ 
+GameLib.D3.World.prototype.AddShape = function(
+    shape, // d3.physics.shape
+    rigidBody,
+    offset, // vec3
+    orientation //quaternion
+) {
+    shape.shape = shape;
+ 
+    /**
+     * TODO:: fix this?
+     */
+    if (this.physics.engineType === GameLib.D3.Physics.TYPE_CANNON) {
+ 
+        var _offset = null;
+        var _orientation = null;
+ 
+        if(offset != null && typeof offset !== 'undefined') {
+            _offset = new this.physics.CANNON.Vec3(offset.x, offset.y, offset.z);
+        }
+ 
+        if(orientation != null && typeof orientation !== 'undefined') {
+            _orientation = new this.physics.CANNON.Quaternion(orientation.x, orientation.y, orientation.z, orientation.w);
+        }
+ 
+        rigidBody.bodyObject.addShape(shape.shapeObject, _offset, _orientation);
+    }
+};
+ 
+GameLib.D3.World.prototype.Wheel = function() {
+ 
+};
+ 
+GameLib.D3.World.prototype.CreateRigidVehicle = function(
+    chassisBody // Physics.RigidBody
+) {
+    var rigidVehicle = new GameLib.D3.Physics.RigidVehicle();
+ 
+    if (this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+        var vehicle = new this.physics.CANNON.RigidVehicle({
+            chassisBody: chassisBody.bodyObject
+        });
+        rigidVehicle.vehicleObject = vehicle;
+        return rigidVehicle;
+    }
+};
+ 
+GameLib.D3.World.prototype.CreateRaycastVehicle = function(
+    chassisBody // Physics.RigidBody
+) {
+    var raycastVehicle = new GameLib.D3.Physics.RaycastVehicle();
+ 
+    if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+        var vehicle = new this.physics.CANNON.RaycastVehicle({
+            chassisBody: chassisBody.bodyObject
+        });
+        raycastVehicle.vehicleObject = vehicle;
+        return raycastVehicle;
+    }
+};
+ 
+GameLib.D3.World.prototype.AddWheelToRigidVehicle = function(
+    vehicle,
+    rigidBody,
+    position,
+    axis,
+    direction
+) {
+    if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+        vehicle.vehicleObject.addWheel({
+            body: rigidBody.bodyObject,
+            position: new this.physics.CANNON.Vec3(position.x, position.y, position.z),
+            axis: new this.physics.CANNON.Vec3(axis.x, axis.y, axis.z),
+            direction: new this.physics.CANNON.Vec3(direction.x, direction.y, direction.z)
+        });
+    }
+};
+ 
+GameLib.D3.World.prototype.AddWheelToRaycastVehicle = function (
+    vehicle, // physics.raycastvehicle
+    options // cannon options
+) {
+    if (this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+        vehicle.vehicleObject.addWheel(options);
+    } else {
+        console.log("function for engine not implemented");
+    }
+};
+ 
+ 
+ 
+GameLib.D3.World.prototype.CreateTriMeshShape = function(
+    vertices,   // flat list of floats
+    indices     // flat list of floats
+) {
+    if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+        return new GameLib.D3.Physics.Shape(new this.physics.CANNON.Trimesh(vertices, indices), GameLib.D3.Physics.SHAPE_TYPE_TRIMESH);
+    }
+};
+ 
+GameLib.D3.World.prototype.CreateSphereShape = function (
+    radius
+) {
+    if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+        return new GameLib.D3.Physics.Shape(new this.physics.CANNON.Sphere(radius), GameLib.D3.Physics.SHAPE_TYPE_SPHERE);
+    }
+};
+ 
+GameLib.D3.World.prototype.CreateBoxShape = function(
+    halfExtensions // vec3
+) {
+    if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+        return new GameLib.D3.Physics.Shape(new this.physics.CANNON.Box(new this.physics.CANNON.Vec3(halfExtensions.x, halfExtensions.y, halfExtensions.z)), GameLib.D3.Physics.SHAPE_TYPE_BOX);
+    }
+};
+ 
+GameLib.D3.World.prototype.CreateCylinderShape = function(
+    radiusTop,
+    radiusBottom,
+    height,
+    numSegments
+) {
+    if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+        return new GameLib.D3.Physics.Shape(new this.physics.CANNON.Cylinder(radiusTop, radiusBottom, height, numSegments), GameLib.D3.Physics.SHAPE_TYPE_CYLINDER);
+    }
+};
+ 
+GameLib.D3.World.prototype.AddRigidBody = function(
+    rigidBody   // Physics.RigidBody
+) {
+    if(this.physics.engineType === GameLib.D3.Physics.TYPE_CANNON) {
+        this.worldObject.addBody(rigidBody.bodyObject);
+    }
+};
+ 
+GameLib.D3.World.prototype.AddVehicle = function(
+    vehicle // note: physics.vehicle
+) {
+    if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+        vehicle.vehicleObject.addToWorld(this.worldObject);
+    }
+};
+ 
+GameLib.D3.World.prototype.Step = function(
+    timeStep
+) {
+    if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+ 
+        // todo: figure out, why this call to internal step is more stable for trimesh collisions.....
+        //this.worldObject.internalStep(timeStep);
+        //return;
+ 
+        var now = performance.now() / 1000;
+ 
+        if(!this.lastCallTime){
+            // last call time not saved, cant guess elapsed time. Take a simple step.
+            this.worldObject.step(timeStep);
+            this.lastCallTime = now;
+            return;
+        }
+ 
+        var timeSinceLastCall = now - this.lastCallTime;
+ 
+        this.worldObject.step(timeStep, timeSinceLastCall);
+ 
+        this.lastCallTime = now;
+    }
+};
+ 
+GameLib.D3.World.prototype.GetIndexedVertices = function(
+    triangleMeshShape
+) {
+ 
+    if(this.engine.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+ 
+        return {
+            vertices : triangleMeshShape.vertices,
+            indices : triangleMeshShape.indices
+        };
+ 
+    } else {
+        // todo: implement this for other physics engines.
+        return null;
+    }
+ 
+};
+ 
+GameLib.D3.World.prototype.GenerateWireframeViewMesh = function(
+    triangleMeshShape,
+    normalLength,
+    scale,
+    opacity,
+    wireframeColor
+) {
+    var geometryTHREE = new THREE.Geometry();
+    var wireframeTHREEMesh = new THREE.Mesh
+    (
+        geometryTHREE,
+        new THREE.MeshBasicMaterial({
+            color: wireframeColor ? wireframeColor : 0xfefefe,
+            wireframe: true,
+            opacity: opacity ? opacity : 0.5
+        })
+    );
+ 
+    var data = this.GetIndexedVertices(triangleMeshShape);
+ 
+    for(var i = 0, l = data.vertices.length / 3; i < l; i++) {
+        geometryTHREE.vertices.push(new THREE.Vector3(data.vertices[i * 3], data.vertices[i * 3 + 1], data.vertices[i * 3 + 2]));
+    }
+ 
+    for(var i = 0, l = data.indices.length / 3; i < l; i++) {
+        var i0 = data.indices[i * 3];
+        var i1 = data.indices[i * 3 + 1];
+        var i2 = data.indices[i * 3 + 2];
+ 
+        geometryTHREE.faces.push(new THREE.Face3(i0, i1, i2));
+ 
+        // Create debug view for normals
+ 
+        // Center point on the mesh itself
+        var centroid = new THREE.Vector3()
+            .add(geometryTHREE.vertices[i0])
+            .add(geometryTHREE.vertices[i1])
+            .add(geometryTHREE.vertices[i2])
+            .divideScalar(3);
+ 
+        var normal = null;
+        if(this.engine.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+            var normal = new this.physics.CANNON.Vec3();
+            triangleMeshShape.getNormal(i, normal);
+        } else {
+            // todo: calculate the normal for v0, v1 & v2 here.
+        }
+ 
+        var arrow = new THREE.ArrowHelper(new THREE.Vector3(normal.x, normal.y, normal.z), centroid, normalLength, new THREE.Color(normal.x, normal.y, normal.z));
+        wireframeTHREEMesh.add( arrow );
+    }
+ 
+    wireframeTHREEMesh.scale.x = scale.x;
+    wireframeTHREEMesh.scale.y = scale.y;
+    wireframeTHREEMesh.scale.z = scale.z;
+ 
+    return wireframeTHREEMesh;
+};
+ 
+GameLib.D3.World.prototype.GenerateTriangleCollisionMesh = function(
+    threeMesh,
+    mass,                       // default = 0
+    friction,                   // default = 10
+    createCollisionSubMeshes,   // boolean. default = false
+    facesPerSubsection,        // int. default = 0
+    subsectionsToMerge         // int. default = 0
+) {
+    var processedFaces = 0;
+    var facesPerSubSection = facesPerSubsection || 0;
+    var subMeshesToMerge = subsectionsToMerge || 0;
+    var totalAmtFaces = threeMesh.geometry.faces.length;
+    var facesToProcess = createCollisionSubMeshes ? (subMeshesToMerge * facesPerSubSection) : totalAmtFaces;
+ 
+    var pairs = []; // output
+ 
+    var vertices = [];
+    var indicies = [];
+ 
+    for(var i = 0; i <= totalAmtFaces; i++) {
+        if(processedFaces == facesToProcess || i == totalAmtFaces) {
+ 
+            var body = null;
+ 
+            if(this.engine.engineType == GameLib.D3.Physics.TYPE_CANNON) {
+ 
+                var meshShape = new this.physics.CANNON.Trimesh(vertices, indicies);
+                meshShape.setScale(new this.physics.CANNON.Vec3(threeMesh.scale.x, threeMesh.scale.y, threeMesh.scale.z));
+                meshShape.updateAABB();
+                meshShape.updateNormals();
+                meshShape.updateEdges();
+                meshShape.updateBoundingSphereRadius();
+                meshShape.updateTree();
+ 
+                body = new this.physics.CANNON.Body({ mass: mass ? mass : 0, friction: friction ? friction : 10 });
+                body.addShape(meshShape);
+ 
+            } else if (this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_AMMO) {
+ 
+            } else if (this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_GOBLIN) {
+ 
+            }
+ 
+            pairs.push({
+                threeObject : createCollisionSubMeshes ? null : threeMesh,
+                physicsObject : body
+            });
+ 
+            vertices = [];
+            indicies = [];
+            processedFaces = 0;
+ 
+            if(i == totalAmtFaces) {
+                return pairs;
+            }
+        }
+ 
+        var face = threeMesh.geometry.faces[i];
+        indicies.push(indicies.length);
+        indicies.push(indicies.length);
+        indicies.push(indicies.length);
+ 
+        var v0 = threeMesh.geometry.vertices[face.a];
+        var v1 = threeMesh.geometry.vertices[face.b];
+        var v2 = threeMesh.geometry.vertices[face.c];
+ 
+        vertices.push(v0.x, v0.y, v0.z);
+        vertices.push(v1.x, v1.y, v1.z);
+        vertices.push(v2.x, v2.y, v2.z);
+ 
+        processedFaces++;
+    }
+};
+ 
+Eif (typeof module !== 'undefined') {
+    module.exports = GameLib;
+}
+
+
+ + + + + + + diff --git a/build/coverage/lcov-report/build/index.html b/build/coverage/lcov-report/build/index.html new file mode 100644 index 0000000..6395199 --- /dev/null +++ b/build/coverage/lcov-report/build/index.html @@ -0,0 +1,93 @@ + + + + Code coverage report for build/ + + + + + + + +
+
+

+ all files build/ +

+
+
+ 16.22% + Statements + 283/1745 +
+
+ 2.87% + Branches + 20/697 +
+
+ 2.05% + Functions + 3/146 +
+
+ 16.22% + Lines + 283/1745 +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
game-lib.js
16.22%283/17452.87%20/6972.05%3/14616.22%283/1745
+
+
+ + + + + + + diff --git a/build/coverage/lcov-report/index.html b/build/coverage/lcov-report/index.html new file mode 100644 index 0000000..c262352 --- /dev/null +++ b/build/coverage/lcov-report/index.html @@ -0,0 +1,93 @@ + + + + Code coverage report for All files + + + + + + + +
+
+

+ / +

+
+
+ 16.22% + Statements + 283/1745 +
+
+ 2.87% + Branches + 20/697 +
+
+ 2.05% + Functions + 3/146 +
+
+ 16.22% + Lines + 283/1745 +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
build/
16.22%283/17452.87%20/6972.05%3/14616.22%283/1745
+
+
+ + + + + + + diff --git a/build/coverage/lcov-report/prettify.css b/build/coverage/lcov-report/prettify.css new file mode 100644 index 0000000..b317a7c --- /dev/null +++ b/build/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/build/coverage/lcov-report/prettify.js b/build/coverage/lcov-report/prettify.js new file mode 100644 index 0000000..ef51e03 --- /dev/null +++ b/build/coverage/lcov-report/prettify.js @@ -0,0 +1 @@ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/build/coverage/lcov-report/sort-arrow-sprite.png b/build/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 0000000..03f704a Binary files /dev/null and b/build/coverage/lcov-report/sort-arrow-sprite.png differ diff --git a/build/coverage/lcov-report/sorter.js b/build/coverage/lcov-report/sorter.js new file mode 100644 index 0000000..6c5034e --- /dev/null +++ b/build/coverage/lcov-report/sorter.js @@ -0,0 +1,158 @@ +var addSorting = (function () { + "use strict"; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { return document.querySelector('.coverage-summary'); } + // returns the thead element of the summary table + function getTableHeader() { return getTable().querySelector('thead tr'); } + // returns the tbody element of the summary table + function getTableBody() { return getTable().querySelector('tbody'); } + // returns the th element for nth column + function getNthColumn(n) { return getTableHeader().querySelectorAll('th')[n]; } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function (a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function (a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function () { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i =0 ; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function () { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(cols); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/build/coverage/lcov.info b/build/coverage/lcov.info new file mode 100644 index 0000000..ad94920 --- /dev/null +++ b/build/coverage/lcov.info @@ -0,0 +1,2743 @@ +TN: +SF:/usr/share/gamewheel/game-lib/build/game-lib.js +FN:2,GameLib +FN:6,(anonymous_2) +FN:14,(anonymous_3) +FN:35,(anonymous_4) +FN:95,(anonymous_5) +FN:129,(anonymous_6) +FN:171,(anonymous_7) +FN:183,(anonymous_8) +FN:195,(anonymous_9) +FN:202,(anonymous_10) +FN:213,(anonymous_11) +FN:221,(anonymous_12) +FN:239,(anonymous_13) +FN:289,(anonymous_14) +FN:300,(anonymous_15) +FN:311,(anonymous_16) +FN:321,(anonymous_17) +FN:329,(anonymous_18) +FN:381,(anonymous_19) +FN:390,(anonymous_20) +FN:404,(anonymous_21) +FN:437,(anonymous_22) +FN:469,(anonymous_23) +FN:477,(anonymous_24) +FN:483,(anonymous_25) +FN:489,(anonymous_26) +FN:497,(anonymous_27) +FN:503,(anonymous_28) +FN:563,(anonymous_29) +FN:582,(anonymous_30) +FN:603,(anonymous_31) +FN:642,(anonymous_32) +FN:648,(anonymous_33) +FN:694,(anonymous_34) +FN:749,(anonymous_35) +FN:883,(anonymous_36) +FN:1335,(anonymous_37) +FN:1487,(anonymous_38) +FN:1491,(anonymous_39) +FN:1509,(anonymous_40) +FN:1532,(anonymous_41) +FN:1539,(anonymous_42) +FN:1565,(anonymous_43) +FN:1572,(anonymous_44) +FN:1589,(anonymous_45) +FN:1596,(anonymous_46) +FN:1602,(anonymous_47) +FN:1608,(anonymous_48) +FN:1614,(anonymous_49) +FN:1631,(anonymous_50) +FN:1640,(anonymous_51) +FN:1737,(anonymous_52) +FN:1841,(anonymous_53) +FN:1956,(anonymous_54) +FN:1974,(anonymous_55) +FN:2059,(anonymous_56) +FN:2067,inProcessed +FN:2085,neighbourOnEdge +FN:2217,(anonymous_59) +FN:2261,(anonymous_60) +FN:2293,(anonymous_61) +FN:2311,(anonymous_62) +FN:2325,(anonymous_63) +FN:2330,(anonymous_64) +FN:2342,(anonymous_65) +FN:2347,(anonymous_66) +FN:2374,(anonymous_67) +FN:2415,(anonymous_68) +FN:2461,(anonymous_69) +FN:2523,(anonymous_70) +FN:2539,(anonymous_71) +FN:2540,(anonymous_72) +FN:2729,(anonymous_73) +FN:2882,(anonymous_74) +FN:2883,(anonymous_75) +FN:2915,(anonymous_76) +FN:2922,(anonymous_77) +FN:3014,(anonymous_78) +FN:3022,(anonymous_79) +FN:3037,(anonymous_80) +FN:3068,(anonymous_81) +FN:3126,(anonymous_82) +FN:3133,(anonymous_83) +FN:3173,(anonymous_84) +FN:3201,(anonymous_85) +FN:3255,(anonymous_86) +FN:3445,(anonymous_87) +FN:3464,(anonymous_88) +FN:3493,(anonymous_89) +FN:3501,(anonymous_90) +FN:3525,(anonymous_91) +FN:3607,(anonymous_92) +FN:3629,(anonymous_93) +FN:3683,(anonymous_94) +FN:3700,(anonymous_95) +FN:3740,(anonymous_96) +FN:3754,(anonymous_97) +FN:3761,(anonymous_98) +FN:3768,(anonymous_99) +FN:3787,(anonymous_100) +FN:3802,(anonymous_101) +FN:3810,(anonymous_102) +FN:3817,(anonymous_103) +FN:3828,(anonymous_104) +FN:3834,(anonymous_105) +FN:3841,(anonymous_106) +FN:3848,(anonymous_107) +FN:3852,(anonymous_108) +FN:3860,(anonymous_109) +FN:3880,(anonymous_110) +FN:3884,(anonymous_111) +FN:3903,(anonymous_112) +FN:3927,(anonymous_113) +FN:3934,(anonymous_114) +FN:3943,(anonymous_115) +FN:3964,(anonymous_116) +FN:3984,(anonymous_117) +FN:4002,(anonymous_118) +FN:4006,(anonymous_119) +FN:4027,(anonymous_120) +FN:4038,(anonymous_121) +FN:4083,(anonymous_122) +FN:4128,(anonymous_123) +FN:4149,(anonymous_124) +FN:4188,(anonymous_125) +FN:4206,(anonymous_126) +FN:4218,(anonymous_127) +FN:4233,(anonymous_128) +FN:4251,(anonymous_129) +FN:4309,(anonymous_130) +FN:4347,(anonymous_131) +FN:4375,(anonymous_132) +FN:4379,(anonymous_133) +FN:4393,(anonymous_134) +FN:4407,(anonymous_135) +FN:4424,(anonymous_136) +FN:4437,(anonymous_137) +FN:4446,(anonymous_138) +FN:4454,(anonymous_139) +FN:4462,(anonymous_140) +FN:4473,(anonymous_141) +FN:4481,(anonymous_142) +FN:4489,(anonymous_143) +FN:4515,(anonymous_144) +FN:4533,(anonymous_145) +FN:4592,(anonymous_146) +FNF:146 +FNH:3 +FNDA:0,GameLib +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:0,(anonymous_17) +FNDA:0,(anonymous_18) +FNDA:0,(anonymous_19) +FNDA:0,(anonymous_20) +FNDA:0,(anonymous_21) +FNDA:0,(anonymous_22) +FNDA:0,(anonymous_23) +FNDA:0,(anonymous_24) +FNDA:0,(anonymous_25) +FNDA:0,(anonymous_26) +FNDA:0,(anonymous_27) +FNDA:0,(anonymous_28) +FNDA:0,(anonymous_29) +FNDA:0,(anonymous_30) +FNDA:0,(anonymous_31) +FNDA:0,(anonymous_32) +FNDA:0,(anonymous_33) +FNDA:0,(anonymous_34) +FNDA:0,(anonymous_35) +FNDA:0,(anonymous_36) +FNDA:0,(anonymous_37) +FNDA:0,(anonymous_38) +FNDA:0,(anonymous_39) +FNDA:0,(anonymous_40) +FNDA:0,(anonymous_41) +FNDA:0,(anonymous_42) +FNDA:0,(anonymous_43) +FNDA:0,(anonymous_44) +FNDA:0,(anonymous_45) +FNDA:0,(anonymous_46) +FNDA:0,(anonymous_47) +FNDA:0,(anonymous_48) +FNDA:0,(anonymous_49) +FNDA:0,(anonymous_50) +FNDA:0,(anonymous_51) +FNDA:0,(anonymous_52) +FNDA:0,(anonymous_53) +FNDA:0,(anonymous_54) +FNDA:0,(anonymous_55) +FNDA:0,(anonymous_56) +FNDA:0,inProcessed +FNDA:0,neighbourOnEdge +FNDA:0,(anonymous_59) +FNDA:0,(anonymous_60) +FNDA:0,(anonymous_61) +FNDA:0,(anonymous_62) +FNDA:0,(anonymous_63) +FNDA:0,(anonymous_64) +FNDA:0,(anonymous_65) +FNDA:0,(anonymous_66) +FNDA:0,(anonymous_67) +FNDA:0,(anonymous_68) +FNDA:0,(anonymous_69) +FNDA:0,(anonymous_70) +FNDA:0,(anonymous_71) +FNDA:0,(anonymous_72) +FNDA:0,(anonymous_73) +FNDA:0,(anonymous_74) +FNDA:0,(anonymous_75) +FNDA:0,(anonymous_76) +FNDA:0,(anonymous_77) +FNDA:0,(anonymous_78) +FNDA:0,(anonymous_79) +FNDA:0,(anonymous_80) +FNDA:0,(anonymous_81) +FNDA:0,(anonymous_82) +FNDA:0,(anonymous_83) +FNDA:0,(anonymous_84) +FNDA:0,(anonymous_85) +FNDA:0,(anonymous_86) +FNDA:0,(anonymous_87) +FNDA:0,(anonymous_88) +FNDA:0,(anonymous_89) +FNDA:0,(anonymous_90) +FNDA:0,(anonymous_91) +FNDA:0,(anonymous_92) +FNDA:0,(anonymous_93) +FNDA:0,(anonymous_94) +FNDA:0,(anonymous_95) +FNDA:0,(anonymous_96) +FNDA:0,(anonymous_97) +FNDA:0,(anonymous_98) +FNDA:4,(anonymous_99) +FNDA:0,(anonymous_100) +FNDA:0,(anonymous_101) +FNDA:0,(anonymous_102) +FNDA:0,(anonymous_103) +FNDA:0,(anonymous_104) +FNDA:0,(anonymous_105) +FNDA:0,(anonymous_106) +FNDA:0,(anonymous_107) +FNDA:0,(anonymous_108) +FNDA:0,(anonymous_109) +FNDA:0,(anonymous_110) +FNDA:0,(anonymous_111) +FNDA:1,(anonymous_112) +FNDA:0,(anonymous_113) +FNDA:0,(anonymous_114) +FNDA:0,(anonymous_115) +FNDA:0,(anonymous_116) +FNDA:0,(anonymous_117) +FNDA:0,(anonymous_118) +FNDA:0,(anonymous_119) +FNDA:0,(anonymous_120) +FNDA:0,(anonymous_121) +FNDA:0,(anonymous_122) +FNDA:0,(anonymous_123) +FNDA:0,(anonymous_124) +FNDA:0,(anonymous_125) +FNDA:0,(anonymous_126) +FNDA:0,(anonymous_127) +FNDA:0,(anonymous_128) +FNDA:0,(anonymous_129) +FNDA:0,(anonymous_130) +FNDA:0,(anonymous_131) +FNDA:0,(anonymous_132) +FNDA:0,(anonymous_133) +FNDA:0,(anonymous_134) +FNDA:0,(anonymous_135) +FNDA:0,(anonymous_136) +FNDA:0,(anonymous_137) +FNDA:0,(anonymous_138) +FNDA:0,(anonymous_139) +FNDA:0,(anonymous_140) +FNDA:0,(anonymous_141) +FNDA:0,(anonymous_142) +FNDA:0,(anonymous_143) +FNDA:0,(anonymous_144) +FNDA:0,(anonymous_145) +FNDA:0,(anonymous_146) +DA:1,1 +DA:2,1 +DA:5,1 +DA:6,1 +DA:14,1 +DA:18,0 +DA:19,0 +DA:35,1 +DA:47,1 +DA:48,1 +DA:49,1 +DA:51,1 +DA:52,0 +DA:54,1 +DA:56,1 +DA:57,1 +DA:59,1 +DA:61,1 +DA:62,1 +DA:64,1 +DA:66,1 +DA:67,1 +DA:69,1 +DA:71,1 +DA:72,1 +DA:74,1 +DA:76,1 +DA:77,1 +DA:79,1 +DA:81,1 +DA:82,1 +DA:84,1 +DA:95,1 +DA:102,0 +DA:104,0 +DA:105,0 +DA:107,0 +DA:109,0 +DA:110,0 +DA:112,0 +DA:114,0 +DA:115,0 +DA:117,0 +DA:119,0 +DA:121,0 +DA:122,0 +DA:129,1 +DA:131,0 +DA:132,0 +DA:133,0 +DA:136,0 +DA:138,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:147,0 +DA:148,0 +DA:151,0 +DA:153,0 +DA:160,1 +DA:161,1 +DA:162,1 +DA:171,1 +DA:172,0 +DA:173,0 +DA:174,0 +DA:175,0 +DA:183,1 +DA:187,0 +DA:188,0 +DA:195,1 +DA:196,0 +DA:202,1 +DA:203,0 +DA:204,0 +DA:205,0 +DA:213,1 +DA:214,0 +DA:221,1 +DA:222,0 +DA:229,1 +DA:230,1 +DA:231,1 +DA:239,1 +DA:244,0 +DA:246,0 +DA:248,0 +DA:250,0 +DA:251,0 +DA:252,0 +DA:254,0 +DA:255,0 +DA:256,0 +DA:257,0 +DA:258,0 +DA:259,0 +DA:261,0 +DA:262,0 +DA:263,0 +DA:264,0 +DA:265,0 +DA:266,0 +DA:268,0 +DA:270,0 +DA:271,0 +DA:272,0 +DA:273,0 +DA:274,0 +DA:276,0 +DA:277,0 +DA:279,0 +DA:280,0 +DA:281,0 +DA:289,1 +DA:290,0 +DA:291,0 +DA:292,0 +DA:293,0 +DA:300,1 +DA:301,0 +DA:302,0 +DA:303,0 +DA:311,1 +DA:312,0 +DA:313,0 +DA:314,0 +DA:321,1 +DA:322,0 +DA:329,1 +DA:330,0 +DA:331,0 +DA:332,0 +DA:334,0 +DA:336,0 +DA:337,0 +DA:339,0 +DA:341,0 +DA:342,0 +DA:343,0 +DA:345,0 +DA:347,0 +DA:348,0 +DA:349,0 +DA:352,0 +DA:354,0 +DA:355,0 +DA:356,0 +DA:358,0 +DA:360,0 +DA:361,0 +DA:362,0 +DA:365,0 +DA:367,0 +DA:369,0 +DA:371,0 +DA:381,1 +DA:382,0 +DA:383,0 +DA:390,1 +DA:391,0 +DA:392,0 +DA:393,0 +DA:395,0 +DA:396,0 +DA:404,1 +DA:405,0 +DA:408,0 +DA:409,0 +DA:412,0 +DA:413,0 +DA:416,0 +DA:417,0 +DA:420,0 +DA:421,0 +DA:424,0 +DA:425,0 +DA:428,0 +DA:429,0 +DA:437,1 +DA:438,0 +DA:442,0 +DA:443,0 +DA:447,0 +DA:448,0 +DA:452,0 +DA:453,0 +DA:457,0 +DA:458,0 +DA:461,0 +DA:462,0 +DA:465,0 +DA:466,0 +DA:469,1 +DA:472,0 +DA:473,0 +DA:474,0 +DA:477,1 +DA:480,0 +DA:483,1 +DA:486,0 +DA:489,1 +DA:493,0 +DA:494,0 +DA:497,1 +DA:500,0 +DA:503,1 +DA:506,0 +DA:508,0 +DA:509,0 +DA:511,0 +DA:513,0 +DA:515,0 +DA:516,0 +DA:518,0 +DA:519,0 +DA:520,0 +DA:521,0 +DA:523,0 +DA:524,0 +DA:526,0 +DA:527,0 +DA:529,0 +DA:531,0 +DA:532,0 +DA:534,0 +DA:536,0 +DA:537,0 +DA:538,0 +DA:539,0 +DA:540,0 +DA:543,0 +DA:544,0 +DA:545,0 +DA:547,0 +DA:552,0 +DA:553,0 +DA:563,1 +DA:568,0 +DA:570,0 +DA:582,1 +DA:587,0 +DA:588,0 +DA:590,0 +DA:592,0 +DA:593,0 +DA:595,0 +DA:597,0 +DA:598,0 +DA:600,0 +DA:603,1 +DA:608,0 +DA:610,0 +DA:611,0 +DA:612,0 +DA:614,0 +DA:615,0 +DA:616,0 +DA:617,0 +DA:618,0 +DA:619,0 +DA:620,0 +DA:621,0 +DA:622,0 +DA:623,0 +DA:624,0 +DA:625,0 +DA:630,0 +DA:631,0 +DA:635,0 +DA:636,0 +DA:638,0 +DA:642,1 +DA:646,0 +DA:648,0 +DA:650,0 +DA:651,0 +DA:652,0 +DA:654,0 +DA:655,0 +DA:657,0 +DA:658,0 +DA:660,0 +DA:661,0 +DA:662,0 +DA:665,0 +DA:666,0 +DA:669,0 +DA:670,0 +DA:671,0 +DA:672,0 +DA:673,0 +DA:680,0 +DA:683,0 +DA:694,1 +DA:701,0 +DA:703,0 +DA:705,0 +DA:707,0 +DA:708,0 +DA:710,0 +DA:712,0 +DA:714,0 +DA:716,0 +DA:717,0 +DA:720,0 +DA:721,0 +DA:724,0 +DA:725,0 +DA:728,0 +DA:749,1 +DA:766,0 +DA:767,0 +DA:768,0 +DA:769,0 +DA:770,0 +DA:772,0 +DA:773,0 +DA:775,0 +DA:777,0 +DA:778,0 +DA:780,0 +DA:782,0 +DA:783,0 +DA:785,0 +DA:787,0 +DA:788,0 +DA:790,0 +DA:792,0 +DA:793,0 +DA:795,0 +DA:797,0 +DA:798,0 +DA:800,0 +DA:802,0 +DA:803,0 +DA:805,0 +DA:807,0 +DA:808,0 +DA:810,0 +DA:812,0 +DA:813,0 +DA:815,0 +DA:817,0 +DA:818,0 +DA:820,0 +DA:883,1 +DA:942,0 +DA:943,0 +DA:944,0 +DA:945,0 +DA:947,0 +DA:949,0 +DA:950,0 +DA:952,0 +DA:954,0 +DA:955,0 +DA:957,0 +DA:959,0 +DA:960,0 +DA:962,0 +DA:964,0 +DA:965,0 +DA:980,0 +DA:982,0 +DA:983,0 +DA:985,0 +DA:987,0 +DA:988,0 +DA:990,0 +DA:992,0 +DA:993,0 +DA:995,0 +DA:997,0 +DA:998,0 +DA:1000,0 +DA:1002,0 +DA:1003,0 +DA:1005,0 +DA:1007,0 +DA:1008,0 +DA:1010,0 +DA:1012,0 +DA:1013,0 +DA:1015,0 +DA:1017,0 +DA:1018,0 +DA:1020,0 +DA:1022,0 +DA:1023,0 +DA:1025,0 +DA:1027,0 +DA:1028,0 +DA:1030,0 +DA:1032,0 +DA:1033,0 +DA:1035,0 +DA:1037,0 +DA:1038,0 +DA:1040,0 +DA:1042,0 +DA:1043,0 +DA:1045,0 +DA:1047,0 +DA:1048,0 +DA:1050,0 +DA:1052,0 +DA:1053,0 +DA:1055,0 +DA:1057,0 +DA:1058,0 +DA:1060,0 +DA:1062,0 +DA:1063,0 +DA:1065,0 +DA:1067,0 +DA:1068,0 +DA:1070,0 +DA:1072,0 +DA:1073,0 +DA:1075,0 +DA:1077,0 +DA:1078,0 +DA:1080,0 +DA:1082,0 +DA:1083,0 +DA:1085,0 +DA:1087,0 +DA:1088,0 +DA:1090,0 +DA:1092,0 +DA:1093,0 +DA:1095,0 +DA:1097,0 +DA:1098,0 +DA:1100,0 +DA:1102,0 +DA:1103,0 +DA:1105,0 +DA:1107,0 +DA:1108,0 +DA:1110,0 +DA:1112,0 +DA:1113,0 +DA:1115,0 +DA:1117,0 +DA:1118,0 +DA:1120,0 +DA:1122,0 +DA:1123,0 +DA:1125,0 +DA:1127,0 +DA:1128,0 +DA:1130,0 +DA:1132,0 +DA:1133,0 +DA:1135,0 +DA:1137,0 +DA:1138,0 +DA:1140,0 +DA:1142,0 +DA:1143,0 +DA:1145,0 +DA:1147,0 +DA:1148,0 +DA:1150,0 +DA:1152,0 +DA:1153,0 +DA:1155,0 +DA:1157,0 +DA:1158,0 +DA:1160,0 +DA:1162,0 +DA:1163,0 +DA:1165,0 +DA:1167,0 +DA:1168,0 +DA:1170,0 +DA:1172,0 +DA:1173,0 +DA:1175,0 +DA:1177,0 +DA:1178,0 +DA:1180,0 +DA:1182,0 +DA:1183,0 +DA:1185,0 +DA:1187,0 +DA:1188,0 +DA:1190,0 +DA:1192,0 +DA:1193,0 +DA:1195,0 +DA:1197,0 +DA:1198,0 +DA:1200,0 +DA:1202,0 +DA:1203,0 +DA:1205,0 +DA:1207,0 +DA:1208,0 +DA:1210,0 +DA:1212,0 +DA:1213,0 +DA:1215,0 +DA:1217,0 +DA:1218,0 +DA:1220,0 +DA:1222,0 +DA:1223,0 +DA:1225,0 +DA:1227,0 +DA:1228,0 +DA:1230,0 +DA:1238,1 +DA:1239,1 +DA:1240,1 +DA:1246,1 +DA:1247,1 +DA:1248,1 +DA:1254,1 +DA:1255,1 +DA:1256,1 +DA:1257,1 +DA:1258,1 +DA:1264,1 +DA:1265,1 +DA:1266,1 +DA:1267,1 +DA:1268,1 +DA:1269,1 +DA:1270,1 +DA:1271,1 +DA:1272,1 +DA:1273,1 +DA:1274,1 +DA:1280,1 +DA:1281,1 +DA:1282,1 +DA:1283,1 +DA:1284,1 +DA:1290,1 +DA:1291,1 +DA:1292,1 +DA:1293,1 +DA:1294,1 +DA:1295,1 +DA:1296,1 +DA:1297,1 +DA:1303,1 +DA:1304,1 +DA:1305,1 +DA:1311,1 +DA:1312,1 +DA:1318,1 +DA:1319,1 +DA:1320,1 +DA:1321,1 +DA:1322,1 +DA:1323,1 +DA:1324,1 +DA:1325,1 +DA:1326,1 +DA:1327,1 +DA:1328,1 +DA:1335,1 +DA:1337,0 +DA:1339,0 +DA:1341,0 +DA:1343,0 +DA:1345,0 +DA:1396,0 +DA:1409,0 +DA:1411,0 +DA:1467,0 +DA:1481,0 +DA:1484,0 +DA:1485,0 +DA:1486,0 +DA:1488,0 +DA:1492,0 +DA:1493,0 +DA:1497,0 +DA:1500,0 +DA:1509,1 +DA:1514,0 +DA:1516,0 +DA:1517,0 +DA:1520,0 +DA:1521,0 +DA:1524,0 +DA:1525,0 +DA:1532,1 +DA:1533,0 +DA:1539,1 +DA:1546,0 +DA:1548,0 +DA:1549,0 +DA:1552,0 +DA:1553,0 +DA:1556,0 +DA:1557,0 +DA:1560,0 +DA:1561,0 +DA:1565,1 +DA:1566,0 +DA:1567,0 +DA:1568,0 +DA:1569,0 +DA:1572,1 +DA:1573,0 +DA:1574,0 +DA:1580,0 +DA:1586,0 +DA:1589,1 +DA:1590,0 +DA:1591,0 +DA:1592,0 +DA:1593,0 +DA:1596,1 +DA:1597,0 +DA:1598,0 +DA:1599,0 +DA:1602,1 +DA:1603,0 +DA:1604,0 +DA:1605,0 +DA:1608,1 +DA:1609,0 +DA:1610,0 +DA:1611,0 +DA:1614,1 +DA:1615,0 +DA:1616,0 +DA:1622,0 +DA:1623,0 +DA:1631,1 +DA:1632,0 +DA:1640,1 +DA:1642,0 +DA:1644,0 +DA:1646,0 +DA:1647,0 +DA:1650,0 +DA:1652,0 +DA:1653,0 +DA:1654,0 +DA:1657,0 +DA:1659,0 +DA:1660,0 +DA:1661,0 +DA:1663,0 +DA:1664,0 +DA:1665,0 +DA:1667,0 +DA:1668,0 +DA:1669,0 +DA:1671,0 +DA:1737,1 +DA:1759,0 +DA:1760,0 +DA:1761,0 +DA:1762,0 +DA:1763,0 +DA:1764,0 +DA:1766,0 +DA:1767,0 +DA:1769,0 +DA:1771,0 +DA:1772,0 +DA:1774,0 +DA:1776,0 +DA:1777,0 +DA:1779,0 +DA:1781,0 +DA:1782,0 +DA:1784,0 +DA:1786,0 +DA:1787,0 +DA:1789,0 +DA:1791,0 +DA:1792,0 +DA:1794,0 +DA:1796,0 +DA:1797,0 +DA:1799,0 +DA:1801,0 +DA:1802,0 +DA:1804,0 +DA:1806,0 +DA:1807,0 +DA:1809,0 +DA:1811,0 +DA:1812,0 +DA:1814,0 +DA:1816,0 +DA:1818,0 +DA:1820,0 +DA:1822,0 +DA:1830,1 +DA:1831,1 +DA:1841,1 +DA:1843,0 +DA:1845,0 +DA:1846,0 +DA:1849,0 +DA:1851,0 +DA:1853,0 +DA:1855,0 +DA:1857,0 +DA:1859,0 +DA:1861,0 +DA:1863,0 +DA:1865,0 +DA:1866,0 +DA:1867,0 +DA:1869,0 +DA:1870,0 +DA:1871,0 +DA:1873,0 +DA:1874,0 +DA:1875,0 +DA:1876,0 +DA:1878,0 +DA:1879,0 +DA:1880,0 +DA:1882,0 +DA:1883,0 +DA:1884,0 +DA:1886,0 +DA:1892,0 +DA:1893,0 +DA:1894,0 +DA:1901,0 +DA:1902,0 +DA:1915,0 +DA:1916,0 +DA:1926,0 +DA:1928,0 +DA:1930,0 +DA:1932,0 +DA:1933,0 +DA:1934,0 +DA:1935,0 +DA:1939,0 +DA:1941,0 +DA:1943,0 +DA:1944,0 +DA:1947,0 +DA:1948,0 +DA:1951,0 +DA:1953,0 +DA:1956,1 +DA:1958,0 +DA:1959,0 +DA:1960,0 +DA:1961,0 +DA:1963,0 +DA:1964,0 +DA:1965,0 +DA:1968,0 +DA:1974,1 +DA:1976,0 +DA:1978,0 +DA:1979,0 +DA:1986,0 +DA:1988,0 +DA:1990,0 +DA:1992,0 +DA:1993,0 +DA:1994,0 +DA:1996,0 +DA:2013,0 +DA:2014,0 +DA:2022,0 +DA:2023,0 +DA:2024,0 +DA:2025,0 +DA:2027,0 +DA:2031,0 +DA:2059,1 +DA:2067,1 +DA:2069,0 +DA:2070,0 +DA:2071,0 +DA:2075,0 +DA:2085,1 +DA:2087,0 +DA:2088,0 +DA:2097,0 +DA:2107,0 +DA:2108,0 +DA:2111,0 +DA:2118,0 +DA:2121,0 +DA:2136,0 +DA:2138,0 +DA:2140,0 +DA:2146,0 +DA:2154,0 +DA:2155,0 +DA:2156,0 +DA:2158,0 +DA:2159,0 +DA:2160,0 +DA:2163,0 +DA:2165,0 +DA:2180,0 +DA:2181,0 +DA:2182,0 +DA:2183,0 +DA:2192,0 +DA:2193,0 +DA:2194,0 +DA:2195,0 +DA:2196,0 +DA:2197,0 +DA:2198,0 +DA:2201,0 +DA:2202,0 +DA:2206,0 +DA:2217,1 +DA:2219,0 +DA:2220,0 +DA:2223,0 +DA:2225,0 +DA:2227,0 +DA:2228,0 +DA:2235,0 +DA:2237,0 +DA:2239,0 +DA:2241,0 +DA:2242,0 +DA:2250,0 +DA:2261,1 +DA:2267,0 +DA:2268,0 +DA:2269,0 +DA:2271,0 +DA:2272,0 +DA:2274,0 +DA:2282,1 +DA:2283,1 +DA:2293,1 +DA:2300,0 +DA:2301,0 +DA:2302,0 +DA:2303,0 +DA:2304,0 +DA:2311,1 +DA:2312,0 +DA:2325,1 +DA:2327,0 +DA:2330,1 +DA:2334,0 +DA:2342,1 +DA:2344,0 +DA:2347,1 +DA:2351,0 +DA:2374,1 +DA:2392,0 +DA:2393,0 +DA:2394,0 +DA:2395,0 +DA:2396,0 +DA:2397,0 +DA:2398,0 +DA:2399,0 +DA:2400,0 +DA:2401,0 +DA:2402,0 +DA:2403,0 +DA:2404,0 +DA:2405,0 +DA:2406,0 +DA:2408,0 +DA:2415,1 +DA:2417,0 +DA:2420,0 +DA:2421,0 +DA:2443,0 +DA:2461,1 +DA:2474,0 +DA:2475,0 +DA:2476,0 +DA:2477,0 +DA:2478,0 +DA:2480,0 +DA:2482,0 +DA:2483,0 +DA:2485,0 +DA:2487,0 +DA:2488,0 +DA:2490,0 +DA:2492,0 +DA:2493,0 +DA:2495,0 +DA:2497,0 +DA:2498,0 +DA:2500,0 +DA:2502,0 +DA:2503,0 +DA:2505,0 +DA:2507,0 +DA:2508,0 +DA:2510,0 +DA:2512,0 +DA:2513,0 +DA:2515,0 +DA:2523,1 +DA:2528,0 +DA:2529,0 +DA:2530,0 +DA:2533,0 +DA:2534,0 +DA:2539,0 +DA:2540,0 +DA:2541,0 +DA:2543,0 +DA:2545,0 +DA:2546,0 +DA:2549,0 +DA:2551,0 +DA:2553,0 +DA:2555,0 +DA:2557,0 +DA:2559,0 +DA:2568,0 +DA:2570,0 +DA:2572,0 +DA:2574,0 +DA:2576,0 +DA:2582,0 +DA:2584,0 +DA:2592,0 +DA:2594,0 +DA:2596,0 +DA:2598,0 +DA:2601,0 +DA:2606,0 +DA:2609,0 +DA:2623,0 +DA:2626,0 +DA:2630,0 +DA:2632,0 +DA:2634,0 +DA:2636,0 +DA:2680,0 +DA:2683,0 +DA:2714,0 +DA:2719,0 +DA:2729,1 +DA:2731,0 +DA:2733,0 +DA:2735,0 +DA:2737,0 +DA:2739,0 +DA:2741,0 +DA:2743,0 +DA:2745,0 +DA:2747,0 +DA:2749,0 +DA:2751,0 +DA:2756,0 +DA:2757,0 +DA:2769,0 +DA:2771,0 +DA:2788,0 +DA:2806,0 +DA:2812,0 +DA:2830,0 +DA:2833,0 +DA:2838,0 +DA:2840,0 +DA:2842,0 +DA:2844,0 +DA:2845,0 +DA:2846,0 +DA:2867,0 +DA:2868,0 +DA:2869,0 +DA:2872,0 +DA:2877,0 +DA:2878,0 +DA:2881,0 +DA:2883,0 +DA:2885,0 +DA:2890,0 +DA:2892,0 +DA:2893,0 +DA:2895,0 +DA:2896,0 +DA:2897,0 +DA:2899,0 +DA:2900,0 +DA:2901,0 +DA:2903,0 +DA:2904,0 +DA:2905,0 +DA:2907,0 +DA:2908,0 +DA:2909,0 +DA:2910,0 +DA:2912,0 +DA:2916,0 +DA:2919,0 +DA:2922,0 +DA:2923,0 +DA:2924,0 +DA:2926,0 +DA:2928,0 +DA:2930,0 +DA:2932,0 +DA:2934,0 +DA:2935,0 +DA:2938,0 +DA:2939,0 +DA:2942,0 +DA:2943,0 +DA:2944,0 +DA:2945,0 +DA:2948,0 +DA:2949,0 +DA:2950,0 +DA:2951,0 +DA:2952,0 +DA:2953,0 +DA:2956,0 +DA:2957,0 +DA:2958,0 +DA:2960,0 +DA:2961,0 +DA:2962,0 +DA:2968,0 +DA:2969,0 +DA:2971,0 +DA:2972,0 +DA:2976,0 +DA:2978,0 +DA:2980,0 +DA:2981,0 +DA:2982,0 +DA:2984,0 +DA:2985,0 +DA:2986,0 +DA:2988,0 +DA:2989,0 +DA:2990,0 +DA:2992,0 +DA:2993,0 +DA:2994,0 +DA:2995,0 +DA:2997,0 +DA:2998,0 +DA:3001,0 +DA:3002,0 +DA:3005,0 +DA:3015,0 +DA:3022,1 +DA:3026,0 +DA:3027,0 +DA:3028,0 +DA:3031,1 +DA:3032,1 +DA:3033,1 +DA:3034,1 +DA:3037,1 +DA:3038,0 +DA:3039,0 +DA:3040,0 +DA:3047,0 +DA:3048,0 +DA:3049,0 +DA:3050,0 +DA:3051,0 +DA:3068,1 +DA:3078,0 +DA:3080,0 +DA:3086,0 +DA:3087,0 +DA:3089,0 +DA:3095,0 +DA:3096,0 +DA:3098,0 +DA:3100,0 +DA:3101,0 +DA:3104,0 +DA:3105,0 +DA:3107,0 +DA:3109,0 +DA:3110,0 +DA:3112,0 +DA:3114,0 +DA:3115,0 +DA:3117,0 +DA:3119,0 +DA:3120,0 +DA:3122,0 +DA:3126,1 +DA:3129,0 +DA:3130,0 +DA:3133,1 +DA:3136,0 +DA:3137,0 +DA:3138,0 +DA:3139,0 +DA:3140,0 +DA:3141,0 +DA:3143,0 +DA:3146,0 +DA:3147,0 +DA:3148,0 +DA:3149,0 +DA:3150,0 +DA:3151,0 +DA:3154,0 +DA:3155,0 +DA:3159,0 +DA:3160,0 +DA:3161,0 +DA:3166,0 +DA:3173,1 +DA:3177,0 +DA:3179,0 +DA:3181,0 +DA:3183,0 +DA:3185,0 +DA:3187,0 +DA:3189,0 +DA:3201,1 +DA:3208,0 +DA:3209,0 +DA:3210,0 +DA:3211,0 +DA:3212,0 +DA:3213,0 +DA:3215,0 +DA:3218,0 +DA:3219,0 +DA:3220,0 +DA:3221,0 +DA:3228,1 +DA:3229,1 +DA:3255,1 +DA:3277,0 +DA:3278,0 +DA:3279,0 +DA:3281,0 +DA:3282,0 +DA:3284,0 +DA:3286,0 +DA:3287,0 +DA:3289,0 +DA:3291,0 +DA:3292,0 +DA:3294,0 +DA:3296,0 +DA:3297,0 +DA:3299,0 +DA:3301,0 +DA:3302,0 +DA:3304,0 +DA:3306,0 +DA:3307,0 +DA:3309,0 +DA:3311,0 +DA:3312,0 +DA:3314,0 +DA:3316,0 +DA:3317,0 +DA:3319,0 +DA:3321,0 +DA:3322,0 +DA:3324,0 +DA:3326,0 +DA:3327,0 +DA:3329,0 +DA:3331,0 +DA:3332,0 +DA:3334,0 +DA:3336,0 +DA:3337,0 +DA:3339,0 +DA:3341,0 +DA:3342,0 +DA:3344,0 +DA:3346,0 +DA:3347,0 +DA:3349,0 +DA:3351,0 +DA:3352,0 +DA:3354,0 +DA:3356,0 +DA:3357,0 +DA:3359,0 +DA:3361,0 +DA:3362,0 +DA:3364,0 +DA:3371,1 +DA:3372,1 +DA:3373,1 +DA:3374,1 +DA:3375,1 +DA:3376,1 +DA:3382,1 +DA:3383,1 +DA:3384,1 +DA:3385,1 +DA:3386,1 +DA:3387,1 +DA:3388,1 +DA:3389,1 +DA:3395,1 +DA:3396,1 +DA:3397,1 +DA:3403,1 +DA:3404,1 +DA:3405,1 +DA:3406,1 +DA:3407,1 +DA:3408,1 +DA:3414,1 +DA:3415,1 +DA:3416,1 +DA:3417,1 +DA:3418,1 +DA:3419,1 +DA:3420,1 +DA:3421,1 +DA:3427,1 +DA:3428,1 +DA:3429,1 +DA:3430,1 +DA:3431,1 +DA:3432,1 +DA:3433,1 +DA:3434,1 +DA:3445,1 +DA:3447,0 +DA:3449,0 +DA:3451,0 +DA:3455,0 +DA:3458,0 +DA:3460,0 +DA:3462,0 +DA:3468,0 +DA:3469,0 +DA:3470,0 +DA:3471,0 +DA:3472,0 +DA:3476,0 +DA:3477,0 +DA:3478,0 +DA:3479,0 +DA:3480,0 +DA:3481,0 +DA:3485,0 +DA:3486,0 +DA:3487,0 +DA:3488,0 +DA:3489,0 +DA:3490,0 +DA:3491,0 +DA:3497,0 +DA:3498,0 +DA:3505,0 +DA:3506,0 +DA:3511,0 +DA:3514,0 +DA:3525,1 +DA:3527,0 +DA:3529,0 +DA:3531,0 +DA:3533,0 +DA:3535,0 +DA:3537,0 +DA:3543,0 +DA:3545,0 +DA:3546,0 +DA:3549,0 +DA:3550,0 +DA:3553,0 +DA:3554,0 +DA:3557,0 +DA:3558,0 +DA:3561,0 +DA:3562,0 +DA:3565,0 +DA:3566,0 +DA:3569,0 +DA:3570,0 +DA:3573,0 +DA:3574,0 +DA:3577,0 +DA:3578,0 +DA:3581,0 +DA:3582,0 +DA:3585,0 +DA:3586,0 +DA:3589,0 +DA:3590,0 +DA:3593,0 +DA:3598,0 +DA:3607,1 +DA:3611,0 +DA:3612,0 +DA:3629,1 +DA:3642,0 +DA:3643,0 +DA:3644,0 +DA:3645,0 +DA:3646,0 +DA:3647,0 +DA:3648,0 +DA:3649,0 +DA:3650,0 +DA:3652,0 +DA:3654,0 +DA:3655,0 +DA:3661,0 +DA:3663,0 +DA:3664,0 +DA:3670,0 +DA:3672,0 +DA:3673,0 +DA:3676,0 +DA:3683,1 +DA:3684,0 +DA:3700,1 +DA:3701,0 +DA:3740,1 +DA:3742,0 +DA:3743,0 +DA:3745,0 +DA:3746,0 +DA:3749,0 +DA:3750,0 +DA:3754,1 +DA:3755,0 +DA:3761,1 +DA:3762,0 +DA:3768,1 +DA:3770,4 +DA:3771,4 +DA:3772,4 +DA:3774,4 +DA:3775,1 +DA:3778,4 +DA:3779,2 +DA:3782,4 +DA:3783,1 +DA:3787,1 +DA:3789,0 +DA:3790,0 +DA:3791,0 +DA:3792,0 +DA:3795,0 +DA:3796,0 +DA:3799,0 +DA:3802,1 +DA:3803,0 +DA:3810,1 +DA:3811,0 +DA:3812,0 +DA:3813,0 +DA:3814,0 +DA:3817,1 +DA:3819,0 +DA:3821,0 +DA:3823,0 +DA:3825,0 +DA:3828,1 +DA:3829,0 +DA:3830,0 +DA:3831,0 +DA:3834,1 +DA:3836,0 +DA:3838,0 +DA:3841,1 +DA:3842,0 +DA:3843,0 +DA:3844,0 +DA:3845,0 +DA:3848,1 +DA:3849,0 +DA:3852,1 +DA:3853,0 +DA:3860,1 +DA:3861,0 +DA:3862,0 +DA:3863,0 +DA:3864,0 +DA:3865,0 +DA:3866,0 +DA:3867,0 +DA:3868,0 +DA:3869,0 +DA:3870,0 +DA:3871,0 +DA:3873,0 +DA:3874,0 +DA:3876,0 +DA:3880,1 +DA:3881,0 +DA:3884,1 +DA:3886,0 +DA:3888,0 +DA:3890,0 +DA:3891,0 +DA:3894,0 +DA:3896,0 +DA:3897,0 +DA:3898,0 +DA:3900,0 +DA:3903,1 +DA:3905,1 +DA:3906,1 +DA:3907,1 +DA:3908,1 +DA:3910,1 +DA:3911,0 +DA:3914,1 +DA:3915,0 +DA:3918,1 +DA:3919,0 +DA:3922,1 +DA:3923,0 +DA:3927,1 +DA:3928,0 +DA:3929,0 +DA:3930,0 +DA:3931,0 +DA:3934,1 +DA:3935,0 +DA:3943,1 +DA:3944,0 +DA:3945,0 +DA:3946,0 +DA:3947,0 +DA:3948,0 +DA:3949,0 +DA:3950,0 +DA:3951,0 +DA:3952,0 +DA:3953,0 +DA:3954,0 +DA:3955,0 +DA:3956,0 +DA:3958,0 +DA:3959,0 +DA:3964,1 +DA:3967,0 +DA:3969,0 +DA:3971,0 +DA:3972,0 +DA:3975,0 +DA:3977,0 +DA:3978,0 +DA:3979,0 +DA:3981,0 +DA:3984,1 +DA:3986,0 +DA:3987,0 +DA:3988,0 +DA:3989,0 +DA:3992,0 +DA:3993,0 +DA:3994,0 +DA:3995,0 +DA:3996,0 +DA:3999,0 +DA:4002,1 +DA:4003,0 +DA:4006,1 +DA:4008,0 +DA:4009,0 +DA:4017,0 +DA:4018,0 +DA:4019,0 +DA:4022,0 +DA:4024,0 +DA:4027,1 +DA:4029,0 +DA:4031,0 +DA:4032,0 +DA:4035,0 +DA:4038,1 +DA:4042,0 +DA:4044,0 +DA:4046,0 +DA:4048,0 +DA:4050,0 +DA:4052,0 +DA:4054,0 +DA:4056,0 +DA:4057,0 +DA:4060,0 +DA:4062,0 +DA:4064,0 +DA:4065,0 +DA:4069,0 +DA:4073,0 +DA:4075,0 +DA:4076,0 +DA:4083,1 +DA:4087,0 +DA:4089,0 +DA:4091,0 +DA:4093,0 +DA:4095,0 +DA:4097,0 +DA:4099,0 +DA:4101,0 +DA:4102,0 +DA:4105,0 +DA:4107,0 +DA:4108,0 +DA:4109,0 +DA:4113,0 +DA:4117,0 +DA:4119,0 +DA:4120,0 +DA:4128,1 +DA:4130,0 +DA:4132,0 +DA:4134,0 +DA:4136,0 +DA:4137,0 +DA:4138,0 +DA:4140,0 +DA:4142,0 +DA:4143,0 +DA:4144,0 +DA:4145,0 +DA:4149,1 +DA:4151,0 +DA:4152,0 +DA:4153,0 +DA:4155,0 +DA:4156,0 +DA:4157,0 +DA:4159,0 +DA:4160,0 +DA:4161,0 +DA:4163,0 +DA:4164,0 +DA:4166,0 +DA:4167,0 +DA:4170,0 +DA:4171,0 +DA:4173,0 +DA:4174,0 +DA:4176,0 +DA:4177,0 +DA:4181,0 +DA:4188,1 +DA:4189,0 +DA:4190,0 +DA:4191,0 +DA:4193,0 +DA:4194,0 +DA:4195,0 +DA:4196,0 +DA:4199,0 +DA:4206,1 +DA:4208,0 +DA:4209,0 +DA:4210,0 +DA:4211,0 +DA:4214,0 +DA:4218,1 +DA:4220,0 +DA:4222,0 +DA:4223,0 +DA:4233,1 +DA:4237,0 +DA:4238,0 +DA:4251,1 +DA:4261,0 +DA:4263,0 +DA:4265,0 +DA:4266,0 +DA:4268,0 +DA:4270,0 +DA:4271,0 +DA:4277,0 +DA:4279,0 +DA:4280,0 +DA:4286,0 +DA:4288,0 +DA:4289,0 +DA:4291,0 +DA:4293,0 +DA:4295,0 +DA:4302,0 +DA:4303,0 +DA:4304,0 +DA:4309,1 +DA:4311,0 +DA:4313,0 +DA:4315,0 +DA:4318,0 +DA:4320,0 +DA:4322,0 +DA:4323,0 +DA:4324,0 +DA:4325,0 +DA:4326,0 +DA:4329,0 +DA:4331,0 +DA:4332,0 +DA:4333,0 +DA:4335,0 +DA:4337,0 +DA:4342,0 +DA:4344,0 +DA:4347,1 +DA:4353,0 +DA:4358,0 +DA:4360,0 +DA:4361,0 +DA:4363,0 +DA:4364,0 +DA:4367,0 +DA:4368,0 +DA:4371,0 +DA:4375,1 +DA:4379,1 +DA:4382,0 +DA:4384,0 +DA:4385,0 +DA:4388,0 +DA:4389,0 +DA:4393,1 +DA:4396,0 +DA:4398,0 +DA:4399,0 +DA:4402,0 +DA:4403,0 +DA:4407,1 +DA:4414,0 +DA:4415,0 +DA:4424,1 +DA:4428,0 +DA:4429,0 +DA:4431,0 +DA:4437,1 +DA:4441,0 +DA:4442,0 +DA:4446,1 +DA:4449,0 +DA:4450,0 +DA:4454,1 +DA:4457,0 +DA:4458,0 +DA:4462,1 +DA:4468,0 +DA:4469,0 +DA:4473,1 +DA:4476,0 +DA:4477,0 +DA:4481,1 +DA:4484,0 +DA:4485,0 +DA:4489,1 +DA:4492,0 +DA:4498,0 +DA:4500,0 +DA:4502,0 +DA:4503,0 +DA:4504,0 +DA:4507,0 +DA:4509,0 +DA:4511,0 +DA:4515,1 +DA:4519,0 +DA:4521,0 +DA:4528,0 +DA:4533,1 +DA:4540,0 +DA:4541,0 +DA:4551,0 +DA:4553,0 +DA:4554,0 +DA:4557,0 +DA:4558,0 +DA:4559,0 +DA:4560,0 +DA:4562,0 +DA:4567,0 +DA:4573,0 +DA:4574,0 +DA:4575,0 +DA:4576,0 +DA:4581,0 +DA:4582,0 +DA:4585,0 +DA:4586,0 +DA:4587,0 +DA:4589,0 +DA:4592,1 +DA:4600,0 +DA:4601,0 +DA:4602,0 +DA:4603,0 +DA:4604,0 +DA:4606,0 +DA:4608,0 +DA:4609,0 +DA:4611,0 +DA:4612,0 +DA:4614,0 +DA:4616,0 +DA:4618,0 +DA:4619,0 +DA:4620,0 +DA:4621,0 +DA:4622,0 +DA:4623,0 +DA:4624,0 +DA:4626,0 +DA:4627,0 +DA:4629,0 +DA:4631,0 +DA:4635,0 +DA:4640,0 +DA:4641,0 +DA:4642,0 +DA:4644,0 +DA:4645,0 +DA:4649,0 +DA:4650,0 +DA:4651,0 +DA:4652,0 +DA:4654,0 +DA:4655,0 +DA:4656,0 +DA:4658,0 +DA:4659,0 +DA:4660,0 +DA:4662,0 +DA:4666,1 +DA:4667,1 +LF:1745 +LH:283 +BRDA:1,1,0,0 +BRDA:1,1,1,1 +BRDA:5,2,0,1 +BRDA:5,2,1,0 +BRDA:51,3,0,0 +BRDA:51,3,1,1 +BRDA:56,4,0,1 +BRDA:56,4,1,0 +BRDA:61,5,0,1 +BRDA:61,5,1,0 +BRDA:66,6,0,1 +BRDA:66,6,1,0 +BRDA:71,7,0,1 +BRDA:71,7,1,0 +BRDA:76,8,0,1 +BRDA:76,8,1,0 +BRDA:81,9,0,1 +BRDA:81,9,1,0 +BRDA:104,10,0,0 +BRDA:104,10,1,0 +BRDA:109,11,0,0 +BRDA:109,11,1,0 +BRDA:114,12,0,0 +BRDA:114,12,1,0 +BRDA:121,13,0,0 +BRDA:121,13,1,0 +BRDA:131,14,0,0 +BRDA:131,14,1,0 +BRDA:140,15,0,0 +BRDA:140,15,1,0 +BRDA:142,16,0,0 +BRDA:142,16,1,0 +BRDA:144,17,0,0 +BRDA:144,17,1,0 +BRDA:203,18,0,0 +BRDA:203,18,1,0 +BRDA:276,19,0,0 +BRDA:276,19,1,0 +BRDA:276,19,2,0 +BRDA:279,20,0,0 +BRDA:279,20,1,0 +BRDA:280,21,0,0 +BRDA:280,21,1,0 +BRDA:280,21,2,0 +BRDA:281,22,0,0 +BRDA:281,22,1,0 +BRDA:281,22,2,0 +BRDA:301,23,0,0 +BRDA:301,23,1,0 +BRDA:312,24,0,0 +BRDA:312,24,1,0 +BRDA:339,25,0,0 +BRDA:339,25,1,0 +BRDA:345,26,0,0 +BRDA:345,26,1,0 +BRDA:352,27,0,0 +BRDA:352,27,1,0 +BRDA:358,28,0,0 +BRDA:358,28,1,0 +BRDA:365,29,0,0 +BRDA:365,29,1,0 +BRDA:369,30,0,0 +BRDA:369,30,1,0 +BRDA:391,31,0,0 +BRDA:391,31,1,0 +BRDA:392,32,0,0 +BRDA:392,32,1,0 +BRDA:392,32,2,0 +BRDA:392,32,3,0 +BRDA:393,33,0,0 +BRDA:393,33,1,0 +BRDA:393,33,2,0 +BRDA:393,33,3,0 +BRDA:405,34,0,0 +BRDA:405,34,1,0 +BRDA:405,34,2,0 +BRDA:405,34,3,0 +BRDA:405,34,4,0 +BRDA:405,34,5,0 +BRDA:438,35,0,0 +BRDA:438,35,1,0 +BRDA:438,35,2,0 +BRDA:438,35,3,0 +BRDA:438,35,4,0 +BRDA:438,35,5,0 +BRDA:438,35,6,0 +BRDA:438,35,7,0 +BRDA:438,35,8,0 +BRDA:438,35,9,0 +BRDA:493,36,0,0 +BRDA:493,36,1,0 +BRDA:511,37,0,0 +BRDA:511,37,1,0 +BRDA:511,38,0,0 +BRDA:511,38,1,0 +BRDA:523,39,0,0 +BRDA:523,39,1,0 +BRDA:524,40,0,0 +BRDA:524,40,1,0 +BRDA:534,41,0,0 +BRDA:534,41,1,0 +BRDA:536,42,0,0 +BRDA:536,42,1,0 +BRDA:537,43,0,0 +BRDA:537,43,1,0 +BRDA:543,44,0,0 +BRDA:543,44,1,0 +BRDA:568,45,0,0 +BRDA:568,45,1,0 +BRDA:587,46,0,0 +BRDA:587,46,1,0 +BRDA:592,47,0,0 +BRDA:592,47,1,0 +BRDA:597,48,0,0 +BRDA:597,48,1,0 +BRDA:707,49,0,0 +BRDA:707,49,1,0 +BRDA:712,50,0,0 +BRDA:712,50,1,0 +BRDA:716,51,0,0 +BRDA:716,51,1,0 +BRDA:720,52,0,0 +BRDA:720,52,1,0 +BRDA:724,53,0,0 +BRDA:724,53,1,0 +BRDA:772,54,0,0 +BRDA:772,54,1,0 +BRDA:777,55,0,0 +BRDA:777,55,1,0 +BRDA:782,56,0,0 +BRDA:782,56,1,0 +BRDA:787,57,0,0 +BRDA:787,57,1,0 +BRDA:792,58,0,0 +BRDA:792,58,1,0 +BRDA:797,59,0,0 +BRDA:797,59,1,0 +BRDA:802,60,0,0 +BRDA:802,60,1,0 +BRDA:807,61,0,0 +BRDA:807,61,1,0 +BRDA:812,62,0,0 +BRDA:812,62,1,0 +BRDA:817,63,0,0 +BRDA:817,63,1,0 +BRDA:944,64,0,0 +BRDA:944,64,1,0 +BRDA:949,65,0,0 +BRDA:949,65,1,0 +BRDA:954,66,0,0 +BRDA:954,66,1,0 +BRDA:959,67,0,0 +BRDA:959,67,1,0 +BRDA:964,68,0,0 +BRDA:964,68,1,0 +BRDA:982,69,0,0 +BRDA:982,69,1,0 +BRDA:987,70,0,0 +BRDA:987,70,1,0 +BRDA:992,71,0,0 +BRDA:992,71,1,0 +BRDA:997,72,0,0 +BRDA:997,72,1,0 +BRDA:1002,73,0,0 +BRDA:1002,73,1,0 +BRDA:1007,74,0,0 +BRDA:1007,74,1,0 +BRDA:1012,75,0,0 +BRDA:1012,75,1,0 +BRDA:1017,76,0,0 +BRDA:1017,76,1,0 +BRDA:1022,77,0,0 +BRDA:1022,77,1,0 +BRDA:1027,78,0,0 +BRDA:1027,78,1,0 +BRDA:1032,79,0,0 +BRDA:1032,79,1,0 +BRDA:1037,80,0,0 +BRDA:1037,80,1,0 +BRDA:1042,81,0,0 +BRDA:1042,81,1,0 +BRDA:1047,82,0,0 +BRDA:1047,82,1,0 +BRDA:1052,83,0,0 +BRDA:1052,83,1,0 +BRDA:1057,84,0,0 +BRDA:1057,84,1,0 +BRDA:1062,85,0,0 +BRDA:1062,85,1,0 +BRDA:1067,86,0,0 +BRDA:1067,86,1,0 +BRDA:1072,87,0,0 +BRDA:1072,87,1,0 +BRDA:1077,88,0,0 +BRDA:1077,88,1,0 +BRDA:1082,89,0,0 +BRDA:1082,89,1,0 +BRDA:1087,90,0,0 +BRDA:1087,90,1,0 +BRDA:1092,91,0,0 +BRDA:1092,91,1,0 +BRDA:1097,92,0,0 +BRDA:1097,92,1,0 +BRDA:1102,93,0,0 +BRDA:1102,93,1,0 +BRDA:1107,94,0,0 +BRDA:1107,94,1,0 +BRDA:1112,95,0,0 +BRDA:1112,95,1,0 +BRDA:1117,96,0,0 +BRDA:1117,96,1,0 +BRDA:1122,97,0,0 +BRDA:1122,97,1,0 +BRDA:1127,98,0,0 +BRDA:1127,98,1,0 +BRDA:1132,99,0,0 +BRDA:1132,99,1,0 +BRDA:1137,100,0,0 +BRDA:1137,100,1,0 +BRDA:1142,101,0,0 +BRDA:1142,101,1,0 +BRDA:1147,102,0,0 +BRDA:1147,102,1,0 +BRDA:1152,103,0,0 +BRDA:1152,103,1,0 +BRDA:1157,104,0,0 +BRDA:1157,104,1,0 +BRDA:1162,105,0,0 +BRDA:1162,105,1,0 +BRDA:1167,106,0,0 +BRDA:1167,106,1,0 +BRDA:1172,107,0,0 +BRDA:1172,107,1,0 +BRDA:1177,108,0,0 +BRDA:1177,108,1,0 +BRDA:1182,109,0,0 +BRDA:1182,109,1,0 +BRDA:1187,110,0,0 +BRDA:1187,110,1,0 +BRDA:1192,111,0,0 +BRDA:1192,111,1,0 +BRDA:1197,112,0,0 +BRDA:1197,112,1,0 +BRDA:1202,113,0,0 +BRDA:1202,113,1,0 +BRDA:1207,114,0,0 +BRDA:1207,114,1,0 +BRDA:1212,115,0,0 +BRDA:1212,115,1,0 +BRDA:1217,116,0,0 +BRDA:1217,116,1,0 +BRDA:1222,117,0,0 +BRDA:1222,117,1,0 +BRDA:1227,118,0,0 +BRDA:1227,118,1,0 +BRDA:1343,119,0,0 +BRDA:1343,119,1,0 +BRDA:1409,120,0,0 +BRDA:1409,120,1,0 +BRDA:1484,121,0,0 +BRDA:1484,121,1,0 +BRDA:1516,122,0,0 +BRDA:1516,122,1,0 +BRDA:1520,123,0,0 +BRDA:1520,123,1,0 +BRDA:1524,124,0,0 +BRDA:1524,124,1,0 +BRDA:1548,125,0,0 +BRDA:1548,125,1,0 +BRDA:1552,126,0,0 +BRDA:1552,126,1,0 +BRDA:1556,127,0,0 +BRDA:1556,127,1,0 +BRDA:1560,128,0,0 +BRDA:1560,128,1,0 +BRDA:1615,129,0,0 +BRDA:1615,129,1,0 +BRDA:1622,130,0,0 +BRDA:1622,130,1,0 +BRDA:1646,131,0,0 +BRDA:1646,131,1,0 +BRDA:1652,132,0,0 +BRDA:1652,132,1,0 +BRDA:1766,133,0,0 +BRDA:1766,133,1,0 +BRDA:1771,134,0,0 +BRDA:1771,134,1,0 +BRDA:1776,135,0,0 +BRDA:1776,135,1,0 +BRDA:1781,136,0,0 +BRDA:1781,136,1,0 +BRDA:1786,137,0,0 +BRDA:1786,137,1,0 +BRDA:1791,138,0,0 +BRDA:1791,138,1,0 +BRDA:1796,139,0,0 +BRDA:1796,139,1,0 +BRDA:1801,140,0,0 +BRDA:1801,140,1,0 +BRDA:1806,141,0,0 +BRDA:1806,141,1,0 +BRDA:1811,142,0,0 +BRDA:1811,142,1,0 +BRDA:1845,143,0,0 +BRDA:1845,143,1,0 +BRDA:1849,144,0,0 +BRDA:1849,144,1,0 +BRDA:1933,145,0,0 +BRDA:1933,145,1,0 +BRDA:1947,146,0,0 +BRDA:1947,146,1,0 +BRDA:2014,147,0,0 +BRDA:2014,147,1,0 +BRDA:2070,148,0,0 +BRDA:2070,148,1,0 +BRDA:2088,149,0,0 +BRDA:2088,149,1,0 +BRDA:2089,150,0,0 +BRDA:2089,150,1,0 +BRDA:2089,150,2,0 +BRDA:2089,150,3,0 +BRDA:2089,150,4,0 +BRDA:2089,150,5,0 +BRDA:2089,150,6,0 +BRDA:2089,150,7,0 +BRDA:2089,150,8,0 +BRDA:2089,150,9,0 +BRDA:2089,150,10,0 +BRDA:2089,150,11,0 +BRDA:2107,151,0,0 +BRDA:2107,151,1,0 +BRDA:2146,152,0,0 +BRDA:2146,152,1,0 +BRDA:2147,153,0,0 +BRDA:2147,153,1,0 +BRDA:2147,153,2,0 +BRDA:2147,153,3,0 +BRDA:2147,153,4,0 +BRDA:2147,153,5,0 +BRDA:2182,154,0,0 +BRDA:2182,154,1,0 +BRDA:2182,155,0,0 +BRDA:2182,155,1,0 +BRDA:2196,156,0,0 +BRDA:2196,156,1,0 +BRDA:2201,157,0,0 +BRDA:2201,157,1,0 +BRDA:2219,158,0,0 +BRDA:2219,158,1,0 +BRDA:2219,159,0,0 +BRDA:2219,159,1,0 +BRDA:2271,160,0,0 +BRDA:2271,160,1,0 +BRDA:2392,161,0,0 +BRDA:2392,161,1,0 +BRDA:2393,162,0,0 +BRDA:2393,162,1,0 +BRDA:2394,163,0,0 +BRDA:2394,163,1,0 +BRDA:2395,164,0,0 +BRDA:2395,164,1,0 +BRDA:2396,165,0,0 +BRDA:2396,165,1,0 +BRDA:2397,166,0,0 +BRDA:2397,166,1,0 +BRDA:2398,167,0,0 +BRDA:2398,167,1,0 +BRDA:2399,168,0,0 +BRDA:2399,168,1,0 +BRDA:2400,169,0,0 +BRDA:2400,169,1,0 +BRDA:2401,170,0,0 +BRDA:2401,170,1,0 +BRDA:2402,171,0,0 +BRDA:2402,171,1,0 +BRDA:2403,172,0,0 +BRDA:2403,172,1,0 +BRDA:2404,173,0,0 +BRDA:2404,173,1,0 +BRDA:2405,174,0,0 +BRDA:2405,174,1,0 +BRDA:2406,175,0,0 +BRDA:2406,175,1,0 +BRDA:2420,176,0,0 +BRDA:2420,176,1,0 +BRDA:2477,177,0,0 +BRDA:2477,177,1,0 +BRDA:2482,178,0,0 +BRDA:2482,178,1,0 +BRDA:2487,179,0,0 +BRDA:2487,179,1,0 +BRDA:2492,180,0,0 +BRDA:2492,180,1,0 +BRDA:2497,181,0,0 +BRDA:2497,181,1,0 +BRDA:2502,182,0,0 +BRDA:2502,182,1,0 +BRDA:2507,183,0,0 +BRDA:2507,183,1,0 +BRDA:2512,184,0,0 +BRDA:2512,184,1,0 +BRDA:2528,185,0,0 +BRDA:2528,185,1,0 +BRDA:2541,186,0,0 +BRDA:2541,186,1,0 +BRDA:2545,187,0,0 +BRDA:2545,187,1,0 +BRDA:2545,188,0,0 +BRDA:2545,188,1,0 +BRDA:2553,189,0,0 +BRDA:2553,189,1,0 +BRDA:2553,190,0,0 +BRDA:2553,190,1,0 +BRDA:2684,191,0,0 +BRDA:2684,191,1,0 +BRDA:2867,192,0,0 +BRDA:2867,192,1,0 +BRDA:2924,193,0,0 +BRDA:2924,193,1,0 +BRDA:2934,194,0,0 +BRDA:2934,194,1,0 +BRDA:2938,195,0,0 +BRDA:2938,195,1,0 +BRDA:2942,196,0,0 +BRDA:2942,196,1,0 +BRDA:2948,197,0,0 +BRDA:2948,197,1,0 +BRDA:2968,198,0,0 +BRDA:2968,198,1,0 +BRDA:3038,199,0,0 +BRDA:3038,199,1,0 +BRDA:3039,200,0,0 +BRDA:3039,200,1,0 +BRDA:3086,201,0,0 +BRDA:3086,201,1,0 +BRDA:3095,202,0,0 +BRDA:3095,202,1,0 +BRDA:3100,203,0,0 +BRDA:3100,203,1,0 +BRDA:3104,204,0,0 +BRDA:3104,204,1,0 +BRDA:3109,205,0,0 +BRDA:3109,205,1,0 +BRDA:3114,206,0,0 +BRDA:3114,206,1,0 +BRDA:3119,207,0,0 +BRDA:3119,207,1,0 +BRDA:3209,208,0,0 +BRDA:3209,208,1,0 +BRDA:3210,209,0,0 +BRDA:3210,209,1,0 +BRDA:3212,210,0,0 +BRDA:3212,210,1,0 +BRDA:3281,211,0,0 +BRDA:3281,211,1,0 +BRDA:3286,212,0,0 +BRDA:3286,212,1,0 +BRDA:3291,213,0,0 +BRDA:3291,213,1,0 +BRDA:3296,214,0,0 +BRDA:3296,214,1,0 +BRDA:3301,215,0,0 +BRDA:3301,215,1,0 +BRDA:3306,216,0,0 +BRDA:3306,216,1,0 +BRDA:3311,217,0,0 +BRDA:3311,217,1,0 +BRDA:3316,218,0,0 +BRDA:3316,218,1,0 +BRDA:3321,219,0,0 +BRDA:3321,219,1,0 +BRDA:3326,220,0,0 +BRDA:3326,220,1,0 +BRDA:3331,221,0,0 +BRDA:3331,221,1,0 +BRDA:3336,222,0,0 +BRDA:3336,222,1,0 +BRDA:3341,223,0,0 +BRDA:3341,223,1,0 +BRDA:3346,224,0,0 +BRDA:3346,224,1,0 +BRDA:3351,225,0,0 +BRDA:3351,225,1,0 +BRDA:3356,226,0,0 +BRDA:3356,226,1,0 +BRDA:3361,227,0,0 +BRDA:3361,227,1,0 +BRDA:3451,228,0,0 +BRDA:3451,228,1,0 +BRDA:3451,229,0,0 +BRDA:3451,229,1,0 +BRDA:3451,229,2,0 +BRDA:3458,230,0,0 +BRDA:3458,230,1,0 +BRDA:3497,231,0,0 +BRDA:3497,231,1,0 +BRDA:3533,232,0,0 +BRDA:3533,232,1,0 +BRDA:3537,233,0,0 +BRDA:3537,233,1,0 +BRDA:3538,234,0,0 +BRDA:3538,234,1,0 +BRDA:3538,234,2,0 +BRDA:3545,235,0,0 +BRDA:3545,235,1,0 +BRDA:3549,236,0,0 +BRDA:3549,236,1,0 +BRDA:3553,237,0,0 +BRDA:3553,237,1,0 +BRDA:3557,238,0,0 +BRDA:3557,238,1,0 +BRDA:3561,239,0,0 +BRDA:3561,239,1,0 +BRDA:3565,240,0,0 +BRDA:3565,240,1,0 +BRDA:3569,241,0,0 +BRDA:3569,241,1,0 +BRDA:3573,242,0,0 +BRDA:3573,242,1,0 +BRDA:3577,243,0,0 +BRDA:3577,243,1,0 +BRDA:3581,244,0,0 +BRDA:3581,244,1,0 +BRDA:3585,245,0,0 +BRDA:3585,245,1,0 +BRDA:3589,246,0,0 +BRDA:3589,246,1,0 +BRDA:3649,247,0,0 +BRDA:3649,247,1,0 +BRDA:3654,248,0,0 +BRDA:3654,248,1,0 +BRDA:3663,249,0,0 +BRDA:3663,249,1,0 +BRDA:3672,250,0,0 +BRDA:3672,250,1,0 +BRDA:3702,251,0,0 +BRDA:3702,251,1,0 +BRDA:3702,251,2,0 +BRDA:3702,251,3,0 +BRDA:3702,251,4,0 +BRDA:3702,251,5,0 +BRDA:3702,251,6,0 +BRDA:3702,251,7,0 +BRDA:3702,251,8,0 +BRDA:3702,251,9,0 +BRDA:3702,251,10,0 +BRDA:3702,251,11,0 +BRDA:3702,251,12,0 +BRDA:3702,251,13,0 +BRDA:3702,251,14,0 +BRDA:3702,251,15,0 +BRDA:3702,251,16,0 +BRDA:3702,251,17,0 +BRDA:3745,252,0,0 +BRDA:3745,252,1,0 +BRDA:3749,253,0,0 +BRDA:3749,253,1,0 +BRDA:3762,254,0,0 +BRDA:3762,254,1,0 +BRDA:3762,254,2,0 +BRDA:3762,254,3,0 +BRDA:3774,255,0,1 +BRDA:3774,255,1,3 +BRDA:3778,256,0,2 +BRDA:3778,256,1,2 +BRDA:3782,257,0,1 +BRDA:3782,257,1,3 +BRDA:3789,258,0,0 +BRDA:3789,258,1,0 +BRDA:3795,259,0,0 +BRDA:3795,259,1,0 +BRDA:3861,260,0,0 +BRDA:3861,260,1,0 +BRDA:3865,261,0,0 +BRDA:3865,261,1,0 +BRDA:3890,262,0,0 +BRDA:3890,262,1,0 +BRDA:3910,263,0,0 +BRDA:3910,263,1,1 +BRDA:3914,264,0,0 +BRDA:3914,264,1,1 +BRDA:3918,265,0,0 +BRDA:3918,265,1,1 +BRDA:3922,266,0,0 +BRDA:3922,266,1,1 +BRDA:3944,267,0,0 +BRDA:3944,267,1,0 +BRDA:3948,268,0,0 +BRDA:3948,268,1,0 +BRDA:3971,269,0,0 +BRDA:3971,269,1,0 +BRDA:3986,270,0,0 +BRDA:3986,270,1,0 +BRDA:3992,271,0,0 +BRDA:3992,271,1,0 +BRDA:4008,272,0,0 +BRDA:4008,272,1,0 +BRDA:4017,273,0,0 +BRDA:4017,273,1,0 +BRDA:4062,274,0,0 +BRDA:4062,274,1,0 +BRDA:4107,275,0,0 +BRDA:4107,275,1,0 +BRDA:4160,276,0,0 +BRDA:4160,276,1,0 +BRDA:4163,277,0,0 +BRDA:4163,277,1,0 +BRDA:4166,278,0,0 +BRDA:4166,278,1,0 +BRDA:4170,279,0,0 +BRDA:4170,279,1,0 +BRDA:4173,280,0,0 +BRDA:4173,280,1,0 +BRDA:4176,281,0,0 +BRDA:4176,281,1,0 +BRDA:4265,282,0,0 +BRDA:4265,282,1,0 +BRDA:4270,283,0,0 +BRDA:4270,283,1,0 +BRDA:4279,284,0,0 +BRDA:4279,284,1,0 +BRDA:4288,285,0,0 +BRDA:4288,285,1,0 +BRDA:4302,286,0,0 +BRDA:4302,286,1,0 +BRDA:4322,287,0,0 +BRDA:4322,287,1,0 +BRDA:4324,288,0,0 +BRDA:4324,288,1,0 +BRDA:4358,289,0,0 +BRDA:4358,289,1,0 +BRDA:4363,290,0,0 +BRDA:4363,290,1,0 +BRDA:4363,291,0,0 +BRDA:4363,291,1,0 +BRDA:4367,292,0,0 +BRDA:4367,292,1,0 +BRDA:4367,293,0,0 +BRDA:4367,293,1,0 +BRDA:4384,294,0,0 +BRDA:4384,294,1,0 +BRDA:4398,295,0,0 +BRDA:4398,295,1,0 +BRDA:4414,296,0,0 +BRDA:4414,296,1,0 +BRDA:4428,297,0,0 +BRDA:4428,297,1,0 +BRDA:4441,298,0,0 +BRDA:4441,298,1,0 +BRDA:4449,299,0,0 +BRDA:4449,299,1,0 +BRDA:4457,300,0,0 +BRDA:4457,300,1,0 +BRDA:4468,301,0,0 +BRDA:4468,301,1,0 +BRDA:4476,302,0,0 +BRDA:4476,302,1,0 +BRDA:4484,303,0,0 +BRDA:4484,303,1,0 +BRDA:4492,304,0,0 +BRDA:4492,304,1,0 +BRDA:4500,305,0,0 +BRDA:4500,305,1,0 +BRDA:4519,306,0,0 +BRDA:4519,306,1,0 +BRDA:4545,307,0,0 +BRDA:4545,307,1,0 +BRDA:4547,308,0,0 +BRDA:4547,308,1,0 +BRDA:4574,309,0,0 +BRDA:4574,309,1,0 +BRDA:4601,310,0,0 +BRDA:4601,310,1,0 +BRDA:4602,311,0,0 +BRDA:4602,311,1,0 +BRDA:4604,312,0,0 +BRDA:4604,312,1,0 +BRDA:4612,313,0,0 +BRDA:4612,313,1,0 +BRDA:4612,314,0,0 +BRDA:4612,314,1,0 +BRDA:4616,315,0,0 +BRDA:4616,315,1,0 +BRDA:4626,316,0,0 +BRDA:4626,316,1,0 +BRDA:4626,317,0,0 +BRDA:4626,317,1,0 +BRDA:4629,318,0,0 +BRDA:4629,318,1,0 +BRDA:4631,319,0,0 +BRDA:4631,319,1,0 +BRDA:4636,320,0,0 +BRDA:4636,320,1,0 +BRDA:4644,321,0,0 +BRDA:4644,321,1,0 +BRDA:4666,322,0,1 +BRDA:4666,322,1,0 +BRF:697 +BRH:20 +end_of_record diff --git a/gulpfile.js b/gulpfile.js index a4a2aa4..73486b5 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -23,7 +23,7 @@ gulp.task( ); gulp.task('test-prepare', function(){ - return gulp.src(['./build/game-lib.js']) + return gulp.src('./build/game-lib.js') .pipe(plumber()) .pipe(istanbul()) .pipe(istanbul.hookRequire()) @@ -40,7 +40,11 @@ gulp.task( .pipe(sort()) .pipe(plumber()) .pipe(mocha({reporter: 'spec'})) - .pipe(istanbul.writeReports()) + .pipe(istanbul.writeReports({ + dir: './build/coverage', + reporters: [ 'lcov' ], + reportOpts: { dir: './build/coverage' } + })) .pipe(istanbul.enforceThresholds({thresholds:{global:90}})) .on('error', function(error) {