commit 579e3bb5df1347320bc2c402ab486a8c13e379c6 Author: Alex Date: Fri Feb 17 17:32:44 2017 -0600 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..52369be --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +libraries/ diff --git a/A1/.gitignore b/A1/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/A1/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/A1/A1.zip b/A1/A1.zip new file mode 100644 index 0000000..e18e089 Binary files /dev/null and b/A1/A1.zip differ diff --git a/A1/CMakeLists.txt b/A1/CMakeLists.txt new file mode 100644 index 0000000..5deaf8f --- /dev/null +++ b/A1/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(A1) + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS}) + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") +ENDIF() diff --git a/A1/README.txt b/A1/README.txt new file mode 100644 index 0000000..2f808ed --- /dev/null +++ b/A1/README.txt @@ -0,0 +1,7 @@ +1) Alexander Huddleston + +2) The last coloring mode goes from blue to green, top to bottom respectively. + +3) http://www.mathopenref.com/coordtrianglearea.html + +4) This was written and compiled on Arch Linux on a 64-bit machine. There should not be any errors when run on another machine, but I am making note here just in case. diff --git a/A1/resources/bunny.obj b/A1/resources/bunny.obj new file mode 100644 index 0000000..18abc08 --- /dev/null +++ b/A1/resources/bunny.obj @@ -0,0 +1,7474 @@ +# OBJ file format with ext .obj +# vertex count = 2503 +# face count = 4968 +v -3.4101800e-003 1.3031957e-001 2.1754370e-002 +v -8.1719160e-002 1.5250145e-001 2.9656090e-002 +v -3.0543480e-002 1.2477885e-001 1.0983400e-003 +v -2.4901590e-002 1.1211138e-001 3.7560240e-002 +v -1.8405680e-002 1.7843055e-001 -2.4219580e-002 +v 1.9067940e-002 1.2144925e-001 3.1968440e-002 +v 6.0412000e-003 1.2494359e-001 3.2652890e-002 +v -1.3469030e-002 1.6299355e-001 -1.2000020e-002 +v -3.4393240e-002 1.7236688e-001 -9.8213000e-004 +v -8.4314160e-002 1.0957263e-001 3.7097300e-003 +v -4.2233540e-002 1.7211574e-001 -4.1799800e-003 +v -6.3308390e-002 1.5660615e-001 -1.3838790e-002 +v -7.6903950e-002 1.6708033e-001 -2.6931360e-002 +v -7.2253920e-002 1.1539550e-001 5.1670300e-002 +v 1.2981330e-002 1.1366375e-001 3.8302950e-002 +v -3.7857280e-002 1.7010102e-001 1.4236000e-003 +v 4.8689400e-003 3.7962370e-002 4.5867630e-002 +v -5.7180550e-002 4.0918830e-002 4.6301340e-002 +v -4.5209070e-002 3.8839100e-002 4.4503770e-002 +v -3.3761490e-002 1.2617876e-001 1.7132300e-003 +v -5.0242270e-002 1.5773747e-001 9.3944500e-003 +v -2.1216950e-002 1.5887938e-001 -4.6923700e-003 +v -5.6472950e-002 1.5778406e-001 8.1786500e-003 +v -5.2802060e-002 4.1319860e-002 4.6169800e-002 +v -4.9960340e-002 4.3101950e-002 4.4462650e-002 +v -2.9748750e-002 3.6539860e-002 5.2493310e-002 +v -3.5438900e-003 4.2659770e-002 4.7541530e-002 +v 4.9304900e-003 4.1982660e-002 4.5723390e-002 +v -3.9088180e-002 1.6872020e-001 -1.1924680e-002 +v -5.6901000e-002 4.5437000e-002 4.3236960e-002 +v -4.1244880e-002 4.3098890e-002 4.2129560e-002 +v -2.6471980e-002 4.5034530e-002 5.1219460e-002 +v -2.1866970e-002 4.4022930e-002 5.3243800e-002 +v -3.6996250e-002 1.6899301e-001 1.3256300e-003 +v -6.7216590e-002 1.6171340e-001 -1.3733710e-002 +v 4.9760060e-002 7.0235220e-002 2.3732020e-002 +v -4.9186640e-002 4.6411230e-002 4.1170040e-002 +v -4.4590380e-002 4.3797990e-002 4.2685460e-002 +v -4.3686470e-002 4.7154500e-002 4.0286310e-002 +v -2.2491950e-002 4.6513620e-002 5.1885310e-002 +v -6.5174200e-003 4.5036200e-002 4.7502780e-002 +v 3.7699000e-004 4.4935790e-002 4.6519930e-002 +v 3.4023920e-002 1.1353879e-001 2.4595280e-002 +v -2.6467900e-002 1.8104250e-001 -8.0811700e-003 +v -1.7533470e-002 4.7964250e-002 4.8829630e-002 +v -7.0012600e-003 4.6416520e-002 4.7485540e-002 +v 5.9862300e-003 4.6689140e-002 4.9073620e-002 +v 9.1007200e-003 4.8474490e-002 4.9353190e-002 +v -3.5453700e-002 1.1244769e-001 3.5055410e-002 +v -7.5983200e-002 1.3820800e-001 4.9216580e-002 +v 3.4838440e-002 4.3153410e-002 2.8954310e-002 +v -5.2655550e-002 4.8494220e-002 3.8731190e-002 +v -4.7378940e-002 4.8456670e-002 3.9126790e-002 +v -3.8933750e-002 4.6364270e-002 4.0364780e-002 +v -2.6468940e-002 4.7816430e-002 4.9322590e-002 +v -2.2365790e-002 4.8073650e-002 5.0126500e-002 +v -1.3373430e-002 4.7892410e-002 4.7883850e-002 +v -1.2193490e-002 4.9470300e-002 4.9484490e-002 +v -6.3364000e-004 4.7193060e-002 4.9136900e-002 +v 2.0656800e-003 5.0104680e-002 5.2290220e-002 +v -2.2749270e-002 4.9883880e-002 4.6605520e-002 +v -1.8002080e-002 4.9917850e-002 4.6947970e-002 +v -7.8036800e-003 5.0169310e-002 5.0988650e-002 +v -2.6843800e-003 5.1247420e-002 5.3186790e-002 +v -6.3875650e-002 1.6140094e-001 -2.0064210e-002 +v 3.2434000e-002 4.5333970e-002 3.0316760e-002 +v -8.8064570e-002 1.2496764e-001 5.7412000e-004 +v -4.1503710e-002 1.6748512e-001 3.2765900e-003 +v -6.4457010e-002 1.5342891e-001 -5.1180400e-003 +v -3.4303190e-002 5.0520150e-002 3.8286020e-002 +v -2.2949400e-002 5.1020650e-002 4.3926450e-002 +v -1.4354710e-002 5.4428200e-002 5.0710310e-002 +v 1.3773100e-003 5.2302710e-002 5.3149010e-002 +v 3.6285000e-003 5.3198640e-002 5.3422710e-002 +v 8.0723800e-003 5.1574140e-002 5.1773560e-002 +v -7.2665890e-002 1.3005582e-001 5.1668200e-002 +v 3.7992780e-002 4.9793200e-002 3.1902020e-002 +v 3.8497260e-002 4.8062400e-002 3.1737450e-002 +v 2.1503510e-002 1.2563988e-001 2.1252620e-002 +v -7.6481330e-002 1.4827412e-001 -8.9376200e-003 +v -8.7240410e-002 1.1967213e-001 -1.7813000e-004 +v -4.3719960e-002 1.6822738e-001 2.3425000e-003 +v -4.0652200e-002 1.2266506e-001 2.6290300e-002 +v -4.6686180e-002 5.4570720e-002 3.7587370e-002 +v -4.4071750e-002 5.1058250e-002 3.8977810e-002 +v -3.8144110e-002 5.0599600e-002 3.9302160e-002 +v -1.9875770e-002 5.1607710e-002 4.6142000e-002 +v -1.6911250e-002 5.1843550e-002 4.8459320e-002 +v -1.6249190e-002 5.4292110e-002 5.0306940e-002 +v -1.0446540e-002 5.3685970e-002 5.1958610e-002 +v -4.3090900e-003 5.4467500e-002 5.3908250e-002 +v 7.8152700e-003 5.5050680e-002 5.2750250e-002 +v 3.7955090e-002 1.0488710e-001 -3.2031800e-003 +v -7.9003790e-002 1.2850550e-001 5.3149340e-002 +v -7.9778990e-002 1.3448894e-001 5.0990290e-002 +v -5.9129700e-002 1.5039712e-001 3.4489540e-002 +v -6.5691790e-002 1.4961818e-001 3.8160980e-002 +v -3.1951660e-002 1.2518394e-001 1.9400580e-002 +v -6.9372590e-002 1.6061775e-001 -9.1905000e-003 +v -4.5225500e-002 1.2935459e-001 2.0377520e-002 +v -4.1879110e-002 5.6164390e-002 3.9796700e-002 +v -3.0614840e-002 5.4412650e-002 3.6694290e-002 +v -2.4787600e-002 5.2606220e-002 4.0839760e-002 +v -2.1588860e-002 5.6836920e-002 4.5467040e-002 +v -2.4264000e-004 5.4536020e-002 5.4641200e-002 +v -8.0900510e-002 1.2558713e-001 5.2155370e-002 +v -2.9996210e-002 1.7811137e-001 -5.2358200e-003 +v 3.5515390e-002 5.0449570e-002 3.1439830e-002 +v 4.3315550e-002 5.2145550e-002 3.2492110e-002 +v -6.3938540e-002 1.5262699e-001 3.4481070e-002 +v -4.4489440e-002 6.1077710e-002 3.9545320e-002 +v -3.8979900e-002 5.7996270e-002 4.0151390e-002 +v -7.9087730e-002 1.7044488e-001 -4.1373170e-002 +v -4.6247300e-003 5.7759650e-002 5.3990710e-002 +v -1.4985500e-003 5.5925480e-002 5.4630800e-002 +v 5.1981700e-003 5.7017990e-002 5.3423530e-002 +v 3.0920000e-005 1.2315746e-001 3.4749660e-002 +v 3.3568300e-002 1.1523716e-001 2.1798410e-002 +v 3.8686300e-002 5.6450590e-002 3.1188930e-002 +v -3.4385780e-002 5.4096000e-002 3.8060290e-002 +v -8.5308300e-003 6.0159420e-002 5.5308950e-002 +v -4.4024000e-004 5.8343410e-002 5.4483410e-002 +v -9.1078730e-002 1.1506037e-001 4.0141810e-002 +v 4.0775480e-002 5.4557490e-002 3.2014740e-002 +v 4.5636880e-002 5.7402620e-002 3.1992220e-002 +v 2.0358850e-002 1.2448747e-001 2.5906340e-002 +v -1.4169700e-002 1.2767892e-001 1.3080500e-003 +v -1.1987590e-002 5.7493210e-002 5.2752420e-002 +v 3.2514500e-003 5.9828640e-002 5.5464300e-002 +v -1.2395240e-002 1.2264726e-001 3.3588280e-002 +v 1.3813780e-002 1.2322188e-001 3.2502590e-002 +v -7.7004310e-002 1.5521281e-001 2.4534770e-002 +v -2.8001360e-002 6.1075420e-002 3.7471210e-002 +v -8.5480000e-004 6.0593520e-002 5.5824810e-002 +v -3.8050200e-002 1.1527068e-001 3.3178540e-002 +v -1.6231340e-002 1.2382942e-001 2.9576990e-002 +v -2.5373550e-002 1.5840012e-001 -1.4801300e-003 +v -6.7818590e-002 1.5454353e-001 3.0233720e-002 +v -4.3082600e-003 6.1418570e-002 5.5688490e-002 +v -3.1958900e-003 1.1912518e-001 3.8349580e-002 +v -6.4292400e-003 1.2201090e-001 3.5740890e-002 +v 4.2312960e-002 5.9099150e-002 3.0848420e-002 +v 4.8510010e-002 6.1780760e-002 3.0347250e-002 +v 5.0412290e-002 6.0312610e-002 3.0245060e-002 +v -3.9185590e-002 6.3074530e-002 4.1382890e-002 +v -3.4448660e-002 6.0780500e-002 3.9543990e-002 +v -1.4746030e-002 6.5583910e-002 5.3730860e-002 +v 2.6645200e-003 6.2700010e-002 5.6525210e-002 +v -1.3991610e-002 1.1962575e-001 3.6251540e-002 +v 1.9659170e-002 1.1236219e-001 3.7545270e-002 +v -3.2597160e-002 1.7498725e-001 -2.5953100e-003 +v -2.1513900e-003 9.9437380e-002 4.9849750e-002 +v -5.6001390e-002 6.1830670e-002 2.7931150e-002 +v -5.4707260e-002 6.3461570e-002 3.1670590e-002 +v -5.1307940e-002 6.0521660e-002 3.1434930e-002 +v -4.1979320e-002 6.9629980e-002 4.1824930e-002 +v -3.0272490e-002 6.2474660e-002 3.7982220e-002 +v -1.1387860e-002 6.4742460e-002 5.4918000e-002 +v 6.9544900e-003 6.4700130e-002 5.5599150e-002 +v 4.3015090e-002 9.7690960e-002 1.0258300e-003 +v 4.0635900e-002 6.1574860e-002 2.9841250e-002 +v 4.6183560e-002 6.1910110e-002 3.0223400e-002 +v 3.7552960e-002 1.0685291e-001 2.6303470e-002 +v -7.8640730e-002 1.6387238e-001 -2.8387790e-002 +v -6.1996240e-002 1.4761484e-001 -4.3256800e-003 +v -5.7499800e-003 6.5488980e-002 5.6173390e-002 +v 2.5369000e-004 6.5741170e-002 5.6569260e-002 +v -2.0542550e-002 1.1979518e-001 3.3003670e-002 +v 4.3155900e-003 1.2782561e-001 2.8646880e-002 +v -4.6549580e-002 6.7652130e-002 3.9635790e-002 +v -1.7420580e-002 6.9659490e-002 5.4089530e-002 +v -1.5242190e-002 7.0909900e-002 5.5004790e-002 +v -1.0282890e-002 6.8926360e-002 5.5289610e-002 +v -1.1289000e-004 6.9288200e-002 5.6579790e-002 +v -3.6309330e-002 1.1876943e-001 3.0674020e-002 +v -7.0325800e-002 6.3367770e-002 1.9809180e-002 +v 4.3023100e-002 6.3795810e-002 2.8039210e-002 +v 4.2831110e-002 8.5556040e-002 2.7873760e-002 +v 1.6981600e-002 1.2715003e-001 2.2931490e-002 +v -4.2121490e-002 1.2825104e-001 1.0751500e-003 +v 1.6329230e-002 1.2251895e-001 3.1375390e-002 +v -8.1264160e-002 1.5381172e-001 2.5897830e-002 +v -3.2257870e-002 8.8192600e-002 -2.5130960e-002 +v -1.3774950e-002 7.0887950e-002 5.4695630e-002 +v 5.2929600e-003 6.8006030e-002 5.5670490e-002 +v 7.6962500e-003 7.2375600e-002 5.6062150e-002 +v 3.4830600e-003 1.2002635e-001 3.6911950e-002 +v 6.6532500e-003 1.1673563e-001 3.8716340e-002 +v 4.6086570e-002 6.6473930e-002 2.6808990e-002 +v 5.2327290e-002 6.4327070e-002 2.8281890e-002 +v -6.1897630e-002 1.2297065e-001 -8.7725500e-003 +v -6.3934700e-003 1.0524472e-001 -2.2841900e-002 +v -3.5218330e-002 6.8559830e-002 4.1381470e-002 +v -3.2689880e-002 6.7729720e-002 4.0124390e-002 +v -2.9245440e-002 6.9551520e-002 3.9369010e-002 +v -5.0024500e-003 6.9655000e-002 5.6892510e-002 +v 1.6573960e-002 1.1890153e-001 3.5042300e-002 +v -8.9385100e-002 9.9024040e-002 1.7521830e-002 +v 4.5719230e-002 6.9489400e-002 2.3549340e-002 +v 5.4537210e-002 6.8796720e-002 2.4517690e-002 +v -4.4989450e-002 7.1577330e-002 4.1929250e-002 +v -4.2439400e-003 1.2914902e-001 2.5829230e-002 +v -7.3880090e-002 1.2091638e-001 5.3395800e-002 +v -7.4033870e-002 1.4406894e-001 4.4994970e-002 +v 5.0400010e-002 6.7292480e-002 2.6851470e-002 +v -5.4056890e-002 1.5671602e-001 -2.4865900e-003 +v 2.6148110e-002 1.2014725e-001 2.7308010e-002 +v -1.0736490e-002 1.2990285e-001 1.0993790e-002 +v -4.5078840e-002 8.7261130e-002 -2.1865520e-002 +v -3.8340900e-002 6.8843770e-002 4.1846470e-002 +v -2.9255580e-002 7.5169210e-002 4.1186430e-002 +v -4.7311210e-002 1.6296037e-001 6.0740300e-003 +v -1.1866030e-002 7.3183750e-002 5.6250050e-002 +v -6.3734600e-003 7.2184340e-002 5.7972980e-002 +v -2.9935300e-003 7.2186440e-002 5.8167190e-002 +v -2.5781060e-002 9.3778180e-002 -2.8388220e-002 +v -1.6692560e-002 1.1568553e-001 3.7853150e-002 +v -8.4123410e-002 1.0832050e-001 2.4730980e-002 +v -7.4294080e-002 1.6356850e-001 -1.5534220e-002 +v -9.4297150e-002 1.2617744e-001 1.9224650e-002 +v -3.5207090e-002 1.2505219e-001 2.1635690e-002 +v -4.9495940e-002 7.3436340e-002 4.1673570e-002 +v -3.3064160e-002 7.6654840e-002 4.1277900e-002 +v -7.3157300e-003 7.3919590e-002 5.7971690e-002 +v 2.1850000e-005 7.3496040e-002 5.7696650e-002 +v 4.1934400e-003 7.2915170e-002 5.6298730e-002 +v -7.7256080e-002 1.4565854e-001 4.3122930e-002 +v 4.1073260e-002 8.8724320e-002 -9.7879400e-003 +v 3.7418710e-002 1.0850822e-001 3.3973000e-004 +v -5.5111380e-002 7.4687840e-002 4.1939740e-002 +v -4.2740230e-002 7.6995340e-002 4.2804080e-002 +v -6.8531190e-002 1.5630045e-001 2.0997710e-002 +v -9.9440200e-003 7.6343100e-002 5.7388560e-002 +v -3.2479200e-003 7.5710690e-002 5.8714640e-002 +v 1.3414380e-002 9.3073740e-002 5.1467750e-002 +v -7.3504440e-002 9.3883340e-002 -1.4751720e-002 +v -7.4471830e-002 1.3507476e-001 5.0688900e-002 +v -2.5851310e-002 1.2182948e-001 2.6079670e-002 +v -3.4022940e-002 1.7597076e-001 -3.7271600e-003 +v -7.5405850e-002 1.6839072e-001 -2.6792980e-002 +v -3.6658410e-002 7.5087300e-002 4.2006940e-002 +v -1.7795480e-002 7.7486190e-002 5.6087240e-002 +v -1.1378660e-002 7.9877150e-002 5.7698880e-002 +v -1.0415000e-004 7.6881950e-002 5.8190740e-002 +v 2.7381400e-003 7.9105680e-002 5.6719190e-002 +v 5.5681200e-003 7.6397140e-002 5.6327220e-002 +v -6.1895860e-002 1.5424247e-001 -1.9018600e-002 +v -7.2646960e-002 1.4098943e-001 4.6976640e-002 +v 1.5799740e-002 1.2901416e-001 1.3236870e-002 +v -1.1703420e-002 9.7355720e-002 5.1592080e-002 +v -5.8922160e-002 7.7545490e-002 4.2961390e-002 +v -5.3121320e-002 7.7912430e-002 4.3334920e-002 +v -5.0745740e-002 7.6148400e-002 4.3137630e-002 +v -4.7401820e-002 7.5550340e-002 4.2630140e-002 +v -4.5055620e-002 7.8796280e-002 4.2341310e-002 +v -3.9517650e-002 7.8127780e-002 4.2918620e-002 +v -1.5245570e-002 8.2940770e-002 5.6934590e-002 +v -1.4557790e-002 7.6582160e-002 5.6493250e-002 +v -5.9406000e-003 7.9038240e-002 5.7969830e-002 +v 3.7176540e-002 1.1064404e-001 1.8811330e-002 +v 2.3929700e-003 1.3162713e-001 1.1955100e-002 +v -9.3644210e-002 1.1789378e-001 1.8662080e-002 +v -6.3939810e-002 7.8621830e-002 4.2083520e-002 +v -4.5376460e-002 8.2383550e-002 4.3282120e-002 +v -3.6505460e-002 8.1152260e-002 4.3162320e-002 +v -3.3244340e-002 8.2266590e-002 4.1852180e-002 +v -3.0800650e-002 8.0068420e-002 4.1798070e-002 +v -2.0578500e-003 8.0998290e-002 5.7553840e-002 +v 8.1848100e-003 8.0756170e-002 5.5374510e-002 +v -1.2953370e-002 1.1593580e-001 3.8920230e-002 +v -7.8081470e-002 1.2351940e-001 5.2136990e-002 +v -2.6580930e-002 1.5567694e-001 -4.1963400e-003 +v -8.2471600e-002 1.1624130e-001 -2.3236300e-003 +v -2.7538480e-002 7.9964780e-002 4.7697210e-002 +v 1.2556400e-003 8.3845570e-002 5.7446440e-002 +v 6.1508300e-003 8.3406240e-002 5.6463500e-002 +v -6.2433240e-002 8.4035270e-002 4.4203120e-002 +v -5.9867170e-002 8.0540510e-002 4.3277090e-002 +v -5.5238340e-002 8.1999450e-002 4.4984770e-002 +v -5.4000400e-002 8.0568410e-002 4.4601460e-002 +v -5.0027020e-002 8.1311330e-002 4.4264180e-002 +v -4.1996120e-002 8.1083670e-002 4.2456150e-002 +v -3.9357940e-002 8.3631380e-002 4.3502350e-002 +v -8.6161480e-002 1.0838594e-001 1.8244920e-002 +v -8.6723010e-002 9.9917250e-002 3.5537100e-003 +v -2.2413700e-002 8.3283520e-002 5.5590700e-002 +v -1.6993180e-002 8.2555820e-002 5.7523880e-002 +v -1.2406010e-002 8.5222570e-002 5.7267780e-002 +v -7.4442100e-003 1.1693417e-001 3.9283850e-002 +v -2.1452000e-003 1.1143287e-001 4.2436620e-002 +v -7.5718220e-002 1.2522734e-001 5.3087330e-002 +v -7.7056660e-002 1.3193469e-001 5.2462430e-002 +v -6.1121040e-002 1.5569660e-001 2.2517050e-002 +v -3.7538540e-002 1.2744127e-001 1.5320870e-002 +v -2.0516700e-003 1.0093469e-001 4.5625920e-002 +v -6.4992150e-002 8.4550900e-002 4.4120060e-002 +v -5.7861950e-002 8.3944360e-002 4.4186030e-002 +v -4.5681080e-002 8.4988010e-002 4.4159500e-002 +v -3.5022640e-002 8.2888160e-002 4.2912760e-002 +v -2.9982010e-002 8.5402300e-002 4.3745080e-002 +v -8.8892260e-002 9.9209100e-002 9.5703200e-003 +v -1.9135300e-002 8.3474800e-002 5.7217390e-002 +v -8.3489710e-002 1.0724729e-001 7.5790000e-004 +v -7.0112800e-002 1.1790350e-001 5.2714160e-002 +v -3.5526320e-002 1.7595563e-001 -4.8676200e-003 +v -7.0831390e-002 1.2254425e-001 5.3274880e-002 +v 4.5133810e-002 9.3630690e-002 6.2336800e-003 +v -5.3616700e-002 8.5346850e-002 4.5332470e-002 +v -4.9000840e-002 8.6221680e-002 4.5352040e-002 +v -3.6744880e-002 8.6083690e-002 4.3612890e-002 +v -1.0872600e-002 8.8826770e-002 5.6665490e-002 +v -3.8450200e-003 8.4787810e-002 5.7197980e-002 +v -4.9020070e-002 1.1771293e-001 3.1581430e-002 +v -4.2914400e-002 1.1835991e-001 3.0645040e-002 +v -5.7684530e-002 1.5561695e-001 1.2983110e-002 +v -2.5411730e-002 1.2472533e-001 1.2886000e-004 +v 1.9012230e-002 1.2736197e-001 1.7786580e-002 +v -5.9498600e-002 8.8845470e-002 4.5109290e-002 +v -5.6931050e-002 8.8101500e-002 4.4692930e-002 +v 3.5765600e-003 1.3138981e-001 7.2086000e-003 +v -1.6683350e-002 8.7266690e-002 5.6741190e-002 +v -8.4980800e-003 8.3990470e-002 5.7605220e-002 +v 3.5078200e-003 8.6339520e-002 5.7048320e-002 +v -2.8398700e-002 1.8070650e-001 -7.8469500e-003 +v -7.6565830e-002 1.1674037e-001 5.1489350e-002 +v 1.7869430e-002 9.0898610e-002 4.8712940e-002 +v -4.0342100e-002 1.1669551e-001 3.2460200e-002 +v 5.9105700e-003 1.3140929e-001 1.6823750e-002 +v -8.5777550e-002 9.1701370e-002 -4.6970000e-005 +v -5.0372230e-002 8.8844660e-002 4.5188000e-002 +v -4.4434130e-002 8.7654530e-002 4.3477620e-002 +v -4.2056390e-002 8.6711520e-002 4.2534630e-002 +v -3.3058460e-002 8.6185500e-002 4.2560350e-002 +v -2.9241910e-002 9.0453360e-002 4.4236610e-002 +v -6.8964100e-003 8.4432910e-002 5.7168580e-002 +v -6.6210600e-003 9.0415250e-002 5.6879750e-002 +v -1.2439100e-003 8.9093200e-002 5.6552120e-002 +v 9.4076000e-003 9.0328050e-002 5.4214140e-002 +v 4.0194810e-002 1.0231597e-001 -2.0048600e-003 +v -8.6227130e-002 1.1466841e-001 2.2102000e-003 +v -8.9495490e-002 9.5632430e-002 1.4234810e-002 +v -6.7132160e-002 1.5709447e-001 -6.2032000e-003 +v -5.2935640e-002 9.0913520e-002 4.4568870e-002 +v -3.6744910e-002 8.8886950e-002 4.3312050e-002 +v -1.3626110e-002 8.9787930e-002 5.6674380e-002 +v 2.3337130e-002 1.2353449e-001 2.4874140e-002 +v -3.7053790e-002 1.2715094e-001 3.5474000e-004 +v -7.3696690e-002 1.5613015e-001 1.4359790e-002 +v -6.5592380e-002 9.1042400e-002 4.4092080e-002 +v -5.8997380e-002 9.2030670e-002 4.5335270e-002 +v -3.3238910e-002 8.8573580e-002 4.3697040e-002 +v -3.1834990e-002 9.0722970e-002 4.4173460e-002 +v -2.0022170e-002 8.8032110e-002 5.5589350e-002 +v -1.1213830e-002 9.2366370e-002 5.6105260e-002 +v 3.9108440e-002 1.0829072e-001 1.3142330e-002 +v 2.8675700e-002 1.1959600e-001 2.4545910e-002 +v -6.8940210e-002 1.5652777e-001 -1.9716000e-003 +v -6.2615110e-002 9.1126880e-002 4.5090730e-002 +v 3.0444560e-002 1.1886441e-001 2.0821750e-002 +v -1.5241090e-002 9.1821720e-002 5.5817230e-002 +v -5.6221700e-003 9.3235010e-002 5.5893630e-002 +v 4.7989900e-003 9.1654840e-002 5.4715170e-002 +v -6.8282400e-002 9.2376840e-002 4.2388730e-002 +v -5.5623730e-002 9.2187420e-002 4.5054970e-002 +v -5.1901030e-002 9.5457620e-002 4.3937650e-002 +v -4.8809030e-002 9.1083890e-002 4.4456690e-002 +v -4.5411560e-002 9.1002130e-002 4.3252770e-002 +v -4.4514550e-002 9.4860420e-002 4.2972490e-002 +v -3.9430320e-002 8.9597620e-002 4.3177890e-002 +v -3.5642240e-002 9.2617410e-002 4.4238490e-002 +v -1.2246000e-004 9.3201160e-002 5.5398380e-002 +v 9.5104600e-003 9.5483870e-002 5.0910600e-002 +v 2.1441660e-002 9.1354960e-002 4.8043360e-002 +v -8.9830300e-003 1.6926449e-001 -2.2683480e-002 +v -7.3019050e-002 1.5602104e-001 2.2419340e-002 +v -6.4760430e-002 1.5311588e-001 -2.0371200e-003 +v -6.9368510e-002 9.5242790e-002 4.2129000e-002 +v -6.0117140e-002 9.5552910e-002 4.4183820e-002 +v -2.9241690e-002 9.4290440e-002 4.4821190e-002 +v -2.6561430e-002 9.3289510e-002 4.4975420e-002 +v -1.4394030e-002 9.4587640e-002 5.3993500e-002 +v -8.8691600e-003 9.5400260e-002 5.4445980e-002 +v -1.2188700e-003 9.6201750e-002 5.3815910e-002 +v 4.0479000e-003 9.5817360e-002 5.2936770e-002 +v -4.6019400e-003 1.2428544e-001 3.3471960e-002 +v -7.8436460e-002 1.3928013e-001 4.8329360e-002 +v 1.0774610e-002 1.3079162e-001 1.4341740e-002 +v -5.6623730e-002 9.6322170e-002 4.3667910e-002 +v -3.6298870e-002 9.5695620e-002 4.3580310e-002 +v -2.4379930e-002 9.5866450e-002 4.4434530e-002 +v 1.0915500e-002 1.2633629e-001 2.9857020e-002 +v -5.8622700e-003 9.7350210e-002 5.2743650e-002 +v 1.6973450e-002 9.7106620e-002 4.7440920e-002 +v -6.7231980e-002 9.9173950e-002 4.1593880e-002 +v -5.4994210e-002 9.9640820e-002 4.2955230e-002 +v -4.8617990e-002 9.6452700e-002 4.4183060e-002 +v -5.5369000e-002 1.5442476e-001 1.6160650e-002 +v -9.4243550e-002 1.2207432e-001 2.3568470e-002 +v 1.3242990e-002 9.6738240e-002 4.8750160e-002 +v 2.0639290e-002 9.6602480e-002 4.6971000e-002 +v 7.3429700e-003 1.2098188e-001 3.5973430e-002 +v -1.3493870e-002 1.2882438e-001 5.9690700e-003 +v -2.0110640e-002 1.2504545e-001 2.3588310e-002 +v -6.9438450e-002 1.6479930e-001 -1.7218700e-002 +v -6.4028050e-002 9.7838670e-002 4.2565330e-002 +v -5.1996350e-002 9.9707850e-002 4.2716590e-002 +v -4.3990880e-002 9.9425460e-002 4.2383430e-002 +v -3.9738250e-002 1.0215357e-001 4.0574410e-002 +v -3.5931490e-002 9.9809950e-002 4.2335800e-002 +v -3.0867600e-002 9.6914680e-002 4.4651400e-002 +v -2.8342070e-002 9.7782680e-002 4.3761280e-002 +v -2.5622580e-002 9.8713420e-002 4.4210890e-002 +v -8.5236620e-002 1.1077356e-001 2.4537670e-002 +v 7.1936000e-003 9.8859470e-002 4.8419510e-002 +v 9.6509200e-003 1.0108782e-001 4.7373080e-002 +v 1.3487100e-002 1.0076420e-001 4.7454290e-002 +v 7.7389800e-003 1.3147500e-001 1.1682970e-002 +v 8.0905000e-004 1.1633319e-001 4.0167560e-002 +v -7.2652570e-002 1.6567918e-001 -1.8212480e-002 +v -5.6009400e-003 1.3076674e-001 1.0516060e-002 +v -2.6303720e-002 1.2518875e-001 1.7392980e-002 +v -4.7590430e-002 1.0081180e-001 4.2349150e-002 +v -4.1460830e-002 9.8544800e-002 4.1778620e-002 +v -3.3582070e-002 1.0383908e-001 4.0737990e-002 +v -2.2870240e-002 1.0284737e-001 4.3544750e-002 +v -2.2361970e-002 9.8207610e-002 4.4765940e-002 +v -1.8870510e-002 9.8973200e-002 4.4489280e-002 +v -7.1433690e-002 7.7573520e-002 3.8060760e-002 +v -7.3001150e-002 1.1826712e-001 5.3034590e-002 +v -6.8466430e-002 1.3498146e-001 -8.3359800e-003 +v -7.4683810e-002 1.0786100e-001 -9.0477100e-003 +v -6.4958960e-002 1.5852021e-001 -1.2595320e-002 +v -7.8931700e-002 1.5093057e-001 3.5151900e-002 +v -7.4113550e-002 9.9442520e-002 3.8337710e-002 +v -7.0456930e-002 1.0098777e-001 3.9794060e-002 +v -5.9058760e-002 1.0041260e-001 4.2725130e-002 +v -4.9187330e-002 1.0452012e-001 4.0301390e-002 +v -2.9151180e-002 1.0197369e-001 4.2633060e-002 +v -1.1599720e-002 1.0107813e-001 4.4191660e-002 +v 5.1450400e-003 1.0163906e-001 4.5423010e-002 +v -5.1495700e-002 1.0496738e-001 4.0347210e-002 +v -2.0218210e-002 1.0214391e-001 4.3701160e-002 +v 4.2515900e-003 1.0523743e-001 4.2563550e-002 +v 1.6832800e-002 1.0337487e-001 4.5287270e-002 +v -2.5661080e-002 1.2562669e-001 4.5537500e-003 +v -7.2141950e-002 1.0536685e-001 3.7523210e-002 +v -6.4984570e-002 1.0371550e-001 4.0647810e-002 +v -6.0652480e-002 1.0467197e-001 4.0906390e-002 +v -5.5308980e-002 1.0365394e-001 4.1516690e-002 +v -4.4243240e-002 1.0431726e-001 4.1339990e-002 +v -1.5513340e-002 1.0436131e-001 4.2919420e-002 +v -7.6323200e-003 1.0304531e-001 4.3710640e-002 +v -7.8046900e-003 1.0516619e-001 4.3825460e-002 +v 9.7163200e-003 1.0523506e-001 4.3603830e-002 +v 3.0300390e-002 1.1553645e-001 2.8685010e-002 +v -4.7496910e-002 1.0635662e-001 4.0165640e-002 +v -3.8978950e-002 1.0683037e-001 3.8247660e-002 +v -2.5869310e-002 1.0426705e-001 4.2207540e-002 +v -1.8057930e-002 1.0503919e-001 4.2802830e-002 +v -1.5180030e-002 1.0807750e-001 4.2350430e-002 +v -3.8981500e-003 1.0566175e-001 4.4047190e-002 +v 2.6820000e-005 1.0446731e-001 4.3775910e-002 +v 1.1978350e-002 1.0403629e-001 4.5396310e-002 +v 1.5004970e-002 1.0726898e-001 4.1811990e-002 +v 2.6488060e-002 1.2230287e-001 2.0398110e-002 +v -3.6225630e-002 1.0634244e-001 3.8644860e-002 +v -2.1126780e-002 1.0932290e-001 4.0715320e-002 +v -1.2819810e-002 1.0457100e-001 4.3465690e-002 +v 5.2847900e-003 1.0943666e-001 4.1674980e-002 +v 8.9403700e-003 1.0710645e-001 4.1243400e-002 +v -5.1839670e-002 1.6062039e-001 7.1421300e-003 +v -5.4201370e-002 1.1451730e-001 3.4843990e-002 +v 1.3226250e-002 1.2958070e-001 1.9689610e-002 +v -6.9382410e-002 1.0865787e-001 3.7507800e-002 +v -6.7691040e-002 1.0734145e-001 3.8018440e-002 +v -6.3782400e-002 1.1037270e-001 3.7579790e-002 +v -5.0749390e-002 1.0928682e-001 3.8297580e-002 +v -9.3936200e-003 1.0742813e-001 4.3454570e-002 +v 1.1760100e-003 1.0932531e-001 4.2662800e-002 +v 9.8020300e-003 1.1003994e-001 3.9945400e-002 +v 2.0131290e-002 1.0732778e-001 4.0323840e-002 +v -2.7872800e-003 1.0577531e-001 -2.2459030e-002 +v -5.4996890e-002 1.0774199e-001 3.9424590e-002 +v -4.5966740e-002 1.0905146e-001 3.8754110e-002 +v -4.2324540e-002 1.0737278e-001 3.9456440e-002 +v -3.2161240e-002 1.0896504e-001 3.8102720e-002 +v -3.0770180e-002 1.1597313e-001 3.2858800e-002 +v -1.1608610e-002 1.0983707e-001 4.2475330e-002 +v -2.9428320e-002 9.3166620e-002 -2.4931860e-002 +v -8.0043570e-002 9.2080160e-002 -9.4198200e-003 +v -4.9797430e-002 1.1342104e-001 3.5117920e-002 +v -4.3723850e-002 1.6191369e-001 5.7713400e-003 +v -5.7981740e-002 1.0943152e-001 3.7997640e-002 +v -4.1491180e-002 1.1224766e-001 3.5873450e-002 +v -2.4929830e-002 1.1592775e-001 3.4094730e-002 +v -2.0881690e-002 1.1409528e-001 3.7872990e-002 +v -7.5519700e-003 1.1183813e-001 4.2039690e-002 +v 3.7667200e-003 1.1240547e-001 4.1494710e-002 +v -6.2829620e-002 1.5189480e-001 -9.2373400e-003 +v -5.9195950e-002 1.1320797e-001 3.6234680e-002 +v -5.1079080e-002 9.3892810e-002 -2.1761690e-002 +v -7.3945370e-002 8.4374880e-002 -1.5154490e-002 +v -7.2146240e-002 1.3486431e-001 -7.7592200e-003 +v -1.9408870e-002 1.7041104e-001 -2.0994830e-002 +v -5.5530450e-002 1.4905531e-001 -1.9602100e-003 +v 1.6688460e-002 3.6976600e-002 4.3000600e-002 +v -5.2277330e-002 1.1775075e-001 3.3769460e-002 +v -6.9201380e-002 9.3039200e-002 -1.6486120e-002 +v 2.6579210e-002 1.1702438e-001 3.0867940e-002 +v -2.3574310e-002 3.7036910e-002 5.4144750e-002 +v -7.3775100e-003 3.8988430e-002 4.8929450e-002 +v 1.3234660e-002 3.8453060e-002 4.4501470e-002 +v 1.9487350e-002 4.0809290e-002 4.2641060e-002 +v -6.3953930e-002 1.4694729e-001 3.8484200e-002 +v -4.9579470e-002 3.6096540e-002 4.5955360e-002 +v -4.3323650e-002 3.6286400e-002 4.4042360e-002 +v -2.9047200e-002 1.2556338e-001 7.7617700e-003 +v -1.7343100e-003 3.9476800e-002 4.7262900e-002 +v -3.1358130e-002 1.5362199e-001 -4.6738900e-003 +v 2.5822000e-003 1.0747582e-001 -2.0606030e-002 +v -5.6802300e-002 1.4514674e-001 3.1740300e-002 +v -5.6464330e-002 3.7683110e-002 4.6819640e-002 +v -5.0964750e-002 3.8312290e-002 4.6286140e-002 +v -5.0980410e-002 1.3486613e-001 2.7585000e-002 +v -2.5647410e-002 3.8860730e-002 5.4161390e-002 +v -2.2542110e-002 4.0615780e-002 5.3986030e-002 +v -1.7618010e-002 3.8911170e-002 5.2403440e-002 +v -1.9711750e-002 1.6829145e-001 -1.3020960e-002 +v 2.3780070e-002 9.5222940e-002 4.6347330e-002 +v 1.4744290e-002 4.2716950e-002 4.4510310e-002 +v 2.1691360e-002 4.0161530e-002 4.0846450e-002 +v -6.4067240e-002 9.0172190e-002 -1.8855520e-002 +v 2.0319150e-002 1.0041961e-001 4.5760520e-002 +v -3.6425000e-002 9.3630690e-002 -2.3534630e-002 +v -1.4981170e-002 4.2571420e-002 5.1404530e-002 +v -5.7335340e-002 1.2340101e-001 4.0231470e-002 +v -5.4172560e-002 1.2337919e-001 3.7576440e-002 +v 2.2625210e-002 4.3621680e-002 4.0904580e-002 +v 2.8810520e-002 4.3352290e-002 3.2157720e-002 +v -4.2764160e-002 1.5727487e-001 5.2016200e-003 +v 9.2231900e-003 4.4125090e-002 4.5057440e-002 +v 1.5048210e-002 4.5755840e-002 4.3793870e-002 +v -6.3757290e-002 1.0251144e-001 -1.7484400e-002 +v -3.4070430e-002 1.6148975e-001 -1.3786960e-002 +v -8.2191500e-002 7.5610200e-002 1.6542620e-002 +v -6.6299420e-002 1.2337119e-001 5.0615920e-002 +v -1.5510100e-002 4.5283110e-002 5.0653040e-002 +v 1.8928020e-002 4.4249610e-002 4.3009830e-002 +v 2.5821800e-002 4.6326610e-002 3.8277230e-002 +v 2.7268700e-002 4.4547790e-002 3.6152520e-002 +v -4.5301340e-002 1.5695057e-001 7.2036900e-003 +v 2.3855760e-002 1.0616625e-001 3.9378080e-002 +v 2.1632670e-002 4.8127270e-002 4.0694430e-002 +v 4.3785360e-002 4.8803700e-002 3.1343420e-002 +v 4.8074790e-002 4.8969960e-002 2.8165490e-002 +v 5.2663090e-002 4.7673620e-002 2.1201270e-002 +v -5.2722450e-002 4.4722850e-002 4.4143250e-002 +v -3.0071610e-002 1.7258324e-001 -6.3597700e-003 +v -3.4508050e-002 1.5447469e-001 1.6504600e-003 +v 1.0629710e-002 4.6711810e-002 4.6472020e-002 +v 1.6743440e-002 4.8439000e-002 4.3678630e-002 +v 2.8827050e-002 9.2133370e-002 4.3920090e-002 +v -5.9937100e-002 1.2726188e-001 4.0771270e-002 +v -3.6752090e-002 1.5802075e-001 4.1862000e-003 +v -3.7885390e-002 1.6199719e-001 2.4686000e-004 +v -2.2047790e-002 1.8348586e-001 -1.2094990e-002 +v -2.4364620e-002 1.8096836e-001 -9.8312000e-003 +v -4.4882280e-002 1.5052959e-001 7.6451700e-003 +v 2.6996760e-002 5.1317780e-002 3.8752040e-002 +v 4.7735750e-002 5.2751040e-002 3.0797290e-002 +v 5.1703790e-002 4.8857380e-002 2.4147970e-002 +v -6.7504360e-002 1.1424088e-001 4.8036050e-002 +v -1.6257520e-002 1.6031250e-001 -9.6926000e-003 +v -6.3926300e-002 1.6792441e-001 -4.0730420e-002 +v -4.1665290e-002 1.4996141e-001 4.5405000e-003 +v -3.5203230e-002 1.6493551e-001 -2.6810000e-003 +v 4.1318770e-002 9.9496740e-002 2.4275750e-002 +v 1.4055220e-002 5.2523910e-002 4.8593880e-002 +v 1.9421220e-002 5.1321300e-002 4.4798910e-002 +v 2.3677990e-002 5.1474390e-002 4.1053270e-002 +v 3.4258130e-002 5.1930810e-002 3.2757880e-002 +v 5.5957340e-002 5.3147410e-002 2.3197720e-002 +v -3.9937960e-002 1.4922850e-001 1.6017200e-003 +v -4.6988800e-002 1.2600802e-001 2.6985500e-002 +v -2.7708370e-002 9.0081290e-002 -3.1911460e-002 +v 1.9204630e-002 5.5166510e-002 4.7722150e-002 +v 2.1886000e-002 5.3927560e-002 4.5102460e-002 +v 3.1286270e-002 5.2863840e-002 3.6913620e-002 +v 4.6661160e-002 5.4719230e-002 3.1976810e-002 +v 5.1823730e-002 5.3276700e-002 2.7927010e-002 +v -2.9264880e-002 1.6140418e-001 -2.1039500e-003 +v -6.8700770e-002 1.4463537e-001 4.3041630e-002 +v -5.6070060e-002 1.5000706e-001 2.9867640e-002 +v 4.4717850e-002 9.4802660e-002 1.2024710e-002 +v -4.1804090e-002 1.5582081e-001 6.4548200e-003 +v -6.8369340e-002 1.2289287e-001 5.2437860e-002 +v -6.4114810e-002 9.5509880e-002 -1.8114610e-002 +v -1.8383130e-002 1.8543664e-001 -1.7136370e-002 +v 1.1745400e-002 5.6678340e-002 5.1914060e-002 +v -5.9375360e-002 1.1998238e-001 4.0548240e-002 +v 5.9092080e-002 5.7956980e-002 2.0270120e-002 +v 4.3547740e-002 9.7389400e-002 1.7314650e-002 +v -2.6291780e-002 1.5963381e-001 -5.1845000e-004 +v 1.4904780e-002 5.6350380e-002 4.9522780e-002 +v 2.4286200e-002 5.4958580e-002 4.3086850e-002 +v 2.8952610e-002 5.6125250e-002 4.0388970e-002 +v -4.9507770e-002 1.2949500e-001 3.0259270e-002 +v 4.0824790e-002 9.5170220e-002 2.8657920e-002 +v 1.7774800e-002 5.8243780e-002 4.8864720e-002 +v 3.3573840e-002 5.8515260e-002 3.8310990e-002 +v 3.6385040e-002 5.6996480e-002 3.3601460e-002 +v -6.4205010e-002 1.2243894e-001 4.8008340e-002 +v -6.5424500e-002 1.4011279e-001 4.1308960e-002 +v 5.0801340e-002 5.7308080e-002 3.0001390e-002 +v 5.6671750e-002 5.6970820e-002 2.4291920e-002 +v -4.9349930e-002 1.4913519e-001 1.1274060e-002 +v -6.9760570e-002 1.3442855e-001 4.8265220e-002 +v 1.9537060e-002 6.0003780e-002 4.8576140e-002 +v 2.7013910e-002 5.9952790e-002 4.3454420e-002 +v 5.7679430e-002 6.1392970e-002 2.4201790e-002 +v -5.6916540e-002 1.2623512e-001 3.9426610e-002 +v 2.3469280e-002 1.1656262e-001 3.3537270e-002 +v -5.8298640e-002 1.3885500e-001 3.2937460e-002 +v 6.4598400e-003 6.0297430e-002 5.4780030e-002 +v 1.0406020e-002 5.9162400e-002 5.2484370e-002 +v 2.3183950e-002 5.8654360e-002 4.5871060e-002 +v 3.3040360e-002 6.1773840e-002 3.9781440e-002 +v -6.4348220e-002 1.2628088e-001 4.6650200e-002 +v -5.7031440e-002 1.1562007e-001 3.6494880e-002 +v 5.4451560e-002 5.8342890e-002 2.7653010e-002 +v -3.0134400e-002 1.7011322e-001 -7.3591600e-003 +v -3.7077100e-002 1.5986369e-001 1.6096500e-003 +v -5.6032760e-002 1.3731083e-001 3.1970590e-002 +v -6.7676470e-002 1.4150325e-001 4.3868140e-002 +v 9.9911700e-003 6.2735270e-002 5.4009240e-002 +v 1.4521510e-002 6.1382890e-002 5.0500900e-002 +v 3.0051740e-002 6.2169610e-002 4.1545810e-002 +v 3.7519170e-002 6.1062710e-002 3.4366020e-002 +v 5.3944010e-002 6.1391550e-002 2.8268530e-002 +v 5.9119900e-002 6.3128810e-002 2.1561830e-002 +v -2.4366390e-002 1.7693266e-001 -1.1719630e-002 +v -1.3253420e-002 1.6627152e-001 -1.4120370e-002 +v 3.9218740e-002 1.0669250e-001 2.0450190e-002 +v -1.7968980e-002 1.8078031e-001 -1.8103430e-002 +v 2.1902390e-002 6.0875970e-002 4.7282360e-002 +v 3.5341750e-002 6.1630030e-002 3.7606020e-002 +v -6.2145620e-002 1.3599775e-001 3.6700970e-002 +v 5.6820620e-002 6.3691150e-002 2.5286090e-002 +v -3.2800040e-002 1.5948699e-001 2.1962800e-003 +v 1.1212140e-002 6.6584120e-002 5.3982180e-002 +v 1.2919590e-002 6.4203580e-002 5.2441150e-002 +v 2.0126950e-002 6.3851330e-002 4.7919660e-002 +v 3.5971760e-002 6.6669610e-002 3.7781400e-002 +v 3.9906940e-002 6.4361260e-002 3.1686660e-002 +v -6.6702350e-002 1.3210600e-001 4.5480940e-002 +v -4.1601430e-002 1.5978000e-001 3.5374700e-003 +v 3.3044580e-002 1.0766252e-001 3.1916150e-002 +v 2.4672100e-002 6.3694500e-002 4.5204640e-002 +v 2.6108660e-002 6.8007640e-002 4.3902690e-002 +v 3.3363940e-002 6.7054760e-002 3.9729480e-002 +v 4.2915790e-002 6.6707700e-002 2.6994720e-002 +v 5.4714960e-002 6.4697160e-002 2.6979680e-002 +v -1.6530940e-002 1.6325000e-001 -9.2475200e-003 +v -1.7891600e-002 1.6113800e-001 -6.7072700e-003 +v 4.1118120e-002 9.7491260e-002 -3.9756700e-003 +v 2.3386770e-002 7.0075990e-002 4.7012620e-002 +v 3.8102900e-002 6.5678440e-002 3.5132520e-002 +v 1.0145240e-002 1.2221678e-001 3.4718950e-002 +v 5.8392410e-002 6.6741240e-002 2.1979460e-002 +v 3.8302050e-002 8.4549140e-002 -1.4478830e-002 +v 3.4126440e-002 9.7053980e-002 3.7590390e-002 +v -3.1355740e-002 1.5809888e-001 1.9128800e-003 +v -5.8259510e-002 1.4099493e-001 3.2440640e-002 +v -6.6817230e-002 1.1951525e-001 5.1490220e-002 +v -6.8090040e-002 1.1647050e-001 5.1151230e-002 +v 1.6568300e-002 6.6269890e-002 5.1009890e-002 +v 2.9362870e-002 6.6509780e-002 4.2289380e-002 +v 3.7027180e-002 9.3949630e-002 -1.1674040e-002 +v 5.6412730e-002 6.7659930e-002 2.3969320e-002 +v -6.1295740e-002 1.4519988e-001 3.7137830e-002 +v 8.3873000e-003 1.1336223e-001 3.9792610e-002 +v 1.1807030e-002 7.0920980e-002 5.4240490e-002 +v 2.9741730e-002 7.0647100e-002 4.1653890e-002 +v 3.6294410e-002 7.1220700e-002 3.7114610e-002 +v 3.9899680e-002 7.0294820e-002 3.2720020e-002 +v -6.2763130e-002 1.3778012e-001 3.6678590e-002 +v -1.5815440e-002 1.7504938e-001 -1.8654160e-002 +v -9.2268990e-002 1.1475156e-001 1.7017380e-002 +v -9.4964000e-004 1.0141111e-001 4.4290070e-002 +v -6.3712920e-002 1.1274250e-001 3.8006760e-002 +v -6.1096020e-002 1.1701650e-001 3.9654020e-002 +v 2.0991870e-002 6.9335450e-002 4.9003540e-002 +v 2.5658530e-002 7.0550460e-002 4.4539930e-002 +v 3.2978560e-002 7.3500690e-002 4.0486510e-002 +v 4.2156130e-002 6.9717580e-002 2.8318230e-002 +v -5.5516860e-002 1.2956070e-001 3.6598450e-002 +v -4.0802290e-002 1.6436059e-001 3.7448800e-003 +v -6.2546500e-003 1.0121650e-001 4.4322030e-002 +v -1.0986820e-002 1.6621199e-001 -1.6047550e-002 +v -3.0351420e-002 1.6448158e-001 -5.3291400e-003 +v 2.6110920e-002 1.0088990e-001 4.1733260e-002 +v -6.5599940e-002 1.1329504e-001 4.2318710e-002 +v 2.8814660e-002 9.6712680e-002 4.2257700e-002 +v 1.5263280e-002 7.1571940e-002 5.2717390e-002 +v 2.8982400e-002 7.4088480e-002 4.3447240e-002 +v 4.4872540e-002 7.5516710e-002 2.3155250e-002 +v -7.8225230e-002 1.4962481e-001 -2.5019400e-003 +v -4.6094940e-002 1.5296850e-001 9.0029700e-003 +v -5.2369030e-002 1.4682913e-001 1.8934650e-002 +v -2.1592100e-002 1.5763440e-001 -6.8623600e-003 +v 1.7176770e-002 7.3066230e-002 5.1826600e-002 +v 2.2687500e-002 7.5149180e-002 4.9312500e-002 +v 3.5472040e-002 7.3076670e-002 3.8482270e-002 +v -8.9480840e-002 1.3839976e-001 2.5061450e-002 +v -5.3216730e-002 1.3221978e-001 3.2978380e-002 +v -3.7776780e-002 1.5551947e-001 4.3700800e-003 +v -9.0549380e-002 1.3511875e-001 2.1680550e-002 +v -6.3366580e-002 1.3037076e-001 4.1669940e-002 +v 1.4074270e-002 7.6651720e-002 5.4221350e-002 +v 1.8109790e-002 7.5806590e-002 5.2488260e-002 +v 4.2209940e-002 7.8861480e-002 2.9187200e-002 +v -5.2115930e-002 1.4179906e-001 2.0510310e-002 +v 2.9063090e-002 1.1149602e-001 3.3805790e-002 +v -5.4731460e-002 1.4267229e-001 2.8980480e-002 +v 2.5903640e-002 7.5536040e-002 4.6416650e-002 +v 3.1298760e-002 7.5907440e-002 4.2699060e-002 +v 3.8446170e-002 7.5649430e-002 3.5050640e-002 +v 4.6351670e-002 7.4079520e-002 1.8354320e-002 +v -4.7656560e-002 1.3077525e-001 2.5523570e-002 +v -1.1447430e-002 1.7131059e-001 -1.9602980e-002 +v -3.6647240e-002 1.6640131e-001 -2.8167000e-004 +v -4.6653530e-002 1.5917824e-001 7.8019000e-003 +v -4.5569890e-002 1.4663612e-001 5.6514200e-003 +v 4.1438880e-002 9.2365100e-002 -7.4587000e-003 +v -6.4287420e-002 1.3463625e-001 3.9945640e-002 +v -6.1128890e-002 1.3178328e-001 3.8915910e-002 +v -4.7843540e-002 1.2215063e-001 2.8833160e-002 +v -4.9536830e-002 1.2491344e-001 3.1778440e-002 +v -7.1135380e-002 1.3817656e-001 4.7853960e-002 +v 1.0113870e-002 7.6468110e-002 5.5256790e-002 +v 1.7897450e-002 7.9516550e-002 5.2759530e-002 +v 2.1740850e-002 8.0250650e-002 5.0425390e-002 +v 2.5271590e-002 7.8724920e-002 4.8026570e-002 +v 3.0885040e-002 7.8999480e-002 4.3388770e-002 +v -6.2441930e-002 1.4084781e-001 3.6965840e-002 +v -6.2165060e-002 1.5666850e-001 -1.7837760e-002 +v 2.0657260e-002 1.0416830e-001 4.3004680e-002 +v -6.3602800e-002 1.1571453e-001 4.2572290e-002 +v 1.4424020e-002 8.0085500e-002 5.3755600e-002 +v 2.8779340e-002 8.2553250e-002 4.4527350e-002 +v 4.4450130e-002 8.1846900e-002 2.4552920e-002 +v 4.5541990e-002 8.3338380e-002 1.9700850e-002 +v -4.9665810e-002 1.2063801e-001 3.2163270e-002 +v -2.9177290e-002 1.7619959e-001 -5.6241100e-003 +v -5.8203130e-002 1.3270975e-001 3.6918680e-002 +v 3.8997050e-002 9.7088220e-002 -7.7799300e-003 +v -5.4725800e-002 1.2071262e-001 3.7451450e-002 +v 1.3189120e-002 8.4211180e-002 5.3065830e-002 +v -1.9926300e-002 1.6489742e-001 -9.9900200e-003 +v 2.0153130e-002 1.1849719e-001 3.4271250e-002 +v -5.5859940e-002 1.1774313e-001 3.7253480e-002 +v 1.8045260e-002 8.3623160e-002 5.1285840e-002 +v -6.3757130e-002 1.5912175e-001 -5.0155730e-002 +v -1.8527620e-002 1.7653197e-001 -1.7043540e-002 +v 2.8734400e-002 1.0360053e-001 3.8035240e-002 +v 4.1414010e-002 1.0284216e-001 1.6578920e-002 +v 2.4411730e-002 9.8016880e-002 4.4687400e-002 +v 2.0925180e-002 8.6311430e-002 4.9433120e-002 +v 3.0445010e-002 8.4959560e-002 4.3011090e-002 +v 3.3030090e-002 8.3781640e-002 4.1636930e-002 +v 3.6975090e-002 7.9876480e-002 3.7198390e-002 +v -7.7721460e-002 1.1355888e-001 4.8155990e-002 +v 2.9250000e-002 1.0651935e-001 3.6590330e-002 +v -5.3078180e-002 1.3754688e-001 2.8266470e-002 +v -6.2990590e-002 1.1999459e-001 4.5235530e-002 +v -6.5398320e-002 1.1751956e-001 4.8735570e-002 +v 3.3373910e-002 1.1227890e-001 2.7788130e-002 +v 3.8413590e-002 8.7489930e-002 3.5185850e-002 +v -6.1945930e-002 1.6479234e-001 -5.6647670e-002 +v -2.2876480e-002 1.7392813e-001 -1.3431140e-002 +v 4.3766230e-002 8.8390020e-002 -3.5708800e-003 +v 3.9291530e-002 1.0125969e-001 2.7550520e-002 +v 1.0936230e-002 8.6027290e-002 5.4732670e-002 +v 2.4108720e-002 8.4492600e-002 4.8292310e-002 +v 3.6758390e-002 9.9195470e-002 3.2837670e-002 +v -5.1941640e-002 1.2565987e-001 3.4587860e-002 +v -3.1582110e-002 1.6641850e-001 -5.7320000e-003 +v 7.6405900e-003 8.6427230e-002 5.6117850e-002 +v 1.6771020e-002 8.8644690e-002 5.0522960e-002 +v 3.4404610e-002 8.6932850e-002 4.0574270e-002 +v 3.6143820e-002 8.4439200e-002 3.7936930e-002 +v 4.1258830e-002 1.0361081e-001 2.6760600e-003 +v 2.4766140e-002 1.1081111e-001 3.6728360e-002 +v -2.2601590e-002 1.6250449e-001 -6.0717000e-003 +v -1.2893670e-002 1.7879041e-001 -2.2624750e-002 +v -2.4939150e-002 1.7031135e-001 -1.1329700e-002 +v -4.8468630e-002 1.4559606e-001 8.3661500e-003 +v 1.2534490e-002 8.9593930e-002 5.3394630e-002 +v 2.5872860e-002 8.8482290e-002 4.6655260e-002 +v 3.2756470e-002 8.8969130e-002 4.2215450e-002 +v -2.3343620e-002 1.6103450e-001 -3.1862400e-003 +v -9.2594970e-002 1.1943826e-001 2.6802950e-002 +v -7.4314840e-002 1.3761738e-001 -6.6698800e-003 +v -9.2499230e-002 1.2131500e-001 2.9256200e-002 +v -7.7378260e-002 1.5764266e-001 -1.4133650e-002 +v -9.2907340e-002 1.2307021e-001 3.6523230e-002 +v 2.8423340e-002 8.8011080e-002 4.4234200e-002 +v 3.5251680e-002 9.0836820e-002 3.9183920e-002 +v 1.5760560e-002 9.3203560e-002 4.9939310e-002 +v 3.8785530e-002 9.4954300e-002 3.2520220e-002 +v -6.1511220e-002 1.2373565e-001 4.3062680e-002 +v -6.8145120e-002 1.2748676e-001 5.0148970e-002 +v -2.0616710e-002 1.8237588e-001 -1.4299100e-002 +v 1.5137190e-002 1.1571495e-001 3.7031980e-002 +v -5.0718270e-002 1.5276300e-001 1.1816680e-002 +v 3.0168690e-002 1.0048686e-001 3.9404710e-002 +v -8.7426500e-002 9.5469530e-002 4.0312400e-003 +v -6.0010390e-002 1.4284463e-001 3.5449690e-002 +v -5.8603310e-002 1.4637237e-001 3.3808800e-002 +v 3.2411650e-002 9.3736150e-002 4.0890240e-002 +v -7.5917780e-002 1.4997690e-001 -1.6842050e-002 +v 1.8596570e-002 3.5293940e-002 -8.6782200e-003 +v 1.7209800e-002 3.5259400e-002 -1.4685160e-002 +v 4.4326540e-002 9.0818120e-002 2.2097520e-002 +v 3.8335910e-002 3.8830830e-002 3.0938100e-003 +v 2.2192920e-002 3.6775320e-002 -2.0919300e-003 +v 1.9636020e-002 3.8234010e-002 -1.2507670e-002 +v 2.3682120e-002 3.9762540e-002 3.7148760e-002 +v 4.6693280e-002 4.2465320e-002 6.5649500e-003 +v 2.1621110e-002 3.7657240e-002 -4.7021600e-003 +v 1.6638610e-002 3.8196090e-002 -1.9884930e-002 +v -9.0253980e-002 1.1366307e-001 3.7720210e-002 +v -9.0593870e-002 1.1373094e-001 1.0276770e-002 +v -6.2541690e-002 1.7679461e-001 -5.7821820e-002 +v -1.1091940e-002 1.7992082e-001 -2.5996430e-002 +v -6.2263130e-002 1.5219935e-001 -2.2578880e-002 +v -4.2276760e-002 9.4982570e-002 -2.2562420e-002 +v 4.3293410e-002 4.1864140e-002 2.0634400e-003 +v 4.3779590e-002 4.4530720e-002 -1.2622500e-003 +v 2.1696990e-002 4.0427270e-002 -9.4629500e-003 +v -1.1183700e-002 1.6450000e-001 -1.6151690e-002 +v -6.2372570e-002 1.5313041e-001 -2.8997120e-002 +v -9.2489300e-003 1.7725850e-001 -2.8270200e-002 +v 4.1477400e-002 8.5509410e-002 -9.1575000e-003 +v -8.1268710e-002 1.0879438e-001 2.9440660e-002 +v 4.9575680e-002 4.3815900e-002 1.4582960e-002 +v 5.2987960e-002 4.7747690e-002 5.0420000e-003 +v 2.1977540e-002 4.2855330e-002 -1.4536230e-002 +v 1.8505700e-002 3.8294100e-002 -1.7136500e-002 +v -3.5100500e-002 1.5203437e-001 -1.3279000e-004 +v 4.8749130e-002 4.5265000e-002 2.3023500e-003 +v 3.1912900e-002 9.9870060e-002 -1.4620980e-002 +v -1.4222520e-002 1.6167426e-001 -1.3349060e-002 +v -4.8663640e-002 1.3638523e-001 6.8063900e-003 +v -9.5837200e-003 1.7426102e-001 -2.8390760e-002 +v 5.2801850e-002 4.6539940e-002 1.0427720e-002 +v 5.1433800e-002 4.8485200e-002 1.0401000e-003 +v 2.3911240e-002 9.8021670e-002 -2.0807290e-002 +v 2.4567060e-002 4.4130110e-002 -1.0820840e-002 +v 2.0356810e-002 4.3662400e-002 -2.0456280e-002 +v -2.1882420e-002 1.1087418e-001 -1.9695320e-002 +v -5.3831800e-002 1.4981693e-001 2.5066610e-002 +v 5.4114210e-002 4.7773090e-002 1.7484000e-002 +v 5.6730570e-002 5.0515740e-002 1.0627080e-002 +v 4.5941820e-002 4.8138820e-002 -3.8715700e-003 +v -8.3817760e-002 1.1109094e-001 2.8524490e-002 +v 2.9207770e-002 4.7450250e-002 -8.5081800e-003 +v 2.8454920e-002 4.8067390e-002 -1.2847240e-002 +v 2.6637260e-002 4.7607100e-002 -1.6427740e-002 +v 2.2040110e-002 4.4992500e-002 -1.7528500e-002 +v 1.9120080e-002 4.7167750e-002 -2.2114680e-002 +v -1.5782200e-002 1.0072957e-001 -2.3724130e-002 +v -6.2514170e-002 1.7213119e-001 -5.2788100e-002 +v -6.2345600e-002 1.4745498e-001 -7.6600200e-003 +v 4.5598180e-002 8.8151720e-002 1.3124070e-002 +v -4.9422610e-002 1.4283525e-001 8.9728300e-003 +v -8.2761860e-002 1.1162341e-001 4.4221460e-002 +v -5.2166220e-002 1.5013661e-001 1.7448750e-002 +v -6.3616740e-002 1.4801371e-001 -2.0170260e-002 +v -5.1492690e-002 1.3796388e-001 2.3662180e-002 +v -6.1517580e-002 1.7517449e-001 -6.0631700e-002 +v 5.6524870e-002 5.0125660e-002 1.5564490e-002 +v 5.5257900e-002 5.1416260e-002 3.2062600e-003 +v 5.0318130e-002 5.2786370e-002 -3.4166300e-003 +v -6.2681950e-002 1.6744086e-001 -4.5713890e-002 +v 5.6520150e-002 5.1179900e-002 1.9940560e-002 +v 5.6907980e-002 5.1578130e-002 7.2538300e-003 +v 5.2854160e-002 5.1898670e-002 -6.2070000e-004 +v -3.8921140e-002 3.3767390e-002 -2.9042560e-002 +v 2.9740700e-002 5.0324690e-002 -1.3990860e-002 +v -6.8796190e-002 3.5117720e-002 -5.2067400e-003 +v 5.8826020e-002 5.5503780e-002 1.8647920e-002 +v -2.6160570e-002 1.2309988e-001 -4.4735500e-003 +v -5.3341960e-002 1.4401200e-001 2.4261390e-002 +v 5.8177390e-002 5.2821320e-002 1.5182420e-002 +v 5.9798140e-002 5.6840180e-002 1.3342730e-002 +v 5.4549870e-002 5.6044630e-002 -6.6158000e-004 +v 2.6775460e-002 5.1423450e-002 -2.0234060e-002 +v -8.6960400e-003 1.7291588e-001 -2.6708770e-002 +v -7.7039560e-002 7.1967020e-002 2.6405070e-002 +v -6.3069890e-002 1.5897471e-001 -4.2951850e-002 +v 3.5706690e-002 5.6083040e-002 -8.9993300e-003 +v 3.2600380e-002 5.3707520e-002 -1.1006150e-002 +v 2.9739960e-002 5.2538430e-002 -1.6224950e-002 +v 5.9238530e-002 5.6362780e-002 9.4530800e-003 +v 5.7421750e-002 5.6012210e-002 4.0245600e-003 +v 2.9062990e-002 5.5210580e-002 -1.8042060e-002 +v -1.7224410e-002 9.5214090e-002 -3.2085300e-002 +v -8.5911380e-002 1.0968787e-001 7.6582400e-003 +v 6.0594930e-002 6.1677210e-002 1.5591560e-002 +v 5.9531640e-002 6.0504600e-002 5.8397000e-003 +v 5.7306470e-002 5.9944620e-002 1.8886400e-003 +v 3.8829380e-002 5.9839830e-002 -6.4252500e-003 +v 3.0662770e-002 5.7300390e-002 -1.6518370e-002 +v -2.7762070e-002 1.2068537e-001 -9.0152900e-003 +v -8.8194590e-002 1.0314633e-001 1.7509020e-002 +v 6.0778800e-002 6.1646560e-002 1.0463990e-002 +v 3.5915080e-002 5.9916380e-002 -1.1966510e-002 +v 2.4251860e-002 5.6457470e-002 -2.4254800e-002 +v -6.1954390e-002 1.6865320e-001 -5.2621160e-002 +v -9.0557930e-002 1.1275994e-001 1.6141030e-002 +v -8.8469220e-002 1.1124294e-001 1.2679160e-002 +v 5.9558010e-002 6.3099260e-002 5.9471000e-003 +v 3.0940440e-002 6.0518080e-002 -1.8132720e-002 +v -9.3575750e-002 1.2474629e-001 2.6213300e-002 +v -9.3189820e-002 1.2019919e-001 3.7913720e-002 +v -9.2296100e-003 1.7314463e-001 -2.4197660e-002 +v -8.1739460e-002 7.6861340e-002 2.3313610e-002 +v -3.6992750e-002 1.5063932e-001 -2.0372300e-003 +v 6.0093570e-002 6.5693450e-002 1.8533320e-002 +v 5.9837240e-002 6.6423180e-002 8.5139400e-003 +v 4.0706180e-002 6.4475310e-002 -5.5920300e-003 +v 3.4745940e-002 6.3261340e-002 -1.4646740e-002 +v -6.1879660e-002 1.6000450e-001 -2.5806250e-002 +v -7.6537810e-002 1.5344875e-001 -1.2898750e-002 +v 3.8111070e-002 6.4811810e-002 -1.1142000e-002 +v 3.1909340e-002 6.4657050e-002 -1.8473410e-002 +v -8.3159350e-002 1.4674277e-001 3.0757900e-003 +v -8.7055900e-002 1.0562761e-001 9.7651100e-003 +v -7.1448330e-002 1.8105301e-001 -5.5478550e-002 +v -8.5632110e-002 1.2461094e-001 -2.7335800e-003 +v 6.0728970e-002 6.5806600e-002 1.3974830e-002 +v 3.9909650e-002 6.8171740e-002 -9.5698200e-003 +v 3.4981790e-002 6.7740790e-002 -1.5683210e-002 +v -9.1822030e-002 1.2747346e-001 3.6458650e-002 +v -6.2425420e-002 1.6366637e-001 -4.9667290e-002 +v -7.1168950e-002 1.4740156e-001 -2.7590940e-002 +v -5.0364760e-002 1.3715763e-001 1.9526100e-003 +v -5.0492650e-002 1.4159899e-001 1.6291740e-002 +v 5.9886670e-002 6.8513050e-002 1.6171610e-002 +v -6.1406990e-002 1.7268822e-001 -5.8265750e-002 +v 2.4990740e-002 6.5897320e-002 -2.3568270e-002 +v -7.4852750e-002 1.4993112e-001 -2.7752940e-002 +v -6.2225690e-002 6.0265200e-002 2.0449290e-002 +v -6.2001940e-002 3.6435020e-002 4.3918940e-002 +v 5.8374570e-002 7.1186410e-002 1.3072740e-002 +v -3.6125040e-002 1.2286688e-001 -8.2927900e-003 +v 2.9216510e-002 6.7850250e-002 -2.0418570e-002 +v -4.1681700e-002 1.2575112e-001 -7.0193300e-003 +v -7.4226550e-002 1.6437012e-001 -3.8240340e-002 +v -9.7845700e-003 1.6928488e-001 -2.4756660e-002 +v -8.9577950e-002 1.2078310e-001 3.5229100e-003 +v -6.2311930e-002 1.6371109e-001 -4.0623990e-002 +v 4.3514770e-002 9.1519890e-002 -2.6468100e-003 +v -4.8434350e-002 1.3754973e-001 1.3244980e-002 +v -8.9313160e-002 1.3653006e-001 3.0458750e-002 +v -7.4230190e-002 1.5652681e-001 -2.5167090e-002 +v 3.7378600e-002 7.3093410e-002 -1.2635370e-002 +v 2.6321810e-002 7.0240650e-002 -2.3878680e-002 +v -4.8023620e-002 1.4426649e-001 4.2498600e-003 +v -9.2019580e-002 1.1611534e-001 3.5842730e-002 +v -7.1305510e-002 7.3899020e-002 3.5969780e-002 +v -6.2059290e-002 1.5697807e-001 -3.3784580e-002 +v -9.7015300e-003 1.6738863e-001 -1.9360250e-002 +v 4.3342140e-002 7.1676120e-002 -2.2304600e-003 +v 4.1772460e-002 6.9568020e-002 -6.1596000e-003 +v 3.3505410e-002 7.2809860e-002 -1.7034800e-002 +v 2.9665000e-002 7.1506830e-002 -2.1282340e-002 +v -2.9460160e-002 1.5550263e-001 -1.1914700e-003 +v -8.6396440e-002 1.0479356e-001 5.9820600e-003 +v -5.4910700e-002 1.4662313e-001 2.8438970e-002 +v 4.4203810e-002 8.5204260e-002 -2.1170500e-003 +v 4.3264350e-002 7.5810540e-002 -3.8843900e-003 +v 1.3096990e-002 9.1126480e-002 -2.9269770e-002 +v -6.7069210e-002 9.1144610e-002 -1.7425950e-002 +v -9.0821680e-002 1.2276896e-001 6.0998500e-003 +v 4.5620000e-002 7.4684430e-002 2.6073900e-003 +v -9.3039800e-002 1.2026416e-001 1.1216820e-002 +v 4.4635590e-002 9.2794290e-002 1.7832070e-002 +v -1.1243390e-002 1.6457514e-001 -1.8240780e-002 +v 4.5511190e-002 8.6953050e-002 3.8865500e-003 +v 4.6252720e-002 7.7373870e-002 6.9140800e-003 +v 4.0281640e-002 7.2637130e-002 -9.2881000e-003 +v 4.3218200e-002 9.9486740e-002 5.0153300e-003 +v -5.1108270e-002 1.4520219e-001 1.4279480e-002 +v 4.4692980e-002 9.2688550e-002 2.2466700e-003 +v 4.3422540e-002 9.1860370e-002 2.4538450e-002 +v 4.0751360e-002 1.0554729e-001 7.5074100e-003 +v -8.5613030e-002 9.6277110e-002 -6.6514000e-004 +v 4.0721470e-002 7.8475530e-002 -8.2130000e-003 +v 3.5538080e-002 7.6062960e-002 -1.4434750e-002 +v -9.2736510e-002 1.2073095e-001 3.2692730e-002 +v -6.2278520e-002 1.5166598e-001 -1.4672730e-002 +v 4.4960220e-002 8.0942630e-002 6.1119000e-004 +v 3.7814740e-002 7.9698150e-002 -1.3289630e-002 +v 3.3864490e-002 7.8656690e-002 -1.7632490e-002 +v -9.1044280e-002 1.4199862e-001 2.1729630e-002 +v -7.4004450e-002 1.7818523e-001 -5.3916320e-002 +v -6.1768650e-002 1.6067957e-001 -3.4046350e-002 +v -4.9747450e-002 1.4112519e-001 5.2937500e-003 +v 4.1065440e-002 9.0460700e-002 2.9888620e-002 +v -7.2916360e-002 6.5057400e-002 1.8794620e-002 +v -9.0949690e-002 1.3895375e-001 1.7371130e-002 +v 4.2879050e-002 1.0093777e-001 9.4753200e-003 +v -7.2455480e-002 1.7610676e-001 -5.3535420e-002 +v -7.5862940e-002 1.5071299e-001 -9.0209000e-003 +v -8.5269820e-002 1.0267793e-001 1.3935600e-003 +v -7.7025570e-002 1.1396763e-001 -4.6168100e-003 +v 4.6280880e-002 7.8702020e-002 1.4786330e-002 +v 4.2106910e-002 8.1533160e-002 -6.6690900e-003 +v 3.6523880e-002 8.1991750e-002 -1.6229590e-002 +v -3.7420220e-002 4.5428500e-002 -2.4226790e-002 +v -8.5148910e-002 1.3965520e-001 2.4808500e-003 +v -6.3313300e-002 1.6503258e-001 -3.2895120e-002 +v -6.1591410e-002 1.5681572e-001 -2.5945630e-002 +v 4.5918540e-002 8.7036220e-002 8.4236300e-003 +v 4.4631140e-002 8.4178380e-002 8.2665000e-004 +v -4.4842870e-002 1.4629393e-001 1.7114800e-003 +v -6.4124180e-002 1.7953625e-001 -5.8730420e-002 +v -6.7070300e-002 1.8072682e-001 -5.6618620e-002 +v -6.4793760e-002 1.7885275e-001 -5.5883250e-002 +v -6.4371030e-002 1.7296209e-001 -4.9225660e-002 +v -7.0381530e-002 1.8071180e-001 -5.3172590e-002 +v -7.5269270e-002 1.5232949e-001 3.4374060e-002 +v -1.6273090e-002 1.2844514e-001 1.6683610e-002 +v -6.2116150e-002 1.5600787e-001 1.8034420e-002 +v -5.6010790e-002 1.5381662e-001 2.5369280e-002 +v -3.7277920e-002 1.7289068e-001 -8.6627000e-004 +v -7.4158700e-002 1.7987275e-001 -5.0794750e-002 +v -7.9039960e-002 1.5537445e-001 1.5141810e-002 +v -7.2505530e-002 1.5459529e-001 2.9588830e-002 +v -6.7738180e-002 1.7728865e-001 -5.0375960e-002 +v -7.5346900e-003 1.0021302e-001 4.7488700e-002 +v -5.9575620e-002 1.5472401e-001 2.6373250e-002 +v -7.7382710e-002 1.5346600e-001 3.0894990e-002 +v -8.1496670e-002 1.5473104e-001 1.9697340e-002 +v -7.2223320e-002 1.5896734e-001 -5.4242300e-003 +v -1.3708500e-002 1.8491150e-001 -2.5549550e-002 +v -4.3465340e-002 1.2451145e-001 2.2518890e-002 +v -6.9103650e-002 1.5559479e-001 1.6370800e-003 +v -7.3748080e-002 1.5539253e-001 2.3491700e-003 +v -6.8192410e-002 1.7439828e-001 -4.5365870e-002 +v -6.0052850e-002 1.5280350e-001 3.2887630e-002 +v -2.3459490e-002 1.2615386e-001 1.6613770e-002 +v -7.2777220e-002 1.7854465e-001 -4.8208800e-002 +v -7.6595580e-002 1.7753227e-001 -4.7118080e-002 +v 1.3906410e-002 1.2790838e-001 2.5110240e-002 +v -8.6367510e-002 1.0906537e-001 1.1980640e-002 +v -3.1358850e-002 1.2140977e-001 2.5971090e-002 +v -4.9104590e-002 1.3666879e-001 1.9314030e-002 +v -4.2930640e-002 1.2928436e-001 9.2700700e-003 +v -6.5320350e-002 1.5390322e-001 9.1386000e-004 +v -3.7606490e-002 1.2422605e-001 2.4313530e-002 +v 9.5078400e-003 1.3041865e-001 2.0715020e-002 +v -1.7976800e-003 1.3117283e-001 1.6360660e-002 +v 3.6231700e-003 1.3076791e-001 2.1168600e-002 +v -9.2674700e-002 1.1701945e-001 1.1889520e-002 +v -6.5739720e-002 1.5565338e-001 2.6017600e-002 +v -8.6561940e-002 1.4249188e-001 8.4326800e-003 +v -7.0731530e-002 1.5569959e-001 6.9058200e-003 +v -8.0840700e-003 1.3030537e-001 1.6872280e-002 +v -4.4286250e-002 1.2606625e-001 2.0795220e-002 +v -7.0222260e-002 1.5143521e-001 3.6718910e-002 +v -1.5210690e-002 1.8463639e-001 -2.2057240e-002 +v -1.7270750e-002 1.8699602e-001 -1.9977570e-002 +v -8.3560950e-002 1.5255943e-001 7.6806700e-003 +v -8.8130280e-002 9.7540510e-002 5.6788000e-003 +v -8.8399240e-002 1.3899000e-001 1.0640660e-002 +v -6.7780550e-002 1.5614453e-001 1.4276320e-002 +v -6.5864600e-003 1.2641717e-001 3.0226390e-002 +v -8.8746180e-002 1.3625578e-001 7.1477800e-003 +v -7.7206730e-002 1.5639950e-001 -1.8972540e-002 +v -9.3176480e-002 1.1821016e-001 2.3362360e-002 +v -2.3506850e-002 1.2672006e-001 1.0996900e-002 +v -6.6546650e-002 1.7171115e-001 -4.2127770e-002 +v -6.9136000e-002 1.7247836e-001 -3.9013330e-002 +v 5.7180270e-002 7.1107690e-002 8.0307600e-003 +v -7.5390870e-002 1.7952824e-001 -5.2402050e-002 +v -3.1828840e-002 1.2639115e-001 1.0013410e-002 +v -8.9888800e-003 1.2952269e-001 2.2026810e-002 +v 3.4325880e-002 1.1193312e-001 -2.2406500e-003 +v -8.1414950e-002 9.7100250e-002 -6.8745800e-003 +v -2.3298830e-002 1.8324307e-001 -1.7923000e-002 +v -6.1641660e-002 1.5582039e-001 1.1099820e-002 +v -8.8826450e-002 9.0483320e-002 2.1204700e-002 +v 5.8373130e-002 6.8067590e-002 5.7247600e-003 +v -4.3045630e-002 1.2785122e-001 1.6842260e-002 +v 3.0835720e-002 1.1554234e-001 -3.1785500e-003 +v -8.8631270e-002 9.4881200e-002 7.9337600e-003 +v -9.1715140e-002 1.1709957e-001 3.0809400e-002 +v -7.2083780e-002 1.7499844e-001 -4.1930320e-002 +v -6.9540630e-002 1.5308527e-001 3.3865720e-002 +v 6.0078690e-002 6.8129260e-002 1.1454500e-002 +v -4.0081060e-002 1.2628381e-001 1.9607250e-002 +v 3.2819930e-002 1.1655625e-001 4.4458600e-003 +v -7.2823220e-002 1.4510601e-001 -1.5654680e-002 +v -8.5270210e-002 1.0551770e-001 2.3290940e-002 +v -7.6051320e-002 1.1103825e-001 -6.2722100e-003 +v -8.6537730e-002 1.5154801e-001 2.5875370e-002 +v 5.5888480e-002 7.2579250e-002 1.0669650e-002 +v -5.4642360e-002 1.5522963e-001 1.2612400e-002 +v 3.6729960e-002 1.1116756e-001 3.8670600e-003 +v 3.1501870e-002 1.1725172e-001 1.6855100e-003 +v -7.8751550e-002 9.5240290e-002 -1.0600670e-002 +v -8.9408160e-002 1.4352815e-001 3.0924750e-002 +v -2.0891130e-002 1.8595338e-001 -1.5037360e-002 +v -7.0863560e-002 1.6136525e-001 -9.7324600e-003 +v -7.0919760e-002 1.7136688e-001 -3.2763750e-002 +v -3.0771290e-002 1.2564075e-001 1.6594770e-002 +v -5.4454180e-002 1.5297699e-001 2.2505190e-002 +v -1.5539500e-003 1.2754717e-001 2.9232870e-002 +v 2.9130550e-002 1.2027445e-001 6.1117500e-003 +v 2.5725940e-002 1.2122705e-001 -3.6150000e-005 +v -8.9318970e-002 9.9546980e-002 1.3418110e-002 +v -7.5429500e-002 1.7095605e-001 -3.2879890e-002 +v -2.8596020e-002 1.1901156e-001 2.9888170e-002 +v 2.1069780e-002 1.2497756e-001 1.0998100e-003 +v -9.2240760e-002 1.1816838e-001 4.1201730e-002 +v 2.4094600e-003 1.0016785e-001 4.6938070e-002 +v -5.6627620e-002 1.5270606e-001 2.9629030e-002 +v -5.7264800e-002 1.5506250e-001 1.9322430e-002 +v -3.6452070e-002 1.2199869e-001 2.7670650e-002 +v -7.4108160e-002 1.7355729e-001 -3.7986840e-002 +v 5.1537130e-002 7.3496690e-002 1.2698700e-002 +v -6.6096040e-002 1.5532529e-001 7.1561800e-003 +v 3.6102000e-002 1.1266103e-001 1.0491780e-002 +v 1.6715210e-002 1.2689851e-001 2.2331000e-004 +v -8.0767920e-002 1.4301400e-001 -1.5312800e-003 +v -9.1757600e-002 1.4334588e-001 1.7790710e-002 +v -8.6824940e-002 1.5280775e-001 1.5521450e-002 +v -6.5808100e-002 1.6764344e-001 -3.0558670e-002 +v -7.8217340e-002 1.6873975e-001 -3.3564250e-002 +v -7.2567060e-002 1.4753230e-001 4.1714090e-002 +v 5.8439960e-002 7.0200810e-002 1.7779620e-002 +v 5.6847560e-002 7.2017160e-002 1.7139380e-002 +v 5.4919390e-002 7.3161610e-002 1.5223590e-002 +v 4.7446900e-002 7.3691410e-002 1.2430020e-002 +v 1.2319360e-002 1.2903768e-001 1.3336200e-003 +v -7.9790640e-002 1.0351662e-001 -6.6275400e-003 +v -7.6655210e-002 1.5509766e-001 7.9686300e-003 +v 2.1747320e-002 1.2118456e-001 3.0878810e-002 +v -7.5260490e-002 1.4938613e-001 3.9175980e-002 +v -2.5919610e-002 1.8272826e-001 -1.3541090e-002 +v -6.7983790e-002 1.6974781e-001 -3.1627490e-002 +v 1.6831110e-002 1.2487146e-001 2.8425580e-002 +v 5.4016490e-002 7.2883850e-002 1.8678010e-002 +v 5.0522750e-002 7.3397910e-002 1.6166890e-002 +v -5.9582440e-002 1.5623338e-001 7.9209900e-003 +v 2.5343500e-002 1.2374750e-001 9.9818800e-003 +v 1.9262750e-002 1.2689390e-001 5.5552100e-003 +v -9.0758520e-002 1.4223375e-001 2.6008130e-002 +v -4.6548490e-002 1.3320769e-001 1.6889630e-002 +v -2.4106950e-002 1.8380887e-001 -1.1544760e-002 +v 8.6784400e-003 1.2894574e-001 2.6156880e-002 +v 2.4919200e-003 1.2983563e-001 2.4847110e-002 +v 5.7345150e-002 6.9482720e-002 2.1153510e-002 +v -8.5329840e-002 1.5339912e-001 2.0378290e-002 +v 3.2877320e-002 1.1691463e-001 9.2957500e-003 +v 2.4246630e-002 1.2377758e-001 4.8764500e-003 +v -4.7765650e-002 1.3301969e-001 2.2874020e-002 +v -6.3541830e-002 1.6332115e-001 -2.5912990e-002 +v -6.6605200e-002 1.6477375e-001 -2.0670760e-002 +v -6.8504220e-002 1.6732018e-001 -2.3959570e-002 +v -7.2759160e-002 1.6965906e-001 -2.7013420e-002 +v 4.8206850e-002 7.2698580e-002 1.6994630e-002 +v -2.7383180e-002 1.2324257e-001 2.1658860e-002 +v -4.5077500e-002 1.3124443e-001 1.1145770e-002 +v 2.9253150e-002 1.2057701e-001 1.2299330e-002 +v 1.3677610e-002 1.2967262e-001 6.9327400e-003 +v 8.4210900e-003 1.3090986e-001 6.2754400e-003 +v 9.6836000e-004 1.3064303e-001 2.5865900e-003 +v 3.0802000e-003 9.8307360e-002 5.0535640e-002 +v -5.2420170e-002 1.5310101e-001 1.2927370e-002 +v -7.0359720e-002 1.6906988e-001 -2.6144260e-002 +v 5.4359390e-002 7.1467260e-002 2.1381250e-002 +v 4.5161440e-002 7.1030380e-002 2.2530690e-002 +v 1.9320440e-002 1.2738348e-001 1.1296310e-002 +v -9.3281210e-002 1.2691094e-001 1.3505010e-002 +v -8.7405060e-002 1.0593990e-001 1.3645920e-002 +v -2.2851640e-002 9.0635040e-002 5.2280460e-002 +v -6.2099370e-002 1.5406697e-001 3.0837360e-002 +v -4.5851560e-002 1.2072981e-001 2.7665040e-002 +v 5.0781670e-002 7.2155170e-002 2.0680180e-002 +v -8.9607270e-002 1.3971105e-001 2.9308560e-002 +v -5.3323050e-002 1.5273520e-001 1.6213860e-002 +v -1.5227080e-002 1.2784878e-001 2.1545200e-002 +v 3.3663540e-002 1.1574212e-001 1.7181290e-002 +v 2.4000260e-002 1.2468761e-001 1.5517930e-002 +v -8.4166840e-002 9.7756820e-002 -3.2761900e-003 +v -3.6223590e-002 1.2777519e-001 9.8501500e-003 +v -3.9189580e-002 1.2828193e-001 5.0346300e-003 +v -3.3674050e-002 1.7774449e-001 -8.1799500e-003 +v -7.4488620e-002 1.5649443e-001 -2.5954600e-003 +v -4.6755620e-002 1.3284294e-001 8.1212800e-003 +v -8.4970410e-002 1.5322309e-001 1.2654460e-002 +v -1.0866210e-002 1.2691699e-001 2.7575440e-002 +v -3.1074000e-003 1.3072898e-001 5.6428500e-003 +v -8.8760540e-002 9.7037440e-002 2.1079040e-002 +v -6.4811320e-002 3.4530640e-002 1.5508440e-002 +v -6.4300260e-002 3.5086450e-002 2.4272050e-002 +v -6.6727020e-002 3.5895770e-002 3.3849430e-002 +v 1.9838510e-002 9.6518890e-002 -2.2785880e-002 +v -3.8670510e-002 1.6070199e-001 -1.2357760e-002 +v -7.6890090e-002 1.3041906e-001 -6.9570100e-003 +v -7.2539730e-002 3.5399270e-002 7.0298800e-003 +v -6.9209050e-002 3.5454810e-002 1.2042140e-002 +v -6.4160810e-002 3.5900770e-002 1.7687570e-002 +v -6.6804150e-002 3.7377740e-002 3.3296290e-002 +v -6.2928350e-002 3.9061660e-002 4.2707680e-002 +v -7.1752230e-002 3.6789350e-002 8.6966700e-003 +v -6.5171380e-002 3.7289500e-002 2.5953770e-002 +v -6.6392030e-002 3.7712350e-002 2.9621950e-002 +v -6.4558720e-002 3.9639900e-002 3.9411530e-002 +v -6.0145790e-002 4.1202050e-002 4.4293830e-002 +v -6.0318430e-002 3.8442990e-002 4.5245950e-002 +v -3.6756310e-002 8.8663360e-002 -2.3868800e-002 +v -3.9494750e-002 3.7551570e-002 4.2870900e-002 +v -7.2016030e-002 3.7572700e-002 3.9789400e-003 +v -7.1693630e-002 3.9461000e-002 6.0145000e-003 +v -7.1165950e-002 3.9366310e-002 8.1142100e-003 +v -6.9000300e-002 3.8467710e-002 1.0768900e-002 +v -6.7253420e-002 3.8142160e-002 1.3533960e-002 +v -6.1125670e-002 3.7790050e-002 1.9710900e-002 +v -3.9179680e-002 4.2406740e-002 4.1476070e-002 +v -3.5145960e-002 3.8585920e-002 4.7732690e-002 +v -2.8950940e-002 3.9285940e-002 5.3309090e-002 +v -1.8223900e-002 9.7494570e-002 4.6847940e-002 +v -6.6916260e-002 1.2278907e-001 -8.9077400e-003 +v -6.3754640e-002 3.8250120e-002 1.6593500e-002 +v -6.4415760e-002 4.1283840e-002 2.8243480e-002 +v -8.5856340e-002 9.7025390e-002 2.7414960e-002 +v -3.7501130e-002 4.0221900e-002 4.4296550e-002 +v -3.4333970e-002 4.0923630e-002 4.8425810e-002 +v -3.1172890e-002 4.0294330e-002 5.1312460e-002 +v -6.9997320e-002 4.2073080e-002 6.6897800e-003 +v -8.0379330e-002 9.7800660e-002 3.3645750e-002 +v -2.6273160e-002 7.7631160e-002 4.8356180e-002 +v -3.7501450e-002 4.2736690e-002 4.2988400e-002 +v -2.6177500e-002 4.2498930e-002 5.3315220e-002 +v -6.9637250e-002 4.1881270e-002 3.1825800e-003 +v -6.7156510e-002 4.1972860e-002 1.0240940e-002 +v -8.7405510e-002 1.0205209e-001 2.2020360e-002 +v -2.3944380e-002 7.8800140e-002 5.3534730e-002 +v -6.0902360e-002 4.3429500e-002 4.2678530e-002 +v -3.1217880e-002 4.3847510e-002 4.9780920e-002 +v -7.5729440e-002 1.0354026e-001 3.6070970e-002 +v -6.2425320e-002 4.1885720e-002 1.4646770e-002 +v -6.1051660e-002 4.4392230e-002 1.2421940e-002 +v 2.5855060e-002 8.9610660e-002 -2.2701840e-002 +v -7.7644960e-002 8.2214940e-002 3.5797660e-002 +v -6.0381270e-002 4.5921420e-002 4.0088740e-002 +v -2.4982010e-002 8.1777650e-002 5.3421060e-002 +v -3.4453850e-002 4.4563960e-002 4.5422990e-002 +v -2.9842910e-002 4.6782280e-002 4.7746920e-002 +v -1.5119580e-002 9.9930020e-002 4.4500270e-002 +v -6.7306470e-002 4.4176830e-002 7.5958300e-003 +v -5.7852990e-002 4.6444500e-002 1.1062610e-002 +v -5.1815260e-002 1.6392582e-001 1.7488800e-003 +v -5.5174130e-002 4.8383880e-002 3.8517780e-002 +v -7.8849150e-002 1.1867375e-001 5.0622870e-002 +v -2.7229070e-002 8.7991480e-002 4.7909730e-002 +v -7.5536880e-002 1.5977062e-001 -1.0438650e-002 +v -3.6151280e-002 4.6505140e-002 4.0740900e-002 +v -2.5439220e-002 9.0677870e-002 4.8852330e-002 +v -8.0050370e-002 1.1670406e-001 4.8762460e-002 +v -5.2513640e-002 4.7577880e-002 1.4858440e-002 +v -3.2043560e-002 5.0461830e-002 3.9341520e-002 +v -3.1487770e-002 4.6930210e-002 4.5253210e-002 +v -2.0321500e-002 9.3999570e-002 5.1588540e-002 +v -7.2145040e-002 9.1556450e-002 4.1494780e-002 +v -5.3644200e-002 4.9358170e-002 1.2201850e-002 +v -8.2403890e-002 1.2186563e-001 4.9365030e-002 +v -4.9754420e-002 4.9738300e-002 3.7037110e-002 +v -3.2332060e-002 4.8672840e-002 4.2523960e-002 +v -2.3122950e-002 9.4515900e-002 4.7358870e-002 +v -8.6347140e-002 9.1722090e-002 2.6811080e-002 +v -5.7713110e-002 4.8717820e-002 7.2765100e-003 +v -8.6970360e-002 8.8912090e-002 2.4879860e-002 +v -9.2237750e-002 1.2488519e-001 4.0786530e-002 +v -1.5862800e-002 9.7021620e-002 5.0139360e-002 +v -2.7720040e-002 5.0502090e-002 4.3340720e-002 +v -8.5918770e-002 1.4263412e-001 3.9849810e-002 +v -7.5097360e-002 9.0073560e-002 3.9581000e-002 +v -8.9430840e-002 1.4730552e-001 2.7694960e-002 +v -5.3288350e-002 5.1925760e-002 1.1730350e-002 +v -5.0168720e-002 5.3462260e-002 1.6255440e-002 +v -8.5986050e-002 1.4670902e-001 3.4827030e-002 +v -6.9937250e-002 8.6076860e-002 4.2175690e-002 +v -5.0399320e-002 5.1831330e-002 3.4037400e-002 +v -8.3298980e-002 1.4960772e-001 3.3740890e-002 +v -2.9174820e-002 5.2264530e-002 3.7637320e-002 +v -8.8763730e-002 1.1944938e-001 4.6560090e-002 +v -7.7693460e-002 1.7367969e-001 -4.1478670e-002 +v -8.3418140e-002 9.4127440e-002 3.0898450e-002 +v -5.6067510e-002 5.3470630e-002 7.3718200e-003 +v -7.8935630e-002 1.4817228e-001 3.9463070e-002 +v -6.7902770e-002 8.7817230e-002 4.3526990e-002 +v -4.4111240e-002 9.2883990e-002 -2.2373210e-002 +v -8.6605100e-002 1.3226807e-001 4.6783020e-002 +v -9.2654280e-002 1.2084025e-001 4.1629650e-002 +v -5.0887310e-002 5.2727900e-002 1.4455790e-002 +v -4.9763410e-002 5.6241200e-002 3.3624250e-002 +v -8.9771330e-002 1.2904861e-001 4.3022990e-002 +v -2.8054240e-002 5.4551030e-002 3.6786850e-002 +v -2.5867080e-002 5.6689210e-002 3.9182240e-002 +v -8.3702200e-002 1.2226381e-001 -3.7301400e-003 +v -8.1455470e-002 1.3012213e-001 5.2117660e-002 +v -5.1458550e-002 5.5878150e-002 1.5900350e-002 +v -7.8597700e-002 1.7441574e-001 -4.6607580e-002 +v -5.2909820e-002 5.7043070e-002 2.0988410e-002 +v -5.2978500e-002 5.9553770e-002 2.6211920e-002 +v -5.2130640e-002 5.6302970e-002 2.6672460e-002 +v -4.7714500e-002 6.1944520e-002 3.6705820e-002 +v -8.3539790e-002 8.1169560e-002 2.7014070e-002 +v -1.8340000e-002 5.7489970e-002 4.9763020e-002 +v -8.0069810e-002 9.0586130e-002 3.4593070e-002 +v -8.3812250e-002 8.6337700e-002 2.9223270e-002 +v -5.5436650e-002 5.9420250e-002 2.3018970e-002 +v -8.2227680e-002 1.4513771e-001 4.0600080e-002 +v -2.4187580e-002 7.2269150e-002 4.7681090e-002 +v -2.5353150e-002 6.2567200e-002 4.0642170e-002 +v -9.1132110e-002 1.2282100e-001 4.4115160e-002 +v -4.6076290e-002 1.6819719e-001 7.3744000e-004 +v -8.7829280e-002 1.4351461e-001 3.5707670e-002 +v -8.6990640e-002 1.3812326e-001 4.2316550e-002 +v -1.5715900e-002 6.0822970e-002 5.2365440e-002 +v -8.3803580e-002 1.2561100e-001 5.0440490e-002 +v -6.2786680e-002 1.1274190e-001 -1.3605440e-002 +v -8.1033840e-002 8.4698180e-002 3.3106400e-002 +v -8.8563540e-002 1.1624535e-001 4.5392840e-002 +v -2.0268380e-002 6.2266810e-002 4.8212120e-002 +v -1.2619630e-002 6.1635030e-002 5.4424080e-002 +v -7.0491190e-002 8.1818160e-002 4.0609890e-002 +v -8.3882520e-002 1.3331465e-001 4.9113540e-002 +v -5.6560350e-002 4.8355540e-002 3.6607050e-002 +v 9.9444900e-003 1.0919723e-001 -1.9472810e-002 +v -5.5928250e-002 3.5917310e-002 4.6376100e-002 +v -7.6003260e-002 1.6361344e-001 -1.8021110e-002 +v -8.3798850e-002 1.0290691e-001 2.8038330e-002 +v -8.8252110e-002 1.2692730e-001 4.6141300e-002 +v -7.9126720e-002 1.0619883e-001 3.2050700e-002 +v -8.8206230e-002 9.4485700e-002 2.3744010e-002 +v -8.9110330e-002 1.3851394e-001 3.7658780e-002 +v -1.9321360e-002 9.2123890e-002 5.3820650e-002 +v -5.8265630e-002 9.0926390e-002 -2.0948690e-002 +v -2.7046310e-002 6.7014450e-002 3.9672140e-002 +v -2.1416300e-002 1.7977662e-001 -2.1732520e-002 +v -7.8240000e-003 1.0924112e-001 -2.2185670e-002 +v -2.3988340e-002 8.5995590e-002 5.3716430e-002 +v -6.0483580e-002 1.5567975e-001 4.3343800e-003 +v -8.6389150e-002 1.2168475e-001 4.8412440e-002 +v -7.4084360e-002 1.4987744e-001 -3.2610050e-002 +v -2.0580600e-002 7.9572500e-002 5.6013880e-002 +v -8.3837500e-002 1.3927865e-001 4.4893850e-002 +v -2.2933960e-002 3.5632910e-002 5.2865490e-002 +v -8.6153620e-002 1.2735612e-001 4.8563960e-002 +v -6.5728590e-002 1.0709818e-001 -1.4317670e-002 +v -2.1481090e-002 7.4194460e-002 5.2857680e-002 +v -7.6423900e-002 1.5736285e-001 -9.0354600e-003 +v -7.7216010e-002 8.5594880e-002 3.7420770e-002 +v -8.4150830e-002 1.2955013e-001 5.0483700e-002 +v -8.1221440e-002 8.1003250e-002 3.1255840e-002 +v -8.1704000e-002 1.0167226e-001 3.0939660e-002 +v -8.6252730e-002 1.0106846e-001 2.5413770e-002 +v -8.0944970e-002 1.3903572e-001 4.7359080e-002 +v -7.8908350e-002 9.4830900e-002 3.5435500e-002 +v -7.3440160e-002 9.5412600e-002 4.0210650e-002 +v -5.2675780e-002 8.8220740e-002 -2.1886300e-002 +v -7.6440670e-002 7.7511060e-002 3.3748300e-002 +v -2.1791140e-002 1.0658035e-001 -2.2327000e-002 +v -8.8360940e-002 1.4996706e-001 2.6044170e-002 +v -2.4078870e-002 6.7906700e-002 4.5178370e-002 +v -2.0018090e-002 6.7569300e-002 5.1565340e-002 +v -8.3577750e-002 1.2052625e-001 4.9177500e-002 +v -1.4655950e-002 1.7456543e-001 -2.5972690e-002 +v -2.7395940e-002 8.4108300e-002 4.8745680e-002 +v -4.1933580e-002 8.8463400e-002 -2.2126350e-002 +v -3.1693900e-002 1.0261265e-001 -2.2352310e-002 +v -2.7890200e-002 1.0440703e-001 -2.2830920e-002 +v -7.3790400e-002 1.2016662e-001 -7.8851200e-003 +v -4.6124160e-002 1.0506369e-001 -2.0457580e-002 +v -2.7412650e-002 7.3269450e-002 4.2641380e-002 +v -4.5532880e-002 3.4736480e-002 -2.1363200e-002 +v -4.4993030e-002 3.9017010e-002 -2.1097830e-002 +v -4.6462610e-002 3.6800270e-002 -1.7778710e-002 +v -8.8366460e-002 1.1361863e-001 5.8227800e-003 +v 5.1746240e-002 7.2897250e-002 9.0647400e-003 +v -7.0385250e-002 3.7450300e-002 -9.3190000e-004 +v -6.0923170e-002 3.8621820e-002 2.2468850e-002 +v -7.7696720e-002 1.7027889e-001 -4.3117910e-002 +v -4.3793210e-002 1.6955506e-001 -7.3026400e-003 +v -7.7587180e-002 1.7717875e-001 -5.0221090e-002 +v -4.0541880e-002 3.8886010e-002 -2.7364950e-002 +v -4.4215850e-002 3.6131460e-002 -2.4252210e-002 +v -6.6634880e-002 4.0430310e-002 -5.0180700e-003 +v -6.9242120e-002 4.1474050e-002 1.9289000e-004 +v -7.5640690e-002 1.5930400e-001 -2.6908460e-002 +v -6.3087030e-002 3.9614170e-002 2.5181560e-002 +v -7.2303020e-002 1.5186699e-001 -4.1544310e-002 +v -4.1051490e-002 4.1528620e-002 -2.4061000e-002 +v -4.6990580e-002 3.8892380e-002 -1.4016920e-002 +v -8.9559690e-002 1.2851666e-001 4.5457500e-003 +v -7.6987340e-002 1.5369375e-001 -2.2970800e-003 +v -7.0121670e-002 1.6882633e-001 -5.1173650e-002 +v -6.4792610e-002 4.1724530e-002 3.1616900e-002 +v -4.2148060e-002 1.2409627e-001 -9.5602500e-003 +v -4.8069700e-002 1.2493027e-001 -8.4076400e-003 +v -4.2150480e-002 4.3343970e-002 -2.1508710e-002 +v -6.7315160e-002 4.4034000e-002 1.5741800e-003 +v -7.3386640e-002 1.5463418e-001 -2.9943830e-002 +v -5.5352770e-002 4.2936210e-002 1.9135490e-002 +v -6.0067770e-002 4.1419500e-002 2.2953280e-002 +v -6.5488460e-002 4.0937780e-002 3.5315470e-002 +v -8.0066400e-002 1.5039650e-001 6.0518000e-004 +v -4.4031300e-002 4.1949070e-002 -1.7993960e-002 +v -4.5186510e-002 4.2453420e-002 -1.4193620e-002 +v -8.3109430e-002 1.0265445e-001 -3.2933400e-003 +v -6.5472800e-002 4.5627570e-002 4.5575400e-003 +v -7.5427730e-002 1.5201213e-001 -1.4393690e-002 +v -5.4473420e-002 4.5937510e-002 2.3612600e-002 +v -6.2464100e-002 4.3722000e-002 2.8493310e-002 +v -6.2832600e-002 4.5182750e-002 3.4622890e-002 +v -6.3538130e-002 4.3524020e-002 3.7974010e-002 +v -6.0255260e-002 4.4749620e-002 -4.1316200e-003 +v -6.3242050e-002 4.5549700e-002 4.8428000e-004 +v -6.2249430e-002 4.6540050e-002 7.1903500e-003 +v -9.1003650e-002 1.4885725e-001 2.1507030e-002 +v -5.7094130e-002 4.5996540e-002 2.6865280e-002 +v -5.7276490e-002 4.7299580e-002 2.9889950e-002 +v -3.9519900e-002 1.7385855e-001 -7.5752600e-003 +v -8.9641110e-002 1.3841920e-001 3.4141800e-002 +v -9.2601430e-002 1.3018652e-001 2.5183580e-002 +v -9.2280860e-002 1.2762053e-001 2.9751670e-002 +v -3.3957310e-002 4.1025060e-002 -2.9660250e-002 +v -9.0199540e-002 1.1657506e-001 5.6754900e-003 +v -5.8515890e-002 4.7731310e-002 2.1246000e-004 +v -7.1723560e-002 1.4617438e-001 -2.1567820e-002 +v -5.2389820e-002 4.5449130e-002 1.7686300e-002 +v -5.9414350e-002 4.7277990e-002 3.4172420e-002 +v -5.7520620e-002 1.5877600e-001 4.1621200e-003 +v -8.0959140e-002 1.0926674e-001 -2.0189900e-003 +v -5.1904000e-002 4.6100060e-002 1.9421290e-002 +v -5.1830050e-002 4.8568730e-002 2.1647030e-002 +v -7.7650400e-002 1.5658012e-001 -1.6599150e-002 +v -3.7416450e-002 4.7682130e-002 -1.7147280e-002 +v -7.8876110e-002 1.5347012e-001 3.9875800e-003 +v -5.7635420e-002 5.0425540e-002 4.6108400e-003 +v -5.2625440e-002 5.0434620e-002 2.9046740e-002 +v -5.2998720e-002 4.9169020e-002 3.3967600e-002 +v -7.3502600e-002 1.6871934e-001 -4.4791800e-002 +v -5.4420720e-002 4.7836520e-002 -5.9186900e-003 +v -5.2312740e-002 5.1085350e-002 2.4485690e-002 +v -7.9129930e-002 1.6736568e-001 -3.5506230e-002 +v 9.4115700e-003 1.2350285e-001 -9.8291000e-003 +v -3.2715700e-002 1.0896631e-001 -1.8941410e-002 +v -3.1133380e-002 4.9607260e-002 -1.9406940e-002 +v 4.5997330e-002 6.9814450e-002 3.0143300e-003 +v 3.3525460e-002 1.0966209e-001 -6.9894800e-003 +v -5.5047160e-002 5.2767560e-002 -3.9461300e-003 +v -5.6897890e-002 4.9655570e-002 -1.5319000e-003 +v -5.0290500e-002 4.9098930e-002 1.7164780e-002 +v -5.0595170e-002 4.9923270e-002 1.9174130e-002 +v -5.1887420e-002 5.3324670e-002 2.8705560e-002 +v -6.7684480e-002 1.6533627e-001 -5.5466400e-002 +v -3.0271440e-002 5.2106080e-002 -1.7676140e-002 +v -9.1087300e-003 1.1141669e-001 -2.0543230e-002 +v -5.7069360e-002 5.4424380e-002 2.3395500e-003 +v -3.2748380e-002 1.7759875e-001 -1.1627470e-002 +v -2.9009580e-002 5.1265290e-002 -2.2175780e-002 +v -3.1383130e-002 5.1791310e-002 -1.3886800e-002 +v -5.5673960e-002 5.6983850e-002 -3.3510400e-003 +v -5.0916050e-002 5.3813610e-002 1.9753140e-002 +v -8.8875380e-002 1.5169443e-001 2.0086580e-002 +v -7.7153050e-002 1.7378676e-001 -4.7867620e-002 +v -7.8577770e-002 1.6420639e-001 -3.1825860e-002 +v -2.7545910e-002 5.4021570e-002 -2.5147390e-002 +v -5.4463660e-002 5.5357450e-002 1.0326840e-002 +v -8.7041410e-002 1.3058932e-001 9.1161000e-004 +v -9.0009340e-002 1.3278082e-001 5.9220600e-003 +v -9.2232620e-002 1.3195400e-001 1.5430650e-002 +v -4.8639980e-002 1.6472475e-001 -5.0591500e-003 +v -5.4066480e-002 5.9959350e-002 -7.5992200e-003 +v -5.7434090e-002 5.7683500e-002 8.7259700e-003 +v -8.6794730e-002 1.3850688e-001 4.5575900e-003 +v -9.2989530e-002 1.3092307e-001 1.9919290e-002 +v -9.1282030e-002 1.3311897e-001 2.4688630e-002 +v 2.1815020e-002 1.1770533e-001 -1.0015300e-002 +v -2.9647120e-002 5.8104260e-002 -2.1311320e-002 +v -3.1289530e-002 5.5208570e-002 -1.4387840e-002 +v -5.9002160e-002 5.9234620e-002 2.6140800e-003 +v -9.0241700e-002 1.3575994e-001 1.4149160e-002 +v -6.1569420e-002 1.7084875e-001 -6.1679170e-002 +v -6.6070180e-002 1.6557822e-001 -5.8644080e-002 +v -2.4539930e-002 1.8005865e-001 -1.8726950e-002 +v -1.6131750e-002 1.8298848e-001 -2.6037190e-002 +v -3.0809390e-002 5.6998040e-002 -1.7835020e-002 +v 1.0464280e-002 9.6180450e-002 -2.5898970e-002 +v -5.7491630e-002 5.9530160e-002 -1.0786100e-003 +v -8.9146460e-002 1.3650500e-001 2.5952780e-002 +v 4.3714500e-003 1.0391901e-001 -2.1515100e-002 +v -9.0377040e-002 1.3252490e-001 3.1082650e-002 +v -9.0795450e-002 1.3855232e-001 2.0562560e-002 +v -9.4237710e-002 1.2615419e-001 2.2201450e-002 +v -9.0336910e-002 1.3119830e-001 3.8138790e-002 +v -4.5082610e-002 1.2218447e-001 -1.1569430e-002 +v 1.1348010e-002 9.8243750e-002 -2.3024250e-002 +v -3.9227920e-002 9.9184630e-002 -2.1912720e-002 +v -6.5509530e-002 1.5857325e-001 -5.5600270e-002 +v -7.7409510e-002 1.6260515e-001 -2.0754580e-002 +v -4.8580010e-002 1.6689211e-001 -2.5256100e-003 +v -7.6922910e-002 1.5351394e-001 -9.0785600e-003 +v -6.7750580e-002 1.5734825e-001 -5.3982110e-002 +v 5.2906410e-002 6.5230450e-002 -5.1112000e-004 +v -2.9054820e-002 6.1084120e-002 -2.4918230e-002 +v -3.1066920e-002 6.5058860e-002 -2.2751080e-002 +v 2.4249720e-002 1.0266151e-001 -1.8313830e-002 +v -5.5473660e-002 1.6050213e-001 1.3763500e-003 +v -6.6642850e-002 1.6040875e-001 -5.6842680e-002 +v -7.8200320e-002 1.6073213e-001 -2.3999690e-002 +v -1.8320680e-002 1.1968625e-001 -1.1110660e-002 +v 2.1712970e-002 1.0956342e-001 -1.5081090e-002 +v -6.8382640e-002 1.5980248e-001 -5.4208800e-002 +v -2.5445620e-002 6.0208550e-002 -3.0864700e-002 +v -2.6540330e-002 6.5084000e-002 -3.1664870e-002 +v -2.8425710e-002 6.2199610e-002 -2.7938500e-002 +v -3.2605750e-002 6.1264600e-002 -1.5453010e-002 +v -7.0872290e-002 1.1611638e-001 -7.9563700e-003 +v -6.9780530e-002 1.5938570e-001 -4.9418240e-002 +v -3.0324870e-002 6.7694720e-002 -2.7654950e-002 +v -3.2977370e-002 6.6365180e-002 -1.8385530e-002 +v 1.3533490e-002 1.0255388e-001 -2.1579310e-002 +v 4.4408530e-002 6.9758860e-002 9.4765000e-004 +v -2.1999000e-003 1.1215881e-001 -1.9658660e-002 +v -7.2028500e-002 6.7046610e-002 -7.2256000e-004 +v -7.8699630e-002 1.7313910e-001 -4.2720470e-002 +v -8.3211970e-002 1.5072131e-001 4.2128500e-003 +v -8.7439060e-002 1.3374875e-001 2.3974700e-003 +v 2.6348020e-002 8.4562230e-002 -2.3151710e-002 +v -7.4901490e-002 7.0419350e-002 -2.2854300e-003 +v -5.4576350e-002 9.1562950e-002 -2.2098700e-002 +v -7.3242520e-002 1.5231332e-001 -3.5703520e-002 +v -7.4550960e-002 1.7218738e-001 -4.7551010e-002 +v -2.8680680e-002 6.8283500e-002 -3.0610160e-002 +v 1.7372900e-002 1.0246037e-001 -2.1487700e-002 +v -8.1257430e-002 7.3025200e-002 7.1020400e-003 +v -7.4982300e-002 1.5407794e-001 -1.8974470e-002 +v -9.1556500e-002 1.3196262e-001 1.0638150e-002 +v -8.2448000e-004 9.5165120e-002 -3.2056320e-002 +v -7.7618830e-002 7.3999130e-002 -5.3263500e-003 +v -7.9858790e-002 7.2755040e-002 3.0420200e-003 +v -8.1627470e-002 7.3470610e-002 1.1161690e-002 +v -7.3679290e-002 1.4785987e-001 -2.0236290e-002 +v -9.1309820e-002 1.4848588e-001 1.6270070e-002 +v -9.0850140e-002 1.4625613e-001 1.4809050e-002 +v -6.8543890e-002 1.7513008e-001 -5.7187900e-002 +v -2.7253960e-002 1.0747453e-001 -2.1279680e-002 +v 2.1443580e-002 1.2273826e-001 -2.9316700e-003 +v -7.9061200e-002 7.3724300e-002 -8.4521000e-004 +v -8.2063500e-002 7.5993670e-002 1.7615500e-003 +v -8.3736580e-002 7.6771840e-002 8.9586000e-003 +v -9.0205720e-002 1.4947775e-001 1.3035090e-002 +v 8.4818000e-004 1.1670025e-001 -1.7337090e-002 +v -7.4577550e-002 1.5164041e-001 -2.8647990e-002 +v -2.9087460e-002 7.2924630e-002 -3.3354470e-002 +v -3.1184020e-002 7.3989530e-002 -3.0339870e-002 +v -3.2606620e-002 7.1955620e-002 -2.4866580e-002 +v -8.0575990e-002 7.6607800e-002 -2.9879400e-003 +v -8.9491020e-002 1.4392581e-001 1.2488490e-002 +v -7.7388410e-002 1.4656426e-001 -4.3543000e-003 +v -7.2896160e-002 1.5834962e-001 -3.4109420e-002 +v 7.1346500e-003 1.1468229e-001 -1.8345640e-002 +v -3.4502610e-002 7.6130020e-002 -2.2373150e-002 +v -8.3890740e-002 8.0789530e-002 2.2951400e-003 +v -8.3740480e-002 7.7240270e-002 4.6673300e-003 +v -8.6204620e-002 8.0930750e-002 1.0535420e-002 +v -8.6061500e-002 7.9931100e-002 1.4440780e-002 +v -8.1542760e-002 7.7950660e-002 2.6727280e-002 +v 2.6666170e-002 1.1268609e-001 -1.0509540e-002 +v -7.6041430e-002 1.5663068e-001 -2.1420480e-002 +v -9.0012110e-002 1.5083344e-001 1.5752740e-002 +v -7.1156510e-002 1.6335125e-001 -4.5360530e-002 +v -3.3210960e-002 7.6873190e-002 -2.7708380e-002 +v -7.3263090e-002 7.9983830e-002 -1.3749940e-002 +v -7.9285950e-002 8.0048830e-002 -7.0125500e-003 +v -8.6034510e-002 8.2645720e-002 1.9542680e-002 +v -8.4335410e-002 8.0729950e-002 2.2180460e-002 +v -7.1351460e-002 1.5727092e-001 -4.2183090e-002 +v -7.3548450e-002 1.6120822e-001 -3.5288420e-002 +v 1.6732620e-002 1.0991230e-001 -1.7020040e-002 +v -3.0978770e-002 7.7020860e-002 -3.2816490e-002 +v -6.2359240e-002 1.7544824e-001 -6.1485990e-002 +v -1.7587870e-002 1.1491318e-001 -1.7205040e-002 +v -8.2354050e-002 8.0876320e-002 -2.4038900e-003 +v -7.8578910e-002 1.4050129e-001 -4.6031000e-003 +v -2.8931080e-002 7.9247620e-002 -3.5049800e-002 +v -3.1225710e-002 8.0413100e-002 -3.2182320e-002 +v -3.3258680e-002 7.9621670e-002 -2.7146060e-002 +v -4.4697400e-002 1.1791537e-001 -1.4725860e-002 +v -7.9723740e-002 8.4226660e-002 -8.7608600e-003 +v -8.5042160e-002 8.3817830e-002 -7.7640000e-005 +v -8.6776400e-002 8.4344860e-002 1.2419030e-002 +v -8.6674670e-002 8.2665010e-002 1.5174340e-002 +v -8.5106250e-002 8.5176580e-002 2.5679440e-002 +v -7.6975760e-002 8.2935940e-002 -1.1450630e-002 +v -8.2776390e-002 8.3430890e-002 -4.3687000e-003 +v -8.6180440e-002 8.2572150e-002 6.3639000e-003 +v -9.1160820e-002 1.4144362e-001 1.5673910e-002 +v -7.4638800e-002 1.4398484e-001 -7.1504600e-003 +v -8.3448500e-002 1.3393299e-001 -1.6873200e-003 +v -7.5804700e-002 1.5134475e-001 -1.9881200e-002 +v -7.4924140e-002 1.5273013e-001 -1.9397440e-002 +v -5.2314440e-002 1.2159646e-001 -1.0798060e-002 +v -3.0734050e-002 8.5427560e-002 -3.0506670e-002 +v -3.2590560e-002 8.1942660e-002 -2.9100210e-002 +v -8.6454830e-002 8.6940490e-002 9.1667000e-004 +v -1.2501820e-002 1.0634409e-001 -2.2360190e-002 +v -8.8585880e-002 1.4605869e-001 9.8780000e-003 +v -8.5609750e-002 1.4712513e-001 6.5981100e-003 +v -8.7511210e-002 1.5061504e-001 1.0152460e-002 +v -6.0113540e-002 3.5550440e-002 4.4907580e-002 +v -8.8284200e-002 8.6869110e-002 8.1029200e-003 +v -8.8812560e-002 8.7765490e-002 1.4226540e-002 +v -8.8001070e-002 8.6626430e-002 1.5466680e-002 +v -8.6991110e-002 8.6444700e-002 2.2420950e-002 +v -7.4609990e-002 1.4727815e-001 -1.4172380e-002 +v -3.4707910e-002 8.4035880e-002 -2.4302260e-002 +v -8.4964900e-002 8.9962540e-002 -3.0068000e-003 +v -8.8091450e-002 8.7741580e-002 4.8489900e-003 +v -9.1490470e-002 1.4543178e-001 2.2277220e-002 +v -9.4380420e-002 1.2183919e-001 1.7904340e-002 +v -2.9164530e-002 8.5393440e-002 -3.3666780e-002 +v -3.0557790e-002 8.8625920e-002 -2.7550670e-002 +v -7.7770550e-002 8.7844840e-002 -1.1694810e-002 +v -8.0728260e-002 8.8204150e-002 -7.8003100e-003 +v -8.3272540e-002 8.9476690e-002 -5.6502900e-003 +v -8.9398710e-002 8.9539000e-002 1.1645550e-002 +v -8.9698390e-002 1.3971257e-001 1.3774760e-002 +v -7.7134890e-002 1.5151225e-001 -5.5823000e-003 +v -5.1121410e-002 1.6374125e-001 -2.6640500e-003 +v -8.6442960e-002 1.2767438e-001 -1.4864100e-003 +v -6.9605590e-002 1.5490763e-001 -5.0188670e-002 +v -8.7265180e-002 9.2110030e-002 4.2059000e-003 +v -8.9086250e-002 9.2377120e-002 1.0569860e-002 +v -8.9612340e-002 9.1599880e-002 1.7812280e-002 +v -8.2732460e-002 1.4196856e-001 1.2529100e-003 +v -7.2618370e-002 1.4368135e-001 -1.0987100e-002 +v -7.7677230e-002 1.6610992e-001 -3.6777320e-002 +v -1.5078060e-002 9.3863440e-002 -3.4317310e-002 +v -7.1057280e-002 1.5476885e-001 -4.5778530e-002 +v -9.2331920e-002 1.2523886e-001 9.1589500e-003 +v -7.6046700e-002 9.1037250e-002 -1.3643150e-002 +v -8.2942810e-002 9.3291700e-002 -6.1856300e-003 +v -1.0411170e-002 9.4592340e-002 -3.3784850e-002 +v -2.9331140e-002 1.1476230e-001 -1.5844640e-002 +v -3.7218250e-002 1.1594244e-001 -1.5173050e-002 +v -1.2429920e-002 1.0286006e-001 -2.3822480e-002 +v 6.6509600e-003 8.8144500e-002 -3.2945810e-002 +v -6.4119900e-003 9.2876210e-002 -3.4817640e-002 +v 1.5800150e-002 1.1996558e-001 -1.1415630e-002 +v 2.9102740e-002 1.0247506e-001 -1.5768380e-002 +v 4.2080690e-002 6.3480630e-002 -2.5405300e-003 +v 2.8723120e-002 9.7943220e-002 -1.7497350e-002 +v -1.9987640e-002 1.0278313e-001 -2.3392920e-002 +v 3.3748350e-002 8.3644140e-002 -1.8630450e-002 +v -1.8685680e-002 1.8689625e-001 -2.0248700e-002 +v 6.4154900e-003 1.1790181e-001 -1.6282740e-002 +v 5.6305210e-002 6.7769910e-002 2.6525000e-003 +v -5.3608300e-003 1.1289400e-001 -1.9613290e-002 +v 4.5769430e-002 6.4628800e-002 -1.2166100e-003 +v -1.0090870e-002 9.8229650e-002 -2.7731360e-002 +v -6.0458520e-002 1.1755645e-001 -1.1354580e-002 +v 1.2933940e-002 1.1887250e-001 -1.3979370e-002 +v 1.5235680e-002 9.4977900e-002 -2.4437140e-002 +v -3.0892950e-002 4.7409030e-002 -2.4954000e-002 +v -1.7766190e-002 1.8572344e-001 -2.3049280e-002 +v -1.3034890e-002 1.1002855e-001 -2.0161170e-002 +v -7.1206550e-002 3.8608570e-002 7.7218000e-004 +v 1.7904800e-002 1.0627709e-001 -1.7729250e-002 +v -3.3623490e-002 1.1840428e-001 -1.1927480e-002 +v -4.9906840e-002 1.1788332e-001 -1.4402480e-002 +v -6.6878100e-003 1.1747209e-001 -1.5359280e-002 +v -1.5451470e-002 1.8597600e-001 -2.4795870e-002 +v -3.0603900e-002 3.8038460e-002 -3.0123840e-002 +v -1.3220270e-002 1.8397188e-001 -2.7519460e-002 +v -4.7859450e-002 1.1162729e-001 -1.7482120e-002 +v -1.3098990e-002 9.0776040e-002 -3.6659270e-002 +v -6.3117340e-002 1.5425437e-001 2.9730400e-003 +v -5.5139750e-002 1.1051601e-001 -1.7672740e-002 +v -1.1096770e-002 1.8202324e-001 -2.8042450e-002 +v -2.6568900e-002 3.4695830e-002 -2.9113750e-002 +v -6.6396600e-003 1.0222209e-001 -2.3519320e-002 +v -5.6996400e-002 1.5741713e-001 6.0244000e-004 +v 1.9076550e-002 9.1870620e-002 -2.4890230e-002 +v 1.3473090e-002 1.2429893e-001 -6.8361400e-003 +v -2.1730490e-002 9.8410960e-002 -2.4306850e-002 +v -1.7142170e-002 9.8057460e-002 -2.4924330e-002 +v -5.8698110e-002 1.5137318e-001 -6.5801000e-004 +v 3.5641100e-003 1.2764883e-001 -4.4672400e-003 +v -8.5369800e-003 9.9921220e-002 -2.4351070e-002 +v -1.2171980e-002 1.8125102e-001 -2.9061170e-002 +v -6.1113980e-002 1.5305212e-001 9.9983000e-004 +v -2.9570620e-002 1.1713871e-001 -1.3675530e-002 +v 3.0530110e-002 1.1221207e-001 -8.1860600e-003 +v -3.1714100e-002 3.5111530e-002 -3.0658990e-002 +v -1.3691130e-002 1.7914707e-001 -2.8126410e-002 +v 1.1620840e-002 1.1548972e-001 -1.6385680e-002 +v -6.1993570e-002 1.5028063e-001 -1.6297100e-003 +v 3.6684020e-002 1.0099570e-001 -9.8485900e-003 +v 4.8512670e-002 7.1798180e-002 6.0005000e-003 +v -4.6583000e-004 1.1983662e-001 -1.3610580e-002 +v 1.6747170e-002 9.0113950e-002 -2.7127190e-002 +v 6.9832400e-003 9.7730080e-002 -2.4800310e-002 +v -4.3226830e-002 4.6263570e-002 -1.1771730e-002 +v -8.3562500e-003 1.1373600e-001 -1.8239810e-002 +v -1.2354410e-002 1.1556773e-001 -1.6486930e-002 +v 4.6834470e-002 7.4354100e-002 1.0139500e-002 +v 2.5319170e-002 1.0931725e-001 -1.3579660e-002 +v -4.2459500e-002 1.1392482e-001 -1.6188050e-002 +v 5.7744640e-002 6.4158440e-002 2.6277600e-003 +v -5.9710530e-002 3.6535780e-002 -9.4949000e-003 +v -3.2078400e-003 1.0962100e-001 -2.1523850e-002 +v 2.7020740e-002 6.1345700e-002 -2.2292060e-002 +v 7.1030200e-003 1.0191162e-001 -2.1230990e-002 +v -3.8225680e-002 1.2465525e-001 -7.3257400e-003 +v 2.5941540e-002 1.1576352e-001 -8.2193900e-003 +v -6.1297960e-002 3.3900220e-002 -9.3216600e-003 +v -5.9466670e-002 1.4743956e-001 -1.8885400e-003 +v 1.0506610e-002 1.0087700e-001 -2.2109510e-002 +v 3.3081340e-002 1.0273382e-001 -1.2787210e-002 +v 1.2517840e-002 1.0475378e-001 -1.9915960e-002 +v 2.3087990e-002 9.3998720e-002 -2.2210680e-002 +v 3.1555430e-002 9.2484730e-002 -1.8204280e-002 +v 6.2723100e-003 9.9910370e-002 -2.2296890e-002 +v -4.0917240e-002 4.6121780e-002 -1.7942580e-002 +v 3.5407360e-002 9.8188850e-002 -1.2008970e-002 +v 9.4135900e-003 1.2121902e-001 -1.2937780e-002 +v 5.3735190e-002 7.2027350e-002 6.8010000e-003 +v 2.5620340e-002 1.1880719e-001 -5.0330800e-003 +v -3.8150260e-002 4.2466610e-002 -2.6893990e-002 +v -2.8212410e-002 1.1116862e-001 -1.8001930e-002 +v -6.0253590e-002 1.4339100e-001 -3.7906300e-003 +v 1.9016880e-002 1.0401450e-001 -1.9333120e-002 +v 7.5446700e-003 9.1682150e-002 -3.1643140e-002 +v -7.0760800e-003 1.2240119e-001 -1.1364410e-002 +v -1.9047500e-002 9.6562130e-002 -2.7579900e-002 +v -1.6953390e-002 1.0669256e-001 -2.2002990e-002 +v -6.7307000e-004 1.0119875e-001 -2.2857770e-002 +v -9.0179300e-003 1.2528031e-001 -7.7912000e-003 +v -6.8136180e-002 1.8006113e-001 -5.8816050e-002 +v -2.3600190e-002 1.1513818e-001 -1.5577390e-002 +v -5.9831220e-002 4.2842260e-002 -6.6469100e-003 +v 5.3124070e-002 5.9012380e-002 -2.8853800e-003 +v -3.6931840e-002 3.7107370e-002 -2.9714170e-002 +v -5.6215140e-002 1.4139213e-001 -2.8027300e-003 +v 3.6695880e-002 1.0372844e-001 -7.9621500e-003 +v -3.5885070e-002 1.2040038e-001 -1.0640470e-002 +v -9.3569500e-003 8.5423730e-002 -3.8112540e-002 +v -6.0127340e-002 1.2041391e-001 -9.3791100e-003 +v -3.9842790e-002 1.2156113e-001 -1.1570310e-002 +v 2.8322200e-002 1.0847957e-001 -1.2623390e-002 +v -1.8733500e-003 1.1593910e-001 -1.7169430e-002 +v 3.8648150e-002 9.0153340e-002 -1.2549680e-002 +v -1.7359200e-003 9.2244170e-002 -3.4310460e-002 +v 5.0000820e-002 6.1612070e-002 -3.4649900e-003 +v 5.5858960e-002 6.2910170e-002 6.9037000e-004 +v 2.0461520e-002 1.1515372e-001 -1.3103780e-002 +v -1.5165840e-002 1.1798075e-001 -1.4465520e-002 +v -7.0859540e-002 7.1510150e-002 3.3895100e-002 +v 2.2674030e-002 8.6606050e-002 -2.4925490e-002 +v 3.5358840e-002 8.7438890e-002 -1.7109050e-002 +v 1.8400920e-002 1.2145507e-001 -7.6804200e-003 +v -2.5425900e-002 4.1421010e-002 -2.9204830e-002 +v -8.2085100e-003 9.6777440e-002 -3.0809780e-002 +v -5.6810660e-002 3.3873940e-002 -1.1166310e-002 +v -3.4588640e-002 4.4744960e-002 -2.7122900e-002 +v -4.0251680e-002 1.1827531e-001 -1.3674080e-002 +v 1.6387020e-002 1.1402346e-001 -1.5496900e-002 +v 4.2635280e-002 6.0797460e-002 -3.4583700e-003 +v -5.0687200e-002 3.5935870e-002 -1.2380790e-002 +v 7.3446800e-003 9.4509570e-002 -2.9683220e-002 +v -1.9706700e-002 9.2917340e-002 -3.4636880e-002 +v -1.2083040e-002 1.2219229e-001 -9.7120900e-003 +v 4.8805930e-002 6.8457810e-002 1.6952900e-003 +v -3.0869700e-003 9.8402500e-002 -2.7403170e-002 +v -5.3198790e-002 1.3672896e-001 -1.6580500e-003 +v -4.7290060e-002 1.3055355e-001 1.6909100e-003 +v 4.4651700e-003 1.2044039e-001 -1.3931400e-002 +v -2.3850100e-003 1.2290534e-001 -1.0382460e-002 +v -2.4833330e-002 9.5858030e-002 -2.5162110e-002 +v -4.2296900e-002 3.6291920e-002 -2.7253600e-002 +v -5.4388260e-002 1.3404922e-001 -3.9920400e-003 +v -5.0539380e-002 1.3336659e-001 -1.0872200e-003 +v 2.6040300e-003 9.6942660e-002 -2.8407060e-002 +v -7.8163100e-003 1.2821209e-001 -1.9430400e-003 +v 6.5111700e-003 1.3002517e-001 9.2881000e-004 +v 3.4742860e-002 9.2274140e-002 -1.5654590e-002 +v -6.7787700e-002 1.8088887e-001 -5.8191050e-002 +v -3.3715410e-002 1.1151566e-001 -1.8078440e-002 +v 4.4630400e-003 1.2427294e-001 -9.4291400e-003 +v -2.3370170e-002 9.3392760e-002 -3.2031820e-002 +v -4.8982070e-002 1.2980647e-001 -1.3229400e-003 +v -7.8164000e-004 1.2822918e-001 -3.2490000e-003 +v 2.4960400e-003 8.9857600e-002 -3.3628450e-002 +v 7.4553300e-003 1.1196790e-001 -1.9554260e-002 +v 2.8791140e-002 9.1157340e-002 -2.0370210e-002 +v -5.3590150e-002 1.2437450e-001 -7.3470400e-003 +v -4.7743630e-002 1.2064432e-001 -1.2812990e-002 +v -1.9616230e-002 1.2109197e-001 -9.5487700e-003 +v -6.5047370e-002 1.7999148e-001 -5.9758600e-002 +v -5.1704160e-002 3.7620360e-002 -1.1763450e-002 +v -5.2124270e-002 1.2929832e-001 -4.1187000e-003 +v -4.5334450e-002 1.2891494e-001 1.5819100e-003 +v -3.0471200e-003 1.2919453e-001 -1.0688000e-003 +v 7.2129600e-003 1.2721957e-001 -5.2073700e-003 +v 1.1669320e-002 1.2720154e-001 -3.1850900e-003 +v 5.3056400e-002 6.9708830e-002 3.1291400e-003 +v -6.3021150e-002 1.7810951e-001 -6.0393570e-002 +v 2.8204800e-002 6.4391270e-002 -2.0698040e-002 +v 3.4400180e-002 1.0503000e-001 -1.0224920e-002 +v 3.0975190e-002 1.0790250e-001 -1.1058430e-002 +v -4.8984390e-002 1.1480518e-001 -1.5966690e-002 +v -3.2821710e-002 1.2300500e-001 -5.9088300e-003 +v -5.0792860e-002 1.2716487e-001 -4.8183200e-003 +v -3.5301670e-002 1.2547815e-001 -3.1542800e-003 +v 5.6455250e-002 6.9951490e-002 4.9191700e-003 +v -1.6240450e-002 1.2512177e-001 -3.6499700e-003 +v -1.6970400e-002 1.1119793e-001 -1.9586410e-002 +v -5.4088120e-002 3.9781210e-002 -1.0544680e-002 +v -3.4190490e-002 4.7514010e-002 -2.2301500e-002 +v 1.3699090e-002 9.3914220e-002 -2.6427690e-002 +v 8.8000000e-004 9.9234930e-002 -2.4355670e-002 +v -4.6459460e-002 1.2723953e-001 -4.8843300e-003 +v -4.1735500e-002 1.2687599e-001 -4.1742000e-003 +v -2.1000480e-002 1.2313643e-001 -6.1190100e-003 +v -1.2130450e-002 1.2572568e-001 -5.2007900e-003 +v -4.3822400e-003 1.2640753e-001 -6.9495200e-003 +v 1.4085700e-003 3.4781990e-002 -2.3265200e-002 +v -1.4846200e-002 3.5070930e-002 -2.6071900e-002 +v -2.1399500e-002 3.4795120e-002 -2.7958820e-002 +v 1.2009220e-002 3.5961900e-002 -2.1735750e-002 +v 3.8249200e-003 3.6129220e-002 -2.3878090e-002 +v -5.1139560e-002 9.6617580e-002 -2.2095120e-002 +v -5.4813320e-002 9.8102480e-002 -2.1425370e-002 +v -2.7597040e-002 1.6979824e-001 -1.8170420e-002 +v 1.3359870e-002 3.9377410e-002 -2.2496330e-002 +v 4.3919300e-003 3.8674430e-002 -2.4170290e-002 +v -6.8478200e-003 3.6444540e-002 -2.5177120e-002 +v -1.3280260e-002 3.7699590e-002 -2.6391810e-002 +v -4.7672760e-002 3.6116650e-002 -1.3301210e-002 +v -4.5590120e-002 1.0853826e-001 -1.8796680e-002 +v -5.0095670e-002 1.0990925e-001 -1.8504510e-002 +v -6.5766640e-002 3.6469550e-002 -7.2073000e-003 +v -2.3455840e-002 1.6824727e-001 -1.8822880e-002 +v -4.5918000e-003 3.8404570e-002 -2.5412870e-002 +v -2.4954130e-002 3.7441060e-002 -2.9152720e-002 +v 2.9007770e-002 3.7358220e-002 -2.7474000e-004 +v -7.9468800e-003 4.1489920e-002 -2.5911270e-002 +v -1.6803800e-002 3.9753810e-002 -2.7565350e-002 +v -6.5156150e-002 1.4034537e-001 -7.6848600e-003 +v -4.7080100e-002 4.0700690e-002 -1.1869830e-002 +v -6.8470630e-002 3.7477700e-002 -4.9557400e-003 +v 3.7326850e-002 4.0209510e-002 -8.5850000e-004 +v 3.5349870e-002 4.1257050e-002 -2.8075100e-003 +v 5.1820700e-003 4.1536320e-002 -2.4065670e-002 +v 1.8660660e-002 1.0030784e-001 -2.2127290e-002 +v -6.0510780e-002 1.0748450e-001 -1.7042300e-002 +v -6.2374340e-002 4.0146090e-002 -7.4040200e-003 +v 2.5456950e-002 3.9483890e-002 -4.0251400e-003 +v -2.2828000e-004 4.3394940e-002 -2.5124420e-002 +v -8.1088400e-003 4.3439060e-002 -2.6140070e-002 +v -1.7362450e-002 4.3237420e-002 -2.7665190e-002 +v -2.6416670e-002 4.4674020e-002 -2.8209740e-002 +v 3.8064500e-003 1.0944331e-001 -2.0203790e-002 +v -5.8232370e-002 9.5690400e-002 -2.0616030e-002 +v -6.6122370e-002 4.2341260e-002 -2.7538800e-003 +v -6.0959920e-002 9.4173040e-002 -1.9015670e-002 +v 3.1352250e-002 4.2649280e-002 -4.6745000e-003 +v -3.3540900e-002 3.6342620e-002 4.9089960e-002 +v 1.7252780e-002 4.4335610e-002 -2.3067190e-002 +v 1.0637660e-002 4.4161560e-002 -2.4926170e-002 +v 4.3843100e-003 4.5806710e-002 -2.6788990e-002 +v -8.2506400e-003 4.5148720e-002 -2.8441070e-002 +v -1.5748410e-002 4.5043860e-002 -2.7877790e-002 +v 2.8990330e-002 4.4697850e-002 -6.1863000e-003 +v 8.1686400e-003 4.5053030e-002 -2.5178740e-002 +v -9.6291000e-004 4.5378230e-002 -2.7308280e-002 +v -1.7033400e-003 4.7819200e-002 -2.9928930e-002 +v -3.1535830e-002 4.4740410e-002 -2.8079410e-002 +v -3.3619650e-002 1.5691468e-001 -1.1024870e-002 +v -5.0751180e-002 4.3109620e-002 -1.0018680e-002 +v 3.6890890e-002 4.7353200e-002 -6.1057100e-003 +v 2.4975630e-002 4.2644580e-002 -7.0169900e-003 +v 2.4562420e-002 4.8369560e-002 -1.9672760e-002 +v 1.3964040e-002 4.5579170e-002 -2.4706510e-002 +v 1.3376130e-002 4.8630300e-002 -2.6551500e-002 +v 3.7308900e-003 4.8127990e-002 -2.9025970e-002 +v -8.7947000e-003 4.7056850e-002 -2.9881630e-002 +v -1.3753770e-002 5.1865060e-002 -3.2243480e-002 +v -2.1200840e-002 4.6657090e-002 -2.7951320e-002 +v 3.9693540e-002 4.5658580e-002 -4.5274100e-003 +v 3.3627400e-002 4.8717730e-002 -6.3904600e-003 +v -6.5352120e-002 9.9294570e-002 -1.6820150e-002 +v 1.2868100e-003 5.0383670e-002 -3.0357440e-002 +v -8.1797500e-003 4.9845800e-002 -3.1071390e-002 +v -1.7184350e-002 4.8210500e-002 -2.9741930e-002 +v -2.6049450e-002 4.7692500e-002 -2.6149500e-002 +v -8.4747010e-002 1.1078350e-001 3.9488380e-002 +v -5.1316870e-002 4.8270690e-002 -7.9310500e-003 +v -8.2506510e-002 1.2765487e-001 -4.6796400e-003 +v 3.8663690e-002 5.1696670e-002 -6.6910200e-003 +v -7.5643160e-002 9.9440450e-002 -1.1927610e-002 +v 2.0284470e-002 5.1349190e-002 -2.4895380e-002 +v 5.9436000e-003 5.0976660e-002 -2.9119360e-002 +v -2.5528290e-002 5.1472710e-002 -2.6884680e-002 +v -3.5562670e-002 4.9399890e-002 -1.2865040e-002 +v -4.2818980e-002 1.6220182e-001 -1.0337510e-002 +v -6.5593600e-002 1.7665711e-001 -6.0504730e-002 +v -3.4151080e-002 1.7442797e-001 -1.3312550e-002 +v 4.3673180e-002 5.0162230e-002 -5.9843500e-003 +v -5.0342410e-002 1.5546197e-001 -5.1927700e-003 +v 2.5464180e-002 5.4029700e-002 -2.1691010e-002 +v 1.0149790e-002 4.9258540e-002 -2.7750590e-002 +v -2.2043190e-002 5.3612020e-002 -3.0135610e-002 +v -3.2875520e-002 5.1677630e-002 -1.0888650e-002 +v -3.7613820e-002 4.9534770e-002 -1.1626140e-002 +v -4.0750630e-002 4.9285110e-002 -1.1286200e-002 +v -4.6385170e-002 4.7490850e-002 -1.0085980e-002 +v 4.4473170e-002 5.3293010e-002 -6.3327900e-003 +v 3.3205620e-002 5.1020650e-002 -7.2382500e-003 +v 1.5678350e-002 5.1169270e-002 -2.6397810e-002 +v 6.8341700e-003 5.5010170e-002 -3.0561130e-002 +v 2.1424700e-003 5.5502800e-002 -3.1334400e-002 +v 5.9285000e-004 5.2867950e-002 -3.0513830e-002 +v -3.6481400e-003 5.1869000e-002 -3.1457940e-002 +v -9.4245600e-003 5.5399220e-002 -3.3653980e-002 +v -1.9302150e-002 5.8224770e-002 -3.3919700e-002 +v -6.1084270e-002 1.3386190e-001 -7.2248900e-003 +v -4.3309760e-002 5.5656840e-002 -1.1402110e-002 +v -6.1080540e-002 1.6833773e-001 -5.9192060e-002 +v 4.7574690e-002 5.2943630e-002 -5.1300300e-003 +v -3.7403030e-002 1.1150775e-001 -1.8243310e-002 +v 1.9972490e-002 5.4409710e-002 -2.7108230e-002 +v 5.3974800e-003 5.8382570e-002 -3.0903760e-002 +v -1.0603590e-002 5.3602910e-002 -3.3403350e-002 +v -3.4998290e-002 5.2331560e-002 -1.0347380e-002 +v -4.6471230e-002 5.1304340e-002 -9.8299800e-003 +v -6.7945360e-002 1.1493603e-001 -9.5107300e-003 +v -7.1048210e-002 1.5161088e-001 -4.4679270e-002 +v -5.8903800e-003 3.4790620e-002 -2.4224470e-002 +v 1.6842140e-002 5.5555670e-002 -2.8284560e-002 +v 1.0711040e-002 5.4687610e-002 -2.9767520e-002 +v -1.1826800e-003 5.9492420e-002 -3.3360920e-002 +v -5.2325900e-003 5.5688960e-002 -3.2840220e-002 +v -5.1705830e-002 5.2470760e-002 -7.4047200e-003 +v -5.2626360e-002 6.0043760e-002 -8.9566900e-003 +v -7.2598590e-002 9.7762720e-002 -1.4434510e-002 +v 4.4331260e-002 5.5818010e-002 -6.0362700e-003 +v 3.8463400e-002 5.4934820e-002 -6.1822500e-003 +v 3.8838620e-002 5.7808260e-002 -5.2584800e-003 +v -9.2015400e-003 5.9510130e-002 -3.4437110e-002 +v -3.5262560e-002 5.5284900e-002 -1.0545060e-002 +v -3.8336450e-002 5.4503540e-002 -1.0905320e-002 +v -1.7727540e-002 3.6289540e-002 5.2222250e-002 +v 5.0006490e-002 5.8095800e-002 -4.6211800e-003 +v 4.6133970e-002 5.9278810e-002 -4.7769600e-003 +v 1.5110300e-002 5.9819840e-002 -2.8645750e-002 +v 1.0312380e-002 5.7586530e-002 -2.9995250e-002 +v -6.1353400e-003 6.0256790e-002 -3.4695830e-002 +v -1.2318220e-002 5.9396390e-002 -3.5268510e-002 +v -1.4466910e-002 6.3136020e-002 -3.6865870e-002 +v -4.6650260e-002 5.9840950e-002 -1.2135840e-002 +v -5.6572080e-002 1.2480275e-001 -7.1885700e-003 +v -7.9237500e-002 1.2055419e-001 -5.6744800e-003 +v -7.9334790e-002 1.2560650e-001 -6.1175900e-003 +v 2.2340000e-002 5.8492230e-002 -2.6014120e-002 +v 7.6270400e-003 6.2098330e-002 -3.1135840e-002 +v 3.3101700e-003 6.0456840e-002 -3.2481070e-002 +v -1.6811880e-002 6.1275230e-002 -3.5929330e-002 +v -3.2491910e-002 5.7196350e-002 -1.2104730e-002 +v -3.4108240e-002 6.1466560e-002 -1.3053130e-002 +v -3.3896980e-002 5.7025330e-002 -1.1047570e-002 +v -3.8623580e-002 5.8303290e-002 -1.1505750e-002 +v -4.5008400e-002 6.2723940e-002 -1.3390450e-002 +v -5.6896010e-002 1.3398739e-001 -5.6270700e-003 +v -4.4853890e-002 1.5746031e-001 -8.6731600e-003 +v -7.8609550e-002 6.9656870e-002 1.1810740e-002 +v -2.3730020e-002 1.0186156e-001 -2.3836400e-002 +v -2.8122930e-002 9.9322390e-002 -2.3580130e-002 +v -5.0076720e-002 1.4997652e-001 -3.6419700e-003 +v -3.3048420e-002 9.5958590e-002 -2.3426460e-002 +v 1.9520390e-002 6.2064770e-002 -2.7292470e-002 +v -3.8864710e-002 1.0333987e-001 -2.0641400e-002 +v -4.8952940e-002 5.6281090e-002 -1.0220880e-002 +v -5.3993040e-002 1.4498656e-001 -1.1093400e-003 +v -4.5530560e-002 9.8510850e-002 -2.1729510e-002 +v -5.0910960e-002 1.0074570e-001 -2.1619430e-002 +v 2.3245830e-002 6.2792530e-002 -2.5047990e-002 +v 9.7412800e-003 6.3181400e-002 -3.1141370e-002 +v -8.6614000e-004 6.4559630e-002 -3.4490930e-002 +v -8.5264000e-003 6.4001730e-002 -3.5850480e-002 +v -4.8451500e-002 6.4794120e-002 -1.3029910e-002 +v -5.2325160e-002 1.0614813e-001 -1.9271240e-002 +v -5.5265350e-002 1.0216682e-001 -1.9897100e-002 +v -5.9042010e-002 9.9032210e-002 -1.9222950e-002 +v -5.7846760e-002 1.0433496e-001 -1.8525740e-002 +v -2.7113460e-002 1.7332156e-001 -1.8538890e-002 +v 2.2832000e-002 6.7082570e-002 -2.6297510e-002 +v 1.4519060e-002 6.4595540e-002 -2.9855690e-002 +v 1.1471330e-002 6.7581440e-002 -3.0901170e-002 +v -1.7739360e-002 6.6260830e-002 -3.7657310e-002 +v -6.5059750e-002 1.3452104e-001 -8.0899900e-003 +v -7.5829320e-002 1.4244605e-001 -5.8090000e-003 +v -4.1362350e-002 6.1637330e-002 -1.2813770e-002 +v -5.6147890e-002 6.1921550e-002 -5.7541100e-003 +v -6.2126110e-002 6.2845360e-002 -4.5202600e-003 +v -3.7292480e-002 1.6449057e-001 -1.3627050e-002 +v -1.9818920e-002 1.6509494e-001 -1.7608980e-002 +v 6.2881100e-003 6.5416350e-002 -3.2563040e-002 +v -5.9250500e-003 6.9515630e-002 -3.5933480e-002 +v -1.0538630e-002 6.7999180e-002 -3.6517060e-002 +v -3.5385700e-002 6.6817430e-002 -1.5434860e-002 +v -5.3994500e-002 6.4638700e-002 -9.3254900e-003 +v -6.3852310e-002 6.5572310e-002 -6.9393300e-003 +v -6.3920880e-002 1.2774242e-001 -8.5494600e-003 +v -2.6940700e-002 3.6184050e-002 5.3351850e-002 +v 1.9618650e-002 6.7007390e-002 -2.8356120e-002 +v 1.2275180e-002 6.9933940e-002 -3.1553160e-002 +v 5.4265100e-003 6.8247960e-002 -3.2730520e-002 +v -4.4084200e-003 6.6619200e-002 -3.4870250e-002 +v -2.1911350e-002 6.7144790e-002 -3.6535750e-002 +v -4.5643150e-002 1.5466949e-001 -7.2969400e-003 +v -5.1673460e-002 6.6850660e-002 -1.2120350e-002 +v -5.8105180e-002 6.6465950e-002 -1.0044340e-002 +v -5.6992260e-002 1.4311862e-001 -2.2403000e-003 +v -8.0651110e-002 1.3119854e-001 -4.4397800e-003 +v -5.6544310e-002 1.2850938e-001 -6.2014700e-003 +v 1.7758080e-002 7.0138540e-002 -2.9404680e-002 +v 6.4980500e-003 7.0791870e-002 -3.3525310e-002 +v 7.5831000e-004 7.0434460e-002 -3.4462560e-002 +v -1.3235950e-002 6.9292820e-002 -3.7917490e-002 +v -6.7390780e-002 1.1889688e-001 -8.7301400e-003 +v -3.8119520e-002 6.4162310e-002 -1.3829140e-002 +v 1.8527400e-003 1.1303356e-001 -1.9794270e-002 +v -7.5950810e-002 6.8170610e-002 1.8117970e-002 +v -1.0001990e-002 7.2671480e-002 -3.7661370e-002 +v -1.7976070e-002 7.0613770e-002 -3.8443880e-002 +v -2.3035990e-002 7.2778460e-002 -3.8072640e-002 +v -2.6120100e-002 7.1177480e-002 -3.5451530e-002 +v -6.8535420e-002 1.3929375e-001 -7.8046600e-003 +v -3.5263040e-002 7.1067650e-002 -1.8011860e-002 +v -4.1558180e-002 6.9774010e-002 -1.6774100e-002 +v -5.2831730e-002 7.0298920e-002 -1.4864960e-002 +v -6.6978850e-002 6.7638980e-002 -6.8094400e-003 +v -1.0244470e-002 1.7895826e-001 -2.9538870e-002 +v -7.5272650e-002 1.2680098e-001 -8.0241700e-003 +v -8.7359900e-002 1.1248315e-001 4.2049490e-002 +v 8.7503000e-003 7.4301560e-002 -3.3398210e-002 +v -6.4249520e-002 1.6045024e-001 -5.7041470e-002 +v -4.4354010e-002 7.3372220e-002 -1.7874430e-002 +v -4.5762580e-002 6.9445320e-002 -1.5928780e-002 +v -4.7957440e-002 7.2542990e-002 -1.6106990e-002 +v -5.7822630e-002 6.9538010e-002 -1.4416470e-002 +v -7.2071600e-002 7.1538150e-002 -7.4714400e-003 +v 2.5472930e-002 7.4094500e-002 -2.4938540e-002 +v 1.5719730e-002 7.3756350e-002 -2.9747770e-002 +v 4.8214000e-003 7.3763980e-002 -3.4552450e-002 +v -2.2528600e-003 7.3921320e-002 -3.5887190e-002 +v -7.3834900e-003 7.4799620e-002 -3.7223830e-002 +v -2.0225340e-002 7.7095190e-002 -3.9044290e-002 +v -3.4016180e-002 7.2101270e-002 -2.0823150e-002 +v -3.8493370e-002 7.2839870e-002 -1.7502230e-002 +v -6.4392550e-002 7.3116330e-002 -1.5335340e-002 +v -6.4480660e-002 7.0187350e-002 -1.2261750e-002 +v -2.3854330e-002 1.6164528e-001 -1.4504190e-002 +v 2.2104450e-002 7.2692600e-002 -2.6900140e-002 +v 1.5532370e-002 7.6586960e-002 -2.9606940e-002 +v 1.1574050e-002 7.4860570e-002 -3.1383860e-002 +v -1.4731560e-002 7.7640750e-002 -3.8490670e-002 +v -1.6018820e-002 7.4288800e-002 -3.8864420e-002 +v -5.1103620e-002 7.3071950e-002 -1.6243060e-002 +v -5.7989540e-002 7.4017880e-002 -1.7522320e-002 +v -6.9608380e-002 7.2322890e-002 -1.0934430e-002 +v -7.5996110e-002 1.1714132e-001 -6.5577200e-003 +v -3.7987660e-002 1.0751453e-001 -1.9975760e-002 +v 1.0696210e-002 7.9889200e-002 -3.2009580e-002 +v -5.3433400e-003 7.8264580e-002 -3.7476940e-002 +v -2.6081990e-002 7.6191290e-002 -3.6780200e-002 +v -3.9161040e-002 1.5718885e-001 -1.0580510e-002 +v -6.5609880e-002 7.5860010e-002 -1.6750060e-002 +v -7.0177600e-002 7.5663330e-002 -1.3839210e-002 +v -7.4291360e-002 7.4808360e-002 -9.3537900e-003 +v -6.3428890e-002 1.7185387e-001 -6.1412170e-002 +v 3.0684890e-002 7.5726870e-002 -2.0778090e-002 +v 1.9305010e-002 7.9017870e-002 -2.7743990e-002 +v -8.5992100e-003 7.9338730e-002 -3.7905180e-002 +v -2.3200110e-002 7.6568500e-002 -3.8386500e-002 +v -3.8117820e-002 7.6390120e-002 -1.8644360e-002 +v -4.4231130e-002 7.7664130e-002 -1.9026580e-002 +v -5.1025500e-002 7.5705070e-002 -1.8186900e-002 +v -7.0595130e-002 1.2994832e-001 -8.7629200e-003 +v 2.8147660e-002 7.8785370e-002 -2.2432450e-002 +v 7.6016000e-003 7.9435920e-002 -3.3714560e-002 +v 4.9502400e-003 7.8027250e-002 -3.4409750e-002 +v -1.5858350e-002 8.1165550e-002 -3.9185590e-002 +v -1.8502080e-002 8.3343870e-002 -3.9010720e-002 +v -7.9739350e-002 1.3606854e-001 -4.1482100e-003 +v -3.0980180e-002 1.6634656e-001 -1.6241160e-002 +v -3.5749800e-002 7.7248350e-002 -1.9374020e-002 +v -4.8944740e-002 7.9086360e-002 -1.9575700e-002 +v -5.5065860e-002 7.8089190e-002 -1.9755480e-002 +v 2.3706000e-002 8.0240410e-002 -2.5450120e-002 +v 1.2254110e-002 8.3456700e-002 -3.0771580e-002 +v 1.8549900e-003 8.4692790e-002 -3.4838500e-002 +v -2.0857000e-004 7.8941410e-002 -3.5782080e-002 +v -4.2710000e-004 8.2947370e-002 -3.6380660e-002 +v -4.4101600e-003 8.2794510e-002 -3.7467250e-002 +v -3.3202320e-002 1.0578320e-001 -2.0647590e-002 +v -3.9206970e-002 8.1536380e-002 -2.0571000e-002 +v -6.0355410e-002 7.9766610e-002 -1.9375540e-002 +v -4.1771830e-002 1.0396706e-001 -2.0832940e-002 +v -1.1204010e-002 8.2713320e-002 -3.8489610e-002 +v -2.3181500e-002 8.1686990e-002 -3.8329160e-002 +v -2.7233190e-002 8.0570950e-002 -3.6620670e-002 +v -3.5470180e-002 8.0196070e-002 -2.2325910e-002 +v -4.4864210e-002 8.1997900e-002 -2.0473520e-002 +v -5.0647890e-002 8.2309430e-002 -2.1365890e-002 +v -5.5522610e-002 8.1927600e-002 -2.1353790e-002 +v -8.8089610e-002 1.1135484e-001 1.8516150e-002 +v -7.2036080e-002 1.1107918e-001 4.5361400e-002 +v -3.3359780e-002 1.6986395e-001 -1.5448990e-002 +v -6.6839030e-002 6.2170510e-002 2.1576840e-002 +v 3.0730560e-002 8.1968990e-002 -2.0040460e-002 +v 1.6224320e-002 8.6480380e-002 -2.8952010e-002 +v -6.9855630e-002 1.0027892e-001 -1.4847830e-002 +v -6.3836170e-002 8.1704600e-002 -1.8908860e-002 +v -6.7914820e-002 8.0136290e-002 -1.7128200e-002 +v -4.5752080e-002 1.6340754e-001 -8.1780500e-003 +v 1.1727540e-002 8.8010780e-002 -3.0860110e-002 +v 7.3334800e-003 8.5270000e-002 -3.2829380e-002 +v -3.4356500e-003 8.7017890e-002 -3.6461000e-002 +v -2.6964110e-002 8.4512810e-002 -3.6361740e-002 +v -3.6553370e-002 8.5316190e-002 -2.2576200e-002 +v -3.8791090e-002 8.5232710e-002 -2.1917600e-002 +v -5.7676940e-002 8.6258340e-002 -2.1098320e-002 +v -6.2581810e-002 8.6394530e-002 -1.9169290e-002 +v -7.1395340e-002 1.2468846e-001 -8.5944200e-003 +v 1.4801570e-002 9.9040900e-002 -2.2842920e-002 +v -2.1162860e-002 1.7491852e-001 -2.1977110e-002 +v -1.4824250e-002 8.7288840e-002 -3.8317070e-002 +v -2.3285750e-002 8.9468030e-002 -3.6027250e-002 +v -5.1595650e-002 8.4422070e-002 -2.1600960e-002 +v -6.9481040e-002 8.5656460e-002 -1.7198420e-002 +v -7.0917210e-002 1.0754846e-001 -1.1496630e-002 +v 3.0145320e-002 8.6284000e-002 -2.0408140e-002 +v -5.5578110e-002 1.1567692e-001 -1.4645990e-002 +v -8.0981100e-003 8.9070080e-002 -3.6552200e-002 +v -8.1206310e-002 1.1205088e-001 -8.8299000e-004 +v -1.8772170e-002 8.9838040e-002 -3.6991710e-002 +v -2.1100420e-002 8.6587670e-002 -3.7849050e-002 +v -2.5809910e-002 8.8889590e-002 -3.5082250e-002 +v -4.8984800e-002 9.0731760e-002 -2.1817170e-002 +v -3.5874870e-002 3.4776000e-002 -3.0845200e-002 +v -3.3164390e-002 3.3606540e-002 -2.9721880e-002 +v -2.5964020e-002 3.3487000e-002 -2.6321120e-002 +v -1.6717530e-002 3.3611640e-002 -2.4625420e-002 +v -5.3486300e-003 3.3829010e-002 -2.2600430e-002 +v 6.4843500e-003 3.4293000e-002 -2.0854930e-002 +v 1.3950350e-002 3.4880000e-002 -1.8612870e-002 +v -4.2465980e-002 3.4189100e-002 -2.7260650e-002 +v -3.3241100e-002 3.3578760e-002 -2.6719450e-002 +v 6.2813500e-003 3.4165800e-002 -1.8764230e-002 +v -4.4265790e-002 3.3663660e-002 -2.1914420e-002 +v -2.3671460e-002 3.3630970e-002 -2.3217760e-002 +v -1.1558580e-002 3.3895430e-002 -2.1054260e-002 +v -2.0406400e-003 3.4053940e-002 -1.9331070e-002 +v 1.7323900e-003 3.4459660e-002 -1.6607870e-002 +v -2.7316070e-002 3.3910070e-002 -2.1353750e-002 +v -1.3371080e-002 3.4361580e-002 -1.9023720e-002 +v 9.5887300e-003 3.4207220e-002 -1.5424050e-002 +v -1.4981540e-002 3.5878180e-002 -1.7992380e-002 +v -2.3474300e-003 3.5903130e-002 -1.5929740e-002 +v 2.2544300e-003 3.6411540e-002 -1.4783970e-002 +v -3.5199130e-002 3.3835210e-002 -2.0508290e-002 +v -2.6075450e-002 3.5918600e-002 -1.9405170e-002 +v 8.2740600e-003 3.5645200e-002 -1.2648700e-002 +v 1.0473640e-002 3.4742600e-002 -1.1262870e-002 +v 1.4055380e-002 3.4483430e-002 -1.4495730e-002 +v -3.6970520e-002 3.5680360e-002 -1.5007790e-002 +v -2.4719500e-003 3.8408770e-002 -1.4159030e-002 +v -3.9481890e-002 3.3618220e-002 -2.3612470e-002 +v -4.1091510e-002 3.4006000e-002 -1.1997540e-002 +v -3.1589810e-002 3.5592330e-002 -1.9204150e-002 +v -2.0086310e-002 3.8064450e-002 -1.7220790e-002 +v -1.1113250e-002 3.8290290e-002 -1.5646360e-002 +v 4.4522600e-003 3.7705190e-002 -1.2957650e-002 +v 1.5870480e-002 3.4416230e-002 -2.9666500e-003 +v -4.7872000e-002 3.4136300e-002 -1.5418250e-002 +v -4.7521640e-002 3.3622720e-002 -1.2804590e-002 +v -3.3407340e-002 3.7577040e-002 -1.6158190e-002 +v -2.7851470e-002 3.8404330e-002 -1.7210420e-002 +v -8.5065300e-003 3.9028950e-002 -1.3000800e-002 +v 6.4552500e-003 3.8165190e-002 -1.0164860e-002 +v 7.4147100e-003 3.4659190e-002 -3.0116800e-003 +v 1.1966200e-002 3.4335400e-002 -5.9571300e-003 +v 2.0414820e-002 3.5567580e-002 -3.7806900e-003 +v -1.9288780e-002 3.8762570e-002 -1.4202620e-002 +v -1.1390100e-003 3.9176760e-002 -1.0381370e-002 +v 3.8149200e-003 3.9024470e-002 -8.0827300e-003 +v 7.5208200e-003 3.6733400e-002 -6.7614300e-003 +v 1.9968120e-002 3.4843990e-002 -1.8984900e-003 +v -4.5058400e-002 3.3600490e-002 -1.2527510e-002 +v -3.0754850e-002 3.8639810e-002 -1.4050770e-002 +v -5.1499810e-002 3.3729110e-002 -1.2082510e-002 +v -2.3756860e-002 3.8585750e-002 -1.1093270e-002 +v 3.9734700e-003 3.8208550e-002 -3.7963500e-003 +v 9.5485400e-003 3.4232620e-002 1.7162000e-003 +v 2.9086550e-002 3.5799990e-002 3.5630900e-003 +v -5.5965200e-002 3.3529910e-002 -9.1246200e-003 +v -1.9523510e-002 3.8505210e-002 -4.5434500e-003 +v 1.6363470e-002 3.4394790e-002 2.2948600e-003 +v 2.1324740e-002 3.4624040e-002 5.6444000e-003 +v -3.9670300e-002 3.6174000e-002 -7.3397700e-003 +v -1.4251730e-002 3.8648030e-002 -4.3030400e-003 +v 2.3262300e-003 3.5348200e-002 2.3246000e-003 +v 1.4014300e-002 3.5703800e-002 3.8878900e-003 +v 1.5322800e-002 3.6239700e-002 3.6628500e-003 +v 2.3753130e-002 3.4670710e-002 3.9885300e-003 +v 3.2369180e-002 3.5816010e-002 7.0246300e-003 +v -6.3715900e-002 3.3776930e-002 -8.0065600e-003 +v -6.4266880e-002 3.3562500e-002 -5.1253200e-003 +v -3.8066600e-002 3.8518600e-002 -7.3079600e-003 +v -9.4308800e-003 3.8887690e-002 -7.4848700e-003 +v 3.9677800e-003 3.4200210e-002 4.9754500e-003 +v 9.4292600e-003 3.6030400e-002 4.5275100e-003 +v 2.9859020e-002 3.4980130e-002 9.8349300e-003 +v -5.2730060e-002 3.3497900e-002 -1.8117500e-003 +v -4.1271000e-002 3.3855400e-002 -1.8800800e-003 +v -3.1105000e-003 3.8946190e-002 -2.7793900e-003 +v 6.2194100e-003 3.5134100e-002 6.5492800e-003 +v 2.0897900e-002 3.5937100e-002 8.7849000e-003 +v 3.5606010e-002 3.6526640e-002 9.8155300e-003 +v -6.7078340e-002 3.3840100e-002 -6.1688300e-003 +v -8.1140000e-004 3.7424170e-002 4.7721500e-003 +v 3.1492300e-003 3.4125310e-002 1.1762220e-002 +v 4.9172000e-003 3.3997100e-002 9.1666100e-003 +v 2.5130800e-002 3.4546910e-002 1.1012580e-002 +v 2.8248620e-002 3.5046370e-002 1.6016700e-002 +v -6.7032970e-002 6.5145960e-002 2.7292860e-002 +v -4.6380170e-002 3.3605230e-002 -8.9435000e-004 +v -3.3163400e-002 3.8195400e-002 -5.2520000e-004 +v -3.2074200e-002 3.8323400e-002 -4.2109000e-004 +v -2.1692690e-002 3.8266010e-002 4.5100800e-003 +v 2.3930750e-002 3.4816710e-002 1.7739160e-002 +v 4.2719120e-002 3.9977070e-002 8.9321600e-003 +v -5.8604080e-002 3.3462230e-002 -2.1667000e-004 +v -3.7314400e-002 3.3633000e-002 4.5724700e-003 +v -1.0423990e-002 3.8488570e-002 6.2292700e-003 +v -1.3896900e-003 3.8651360e-002 2.3966500e-003 +v -3.0845000e-004 3.5462480e-002 8.2607200e-003 +v -1.4089000e-003 3.6193080e-002 1.2944550e-002 +v 2.2252900e-002 3.6583300e-002 1.3979700e-002 +v -7.0961830e-002 3.4345730e-002 -7.8374000e-004 +v -6.9066180e-002 3.3717630e-002 -1.9761000e-004 +v -6.4825640e-002 3.3505860e-002 2.8222500e-003 +v -4.7059660e-002 3.3501860e-002 3.5646400e-003 +v -3.6953800e-003 3.8172780e-002 1.3046800e-002 +v 3.3475850e-002 3.6447340e-002 1.6266960e-002 +v 3.7249610e-002 3.7509920e-002 1.4815820e-002 +v -4.5675940e-002 3.3703640e-002 6.4300300e-003 +v -3.8639270e-002 3.3937310e-002 8.5506500e-003 +v -9.5064100e-003 3.8352640e-002 1.5570660e-002 +v 2.1499800e-002 3.5807100e-002 1.8169400e-002 +v 4.4876460e-002 4.1230990e-002 1.6008250e-002 +v -7.2474010e-002 3.6255930e-002 1.5532600e-003 +v -7.1498130e-002 3.4452970e-002 4.2026500e-003 +v -2.7790900e-002 3.8062900e-002 7.9376100e-003 +v -1.6556410e-002 3.8286470e-002 1.0215790e-002 +v 8.1043500e-003 3.4842900e-002 1.8134600e-002 +v 2.3589460e-002 3.5890600e-002 2.5337690e-002 +v 4.1261350e-002 4.0585070e-002 2.0751930e-002 +v -5.1350870e-002 3.3645700e-002 8.0329400e-003 +v -4.7104300e-002 3.5549500e-002 8.0803900e-003 +v -1.4103500e-003 3.6999940e-002 1.6982030e-002 +v 9.1714000e-004 3.4803380e-002 1.5634690e-002 +v 2.8887900e-003 3.4636250e-002 1.8849770e-002 +v 1.3279200e-002 3.4379500e-002 2.1423700e-002 +v 1.4322700e-002 3.4425500e-002 2.1593200e-002 +v 1.7490100e-002 3.4646300e-002 2.2040900e-002 +v 2.9868460e-002 3.6248820e-002 1.9872200e-002 +v -3.9222000e-002 3.6326200e-002 1.0789900e-002 +v -3.0307100e-002 3.3995400e-002 1.4706400e-002 +v 2.0081230e-002 3.5172700e-002 2.8018770e-002 +v 2.4989010e-002 3.8104580e-002 2.9429570e-002 +v 3.3584130e-002 3.8303930e-002 2.2928670e-002 +v 4.9015720e-002 4.4573630e-002 2.0659450e-002 +v -5.8225970e-002 6.6607310e-002 3.5050280e-002 +v -6.7330830e-002 3.3846440e-002 8.7266300e-003 +v -3.4692330e-002 3.3828710e-002 1.2438580e-002 +v -2.9803200e-002 3.4287000e-002 1.6353100e-002 +v 1.7023800e-003 3.6310890e-002 2.1179600e-002 +v 4.5137020e-002 4.4625440e-002 2.5516510e-002 +v -6.8876490e-002 1.1022176e-001 3.9004630e-002 +v -5.7680560e-002 3.3622690e-002 1.4040310e-002 +v -5.3210500e-002 3.3585300e-002 1.3987000e-002 +v -3.5711600e-002 3.5891600e-002 1.5502900e-002 +v -2.8861500e-002 3.5396700e-002 1.7350000e-002 +v -2.6580500e-002 3.7742600e-002 1.5705300e-002 +v -1.0974400e-003 3.8147840e-002 2.0427010e-002 +v 3.5047710e-002 4.0973940e-002 2.6970390e-002 +v -6.9685460e-002 3.4478780e-002 9.7984300e-003 +v -5.4019000e-002 3.3309900e-002 1.5848000e-002 +v 4.4816800e-003 3.7117830e-002 2.4755300e-002 +v 6.6605500e-003 3.5204730e-002 2.4315930e-002 +v 8.3833000e-003 3.4748700e-002 2.4057310e-002 +v 3.8883100e-002 4.1032980e-002 2.4976570e-002 +v -2.6441900e-003 3.8727070e-002 2.5131260e-002 +v 3.2222300e-003 3.8708440e-002 2.5898750e-002 +v 9.0016500e-003 3.6890930e-002 2.8482190e-002 +v 1.3196980e-002 3.4835790e-002 3.1630980e-002 +v 2.2291600e-002 3.7053310e-002 3.3101020e-002 +v 2.8948390e-002 3.9160020e-002 2.7234810e-002 +v -8.7773470e-002 1.1181412e-001 3.7144310e-002 +v -1.7870490e-002 3.8203890e-002 2.0243220e-002 +v 1.0087420e-002 3.7047690e-002 3.0822500e-002 +v 4.2296550e-002 4.5435770e-002 2.9040920e-002 +v -8.4341340e-002 1.1388013e-001 4.6513480e-002 +v -7.3795710e-002 1.0895629e-001 3.9217250e-002 +v -5.1243340e-002 6.4239200e-002 3.4258040e-002 +v -6.1777390e-002 3.4017860e-002 1.6900580e-002 +v -3.6665100e-002 3.5304200e-002 2.3032000e-002 +v -1.4930180e-002 3.8643510e-002 2.9378330e-002 +v -8.0894520e-002 1.0967225e-001 3.7910230e-002 +v -8.9822620e-002 1.1387199e-001 3.2845310e-002 +v -6.9655510e-002 6.8728370e-002 3.1127880e-002 +v -7.8449800e-002 1.0988832e-001 4.2517920e-002 +v -7.5824140e-002 1.0794900e-001 3.7128750e-002 +v -5.5740630e-002 3.4128050e-002 2.6674360e-002 +v -3.8279600e-002 3.5429000e-002 2.4380600e-002 +v -3.5283340e-002 3.4179780e-002 2.2744860e-002 +v -2.5798070e-002 3.7865000e-002 1.9981460e-002 +v 6.9064300e-003 3.9004270e-002 2.9548510e-002 +v 1.5448990e-002 3.4852440e-002 3.6984890e-002 +v 1.9128230e-002 3.5640640e-002 3.6642280e-002 +v -6.3664970e-002 6.6047840e-002 3.1828080e-002 +v 3.9604800e-002 4.4939530e-002 2.9992360e-002 +v -8.0294310e-002 7.1702430e-002 1.5995300e-002 +v -5.4185430e-002 6.7322700e-002 3.6935610e-002 +v -7.3110210e-002 1.4847168e-001 -2.8748470e-002 +v -5.8999980e-002 7.3751550e-002 4.1197080e-002 +v -5.9520730e-002 6.1040260e-002 -2.3753800e-003 +v -6.2791800e-002 3.4596760e-002 2.3505640e-002 +v -4.1895500e-002 3.3668300e-002 2.6940000e-002 +v 8.9808200e-003 3.7639400e-002 3.3900800e-002 +v 8.5287800e-003 3.4888000e-002 3.6265100e-002 +v -8.9803890e-002 1.1498106e-001 4.2771650e-002 +v -6.5545420e-002 7.4430370e-002 3.9168070e-002 +v -6.4644190e-002 6.1723230e-002 2.2552000e-004 +v 5.2496900e-003 3.9507100e-002 3.3271200e-002 +v 2.0250320e-002 3.7033170e-002 3.9327190e-002 +v -6.7006400e-002 6.3292870e-002 -1.7493900e-003 +v -6.4479770e-002 6.0651470e-002 4.2343200e-003 +v -5.7219630e-002 5.7000470e-002 4.9175800e-003 +v -7.4362810e-002 7.2437050e-002 3.1430040e-002 +v -6.2019000e-002 3.4343180e-002 3.1883280e-002 +v -4.6870820e-002 3.4444130e-002 3.0513130e-002 +v -2.0814280e-002 3.8400960e-002 2.7868430e-002 +v 1.6439350e-002 3.5635110e-002 4.1281040e-002 +v -6.9087160e-002 1.1205014e-001 4.5320060e-002 +v -7.1811570e-002 1.4861318e-001 -3.4639490e-002 +v -6.9538770e-002 6.3074750e-002 3.5758200e-003 +v -8.4863890e-002 7.8392100e-002 1.6462010e-002 +v -9.1188780e-002 1.1588893e-001 2.4705540e-002 +v -8.8827760e-002 1.1359169e-001 2.3873640e-002 +v -7.1302830e-002 1.1325363e-001 4.9444530e-002 +v -5.4876950e-002 7.0282330e-002 3.8828200e-002 +v -7.7208880e-002 1.0715887e-001 3.4738290e-002 +v -6.1241780e-002 5.9007440e-002 8.0916600e-003 +v -6.5885650e-002 3.5025080e-002 2.9416520e-002 +v -5.7889430e-002 3.4419570e-002 3.6265760e-002 +v -5.1847710e-002 3.4470270e-002 3.4635180e-002 +v -3.4834600e-002 3.4721400e-002 3.4578200e-002 +v -3.0984700e-002 3.8191900e-002 3.2390100e-002 +v -4.9613100e-003 3.9364900e-002 3.6702200e-002 +v 1.2224170e-002 3.5177480e-002 4.2620580e-002 +v -7.4898220e-002 1.1458863e-001 5.0776480e-002 +v -8.0469100e-002 1.1357963e-001 4.6643440e-002 +v -7.4107560e-002 6.9586030e-002 2.7264400e-002 +v -7.9002620e-002 7.6339320e-002 2.9248090e-002 +v -6.5297080e-002 3.4778970e-002 3.3744340e-002 +v -3.3656400e-002 3.4344100e-002 3.6914100e-002 +v 4.9318500e-003 3.4814800e-002 4.3462110e-002 +v 1.1347440e-002 3.6213020e-002 4.4652280e-002 +v -6.0569260e-002 7.1154540e-002 3.8653760e-002 +v -8.8979470e-002 1.1450869e-001 2.8446030e-002 +v -6.8543520e-002 6.1090480e-002 1.0557760e-002 +v -8.2710960e-002 1.1648975e-001 4.8518530e-002 +v -4.1913210e-002 3.4467720e-002 3.3200040e-002 +v -1.1289800e-002 3.9529200e-002 3.8844100e-002 +v -2.8261900e-003 3.4885340e-002 4.5611410e-002 +v -6.4561210e-002 5.9484140e-002 1.3061680e-002 +v -5.8581440e-002 5.7801460e-002 1.3429540e-002 +v -2.3320000e-002 3.9169500e-002 3.8473300e-002 +v -1.8159900e-002 3.9322300e-002 3.9402900e-002 +v -1.6471400e-002 3.4812800e-002 4.3684700e-002 +v 3.2906600e-003 3.5833470e-002 4.6024610e-002 +v -8.5229630e-002 1.1200712e-001 3.0416940e-002 +v -8.5644730e-002 1.1131719e-001 3.4234780e-002 +v -7.4530360e-002 6.6680690e-002 4.6953300e-003 +v -7.1112970e-002 6.2751470e-002 8.7995500e-003 +v -6.1149380e-002 5.8834410e-002 1.6539440e-002 +v -4.6912270e-002 3.4627180e-002 3.9739710e-002 +v -4.0760350e-002 3.4668230e-002 4.0492530e-002 +v -2.6323100e-002 3.4658000e-002 4.3473500e-002 +v -3.1836600e-003 3.6229910e-002 4.7873100e-002 +v -7.9940490e-002 1.0916678e-001 3.4119800e-002 +v -5.9712170e-002 6.3165280e-002 2.8789180e-002 +v -5.1176600e-002 6.8061880e-002 3.7398330e-002 +v -5.0126580e-002 7.0933150e-002 3.9481010e-002 +v -7.2790130e-002 6.4399880e-002 1.5205950e-002 +v -6.8511230e-002 6.1214650e-002 1.5354080e-002 +v -3.9343210e-002 3.5440180e-002 4.2492560e-002 +v -8.1305900e-003 3.5008350e-002 4.7502400e-002 +v -6.6080670e-002 7.0202740e-002 3.5552860e-002 +v -6.8602600e-002 1.4992277e-001 -4.0051350e-002 +v -7.1722100e-002 6.7023040e-002 2.4959750e-002 +v -7.5115010e-002 6.6557040e-002 1.0244090e-002 +v -6.5146650e-002 3.5945650e-002 3.9775080e-002 +v -3.6898600e-002 3.5924640e-002 4.4794170e-002 +v -9.4780400e-003 3.5977600e-002 4.9434210e-002 +v -8.5175960e-002 1.1706809e-001 4.8139420e-002 +v -6.3366400e-002 6.2790260e-002 2.5647610e-002 +v -6.6633330e-002 6.1001700e-002 1.8101240e-002 +v -5.8167590e-002 5.9985190e-002 2.2606060e-002 +v -6.4212210e-002 3.4992560e-002 3.9401920e-002 +v -5.3425790e-002 3.4560020e-002 4.2782420e-002 +v -1.8031490e-002 3.4859970e-002 4.9264760e-002 +v -1.1440410e-002 3.7640770e-002 5.0275730e-002 +v -7.5165320e-002 1.1154286e-001 4.6707180e-002 +v -7.7168390e-002 6.9826450e-002 5.0605600e-003 +v -7.2801360e-002 6.4382590e-002 1.2089080e-002 +v -7.8022000e-002 7.0995160e-002 2.1322150e-002 +v -6.1263370e-002 3.4690410e-002 4.1994900e-002 +v -5.4403750e-002 3.5007310e-002 4.4874590e-002 +v -4.5754280e-002 3.5206980e-002 4.3518120e-002 +v -3.3832440e-002 3.5168820e-002 4.6957890e-002 +v -2.8657630e-002 3.5083380e-002 5.0549440e-002 +v -1.5306440e-002 3.5246410e-002 5.0133810e-002 +v -6.5283650e-002 1.5592447e-001 -4.9865930e-002 +v -6.6467860e-002 1.4871539e-001 -3.1579300e-002 +v -6.2095980e-002 1.6388324e-001 -5.8385930e-002 +v -6.3274890e-002 1.5245731e-001 -3.2221730e-002 +v -4.3755720e-002 1.4773408e-001 -2.1433200e-003 +v -6.5696940e-002 1.4561631e-001 -1.8974710e-002 +v -6.6713650e-002 1.5358824e-001 -4.9097100e-002 +v -1.0482810e-002 1.6668287e-001 -2.1746090e-002 +v -6.2744510e-002 1.6397531e-001 -5.9398280e-002 +v -7.0413230e-002 1.4129200e-001 -8.4590800e-003 +v -6.1530380e-002 1.4037628e-001 -6.2734700e-003 +v -1.1452460e-002 1.7220633e-001 -2.6844980e-002 +v -6.3731140e-002 1.6577037e-001 -6.0103610e-002 +v -2.8218820e-002 1.5758144e-001 -1.0999490e-002 +v -1.8471270e-002 1.5967716e-001 -1.1169510e-002 +v -6.6700710e-002 1.5236775e-001 -4.5266390e-002 +v -4.9896410e-002 1.4670859e-001 -1.8614200e-003 +v -3.1449640e-002 1.5460463e-001 -7.6802300e-003 +v -6.7447660e-002 1.5507675e-001 -5.1594250e-002 +v -1.0906650e-002 1.7649301e-001 -2.9246300e-002 +v -7.2083600e-002 1.4965550e-001 -3.9265860e-002 +v -6.4230830e-002 1.4877806e-001 -2.5899710e-002 +v -6.3056640e-002 1.4341650e-001 -7.4907700e-003 +v -5.3043350e-002 1.4092550e-001 -4.7408000e-004 +v -3.9269410e-002 1.5205232e-001 -6.6203800e-003 +v -6.4796930e-002 1.5210615e-001 -3.6185520e-002 +v -6.4400320e-002 1.5834400e-001 -5.4256370e-002 +v -6.6178120e-002 1.4218350e-001 -9.3766300e-003 +v -6.7751430e-002 1.4605207e-001 -2.3333300e-002 +v -6.4731580e-002 1.5410067e-001 -4.0464820e-002 +v -2.4265590e-002 1.5687690e-001 -7.8509300e-003 +v -1.5723180e-002 1.6312344e-001 -1.6396570e-002 +v -7.0887660e-002 1.4404618e-001 -1.4908480e-002 +v -4.4341830e-002 1.5113809e-001 -5.6859800e-003 +v -6.2896810e-002 1.4694778e-001 -1.3098620e-002 +v -6.3755400e-002 1.4428875e-001 -1.1395730e-002 +v -6.8214560e-002 1.4390932e-001 -1.4984170e-002 +v -5.0271440e-002 1.4336563e-001 1.5153000e-003 +v -2.8535590e-002 1.6208479e-001 -1.4786030e-002 +v -6.5810700e-002 1.4359119e-001 -1.2585380e-002 +v -5.6179200e-002 1.3774406e-001 -4.0674300e-003 +v -6.8866880e-002 1.4723338e-001 -2.8739870e-002 +v -6.0965420e-002 1.7002113e-001 -6.0839390e-002 +v -1.3895490e-002 1.6787168e-001 -2.1897230e-002 +v -6.9413000e-002 1.5121847e-001 -4.4538540e-002 +v -5.5039800e-002 5.7309700e-002 1.6990900e-002 +f 1069 1647 1578 +f 1058 909 939 +f 421 1176 238 +f 1055 1101 1042 +f 238 1059 1126 +f 1254 30 1261 +f 1065 1071 1 +f 1037 1130 1120 +f 1570 2381 1585 +f 2434 2502 2473 +f 1632 1654 1646 +f 1144 1166 669 +f 1202 1440 305 +f 1071 1090 1 +f 1555 1570 1584 +f 1184 1174 404 +f 65 432 12 +f 1032 1085 574 +f 1789 2207 2223 +f 1154 1118 1184 +f 1141 1086 1154 +f 99 1117 342 +f 404 1174 419 +f 489 2000 1998 +f 1118 1174 1184 +f 1196 403 136 +f 1495 717 1490 +f 1804 402 1207 +f 2272 1398 891 +f 1100 1002 804 +f 1596 1595 2381 +f 208 420 1207 +f 402 208 1207 +f 1455 1935 1925 +f 1176 1059 238 +f 1150 1040 348 +f 1957 1537 2051 +f 1124 1189 939 +f 1804 1207 1823 +f 1381 1300 1109 +f 383 384 1182 +f 1085 1086 1141 +f 1040 1046 132 +f 220 1495 1188 +f 420 261 1207 +f 261 420 1065 +f 1055 1133 1101 +f 1054 421 403 +f 182 1109 2 +f 1181 1207 320 +f 545 1570 1561 +f 35 342 432 +f 1024 574 1141 +f 432 342 12 +f 1489 1081 1547 +f 1181 320 1805 +f 1516 1683 1507 +f 357 1117 1047 +f 1561 1570 1555 +f 1090 1196 1206 +f 1047 1203 1051 +f 1165 202 1121 +f 1099 341 301 +f 1174 240 419 +f 922 921 833 +f 1121 1080 385 +f 815 21 1183 +f 35 99 342 +f 1083 398 262 +f 106 94 1317 +f 94 292 1317 +f 292 95 1317 +f 940 1039 1033 +f 1300 1306 433 +f 21 212 471 +f 1120 1131 1037 +f 833 921 688 +f 1117 357 342 +f 106 271 94 +f 386 227 1375 +f 1130 1044 1053 +f 419 240 219 +f 1255 1244 32 +f 1557 1081 1489 +f 2062 2120 2109 +f 2034 2110 430 +f 23 315 1111 +f 291 94 271 +f 291 292 94 +f 50 386 95 +f 964 734 665 +f 1616 1585 1611 +f 445 1084 402 +f 574 1085 1141 +f 1654 341 1653 +f 220 1188 1640 +f 342 69 12 +f 417 261 328 +f 292 50 95 +f 204 227 386 +f 50 204 386 +f 1276 1471 1311 +f 1206 1196 136 +f 1033 1055 1042 +f 1037 1044 1130 +f 1180 320 417 +f 1121 202 1080 +f 325 203 271 +f 291 76 292 +f 292 237 50 +f 2159 1696 1767 +f 583 929 850 +f 1584 1585 1616 +f 1495 1490 1188 +f 1557 1489 1660 +f 1078 1069 1494 +f 1972 1992 1971 +f 183 1226 2000 +f 325 429 203 +f 292 76 237 +f 1152 227 1143 +f 1488 1412 1489 +f 1638 1646 1653 +f 1947 1869 2468 +f 203 306 291 +f 306 76 291 +f 237 248 50 +f 204 1143 227 +f 2395 14 429 +f 1502 881 2500 +f 1 1090 202 +f 1652 1653 1099 +f 2117 1863 2496 +f 50 248 204 +f 160 792 994 +f 884 888 857 +f 544 2117 2496 +f 1090 1206 202 +f 2463 879 2492 +f 429 306 203 +f 498 188 418 +f 865 884 857 +f 994 998 1014 +f 884 897 888 +f 1795 948 1802 +f 208 1035 1071 +f 1065 1 1066 +f 377 435 1377 +f 304 429 14 +f 304 306 429 +f 73 60 74 +f 248 592 204 +f 846 2264 829 +f 897 912 906 +f 1004 991 992 +f 1422 1421 1233 +f 980 10 303 +f 1058 922 909 +f 2436 2449 2418 +f 394 435 377 +f 435 475 446 +f 475 474 446 +f 336 337 361 +f 338 235 372 +f 624 148 129 +f 812 306 596 +f 1726 992 1019 +f 945 1514 1511 +f 1069 1627 1628 +f 1812 1823 1181 +f 1165 1121 169 +f 447 475 435 +f 2487 2458 901 +f 42 59 46 +f 401 7 187 +f 1010 970 797 +f 1513 220 1640 +f 2474 2491 2462 +f 594 307 1014 +f 398 1513 1640 +f 307 594 1026 +f 545 2381 1570 +f 403 421 238 +f 445 402 127 +f 1611 1631 1616 +f 1805 1180 1148 +f 394 447 435 +f 2341 2413 2376 +f 75 74 60 +f 541 47 42 +f 47 59 42 +f 541 42 28 +f 917 931 1103 +f 897 906 883 +f 2484 2068 779 +f 888 883 857 +f 261 1065 328 +f 363 1307 349 +f 377 363 394 +f 444 747 464 +f 323 338 362 +f 92 116 74 +f 592 634 97 +f 982 1027 1004 +f 1020 982 1004 +f 1084 1054 1035 +f 208 402 1084 +f 421 1119 1176 +f 1207 1181 1823 +f 1179 1187 1160 +f 263 296 1343 +f 1298 296 1307 +f 1307 296 349 +f 405 363 349 +f 405 394 363 +f 405 447 394 +f 362 372 384 +f 338 372 362 +f 983 1004 987 +f 122 134 139 +f 415 440 414 +f 75 92 74 +f 226 186 246 +f 796 787 700 +f 1119 1059 1176 +f 122 114 91 +f 624 129 116 +f 641 558 631 +f 1311 1318 1487 +f 100 1162 1170 +f 1653 341 1099 +f 1316 1983 273 +f 263 277 296 +f 296 358 349 +f 436 447 405 +f 109 554 570 +f 504 1385 2501 +f 115 122 91 +f 2068 2460 779 +f 43 777 163 +f 378 405 349 +f 358 378 349 +f 448 447 436 +f 448 476 447 +f 78 77 108 +f 75 60 47 +f 1764 2481 1795 +f 717 714 1512 +f 1490 717 1501 +f 238 1126 168 +f 1878 1866 826 +f 2025 2360 2367 +f 251 278 263 +f 278 277 263 +f 277 318 296 +f 296 318 358 +f 318 350 358 +f 378 436 405 +f 384 372 1182 +f 454 440 415 +f 987 1004 992 +f 493 476 448 +f 323 788 338 +f 403 238 136 +f 1565 1503 1474 +f 297 277 278 +f 297 318 277 +f 358 350 378 +f 378 388 436 +f 476 493 500 +f 73 105 60 +f 323 337 312 +f 953 1573 2358 +f 142 161 119 +f 454 443 440 +f 1862 1871 1405 +f 297 319 318 +f 560 47 541 +f 170 1323 111 +f 357 1047 1050 +f 1119 98 1059 +f 1838 1877 1900 +f 2359 230 251 +f 350 364 378 +f 449 448 436 +f 449 493 448 +f 185 186 226 +f 443 469 479 +f 874 165 2480 +f 463 444 464 +f 64 105 91 +f 1182 440 1129 +f 1958 1651 2502 +f 1238 2034 191 +f 251 279 278 +f 278 279 297 +f 364 388 378 +f 483 493 449 +f 134 148 139 +f 244 268 259 +f 910 942 930 +f 105 115 91 +f 24 30 18 +f 1132 487 1059 +f 1869 1947 2021 +f 2497 2494 2463 +f 2359 2385 230 +f 230 280 251 +f 251 280 279 +f 279 308 297 +f 297 308 319 +f 319 364 318 +f 364 350 318 +f 388 395 436 +f 436 395 449 +f 493 472 500 +f 122 129 134 +f 125 142 124 +f 373 400 393 +f 24 557 30 +f 2264 2278 2251 +f 1261 30 1269 +f 1730 1862 1877 +f 252 280 230 +f 343 364 319 +f 364 343 388 +f 63 64 91 +f 399 393 416 +f 416 444 463 +f 162 189 142 +f 768 373 326 +f 189 661 177 +f 189 199 661 +f 847 887 864 +f 533 747 444 +f 1744 1022 1418 +f 1170 524 729 +f 121 1342 128 +f 1236 1244 26 +f 280 281 279 +f 281 308 279 +f 343 319 308 +f 343 365 388 +f 388 365 395 +f 365 406 395 +f 406 449 395 +f 483 477 493 +f 477 491 472 +f 493 477 472 +f 78 109 77 +f 166 174 196 +f 481 150 814 +f 63 59 64 +f 326 373 393 +f 643 260 43 +f 230 253 252 +f 449 441 483 +f 441 477 483 +f 415 416 463 +f 226 246 245 +f 464 470 454 +f 323 362 337 +f 52 37 1283 +f 253 281 252 +f 281 280 252 +f 309 308 281 +f 330 343 308 +f 366 365 343 +f 441 449 406 +f 464 814 15 +f 883 906 887 +f 337 362 371 +f 479 498 290 +f 247 746 1003 +f 25 37 557 +f 640 930 669 +f 2486 2499 2459 +f 309 330 308 +f 343 330 366 +f 441 437 477 +f 290 498 418 +f 124 119 108 +f 77 124 108 +f 589 125 109 +f 570 589 109 +f 125 162 142 +f 1045 433 1034 +f 1207 261 320 +f 2004 2474 2495 +f 1215 1228 2285 +f 365 396 406 +f 396 422 406 +f 422 437 441 +f 406 422 441 +f 59 47 60 +f 51 78 66 +f 361 371 383 +f 196 215 214 +f 463 454 415 +f 27 41 535 +f 53 1283 37 +f 84 1299 1283 +f 1805 320 1180 +f 254 253 222 +f 254 281 253 +f 309 366 330 +f 396 365 366 +f 456 477 437 +f 484 491 477 +f 2480 2485 2493 +f 418 188 187 +f 53 85 1283 +f 85 84 1283 +f 420 1071 1065 +f 264 281 254 +f 298 309 281 +f 368 366 367 +f 368 396 366 +f 1639 1564 1139 +f 560 48 47 +f 82 471 212 +f 25 38 37 +f 202 1206 1080 +f 264 298 281 +f 298 331 309 +f 309 331 366 +f 331 367 366 +f 396 368 422 +f 422 456 437 +f 491 1192 313 +f 1699 2064 1710 +f 462 443 479 +f 371 362 384 +f 2502 2476 2464 +f 371 384 383 +f 21 732 212 +f 1571 1629 1627 +f 38 39 53 +f 37 38 53 +f 39 85 53 +f 1173 1184 404 +f 1006 2142 1674 +f 201 255 254 +f 255 264 254 +f 368 407 422 +f 450 456 422 +f 450 484 456 +f 456 484 477 +f 314 1192 491 +f 2027 2501 2489 +f 2475 2471 2488 +f 551 492 732 +f 464 481 814 +f 1081 1494 1547 +f 201 231 255 +f 407 450 422 +f 484 494 491 +f 494 327 491 +f 327 314 491 +f 876 797 995 +f 847 856 829 +f 125 143 162 +f 134 129 148 +f 1564 1571 1627 +f 417 320 261 +f 328 1065 1066 +f 170 156 201 +f 156 231 201 +f 231 282 255 +f 282 264 255 +f 450 485 484 +f 484 485 494 +f 2463 2486 2479 +f 159 185 167 +f 492 68 212 +f 732 492 212 +f 68 82 212 +f 1311 1471 1296 +f 101 156 111 +f 332 264 282 +f 332 298 264 +f 332 331 298 +f 331 332 367 +f 407 423 450 +f 450 423 485 +f 804 1002 1443 +f 2484 779 946 +f 689 443 462 +f 440 689 1129 +f 166 167 174 +f 38 31 39 +f 112 145 101 +f 101 145 156 +f 156 256 231 +f 332 423 368 +f 367 332 368 +f 368 423 407 +f 946 779 920 +f 1432 1261 1449 +f 461 478 453 +f 464 15 470 +f 31 54 39 +f 39 54 85 +f 86 101 85 +f 145 210 156 +f 282 283 332 +f 283 369 332 +f 369 423 332 +f 423 408 485 +f 854 876 965 +f 78 108 66 +f 440 443 689 +f 374 2465 961 +f 929 519 979 +f 54 86 85 +f 156 241 256 +f 256 282 231 +f 256 283 282 +f 389 423 369 +f 389 408 423 +f 408 457 485 +f 457 49 485 +f 485 49 494 +f 494 135 327 +f 175 83 314 +f 1167 1140 1483 +f 196 174 215 +f 697 16 68 +f 1038 82 16 +f 140 117 141 +f 1654 1653 1646 +f 1234 54 31 +f 86 112 101 +f 210 241 156 +f 923 917 911 +f 697 34 16 +f 145 193 210 +f 256 265 283 +f 265 310 283 +f 283 310 369 +f 310 344 369 +f 344 370 369 +f 370 389 369 +f 409 408 389 +f 409 466 408 +f 466 457 408 +f 466 49 457 +f 49 135 494 +f 174 225 215 +f 1014 766 602 +f 826 2220 2215 +f 1078 1494 1081 +f 1273 70 86 +f 120 112 86 +f 146 145 112 +f 146 193 145 +f 265 256 241 +f 223 265 241 +f 486 49 466 +f 175 327 135 +f 105 122 115 +f 480 15 681 +f 225 234 215 +f 731 34 697 +f 86 54 1273 +f 70 120 86 +f 193 241 210 +f 299 310 265 +f 310 333 344 +f 344 351 370 +f 424 466 409 +f 135 49 175 +f 214 215 234 +f 48 75 47 +f 34 9 1038 +f 16 34 1038 +f 203 291 271 +f 9 558 754 +f 1195 397 1120 +f 120 146 112 +f 146 194 193 +f 266 265 223 +f 266 299 265 +f 299 333 310 +f 333 351 344 +f 382 383 392 +f 399 416 415 +f 266 333 299 +f 351 352 370 +f 424 486 466 +f 487 175 49 +f 7 117 187 +f 1182 414 440 +f 41 42 46 +f 290 289 497 +f 2502 2464 2473 +f 372 399 414 +f 1570 1585 1584 +f 1066 1 1165 +f 1 202 1165 +f 120 70 102 +f 157 146 120 +f 194 223 193 +f 223 241 193 +f 352 379 370 +f 370 379 389 +f 410 409 389 +f 2478 1409 1958 +f 806 945 1002 +f 157 194 146 +f 267 266 223 +f 267 333 266 +f 379 410 389 +f 410 438 409 +f 438 424 409 +f 190 205 143 +f 337 371 361 +f 2215 830 826 +f 1631 1646 1638 +f 102 157 120 +f 157 195 194 +f 195 223 194 +f 195 211 223 +f 223 211 267 +f 267 300 333 +f 300 334 351 +f 333 300 351 +f 351 334 352 +f 410 411 438 +f 438 486 424 +f 487 49 486 +f 875 594 989 +f 108 581 66 +f 225 245 244 +f 312 336 335 +f 151 754 107 +f 274 1386 300 +f 352 334 379 +f 923 1729 1096 +f 244 245 268 +f 463 464 454 +f 414 399 415 +f 15 480 470 +f 1647 1069 1078 +f 909 922 833 +f 387 417 328 +f 133 157 102 +f 1314 133 102 +f 133 195 157 +f 1148 1179 1160 +f 1046 1167 182 +f 379 411 410 +f 792 339 229 +f 391 7 668 +f 185 226 174 +f 461 290 497 +f 2027 504 2501 +f 1196 1054 403 +f 728 1019 752 +f 2459 2483 2461 +f 1291 1264 55 +f 133 1356 195 +f 195 1356 211 +f 412 438 411 +f 4 486 438 +f 458 4 438 +f 4 487 486 +f 1720 1572 1771 +f 245 275 268 +f 1869 2021 2059 +f 235 399 372 +f 64 60 105 +f 836 2492 879 +f 1315 133 1314 +f 1331 1382 1356 +f 1310 926 1128 +f 7 1121 117 +f 119 161 611 +f 380 379 334 +f 379 380 411 +f 467 4 458 +f 495 487 4 +f 495 1126 487 +f 416 400 533 +f 479 469 498 +f 74 116 73 +f 478 461 497 +f 393 400 416 +f 61 1291 55 +f 505 1999 2474 +f 1999 2491 2474 +f 199 189 36 +f 1164 1165 169 +f 1179 387 249 +f 390 411 380 +f 411 390 412 +f 458 438 412 +f 495 168 1126 +f 480 469 470 +f 116 122 105 +f 418 187 140 +f 185 174 167 +f 166 148 167 +f 470 469 443 +f 40 55 32 +f 61 71 1291 +f 71 103 1291 +f 1184 1173 1154 +f 634 514 97 +f 425 458 412 +f 917 923 931 +f 2472 2489 853 +f 754 641 567 +f 44 567 1163 +f 454 470 443 +f 40 32 1249 +f 33 40 1249 +f 56 55 40 +f 56 61 55 +f 451 1265 439 +f 1180 417 1179 +f 1099 301 1077 +f 1189 1058 939 +f 1059 221 1132 +f 598 1074 1075 +f 412 426 425 +f 650 186 185 +f 234 244 259 +f 226 245 225 +f 1033 1042 1030 +f 2492 836 247 +f 7 169 1121 +f 1462 1322 1482 +f 425 467 458 +f 496 4 467 +f 1751 2468 2480 +f 290 418 140 +f 326 789 762 +f 142 177 161 +f 165 1751 2480 +f 87 103 71 +f 103 87 104 +f 1180 1179 1148 +f 417 387 1179 +f 2081 2060 2031 +f 1154 1173 1141 +f 181 131 197 +f 442 425 426 +f 614 144 143 +f 876 1010 797 +f 40 45 56 +f 56 45 61 +f 87 71 61 +f 1563 1437 1590 +f 1121 385 117 +f 1148 1160 1137 +f 1449 1459 1439 +f 1028 2462 929 +f 442 459 425 +f 459 467 425 +f 168 495 4 +f 496 168 4 +f 1763 1403 1444 +f 140 187 117 +f 244 234 225 +f 246 740 269 +f 372 414 1182 +f 40 547 45 +f 45 62 61 +f 62 87 61 +f 87 88 104 +f 1084 517 1054 +f 387 328 1064 +f 2467 2497 2485 +f 286 1363 302 +f 205 189 162 +f 290 140 289 +f 214 234 224 +f 393 399 809 +f 315 1131 397 +f 302 321 353 +f 1164 169 391 +f 427 459 442 +f 217 496 467 +f 217 168 496 +f 978 969 2074 +f 361 383 382 +f 269 276 245 +f 1440 11 305 +f 62 88 87 +f 328 1066 1064 +f 1066 1165 1164 +f 242 287 302 +f 1363 242 302 +f 287 321 302 +f 1179 249 1187 +f 983 1020 1004 +f 464 747 481 +f 788 323 276 +f 269 245 246 +f 88 89 1325 +f 171 172 242 +f 360 353 321 +f 360 1354 353 +f 1057 1064 1164 +f 2184 2188 2183 +f 460 459 451 +f 460 467 459 +f 149 168 217 +f 149 136 168 +f 116 129 122 +f 109 124 77 +f 159 167 148 +f 28 42 41 +f 57 88 62 +f 45 57 62 +f 1336 1325 89 +f 89 72 1336 +f 147 172 171 +f 172 258 242 +f 258 257 242 +f 257 287 242 +f 257 321 287 +f 345 360 321 +f 360 381 1354 +f 1069 938 1655 +f 387 473 249 +f 270 217 467 +f 130 136 149 +f 851 847 829 +f 983 987 975 +f 189 177 142 +f 88 72 89 +f 184 258 172 +f 257 288 321 +f 1265 451 459 +f 270 149 217 +f 226 225 174 +f 27 28 41 +f 109 125 124 +f 547 57 45 +f 57 58 88 +f 88 58 72 +f 2476 2484 2458 +f 147 184 172 +f 184 213 258 +f 258 243 257 +f 243 288 257 +f 345 321 288 +f 391 169 7 +f 468 460 451 +f 468 488 460 +f 270 467 460 +f 488 270 460 +f 1206 136 130 +f 481 793 150 +f 143 205 162 +f 142 119 124 +f 58 90 72 +f 90 128 72 +f 147 173 184 +f 173 213 184 +f 213 233 258 +f 258 233 243 +f 354 360 345 +f 354 381 360 +f 1026 991 307 +f 268 312 259 +f 1206 130 1080 +f 116 105 73 +f 139 148 166 +f 275 312 268 +f 188 401 187 +f 2479 2459 2461 +f 58 63 90 +f 1064 1066 1164 +f 1064 473 387 +f 288 311 345 +f 311 354 345 +f 996 994 307 +f 452 468 439 +f 452 478 468 +f 478 488 468 +f 141 130 149 +f 1564 1639 1563 +f 547 41 57 +f 2081 2107 2060 +f 382 381 354 +f 497 270 488 +f 289 149 270 +f 289 141 149 +f 114 122 139 +f 59 60 64 +f 275 323 312 +f 401 668 7 +f 41 46 57 +f 57 46 58 +f 1459 1345 1269 +f 1342 121 158 +f 166 173 158 +f 213 224 233 +f 233 259 243 +f 243 322 288 +f 322 311 288 +f 453 478 452 +f 497 289 270 +f 912 911 906 +f 276 323 275 +f 276 275 245 +f 46 63 58 +f 90 121 128 +f 173 214 213 +f 213 214 224 +f 259 322 243 +f 336 311 322 +f 336 354 311 +f 361 382 354 +f 1043 439 1290 +f 497 488 478 +f 385 130 141 +f 385 1080 130 +f 144 190 143 +f 535 41 547 +f 121 166 158 +f 335 336 322 +f 354 336 361 +f 2004 2481 1764 +f 698 439 1043 +f 289 140 141 +f 923 1096 931 +f 650 185 159 +f 46 59 63 +f 63 91 90 +f 90 114 121 +f 121 139 166 +f 173 196 214 +f 259 335 322 +f 2478 2502 2434 +f 312 337 336 +f 90 91 114 +f 114 139 121 +f 166 196 173 +f 224 234 233 +f 234 259 233 +f 259 312 335 +f 1124 916 1189 +f 542 541 530 +f 462 479 290 +f 269 783 276 +f 813 567 641 +f 276 783 788 +f 82 1038 1333 +f 816 701 703 +f 672 137 603 +f 625 635 624 +f 2457 2439 1973 +f 767 533 529 +f 2468 1869 2480 +f 662 190 639 +f 711 720 719 +f 630 639 614 +f 161 654 638 +f 781 991 982 +f 1227 31 516 +f 648 639 630 +f 630 614 590 +f 2098 544 1899 +f 578 579 586 +f 697 492 551 +f 529 533 400 +f 869 859 870 +f 1732 924 914 +f 1004 1027 991 +f 801 591 603 +f 636 676 651 +f 876 949 965 +f 2207 1789 1859 +f 76 739 237 +f 188 681 15 +f 578 604 599 +f 797 616 995 +f 510 2035 1365 +f 76 812 617 +f 617 739 76 +f 1468 93 1765 +f 596 546 812 +f 1457 1305 1477 +f 760 197 150 +f 671 773 765 +f 586 609 604 +f 591 700 632 +f 476 2312 474 +f 2084 2027 2489 +f 582 590 571 +f 1555 2449 1996 +f 674 546 596 +f 812 655 617 +f 161 177 661 +f 599 604 636 +f 700 787 576 +f 776 675 572 +f 776 674 675 +f 617 634 739 +f 591 632 649 +f 612 546 674 +f 617 655 634 +f 728 752 706 +f 571 2311 2305 +f 775 674 776 +f 775 612 674 +f 612 628 546 +f 546 628 812 +f 812 628 655 +f 620 630 615 +f 620 648 630 +f 667 653 646 +f 810 782 785 +f 150 197 814 +f 534 1517 2000 +f 702 572 2378 +f 748 776 572 +f 655 613 634 +f 911 917 905 +f 648 679 662 +f 727 771 713 +f 750 807 799 +f 639 190 144 +f 662 679 200 +f 702 748 572 +f 775 776 748 +f 628 718 655 +f 626 658 645 +f 791 778 790 +f 612 811 628 +f 613 514 634 +f 1380 1756 1673 +f 570 590 614 +f 720 741 719 +f 1074 795 835 +f 614 639 144 +f 612 775 811 +f 718 735 655 +f 655 735 613 +f 798 338 788 +f 636 652 676 +f 571 590 555 +f 528 730 687 +f 690 702 2312 +f 476 690 2312 +f 811 718 628 +f 721 778 727 +f 748 702 690 +f 735 686 613 +f 1517 2002 2127 +f 654 685 667 +f 569 588 606 +f 513 531 538 +f 538 549 548 +f 549 553 548 +f 550 588 549 +f 1903 869 870 +f 691 775 748 +f 691 600 775 +f 600 811 775 +f 811 563 718 +f 563 736 718 +f 718 736 735 +f 736 647 735 +f 735 647 686 +f 686 745 613 +f 745 514 613 +f 569 606 605 +f 654 667 638 +f 851 857 847 +f 588 569 549 +f 690 691 748 +f 680 514 745 +f 2127 2002 2094 +f 747 701 481 +f 400 373 529 +f 600 536 811 +f 536 563 811 +f 1306 227 1152 +f 522 24 18 +f 523 24 522 +f 865 857 851 +f 2031 2060 1540 +f 767 701 747 +f 618 652 609 +f 652 636 609 +f 573 22 710 +f 642 699 730 +f 1522 1518 2476 +f 500 629 691 +f 690 500 691 +f 691 629 600 +f 780 644 641 +f 579 578 561 +f 131 668 197 +f 197 668 814 +f 789 809 798 +f 622 760 150 +f 621 563 536 +f 673 745 686 +f 673 818 745 +f 818 680 745 +f 680 96 514 +f 2495 2462 1028 +f 1028 583 575 +f 663 794 664 +f 629 761 600 +f 761 757 600 +f 600 757 536 +f 621 696 563 +f 755 736 563 +f 696 755 563 +f 633 736 755 +f 633 647 736 +f 623 686 647 +f 633 623 647 +f 686 623 673 +f 819 680 818 +f 680 819 96 +f 1729 1677 1096 +f 2482 1899 2471 +f 537 536 757 +f 536 537 621 +f 673 819 818 +f 2428 222 230 +f 25 24 523 +f 25 557 24 +f 38 25 19 +f 710 22 272 +f 663 759 794 +f 1120 878 1195 +f 537 696 621 +f 696 633 755 +f 822 2215 2220 +f 97 96 1053 +f 750 784 743 +f 887 905 864 +f 768 784 373 +f 512 513 548 +f 573 664 22 +f 696 715 633 +f 673 521 819 +f 2454 2453 2445 +f 883 887 847 +f 306 812 76 +f 642 528 759 +f 798 809 235 +f 994 792 998 +f 587 626 586 +f 1900 1918 1937 +f 645 652 618 +f 537 786 696 +f 521 593 819 +f 515 19 523 +f 741 749 719 +f 789 326 809 +f 539 581 550 +f 657 777 723 +f 684 713 660 +f 692 712 720 +f 652 666 692 +f 507 761 629 +f 472 507 629 +f 507 757 761 +f 623 633 673 +f 724 521 673 +f 515 516 19 +f 304 675 674 +f 178 778 721 +f 947 1447 2358 +f 626 645 618 +f 586 626 618 +f 784 768 742 +f 753 537 757 +f 537 753 786 +f 724 981 521 +f 521 981 593 +f 979 559 850 +f 637 660 677 +f 787 631 576 +f 141 117 385 +f 809 399 235 +f 641 754 558 +f 542 553 561 +f 742 768 762 +f 444 416 533 +f 528 687 796 +f 813 598 566 +f 1490 1501 1557 +f 753 757 507 +f 786 715 696 +f 633 724 673 +f 2090 2062 2109 +f 646 653 660 +f 660 694 683 +f 677 660 683 +f 1872 839 838 +f 1224 18 30 +f 326 393 809 +f 799 529 373 +f 313 507 472 +f 715 774 633 +f 974 699 841 +f 703 820 816 +f 692 711 676 +f 1014 355 766 +f 875 752 1019 +f 627 646 660 +f 711 692 720 +f 652 692 676 +f 799 373 784 +f 813 566 567 +f 2462 2482 2475 +f 764 644 780 +f 1479 1924 1916 +f 753 738 786 +f 738 607 786 +f 786 607 715 +f 715 524 774 +f 633 774 724 +f 559 979 672 +f 758 798 783 +f 683 694 705 +f 820 703 562 +f 764 687 644 +f 744 743 725 +f 313 753 507 +f 607 524 715 +f 664 801 22 +f 646 627 610 +f 800 820 562 +f 750 769 807 +f 767 747 533 +f 578 586 604 +f 862 593 981 +f 688 2382 1083 +f 306 304 674 +f 738 584 607 +f 168 136 238 +f 773 552 765 +f 2473 2464 2458 +f 773 793 552 +f 626 619 658 +f 1007 1139 1013 +f 562 529 799 +f 744 750 743 +f 659 683 693 +f 677 683 659 +f 313 737 753 +f 753 737 738 +f 607 729 524 +f 27 518 28 +f 553 569 580 +f 657 163 777 +f 580 569 605 +f 789 798 758 +f 769 562 807 +f 820 671 816 +f 638 646 611 +f 1074 598 644 +f 750 799 784 +f 1931 907 898 +f 2483 2487 2461 +f 737 584 738 +f 1439 1438 1431 +f 2098 1213 544 +f 48 578 75 +f 796 631 787 +f 815 732 21 +f 581 588 550 +f 625 636 651 +f 778 1011 810 +f 693 705 725 +f 693 683 705 +f 236 1921 1966 +f 584 729 607 +f 2237 1866 2227 +f 530 541 28 +f 237 739 248 +f 512 530 28 +f 727 778 771 +f 684 727 713 +f 2237 2220 826 +f 542 561 560 +f 528 796 700 +f 808 785 671 +f 739 592 248 +f 895 905 896 +f 740 246 186 +f 272 137 979 +f 770 769 744 +f 712 742 720 +f 1213 2026 544 +f 1888 1235 2438 +f 555 554 2311 +f 737 313 1192 +f 1585 1612 1611 +f 695 721 685 +f 518 17 28 +f 769 770 562 +f 719 749 740 +f 648 669 679 +f 773 657 723 +f 606 637 619 +f 2072 2062 2042 +f 606 619 626 +f 549 569 553 +f 161 638 611 +f 910 917 942 +f 917 1103 942 +f 991 1026 992 +f 979 137 672 +f 785 163 657 +f 710 2488 2472 +f 611 581 119 +f 808 671 820 +f 1820 1900 1870 +f 759 700 591 +f 637 677 619 +f 2494 2490 2463 +f 671 765 816 +f 687 764 780 +f 1019 992 1026 +f 1726 1719 987 +f 713 771 694 +f 51 2355 78 +f 510 526 525 +f 525 526 1249 +f 526 33 1249 +f 2311 554 2335 +f 827 848 840 +f 603 591 649 +f 758 269 740 +f 1595 1612 1586 +f 1694 1048 1699 +f 682 740 186 +f 22 801 603 +f 555 570 554 +f 1053 110 97 +f 615 582 601 +f 814 668 188 +f 725 705 744 +f 528 700 759 +f 640 648 620 +f 703 701 562 +f 886 892 582 +f 631 731 576 +f 1087 1835 1747 +f 882 864 895 +f 956 950 1103 +f 1502 2500 2470 +f 205 190 200 +f 815 878 616 +f 616 878 995 +f 1183 878 815 +f 1601 1827 881 +f 527 535 526 +f 2184 2183 2175 +f 1142 1125 1133 +f 235 338 798 +f 160 339 792 +f 599 92 75 +f 598 1116 566 +f 631 558 731 +f 771 770 744 +f 730 528 642 +f 841 699 642 +f 668 401 188 +f 510 527 526 +f 749 758 740 +f 706 721 695 +f 694 726 705 +f 694 744 726 +f 906 911 905 +f 661 695 161 +f 708 815 616 +f 535 547 33 +f 794 759 591 +f 778 808 790 +f 269 758 783 +f 771 744 694 +f 800 808 820 +f 571 886 582 +f 854 948 1010 +f 906 905 887 +f 625 651 635 +f 2000 1226 534 +f 2140 1504 2016 +f 601 620 615 +f 620 601 640 +f 648 640 669 +f 698 452 439 +f 671 785 657 +f 1561 2356 545 +f 685 653 667 +f 685 727 684 +f 568 616 797 +f 708 732 815 +f 93 229 339 +f 865 851 839 +f 942 1103 950 +f 589 614 125 +f 606 610 627 +f 951 834 873 +f 92 599 625 +f 1878 830 1902 +f 2482 2098 1899 +f 568 708 616 +f 708 551 732 +f 2434 2487 2483 +f 160 964 665 +f 2316 2391 2309 +f 762 758 749 +f 570 614 589 +f 888 897 883 +f 2000 1517 1388 +f 685 721 727 +f 588 610 606 +f 653 685 684 +f 651 650 635 +f 760 1151 6 +f 793 622 150 +f 651 676 650 +f 744 769 750 +f 541 542 560 +f 476 500 690 +f 473 1064 1057 +f 561 578 560 +f 636 625 599 +f 876 995 949 +f 829 856 846 +f 682 704 740 +f 791 790 770 +f 2466 2500 2460 +f 579 587 586 +f 1352 1208 1095 +f 1684 1479 1916 +f 604 609 636 +f 751 721 706 +f 810 608 782 +f 672 603 649 +f 475 447 476 +f 794 591 801 +f 682 186 650 +f 808 800 790 +f 644 598 813 +f 704 719 740 +f 1011 608 810 +f 1192 584 737 +f 687 780 796 +f 2337 474 2312 +f 638 667 646 +f 706 1186 728 +f 733 575 568 +f 595 551 708 +f 595 540 551 +f 1308 501 1852 +f 665 339 160 +f 527 2447 535 +f 558 9 731 +f 723 793 773 +f 660 713 694 +f 693 725 666 +f 562 767 529 +f 550 538 531 +f 2267 2287 2233 +f 996 964 160 +f 2068 2470 2466 +f 704 711 719 +f 741 762 749 +f 605 606 626 +f 548 542 530 +f 995 878 709 +f 1898 1684 1916 +f 778 791 771 +f 782 163 785 +f 789 758 762 +f 857 883 847 +f 733 970 1028 +f 838 829 825 +f 2447 511 535 +f 22 603 137 +f 705 726 744 +f 605 587 580 +f 512 548 530 +f 743 784 742 +f 790 800 770 +f 778 810 808 +f 1014 998 355 +f 708 568 595 +f 656 697 551 +f 540 656 551 +f 143 125 614 +f 1000 1020 983 +f 778 178 1011 +f 676 704 682 +f 637 627 660 +f 606 627 637 +f 701 552 481 +f 808 810 785 +f 590 570 555 +f 716 595 568 +f 2355 2335 554 +f 912 1729 911 +f 1076 1456 1546 +f 697 68 492 +f 676 711 704 +f 839 851 838 +f 1028 575 733 +f 1020 844 982 +f 716 568 575 +f 844 781 982 +f 1238 2156 2034 +f 553 580 561 +f 580 579 561 +f 452 461 453 +f 560 578 48 +f 564 540 595 +f 632 656 540 +f 564 632 540 +f 75 578 599 +f 518 27 535 +f 511 518 535 +f 783 798 788 +f 642 759 663 +f 720 742 741 +f 605 626 587 +f 580 587 579 +f 725 712 666 +f 562 701 767 +f 1729 923 911 +f 712 743 742 +f 619 677 658 +f 161 695 654 +f 770 800 562 +f 2084 2489 2472 +f 575 559 716 +f 716 564 595 +f 654 695 685 +f 843 855 2064 +f 34 731 9 +f 527 510 1973 +f 723 622 793 +f 992 1726 987 +f 693 666 652 +f 2472 853 573 +f 624 159 148 +f 671 657 773 +f 681 188 498 +f 797 970 733 +f 565 656 632 +f 565 697 656 +f 565 731 697 +f 1949 951 920 +f 85 111 84 +f 662 200 190 +f 44 324 754 +f 33 547 40 +f 658 693 652 +f 658 652 645 +f 664 794 801 +f 666 712 692 +f 639 648 662 +f 611 646 610 +f 850 559 575 +f 1447 2490 1106 +f 1972 1955 1935 +f 582 615 590 +f 66 581 539 +f 780 641 631 +f 796 780 631 +f 1049 1192 83 +f 1348 13 1519 +f 799 807 562 +f 581 611 588 +f 687 795 644 +f 663 8 642 +f 1936 1972 1935 +f 650 676 682 +f 615 630 590 +f 730 795 687 +f 742 762 741 +f 548 553 542 +f 1048 1692 1074 +f 658 659 693 +f 37 52 30 +f 611 610 588 +f 649 632 564 +f 565 576 731 +f 2138 922 1058 +f 1204 854 965 +f 725 743 712 +f 644 813 641 +f 660 653 684 +f 771 791 770 +f 644 795 1074 +f 469 480 681 +f 559 672 564 +f 716 559 564 +f 672 649 564 +f 2161 1378 2171 +f 474 475 476 +f 816 765 701 +f 765 552 701 +f 513 538 548 +f 754 324 107 +f 609 586 618 +f 25 523 19 +f 677 659 658 +f 689 452 698 +f 1334 1115 1353 +f 700 565 632 +f 700 576 565 +f 481 552 793 +f 763 901 2458 +f 550 549 538 +f 781 964 996 +f 1596 1634 1595 +f 198 916 1124 +f 198 1124 341 +f 842 973 1025 +f 842 1025 836 +f 1009 1024 934 +f 573 710 2472 +f 1100 971 1002 +f 1501 1081 1557 +f 1225 1219 955 +f 413 2138 284 +f 955 1630 522 +f 341 1124 301 +f 2333 2376 2350 +f 1107 218 284 +f 398 925 1513 +f 1513 1442 1495 +f 1935 1455 1744 +f 1723 1935 1744 +f 825 1872 838 +f 1495 1442 1496 +f 963 1024 1009 +f 1511 1514 966 +f 1775 1729 912 +f 688 262 1067 +f 714 1007 1512 +f 919 1732 914 +f 2319 2331 2304 +f 2400 2407 2391 +f 1674 2164 1780 +f 843 927 899 +f 1660 988 1188 +f 1067 262 1640 +f 1381 1109 1483 +f 1437 1381 1483 +f 2495 1010 948 +f 1514 1289 1313 +f 899 374 961 +f 1438 1430 1422 +f 1634 1095 1632 +f 2487 973 2461 +f 1003 499 874 +f 849 848 827 +f 1430 1462 1453 +f 2496 2084 2471 +f 909 10 980 +f 730 927 835 +f 2031 1540 1536 +f 831 849 2178 +f 881 834 951 +f 1841 1722 1803 +f 1005 670 1020 +f 1021 670 1005 +f 1869 2059 2467 +f 903 902 1939 +f 2476 2502 1651 +f 853 8 573 +f 1850 831 2178 +f 934 746 247 +f 934 65 746 +f 301 285 1077 +f 968 944 977 +f 970 2495 1028 +f 974 2465 374 +f 899 927 374 +f 1882 1898 1916 +f 1613 1634 1596 +f 909 833 1396 +f 2492 247 1003 +f 919 914 1931 +f 1459 1299 1458 +f 1634 1632 1633 +f 844 670 228 +f 2494 2497 2467 +f 901 973 2487 +f 228 1772 734 +f 1701 1709 1666 +f 963 574 1024 +f 847 864 856 +f 1730 1736 2239 +f 870 859 848 +f 2074 2111 2103 +f 1140 1590 1483 +f 927 730 974 +f 2103 978 2074 +f 756 1745 1718 +f 848 859 840 +f 1296 1482 1320 +f 2331 51 66 +f 1067 988 962 +f 1396 833 1445 +f 1001 1005 1000 +f 901 1009 973 +f 1099 1077 817 +f 933 944 936 +f 952 958 1828 +f 988 1660 986 +f 833 1067 1445 +f 1067 1640 988 +f 218 413 284 +f 1843 180 347 +f 1846 1708 1798 +f 2469 2477 855 +f 1006 1021 1005 +f 381 382 250 +f 2369 828 531 +f 968 977 1001 +f 2460 1949 779 +f 1194 1441 1115 +f 1001 1000 968 +f 756 678 1745 +f 963 1009 901 +f 2471 2084 2472 +f 841 642 8 +f 982 991 1027 +f 670 844 1020 +f 1289 1514 945 +f 869 904 890 +f 1161 1115 1639 +f 823 2178 849 +f 746 12 499 +f 263 428 2366 +f 1685 1075 1692 +f 1002 926 806 +f 1799 1755 216 +f 944 968 993 +f 943 944 993 +f 31 38 19 +f 531 828 550 +f 1501 1078 1081 +f 1921 1149 431 +f 936 943 932 +f 1660 1489 1412 +f 301 980 285 +f 903 918 902 +f 869 890 868 +f 890 903 867 +f 1003 746 499 +f 951 1949 2500 +f 990 841 853 +f 1595 1634 1611 +f 374 927 974 +f 836 1025 247 +f 1653 1652 1638 +f 1303 1545 1142 +f 1616 1631 1638 +f 1629 1546 1628 +f 936 932 913 +f 513 506 531 +f 868 890 867 +f 2330 2369 2353 +f 924 918 914 +f 907 914 904 +f 1258 1421 1267 +f 301 939 980 +f 1472 1482 1296 +f 868 867 859 +f 472 491 313 +f 272 519 2488 +f 1471 1472 1296 +f 1025 934 247 +f 1634 1633 1611 +f 2176 1847 2177 +f 1310 1289 806 +f 924 933 918 +f 1969 1968 902 +f 2107 2128 2118 +f 1428 1436 1287 +f 1139 1564 1617 +f 2378 572 2384 +f 853 841 8 +f 2501 961 2465 +f 1221 1240 1408 +f 1069 1578 1627 +f 1006 1005 1001 +f 1617 1564 1578 +f 828 539 550 +f 1791 2168 2160 +f 1829 1718 1739 +f 1968 1939 902 +f 756 1718 665 +f 1998 2000 1388 +f 2451 545 2356 +f 178 997 1011 +f 1275 325 1270 +f 1709 872 1666 +f 2176 1959 1847 +f 944 943 936 +f 2424 518 511 +f 1445 1067 962 +f 2007 952 1828 +f 2052 2061 2081 +f 828 2303 539 +f 835 1699 1048 +f 1709 1706 872 +f 885 574 963 +f 1318 1296 1320 +f 859 867 1902 +f 1452 1448 1421 +f 943 993 976 +f 993 1000 983 +f 854 1010 876 +f 988 986 962 +f 2031 2052 2081 +f 924 1732 1828 +f 965 949 1060 +f 781 228 734 +f 1718 1765 665 +f 943 976 932 +f 1680 1794 1783 +f 1448 1471 1276 +f 1276 1267 1421 +f 1931 914 907 +f 991 781 996 +f 1276 1421 1448 +f 10 909 1396 +f 831 860 849 +f 1523 1762 1774 +f 924 1828 937 +f 307 994 1014 +f 946 963 901 +f 978 2103 977 +f 977 1006 1001 +f 1007 1161 1639 +f 1639 1294 1437 +f 885 1032 574 +f 1294 1381 1437 +f 733 568 797 +f 792 229 1112 +f 119 581 108 +f 843 835 927 +f 1889 860 831 +f 2211 2216 2204 +f 2400 2431 2422 +f 2103 1006 977 +f 840 1902 830 +f 827 840 830 +f 827 830 822 +f 1003 874 2492 +f 1432 1439 1431 +f 781 734 964 +f 1937 1936 1723 +f 918 913 902 +f 958 977 944 +f 1850 2178 2177 +f 1005 1020 1000 +f 991 996 307 +f 1396 1445 340 +f 2179 1763 889 +f 939 909 980 +f 1828 958 937 +f 978 977 958 +f 1590 1571 1563 +f 779 1949 920 +f 1551 1362 1573 +f 2103 2142 1006 +f 920 885 963 +f 946 920 963 +f 1584 1616 1583 +f 1453 1472 1452 +f 1647 1617 1578 +f 1578 1564 1627 +f 1628 938 1069 +f 869 868 859 +f 993 983 976 +f 912 1762 1775 +f 752 751 706 +f 1628 1546 938 +f 844 228 781 +f 840 859 1902 +f 898 907 904 +f 1025 973 1009 +f 663 664 573 +f 763 946 901 +f 898 904 869 +f 2172 889 1763 +f 1128 926 971 +f 860 848 849 +f 904 903 890 +f 2486 2459 2479 +f 577 782 608 +f 933 936 918 +f 2177 1847 1851 +f 665 1765 339 +f 937 958 944 +f 894 981 724 +f 968 1000 993 +f 2192 2195 2205 +f 1652 1099 817 +f 997 608 1011 +f 997 577 608 +f 577 163 782 +f 1112 998 792 +f 2177 1851 1850 +f 1257 1421 1258 +f 951 873 920 +f 822 830 2215 +f 1899 2496 2471 +f 1773 1668 1558 +f 904 914 903 +f 932 1671 913 +f 873 885 920 +f 1013 1617 1647 +f 873 1032 885 +f 894 862 981 +f 2469 855 961 +f 913 1671 1969 +f 2477 2064 855 +f 918 936 913 +f 860 870 848 +f 937 944 933 +f 1501 1013 1647 +f 824 178 751 +f 824 997 178 +f 824 577 997 +f 643 163 577 +f 863 856 882 +f 2128 2153 2134 +f 722 774 880 +f 722 894 774 +f 864 905 895 +f 850 575 583 +f 914 918 903 +f 924 937 933 +f 1501 717 1013 +f 1587 1324 928 +f 717 1512 1013 +f 602 577 824 +f 766 643 577 +f 894 709 862 +f 709 878 862 +f 976 975 932 +f 1324 1596 928 +f 880 524 1060 +f 2434 2459 2499 +f 1324 1613 1596 +f 752 824 751 +f 602 766 577 +f 1014 602 594 +f 1387 1226 2152 +f 2153 1387 2152 +f 669 930 950 +f 1710 1694 1699 +f 768 326 762 +f 582 892 601 +f 974 990 2465 +f 624 116 625 +f 835 795 730 +f 2458 2484 763 +f 989 602 824 +f 2064 2477 1710 +f 976 983 975 +f 949 722 880 +f 996 160 994 +f 2305 863 556 +f 556 863 886 +f 601 910 640 +f 2264 825 829 +f 989 824 752 +f 856 864 882 +f 1595 1586 2381 +f 1627 1629 1628 +f 2174 2180 2173 +f 2128 2134 2118 +f 137 272 22 +f 949 880 1060 +f 995 894 722 +f 894 995 709 +f 894 724 774 +f 886 895 892 +f 640 910 930 +f 871 870 860 +f 846 856 863 +f 1026 875 1019 +f 838 851 829 +f 1024 1171 934 +f 36 189 205 +f 863 882 886 +f 886 882 895 +f 875 1026 594 +f 52 1459 1269 +f 896 917 910 +f 1025 1009 934 +f 949 995 722 +f 2152 1226 1636 +f 895 896 892 +f 892 910 601 +f 942 950 930 +f 875 989 752 +f 594 602 989 +f 766 355 643 +f 355 260 643 +f 905 917 896 +f 965 1060 1162 +f 892 896 910 +f 1101 1052 1042 +f 1029 1031 834 +f 1101 1133 1118 +f 342 357 376 +f 516 515 2454 +f 1656 2494 2467 +f 1056 1303 1133 +f 1120 1130 862 +f 69 342 376 +f 1055 1056 1133 +f 499 69 165 +f 85 101 111 +f 1031 1032 834 +f 200 679 1166 +f 1031 1042 1032 +f 1171 65 934 +f 1822 1204 1177 +f 1096 956 1103 +f 514 96 97 +f 956 1145 1144 +f 1185 1166 1144 +f 1145 1185 1144 +f 1185 200 1166 +f 375 132 1041 +f 1153 1202 305 +f 32 1244 1249 +f 1096 1087 956 +f 554 78 2355 +f 1191 138 110 +f 65 35 432 +f 1087 1110 956 +f 1110 1146 956 +f 956 1146 1145 +f 1146 1156 1145 +f 1145 1156 1185 +f 950 956 1144 +f 2481 2495 948 +f 1156 1193 1185 +f 1050 1047 1051 +f 239 151 107 +f 1185 1193 36 +f 1747 1110 1087 +f 1134 1146 1110 +f 1146 1157 1156 +f 1156 1157 1193 +f 1041 1045 1034 +f 1397 1134 1110 +f 1157 1146 1134 +f 1157 1175 1193 +f 1193 199 36 +f 1090 1035 1196 +f 1456 1150 1051 +f 1175 199 1193 +f 1186 695 199 +f 1186 199 1175 +f 1175 1157 1134 +f 728 1186 1175 +f 197 760 6 +f 1130 593 862 +f 1167 1109 182 +f 1194 1115 1161 +f 2140 1928 1504 +f 921 922 2138 +f 1147 1134 1397 +f 1719 1147 1397 +f 1147 1175 1134 +f 1175 1147 728 +f 341 1654 1208 +f 754 151 9 +f 284 2138 1058 +f 1188 1557 1660 +f 1191 110 1053 +f 916 284 1189 +f 284 1058 1189 +f 2094 1465 2127 +f 1726 1019 1147 +f 1147 1019 728 +f 593 1130 96 +f 239 305 1038 +f 1036 1131 315 +f 397 1131 1120 +f 1053 96 1130 +f 2467 2485 1869 +f 517 1089 421 +f 834 1827 1029 +f 419 1047 1117 +f 1034 433 1306 +f 2239 1862 1730 +f 1453 1462 1472 +f 1408 1422 1399 +f 471 23 1111 +f 1205 1150 1456 +f 1205 1040 1150 +f 1131 1036 293 +f 293 1068 1044 +f 375 1041 138 +f 1205 1140 1046 +f 1040 1205 1046 +f 1140 1167 1046 +f 1104 1049 83 +f 1052 1085 1032 +f 1044 1068 1191 +f 1167 1483 1109 +f 208 1084 1035 +f 1040 132 375 +f 1834 20 3 +f 1050 1051 1070 +f 1133 1125 1174 +f 11 1440 1401 +f 420 208 1071 +f 1135 1079 1094 +f 1086 1101 1118 +f 1029 1030 1031 +f 1200 1061 294 +f 1191 1068 138 +f 1171 1141 65 +f 1141 1172 65 +f 1172 35 65 +f 1172 404 35 +f 404 99 35 +f 221 1104 1063 +f 802 398 1083 +f 20 1089 3 +f 2064 1699 835 +f 1042 1052 1032 +f 1433 1261 1432 +f 1323 2338 155 +f 1076 1205 1456 +f 1088 1402 1056 +f 1150 348 1070 +f 1200 1089 20 +f 1097 1162 100 +f 1032 873 834 +f 21 471 1111 +f 294 1097 1104 +f 1072 100 584 +f 1151 760 622 +f 132 1045 1041 +f 1050 1070 1135 +f 1088 1039 940 +f 650 159 635 +f 100 1170 729 +f 729 584 100 +f 1103 931 1096 +f 925 1443 1513 +f 138 1102 110 +f 1034 1306 1152 +f 1071 1035 1090 +f 100 1072 1097 +f 23 1158 315 +f 1068 375 138 +f 1586 1612 1585 +f 1819 1030 1029 +f 1041 1034 1102 +f 232 375 1068 +f 348 1079 1070 +f 1061 1097 294 +f 1513 1443 1442 +f 1200 294 1119 +f 376 1050 1062 +f 1094 1036 315 +f 1200 1119 1089 +f 1111 1183 21 +f 1044 1191 1053 +f 698 295 689 +f 1079 232 1036 +f 404 1117 99 +f 1495 1496 717 +f 1119 294 98 +f 3 1089 517 +f 1132 1063 83 +f 1132 83 175 +f 132 1046 182 +f 1111 1195 1183 +f 1131 1044 1037 +f 127 402 1804 +f 219 1272 1047 +f 1697 1135 1094 +f 2140 1854 2117 +f 1111 397 1195 +f 1177 1162 1097 +f 1061 1177 1097 +f 717 1509 714 +f 2 1300 433 +f 462 290 461 +f 98 294 221 +f 294 1104 221 +f 714 1161 1007 +f 1073 1152 1143 +f 1697 1094 1360 +f 1223 1423 1218 +f 836 2479 842 +f 1097 1072 1049 +f 348 1040 375 +f 3 517 316 +f 180 1061 1201 +f 348 375 232 +f 1432 1431 1415 +f 220 1513 1495 +f 1104 1097 1049 +f 306 674 596 +f 777 455 723 +f 2170 2151 1641 +f 1047 419 219 +f 1102 1034 1073 +f 1073 1034 1152 +f 1035 1054 1196 +f 1177 1204 1162 +f 746 65 12 +f 751 178 721 +f 1054 517 421 +f 1051 1150 1070 +f 1102 1073 110 +f 998 1136 355 +f 567 566 1163 +f 1111 315 397 +f 1048 1074 835 +f 1158 1094 315 +f 1374 1107 1252 +f 1112 1136 998 +f 472 629 500 +f 355 1136 260 +f 260 118 43 +f 1104 83 1063 +f 376 357 1050 +f 1463 1142 1545 +f 1036 232 293 +f 1030 1042 1031 +f 1079 348 232 +f 221 1063 1132 +f 1094 1079 1036 +f 1076 1629 1205 +f 1136 1197 260 +f 260 1197 118 +f 1204 965 1162 +f 293 232 1068 +f 1590 1205 1629 +f 1205 1590 1140 +f 250 382 392 +f 1296 1318 1311 +f 347 1201 20 +f 1201 1200 20 +f 132 182 1045 +f 1101 1086 1052 +f 1033 1039 1055 +f 138 1041 1102 +f 970 1010 2495 +f 455 777 43 +f 1992 1948 2023 +f 20 1834 347 +f 1072 584 1049 +f 584 1192 1049 +f 182 2 1045 +f 1163 324 44 +f 1360 1094 1158 +f 1450 1360 1158 +f 1091 1112 229 +f 509 723 455 +f 207 509 455 +f 1251 1257 1266 +f 1488 1489 1547 +f 2157 1541 1875 +f 305 107 324 +f 1045 2 433 +f 1070 1079 1135 +f 1136 1168 1197 +f 1197 359 118 +f 118 359 43 +f 359 356 43 +f 356 455 43 +f 356 207 455 +f 1240 1422 1408 +f 1163 1153 324 +f 1201 1061 1200 +f 1052 1086 1085 +f 1024 1141 1171 +f 1112 1105 1136 +f 1050 1135 1062 +f 1105 1168 1136 +f 1168 1178 1197 +f 1197 1178 359 +f 1173 404 1172 +f 465 356 359 +f 1174 1125 240 +f 1240 1431 1422 +f 1098 1113 1105 +f 1112 1098 1105 +f 1105 1178 1168 +f 1178 465 359 +f 1091 1098 1112 +f 1133 1174 1118 +f 98 221 1059 +f 487 1132 175 +f 980 1017 285 +f 465 207 356 +f 180 1201 347 +f 1060 524 1170 +f 445 127 316 +f 1431 1438 1422 +f 498 469 681 +f 940 1807 1759 +f 381 250 1290 +f 1113 1122 1105 +f 1105 1122 1178 +f 1151 509 207 +f 1236 2035 525 +f 1131 293 1044 +f 346 207 465 +f 346 1151 207 +f 1822 1796 1204 +f 1143 204 97 +f 123 1128 971 +f 2153 2152 2134 +f 126 1151 346 +f 517 445 316 +f 1450 1158 23 +f 1458 1462 1430 +f 1129 152 1182 +f 1122 1159 1178 +f 1178 1198 465 +f 79 346 465 +f 126 1155 1151 +f 1151 1155 6 +f 295 1129 689 +f 1073 1143 97 +f 1098 1123 1113 +f 1113 1123 1122 +f 1123 1169 1122 +f 1178 1159 1198 +f 1198 79 465 +f 392 383 152 +f 1822 1061 180 +f 116 92 625 +f 421 1089 1119 +f 1129 295 152 +f 110 1073 97 +f 1173 1172 1141 +f 1122 1169 1159 +f 79 126 346 +f 1155 181 6 +f 971 926 1002 +f 295 1043 152 +f 1039 1088 1056 +f 1428 1266 1436 +f 404 419 1117 +f 836 879 2479 +f 2464 2476 2458 +f 1198 317 79 +f 1124 939 301 +f 44 754 567 +f 1039 1056 1055 +f 1439 1459 1458 +f 1660 1412 986 +f 1169 1160 1159 +f 179 1155 126 +f 1155 131 181 +f 1061 1822 1177 +f 1153 305 324 +f 175 314 327 +f 1160 1187 1159 +f 1159 1187 1198 +f 1198 1187 317 +f 79 179 126 +f 1043 250 392 +f 152 1043 392 +f 96 819 593 +f 1123 1127 1169 +f 317 179 79 +f 1057 1155 179 +f 1155 391 131 +f 131 391 668 +f 2381 1586 1585 +f 12 69 499 +f 262 398 1640 +f 2107 2118 2060 +f 2130 2094 2002 +f 1187 249 317 +f 1155 1057 391 +f 1290 439 1265 +f 305 239 107 +f 1127 1160 1169 +f 317 473 179 +f 473 1057 179 +f 83 1192 314 +f 1043 1290 250 +f 1807 940 1030 +f 517 1084 445 +f 1057 1164 391 +f 2492 2480 2493 +f 163 643 43 +f 1056 1545 1303 +f 1069 1655 1023 +f 249 473 317 +f 1162 1060 1170 +f 1086 1118 1154 +f 82 68 16 +f 1989 1990 1536 +f 1633 1632 1611 +f 1487 2372 1305 +f 1494 1069 1023 +f 1137 1160 1127 +f 669 1166 679 +f 390 1285 426 +f 1955 1972 1971 +f 1219 1223 2437 +f 1254 1261 1223 +f 1319 1545 1056 +f 1320 1328 2443 +f 1261 1433 1223 +f 1219 1254 1223 +f 254 222 2428 +f 1237 1290 1265 +f 1284 1273 1263 +f 1277 1291 1301 +f 1314 102 1301 +f 1280 363 377 +f 1313 1353 1514 +f 468 451 439 +f 1918 1964 1956 +f 2026 29 2140 +f 1354 381 1279 +f 1224 30 1254 +f 147 158 173 +f 1247 1253 274 +f 1271 380 334 +f 2043 2072 2042 +f 274 300 267 +f 1356 1392 211 +f 13 240 1142 +f 1382 1330 1392 +f 1312 1323 155 +f 240 1125 1142 +f 2358 1573 1362 +f 1236 1249 1244 +f 1272 219 1348 +f 1271 1274 380 +f 191 2034 1982 +f 1992 2052 1990 +f 462 452 689 +f 2262 2286 2261 +f 183 489 1642 +f 2485 2480 1869 +f 84 111 1323 +f 1190 353 1354 +f 446 434 435 +f 1336 171 1341 +f 2021 430 2059 +f 862 878 1120 +f 1263 1273 1248 +f 1966 1921 2144 +f 1312 84 1323 +f 240 13 1348 +f 1359 1274 1271 +f 1392 1330 1247 +f 1520 1333 11 +f 1368 1253 1247 +f 1279 1285 1190 +f 2465 990 2489 +f 1272 1519 805 +f 1369 1272 805 +f 1317 95 1344 +f 1242 1248 1234 +f 1368 242 1363 +f 274 1262 1386 +f 532 597 1886 +f 2117 2026 2140 +f 1392 1247 274 +f 2162 508 985 +f 1964 1469 1965 +f 1315 104 1331 +f 1392 1356 1382 +f 128 1342 1336 +f 1285 427 426 +f 1219 1224 1254 +f 1320 1322 1321 +f 1320 1321 1328 +f 153 2443 1328 +f 1321 153 1328 +f 1235 1244 1243 +f 1225 1224 1219 +f 1359 353 1190 +f 1312 1473 1458 +f 1336 1342 147 +f 305 1333 1038 +f 1336 147 171 +f 516 31 19 +f 2479 2461 842 +f 1237 1265 427 +f 1263 1278 1284 +f 881 1827 834 +f 1237 427 1285 +f 1299 1312 1458 +f 1190 1285 1274 +f 1363 286 1253 +f 2330 2303 828 +f 427 442 426 +f 2493 2463 2492 +f 1285 380 1274 +f 522 18 1225 +f 2471 2472 2488 +f 2338 154 1321 +f 1423 1415 1218 +f 1225 18 1224 +f 1253 286 1262 +f 286 353 1359 +f 171 1368 1383 +f 1273 54 1234 +f 1973 2447 527 +f 1322 155 1321 +f 1203 1369 1413 +f 1307 363 1298 +f 1364 1375 1329 +f 1329 227 1306 +f 296 1298 1343 +f 947 2499 1447 +f 1203 1047 1272 +f 1098 1748 1123 +f 1519 1272 1348 +f 1277 70 1273 +f 1282 1337 1361 +f 286 302 353 +f 103 104 1315 +f 1377 435 434 +f 1449 1261 1345 +f 926 1310 806 +f 1263 1248 1242 +f 985 508 597 +f 1415 1222 1218 +f 88 1325 104 +f 170 111 156 +f 1384 1282 1361 +f 274 1253 1262 +f 1371 1317 1344 +f 1371 1366 1337 +f 1345 1459 1449 +f 171 1383 1341 +f 2438 1235 1227 +f 2134 1582 2118 +f 428 1260 1379 +f 1336 1341 1325 +f 1235 1242 1227 +f 1228 1687 2284 +f 1854 2140 2016 +f 1866 1887 1873 +f 1343 1298 1370 +f 1384 1361 2440 +f 171 242 1368 +f 1344 1309 1366 +f 1371 1344 1366 +f 1280 1377 1293 +f 200 1185 205 +f 1330 1383 1368 +f 1255 1264 1263 +f 543 1367 1876 +f 1343 1370 1260 +f 1293 1326 1370 +f 2440 1361 1302 +f 1282 1384 2406 +f 271 1337 1282 +f 170 2338 1323 +f 1528 1503 2470 +f 515 1347 2453 +f 1997 1705 1998 +f 2285 1228 2284 +f 1229 1250 1228 +f 1330 1368 1247 +f 1919 1619 2045 +f 1344 1364 1335 +f 1222 1240 1221 +f 1212 858 1741 +f 2388 1222 1221 +f 1528 2470 2068 +f 501 1308 2171 +f 1295 1311 1487 +f 2116 1619 1655 +f 1220 1229 1228 +f 8 663 573 +f 1343 1260 428 +f 1337 1366 1361 +f 1298 1280 1293 +f 1269 1345 1261 +f 1279 381 1290 +f 1230 1229 1220 +f 1230 1245 1229 +f 1245 1250 1229 +f 1227 1234 31 +f 1302 1361 1350 +f 1245 1266 1428 +f 1992 2023 2052 +f 2482 2471 2475 +f 452 462 461 +f 271 1282 1275 +f 1991 1989 1934 +f 1366 1309 1350 +f 1344 1335 1309 +f 730 699 974 +f 1374 1252 1208 +f 597 508 1912 +f 1363 1253 1368 +f 1386 1271 300 +f 1211 1218 1222 +f 1376 1377 434 +f 2399 2437 1211 +f 1284 1291 1277 +f 1230 1251 1245 +f 1251 1266 1245 +f 1317 1371 1337 +f 1288 1286 1095 +f 1095 1286 1352 +f 1241 1208 1352 +f 1241 1374 1208 +f 1284 1278 1291 +f 211 1392 267 +f 1344 1375 1364 +f 929 583 1028 +f 1361 1366 1350 +f 1115 1294 1639 +f 1291 103 1301 +f 1220 1231 1230 +f 1231 1251 1230 +f 1234 1248 1273 +f 1255 55 1264 +f 1360 1450 1702 +f 363 1280 1298 +f 1369 1203 1272 +f 1415 1240 1222 +f 1216 1231 1220 +f 1243 1263 1235 +f 1375 227 1329 +f 1264 1278 1263 +f 855 899 961 +f 1286 1241 1352 +f 2081 2128 2107 +f 1223 1433 1423 +f 1473 1312 155 +f 154 153 1321 +f 1377 1376 1293 +f 1392 274 267 +f 334 300 1271 +f 1955 1991 1934 +f 1613 1327 1288 +f 1327 1286 1288 +f 1349 1374 1241 +f 2370 2025 2367 +f 1315 1331 133 +f 434 446 1256 +f 1232 1251 1231 +f 1243 1244 1255 +f 1286 1304 1241 +f 1349 1107 1374 +f 1359 1271 1386 +f 1227 516 2431 +f 219 240 1348 +f 1270 271 1275 +f 1255 1263 1243 +f 2026 1926 29 +f 1683 2157 1212 +f 1326 1293 1376 +f 1255 32 55 +f 104 1325 1341 +f 519 2462 2475 +f 2154 2161 2137 +f 1376 434 1246 +f 1246 434 1256 +f 1257 1251 1232 +f 1262 1359 1386 +f 2195 2192 2186 +f 1308 534 1226 +f 2026 2117 544 +f 1327 1613 1324 +f 1327 1326 1286 +f 1286 1326 1304 +f 104 1341 1331 +f 774 524 880 +f 837 1517 534 +f 1127 1123 1567 +f 1279 1237 1285 +f 1297 1381 1294 +f 1217 1232 1216 +f 1142 1519 13 +f 1436 1267 1287 +f 1324 1372 1327 +f 1304 1246 1241 +f 1246 1349 1241 +f 1246 1373 1349 +f 286 1359 1262 +f 1382 1383 1330 +f 1284 1277 1273 +f 489 1998 1799 +f 1675 1116 1075 +f 106 1317 1337 +f 1311 1295 1281 +f 1292 1364 1329 +f 1335 1364 1292 +f 1334 1294 1115 +f 1334 1297 1294 +f 1300 1381 1297 +f 973 842 2461 +f 1217 1239 1232 +f 1232 1239 1257 +f 1258 1267 1436 +f 1359 1190 1274 +f 1862 1405 1877 +f 1372 1339 1327 +f 1339 1326 1327 +f 1373 1351 1349 +f 1276 1311 1281 +f 1256 2386 1351 +f 2 1109 1300 +f 482 1731 520 +f 803 1604 2022 +f 1223 1218 1211 +f 1341 1383 1382 +f 1298 1293 1370 +f 1190 1354 1279 +f 1324 2398 1372 +f 1714 1700 2173 +f 183 2000 489 +f 1701 1666 192 +f 1227 1242 1234 +f 1332 1289 1310 +f 1517 2005 2130 +f 1331 1341 1382 +f 525 1249 1236 +f 23 1268 1450 +f 1264 1291 1278 +f 1281 1287 1267 +f 1295 1305 1287 +f 1281 1295 1287 +f 1487 1305 1295 +f 1605 2097 2058 +f 1326 1376 1304 +f 1304 1376 1246 +f 1316 1919 1984 +f 2500 1949 2460 +f 1332 1313 1289 +f 2189 2181 2177 +f 1335 1334 1353 +f 1292 1297 1334 +f 1428 1250 1245 +f 969 958 952 +f 1217 1233 1239 +f 1233 1257 1239 +f 1876 1367 1338 +f 1379 1260 1372 +f 1372 1260 1339 +f 1128 1302 1310 +f 1310 1302 1332 +f 1335 1353 1313 +f 1292 1334 1335 +f 1297 1329 1300 +f 1279 1290 1237 +f 1301 103 1314 +f 70 1301 102 +f 23 1333 1268 +f 380 1285 390 +f 772 325 1275 +f 1314 103 1315 +f 2473 2458 2487 +f 1276 1281 1267 +f 1344 95 1375 +f 2053 1771 1572 +f 1246 1256 1373 +f 1373 1256 1351 +f 1340 1302 1128 +f 1350 1313 1332 +f 1329 1297 1292 +f 2434 2473 2487 +f 106 1337 271 +f 23 471 1333 +f 622 723 509 +f 1388 1517 2127 +f 1991 1990 1989 +f 183 1636 1226 +f 2133 1605 2151 +f 1260 1370 1339 +f 1339 1370 1326 +f 867 1894 1902 +f 390 426 412 +f 1235 1263 1242 +f 1399 1422 1233 +f 305 11 1333 +f 1300 1329 1306 +f 1302 1350 1332 +f 1350 1309 1313 +f 1309 1335 1313 +f 2470 2102 1502 +f 1787 1531 1599 +f 1724 1725 1691 +f 1827 1601 1927 +f 1678 1358 1476 +f 1823 1812 1846 +f 1805 1824 1708 +f 1746 1676 1797 +f 325 2395 429 +f 1835 1677 1826 +f 1507 1790 1722 +f 1526 1672 858 +f 158 147 1342 +f 1462 1473 1322 +f 1474 1414 1565 +f 1761 1900 1877 +f 940 1759 1008 +f 1565 1015 1008 +f 1924 1533 1933 +f 1878 826 830 +f 1565 1414 1015 +f 1402 1088 1008 +f 1538 1532 1651 +f 1015 1552 1008 +f 1538 1591 1474 +f 1532 1538 1474 +f 1474 1591 1414 +f 1484 1402 1008 +f 1552 1484 1008 +f 1414 1460 1015 +f 1015 1460 1552 +f 806 1289 945 +f 1597 1538 1659 +f 1484 1319 1402 +f 1056 1402 1319 +f 1538 1597 1591 +f 1591 960 1414 +f 1414 960 1460 +f 1925 1466 1455 +f 1552 1400 1484 +f 1484 1400 1319 +f 1400 113 1319 +f 1597 1580 1591 +f 1460 1400 1552 +f 1514 1441 966 +f 1597 1659 1409 +f 1657 113 1400 +f 1460 1657 1400 +f 1288 1095 1634 +f 1551 1597 1409 +f 1580 1598 1591 +f 1591 1598 960 +f 1536 1990 2031 +f 960 1657 1460 +f 1809 1746 1797 +f 1423 1433 1432 +f 2478 1362 1409 +f 1463 1545 113 +f 1657 1463 113 +f 1457 1287 1305 +f 1682 1716 1746 +f 1434 1761 1885 +f 1013 1139 1617 +f 2379 1362 2478 +f 1420 1597 1551 +f 1420 1580 1597 +f 1664 1808 1712 +f 2256 2250 2231 +f 1362 1551 1409 +f 2196 2214 2213 +f 1691 1725 1777 +f 1626 192 1666 +f 1534 1574 2058 +f 1574 1600 1605 +f 1600 1606 1605 +f 1606 1641 1605 +f 1573 1420 1551 +f 1657 1485 1463 +f 678 1806 1742 +f 1534 1553 1574 +f 1574 1575 1600 +f 1810 2170 585 +f 1623 1641 1606 +f 1407 1657 960 +f 1598 1407 960 +f 1485 1142 1463 +f 1716 1581 1676 +f 1738 1743 1733 +f 843 2064 835 +f 1539 1575 1574 +f 1553 1539 1574 +f 1575 1592 1600 +f 1592 1624 1606 +f 1600 1592 1606 +f 1642 585 1641 +f 1623 1642 1641 +f 1485 164 1142 +f 1738 1516 1743 +f 1809 1720 1798 +f 1533 1535 1534 +f 1592 1607 1624 +f 1624 1623 1606 +f 1163 566 1116 +f 1407 1485 1657 +f 1432 1449 1439 +f 1100 802 2382 +f 1743 1516 1722 +f 1746 1716 1676 +f 1535 1539 1534 +f 1534 1539 1553 +f 1642 1623 1624 +f 1095 1208 1654 +f 967 1407 1598 +f 1580 967 1598 +f 1809 1797 1720 +f 1924 1524 1535 +f 1533 1924 1535 +f 1539 1576 1575 +f 1642 216 585 +f 1407 1529 1485 +f 1485 1529 164 +f 1472 1462 1482 +f 1415 1431 1240 +f 966 1194 714 +f 383 1182 152 +f 474 2337 446 +f 1743 1841 1757 +f 1486 1524 1924 +f 1535 1525 1539 +f 1575 1576 1592 +f 1420 967 1580 +f 1288 1634 1613 +f 459 427 1265 +f 1404 2179 1393 +f 1404 1403 1800 +f 1404 1410 1403 +f 1410 1749 1403 +f 1349 1351 218 +f 1486 1498 1524 +f 1535 1524 1525 +f 1607 1636 1624 +f 183 1642 1624 +f 1636 183 1624 +f 1107 1349 218 +f 1351 845 218 +f 164 1519 1142 +f 845 413 218 +f 1525 1576 1539 +f 1576 1582 1592 +f 1592 2134 1607 +f 2134 1636 1607 +f 2147 1491 1401 +f 1407 1589 1529 +f 1529 1519 164 +f 1693 1763 1444 +f 1924 1479 1486 +f 1592 1582 2134 +f 499 165 874 +f 2176 1857 1959 +f 2327 2368 2326 +f 2358 821 953 +f 953 821 1573 +f 1824 1704 1464 +f 1731 1358 1678 +f 1394 1410 1404 +f 1394 1418 1410 +f 1466 1479 1839 +f 1486 1479 1498 +f 1498 1525 1524 +f 1576 2080 1582 +f 1785 1684 1898 +f 804 398 802 +f 804 925 398 +f 1447 1562 2358 +f 2358 1562 821 +f 821 1620 1573 +f 1620 1420 1573 +f 1420 1556 967 +f 1393 1394 1404 +f 1525 2080 1576 +f 1621 1420 1620 +f 1621 1556 1420 +f 967 1589 1407 +f 1505 5 1357 +f 1266 1258 1436 +f 1393 1395 1394 +f 2176 2175 1848 +f 1455 1466 1839 +f 1525 1540 2080 +f 1582 2080 2118 +f 1100 804 802 +f 1556 1589 967 +f 1589 1082 1529 +f 1093 1685 1357 +f 1504 1093 1357 +f 1425 1418 1394 +f 1475 1479 1466 +f 1479 1506 1498 +f 1789 1784 1730 +f 2501 2465 2489 +f 1438 1458 1430 +f 1462 1458 1473 +f 1454 805 1529 +f 1082 1454 1529 +f 1529 805 1519 +f 1425 1394 1395 +f 1425 1744 1418 +f 1479 1475 1506 +f 1540 2060 2080 +f 1556 1082 1589 +f 1443 945 1511 +f 1506 1536 1498 +f 1498 1536 1525 +f 1525 1536 1540 +f 1670 852 1672 +f 1998 1388 1389 +f 1511 966 1509 +f 1509 966 714 +f 1442 1443 1496 +f 1562 1635 821 +f 155 1322 1473 +f 1439 1458 1438 +f 1426 1425 1395 +f 1475 1499 1506 +f 1735 1588 1776 +f 2422 2454 2421 +f 1423 1432 1415 +f 1559 2101 2073 +f 845 866 413 +f 1429 1620 821 +f 1620 1429 1621 +f 1228 1250 1687 +f 1002 945 1443 +f 2382 802 1083 +f 1859 1411 1395 +f 1411 1426 1395 +f 1426 1744 1425 +f 1590 1437 1483 +f 1480 1475 1466 +f 1480 1499 1475 +f 1510 1733 1743 +f 1663 1696 1658 +f 1430 1453 1452 +f 1452 1472 1471 +f 1452 1471 1448 +f 1430 1452 1421 +f 1430 1421 1422 +f 1429 1082 1556 +f 1621 1429 1556 +f 1351 2386 845 +f 1126 1059 487 +f 1639 1437 1563 +f 1504 1928 1093 +f 1499 1536 1506 +f 1588 1770 1727 +f 1110 1747 1397 +f 1776 1588 1531 +f 1322 1320 1482 +f 1590 1629 1571 +f 1730 1877 1838 +f 1429 935 1082 +f 1082 935 1454 +f 804 1443 925 +f 1139 1007 1639 +f 1925 1480 1466 +f 1934 1989 1480 +f 1499 1989 1536 +f 1727 1526 1531 +f 1593 1614 502 +f 2455 2431 2400 +f 1755 1680 908 +f 1563 1571 1564 +f 1647 1078 1501 +f 2490 1635 1106 +f 1496 1511 717 +f 2454 2431 516 +f 1478 1153 1093 +f 1870 1426 1411 +f 1426 1723 1744 +f 962 986 1412 +f 717 1511 1509 +f 1825 1704 1824 +f 2225 2234 2253 +f 1490 1557 1188 +f 1635 80 821 +f 805 1454 935 +f 1186 706 695 +f 1194 1161 714 +f 1512 1007 1013 +f 592 97 204 +f 1258 1266 1257 +f 82 1333 471 +f 1694 1710 1505 +f 1643 490 1661 +f 1661 490 1114 +f 1518 2068 2484 +f 1750 1808 1664 +f 1656 1635 2490 +f 935 1521 805 +f 1546 1629 1076 +f 1301 70 1277 +f 966 1441 1194 +f 1148 1825 1824 +f 1614 1609 1643 +f 1114 1092 1921 +f 1770 1739 1670 +f 1631 1632 1646 +f 821 1016 1429 +f 1429 1016 935 +f 1632 1095 1654 +f 1083 262 688 +f 1724 1686 1725 +f 1644 490 1643 +f 1092 1149 1921 +f 3 893 1832 +f 988 1640 1188 +f 916 1107 284 +f 1656 80 1635 +f 1016 821 80 +f 1016 1521 935 +f 1478 1202 1153 +f 1401 1928 29 +f 1440 1478 1928 +f 1849 1700 1865 +f 1595 1611 1612 +f 1208 198 341 +f 1464 1704 1746 +f 2143 984 1721 +f 1848 1849 1868 +f 1662 1114 490 +f 1669 1787 1682 +f 1656 1618 80 +f 198 1208 916 +f 1440 1928 1401 +f 1521 1369 805 +f 1252 1107 916 +f 1745 678 1672 +f 1703 1779 1721 +f 1750 1465 1808 +f 1609 1644 1643 +f 1092 1114 1662 +f 1826 1523 1793 +f 2262 2261 2224 +f 1696 2166 1767 +f 1016 1648 1521 +f 1208 1252 916 +f 833 688 1067 +f 1794 1803 1558 +f 28 17 512 +f 1750 861 1566 +f 1594 1644 1609 +f 1644 1645 490 +f 490 1645 1662 +f 2229 2262 2224 +f 1602 861 1760 +f 1530 1777 1760 +f 872 1706 1673 +f 1696 1668 2166 +f 1708 1809 1798 +f 1581 1716 1814 +f 1709 1794 1680 +f 1233 1421 1257 +f 1724 1476 1686 +f 1469 1481 1965 +f 1965 1481 1492 +f 2073 1549 1559 +f 1594 1615 1644 +f 1799 1706 1755 +f 1725 1686 1837 +f 1720 1797 1572 +f 1618 2467 2022 +f 1618 1579 80 +f 1648 1016 80 +f 2134 2152 1636 +f 1611 1632 1631 +f 1761 1434 1470 +f 1559 1577 1594 +f 1603 1615 1594 +f 1615 1645 1644 +f 1637 1662 1645 +f 1662 1199 1092 +f 1199 1149 1092 +f 1451 1108 1149 +f 665 734 756 +f 1865 1700 1714 +f 1709 1841 1794 +f 1618 2022 1579 +f 1648 1413 1369 +f 1521 1648 1369 +f 1520 11 1401 +f 1446 1470 1434 +f 1798 1691 1754 +f 2063 1544 2073 +f 2073 1544 1549 +f 1594 1577 1603 +f 1615 1637 1645 +f 1637 1199 1662 +f 1427 1149 1199 +f 2167 1108 1451 +f 1997 1673 1705 +f 1706 1799 1705 +f 1841 1709 1757 +f 1604 1579 2022 +f 1579 707 80 +f 80 707 1648 +f 1520 1401 1491 +f 1649 1520 1491 +f 1435 1434 1885 +f 1470 1469 1461 +f 1481 1508 2024 +f 2370 1544 2063 +f 1549 1568 1559 +f 1559 1568 1577 +f 1603 1610 1615 +f 1615 1610 1637 +f 999 1199 1637 +f 1451 1149 1427 +f 1137 1825 1148 +f 1706 1705 1673 +f 1138 1604 2116 +f 1138 1579 1604 +f 1413 1648 707 +f 2360 2024 1508 +f 598 1075 1116 +f 229 93 1468 +f 1839 1479 1684 +f 2216 2229 2224 +f 1610 1625 1637 +f 329 999 1637 +f 1199 1017 1427 +f 1017 303 1427 +f 303 1451 1427 +f 1792 1754 1777 +f 2309 2391 2301 +f 1655 1138 2116 +f 1138 707 1579 +f 1649 1491 206 +f 1406 1885 1398 +f 1406 1419 1885 +f 1419 1435 1885 +f 1434 1435 1446 +f 1470 1481 1469 +f 1577 1583 1603 +f 999 1017 1199 +f 81 67 941 +f 67 1650 941 +f 1259 1815 2164 +f 1619 2116 2045 +f 1424 707 1138 +f 1702 1649 206 +f 1687 1406 1398 +f 1477 1481 1470 +f 1568 1569 1577 +f 1577 1569 1583 +f 1603 1583 1610 +f 1625 329 1637 +f 2167 340 273 +f 81 273 340 +f 81 962 67 +f 1547 1619 1488 +f 1830 1739 1770 +f 938 1424 1138 +f 1424 1413 707 +f 1527 1649 1702 +f 1527 1520 1649 +f 1527 1268 1520 +f 1250 1406 1687 +f 1441 1353 1115 +f 1203 1413 1051 +f 1250 1419 1406 +f 1477 2372 1481 +f 1481 2372 1508 +f 2449 1560 1568 +f 1549 2449 1568 +f 1568 1560 1569 +f 1569 1584 1583 +f 1652 329 1625 +f 329 817 999 +f 285 1017 999 +f 303 10 1451 +f 10 2167 1451 +f 1412 1650 67 +f 1412 1488 1650 +f 1547 1023 1619 +f 1023 1655 1619 +f 1655 938 1138 +f 1456 1413 1424 +f 1457 1470 1446 +f 1457 1477 1470 +f 329 1652 817 +f 10 340 2167 +f 938 1546 1424 +f 1546 1456 1424 +f 1259 1548 1779 +f 2052 2031 1990 +f 1440 1202 1478 +f 1428 1419 1250 +f 1428 1435 1419 +f 1428 1446 1435 +f 1934 1935 1955 +f 1560 1584 1569 +f 1610 1638 1625 +f 1638 1652 1625 +f 817 1077 999 +f 1077 285 999 +f 980 303 1017 +f 962 1412 67 +f 1494 1023 1547 +f 325 271 1270 +f 1443 1511 1496 +f 1450 1268 1527 +f 1514 1353 1441 +f 1287 1446 1428 +f 1446 1287 1457 +f 1305 2372 1477 +f 1992 1990 1991 +f 1992 1991 1971 +f 1971 1991 1955 +f 2449 1549 2418 +f 1583 1616 1610 +f 1610 1616 1638 +f 10 1396 340 +f 340 1445 81 +f 1445 962 81 +f 1790 984 1753 +f 984 2148 1753 +f 1588 1713 1770 +f 969 978 958 +f 1741 1779 1703 +f 1758 1846 1754 +f 1827 1819 1029 +f 1818 1530 1712 +f 1750 1566 2127 +f 2459 2434 2483 +f 1798 1720 1771 +f 1794 1841 1803 +f 216 1755 1810 +f 1098 1735 1748 +f 1735 1497 1748 +f 1502 2102 1601 +f 881 1502 1601 +f 1455 1839 1744 +f 1706 1709 1680 +f 1212 1741 1703 +f 1788 1969 1671 +f 1075 1074 1692 +f 951 2500 881 +f 2490 2486 2463 +f 1748 1497 1781 +f 1721 984 1840 +f 1815 1259 1741 +f 1626 1756 1837 +f 975 987 1542 +f 2230 2236 2235 +f 1772 678 734 +f 1542 1671 975 +f 1806 1772 1780 +f 678 1772 1806 +f 2218 2225 2268 +f 1828 1732 2007 +f 1526 1688 1531 +f 1752 1526 1554 +f 1844 1818 1712 +f 1823 1846 1804 +f 1781 1669 1704 +f 1721 1779 2143 +f 1770 1670 1526 +f 1497 1669 1781 +f 1098 1713 1735 +f 1742 1815 1741 +f 1526 858 1875 +f 1599 1531 1688 +f 1803 1790 1558 +f 1703 1721 1683 +f 1832 1766 957 +f 1542 1679 1671 +f 1679 1788 1671 +f 1927 1819 1827 +f 1718 1745 1739 +f 1684 1022 1839 +f 1459 1283 1299 +f 1022 1410 1418 +f 2368 2393 2326 +f 1669 1497 1776 +f 1875 858 1212 +f 1739 1745 852 +f 1964 1918 1461 +f 1356 133 1331 +f 1765 1829 1468 +f 858 1742 1741 +f 1006 1674 1021 +f 1723 1936 1935 +f 1468 1713 1098 +f 1724 1678 1476 +f 1680 1783 908 +f 1731 1543 520 +f 1683 1721 1840 +f 1467 1679 1542 +f 1812 1708 1846 +f 1679 1975 1788 +f 1713 1830 1770 +f 1803 1722 1790 +f 2301 2391 2349 +f 1713 1588 1735 +f 1836 1530 1818 +f 1837 1756 861 +f 886 571 556 +f 1181 1805 1812 +f 1706 1680 1755 +f 1677 1729 1775 +f 1776 1787 1669 +f 1526 1670 1672 +f 1727 1770 1526 +f 987 1467 1542 +f 1567 1704 1137 +f 1693 1865 1714 +f 897 1762 912 +f 1135 1697 1062 +f 1697 376 1062 +f 1543 1731 1678 +f 1793 1679 1467 +f 1777 1602 1760 +f 1846 1798 1754 +f 1835 1096 1677 +f 1033 1030 940 +f 1450 1527 1702 +f 1717 376 1697 +f 1711 1717 1697 +f 1717 165 376 +f 1840 984 1790 +f 1669 1746 1704 +f 1669 1682 1746 +f 2301 2349 2308 +f 1882 1444 1898 +f 1820 1789 1730 +f 861 1380 1566 +f 2301 2308 2266 +f 1771 1543 1691 +f 1958 1659 1651 +f 1697 1360 1711 +f 1711 1737 1717 +f 1717 1737 165 +f 1790 1753 1558 +f 1668 1696 1663 +f 1360 1702 1711 +f 1702 1707 1711 +f 1707 1737 1711 +f 1737 1751 165 +f 1444 1782 1693 +f 1716 1787 1599 +f 1744 1839 1022 +f 1898 1444 1785 +f 206 1707 1702 +f 1764 2468 1751 +f 316 1844 893 +f 893 1844 915 +f 1845 1804 1758 +f 1380 861 1756 +f 1780 670 1021 +f 1714 2172 1763 +f 1783 1558 1663 +f 1750 2127 1465 +f 1798 1771 1691 +f 1691 1543 1724 +f 1872 1910 839 +f 1737 2044 1751 +f 1751 2044 1764 +f 1757 1701 482 +f 1725 1602 1777 +f 1836 1845 1530 +f 2102 2470 1503 +f 2496 1899 544 +f 763 2484 946 +f 987 1719 1467 +f 1845 1758 1792 +f 1725 1837 1602 +f 1872 1866 1873 +f 1712 1530 1760 +f 489 1799 216 +f 1760 861 1750 +f 2068 2466 2460 +f 1696 2159 2168 +f 377 1377 1280 +f 1797 1676 1572 +f 1581 2053 1572 +f 1676 1581 1572 +f 1764 2498 2468 +f 2468 2498 1994 +f 1861 1695 1860 +f 2481 2004 2495 +f 1826 1677 1523 +f 1670 1739 852 +f 2234 2269 2253 +f 1724 1543 1678 +f 1658 2168 1791 +f 1397 1747 1719 +f 1696 2168 1658 +f 979 519 272 +f 1774 1975 1679 +f 975 1671 932 +f 1787 1716 1682 +f 1835 1826 1747 +f 2501 2469 961 +f 1810 908 1791 +f 1982 1768 191 +f 1137 1704 1825 +f 1804 1846 1758 +f 2004 2044 1737 +f 913 1969 902 +f 2498 1795 1801 +f 915 1844 1712 +f 1689 915 1712 +f 1740 1752 1541 +f 695 661 199 +f 1865 1693 1782 +f 1824 1464 1809 +f 1829 1765 1718 +f 1816 1768 1982 +f 1816 1622 1768 +f 1622 2165 1681 +f 1768 1622 1681 +f 670 1772 228 +f 1283 1459 52 +f 1785 1444 1749 +f 1675 1075 1685 +f 1567 1781 1704 +f 1858 1857 1848 +f 1526 1752 1688 +f 1791 2160 1810 +f 908 1658 1791 +f 1813 1773 1558 +f 1845 1792 1530 +f 69 376 165 +f 3 1832 1834 +f 1722 1516 1507 +f 1801 1821 1994 +f 1833 1982 2046 +f 1821 1833 2046 +f 1833 1816 1982 +f 1022 1785 1749 +f 2160 2170 1810 +f 1147 1719 1726 +f 1683 1840 1507 +f 1467 1719 1793 +f 1795 1802 1801 +f 1802 1811 1801 +f 1801 1811 1821 +f 1690 2165 1622 +f 1934 1480 1925 +f 229 1468 1091 +f 1780 2164 1742 +f 1672 1742 858 +f 1833 1417 1816 +f 1417 1622 1816 +f 1831 2165 1690 +f 1668 1663 1558 +f 1719 1747 1826 +f 1760 1750 1664 +f 1817 1690 1622 +f 1530 1792 1777 +f 948 1796 1802 +f 1796 1811 1802 +f 1515 1817 1622 +f 1695 1861 1831 +f 1783 1663 1658 +f 1749 1410 1022 +f 854 1796 948 +f 1811 1842 1833 +f 1821 1811 1833 +f 1833 1842 1417 +f 1622 1417 1515 +f 127 1804 1845 +f 1686 1626 1837 +f 1608 1690 1817 +f 1523 1775 1762 +f 127 1845 1836 +f 1812 1805 1708 +f 1523 1677 1775 +f 1780 1772 670 +f 1758 1754 1792 +f 1204 1796 854 +f 1822 1842 1811 +f 1608 1831 1690 +f 1822 1811 1796 +f 1842 1416 1417 +f 1417 1416 1515 +f 1515 1608 1817 +f 1728 1831 1608 +f 908 1783 1658 +f 127 1836 316 +f 1805 1148 1824 +f 852 1745 1672 +f 1478 1093 1928 +f 1822 1843 1842 +f 1843 959 1842 +f 1842 959 1416 +f 1728 1695 1831 +f 1728 1860 1695 +f 2346 446 2337 +f 1602 1837 861 +f 1087 1096 1835 +f 1708 1824 1809 +f 2004 1737 505 +f 1567 1748 1781 +f 520 1543 1883 +f 1760 1664 1712 +f 128 1336 72 +f 2053 1883 1543 +f 1822 180 1843 +f 1786 1608 1515 +f 929 2462 519 +f 512 2402 506 +f 1212 1703 1683 +f 1830 1829 1739 +f 2053 1543 1771 +f 1416 1769 1515 +f 1769 1786 1515 +f 1786 1728 1608 +f 1712 1808 1689 +f 1794 1558 1783 +f 1497 1735 1776 +f 1127 1567 1137 +f 1123 1748 1567 +f 36 205 1185 +f 959 1734 1416 +f 1738 1733 1541 +f 1774 1762 1974 +f 1752 1554 1541 +f 1752 1740 1688 +f 1526 1875 1554 +f 1468 1829 1830 +f 1755 908 1810 +f 1716 1599 1814 +f 1806 1780 1742 +f 2308 2349 2340 +f 1832 915 1689 +f 1713 1468 1830 +f 1814 1599 1346 +f 1832 1689 1766 +f 1022 1684 1785 +f 1093 1153 1116 +f 1672 678 1742 +f 1675 1685 1093 +f 1841 1743 1722 +f 1814 2053 1581 +f 1464 1746 1809 +f 2485 2497 2493 +f 1416 1734 1769 +f 1665 1728 1786 +f 1665 1951 1728 +f 1951 1860 1728 +f 1951 2094 1860 +f 1844 1836 1818 +f 316 1836 1844 +f 1776 1531 1787 +f 1719 1826 1793 +f 2147 1401 29 +f 2111 2121 1548 +f 1741 1259 1779 +f 1843 347 1834 +f 1843 1734 959 +f 1766 1769 1734 +f 957 1766 1734 +f 1766 1786 1769 +f 1766 1689 1786 +f 1689 1665 1786 +f 1754 1691 1777 +f 1507 1840 1790 +f 1761 1470 1461 +f 1523 1679 1793 +f 1091 1468 1098 +f 1820 1730 1838 +f 1843 1834 1734 +f 1808 1951 1665 +f 1588 1727 1531 +f 893 915 1832 +f 1523 1774 1679 +f 272 2488 710 +f 1093 1116 1675 +f 2340 2349 2348 +f 1832 1734 1834 +f 1832 957 1734 +f 1951 1808 2094 +f 1685 1692 1505 +f 1043 295 698 +f 2143 1779 2121 +f 1689 1808 1665 +f 1693 1714 1763 +f 1738 2157 1516 +f 1114 1921 236 +f 1268 1333 1520 +f 1149 1108 431 +f 508 2144 1912 +f 1957 1108 1537 +f 431 1108 1957 +f 1018 1108 2167 +f 1338 1957 1681 +f 2163 1957 1338 +f 1983 1390 2093 +f 30 557 37 +f 1714 2173 2172 +f 1983 1984 1390 +f 1984 2065 1390 +f 884 1762 897 +f 2065 1984 1214 +f 1950 1974 1762 +f 884 1950 1762 +f 2012 1698 1861 +f 1214 2116 803 +f 1950 1938 1974 +f 1938 1967 1974 +f 1900 1761 1461 +f 865 1929 884 +f 884 1929 1950 +f 2062 2071 2042 +f 919 1985 1732 +f 1593 502 2146 +f 1995 1213 2098 +f 1522 2476 1651 +f 2174 1849 2175 +f 1480 1989 1499 +f 1929 1938 1950 +f 1605 2058 1574 +f 2097 1605 2133 +f 1912 2014 1886 +f 2092 2082 2083 +f 206 1930 505 +f 2101 2100 2092 +f 2073 2101 2092 +f 839 1910 865 +f 1910 1901 1929 +f 865 1910 1929 +f 1967 1788 1975 +f 2073 2092 2063 +f 2101 1593 2100 +f 2015 1876 1698 +f 1853 1884 2014 +f 1831 1698 2165 +f 1316 273 81 +f 1901 1920 1929 +f 1929 1920 1938 +f 1920 1968 1967 +f 1938 1920 1967 +f 1849 2174 1700 +f 2173 1700 2174 +f 2062 2072 2091 +f 803 2467 2059 +f 2239 1736 2240 +f 1505 1357 1685 +f 1358 1686 1476 +f 1967 1968 1788 +f 1968 1969 1788 +f 2065 2110 2156 +f 2065 1214 2110 +f 2110 1214 503 +f 273 2093 1018 +f 273 1983 2093 +f 532 1886 2155 +f 2034 2021 1947 +f 216 1810 585 +f 1912 543 2014 +f 1390 2051 1537 +f 1872 1873 1910 +f 1984 2045 1214 +f 597 1912 1886 +f 1593 2146 2100 +f 2071 2062 2090 +f 2034 2046 1982 +f 2034 1947 2046 +f 1214 2045 2116 +f 1873 1887 1910 +f 1887 1901 1910 +f 1562 1447 1106 +f 2163 431 1957 +f 1948 1972 1936 +f 1972 1948 1992 +f 2014 2015 2013 +f 1853 2014 2013 +f 1550 1884 1853 +f 1947 2468 1994 +f 1355 1550 2154 +f 1355 1884 1550 +f 2081 2108 2128 +f 2024 1965 1492 +f 2024 2032 1965 +f 2116 1604 803 +f 1901 1911 1920 +f 1939 1968 1920 +f 1911 1939 1920 +f 872 1626 1666 +f 2062 2091 2120 +f 1819 1927 1759 +f 1021 1674 1780 +f 872 1673 1756 +f 1550 501 2171 +f 1378 1550 2171 +f 2146 2162 2145 +f 1358 482 192 +f 2109 2120 2119 +f 1866 1872 2227 +f 1391 2012 1860 +f 2136 2137 2161 +f 2162 1661 236 +f 1887 1894 1901 +f 1901 1894 1911 +f 505 1707 206 +f 2120 2137 2136 +f 2142 2164 1674 +f 1860 2012 1861 +f 1894 1939 1911 +f 2080 2060 2118 +f 2162 236 508 +f 2164 1815 1742 +f 1018 2093 1537 +f 2154 1378 2161 +f 2041 2098 2491 +f 2043 2042 2032 +f 1108 1018 1537 +f 1465 2094 1808 +f 502 1643 1661 +f 2467 1618 1656 +f 2119 2136 2135 +f 2119 2108 2071 +f 878 1183 1195 +f 2101 1594 1593 +f 2033 2370 2063 +f 2482 2491 2098 +f 1282 2406 1275 +f 2003 1948 1956 +f 2043 2032 2024 +f 2025 2043 2024 +f 2154 1550 1378 +f 1795 2498 1764 +f 2142 1548 2164 +f 2431 2454 2422 +f 1981 2011 1993 +f 2349 2391 2362 +f 502 2162 2146 +f 2025 2024 2360 +f 2129 2120 2091 +f 1732 1985 2007 +f 2171 1308 209 +f 1930 1995 2041 +f 1390 1238 2051 +f 1866 1878 1887 +f 1878 1894 1887 +f 1965 2032 2011 +f 874 2480 2492 +f 2071 2108 2069 +f 1358 1731 482 +f 430 2021 2034 +f 1965 2003 1964 +f 1855 1889 831 +f 1668 1773 2150 +f 1390 2156 1238 +f 898 869 1903 +f 2391 2407 2362 +f 2121 2111 2074 +f 1548 1259 2164 +f 2099 2129 2091 +f 1550 1853 501 +f 1853 1852 501 +f 952 2017 969 +f 2085 2121 2074 +f 2130 2006 1391 +f 2144 1367 543 +f 2100 2146 2099 +f 1545 1319 113 +f 1903 1922 898 +f 1922 1931 898 +f 585 2170 1641 +f 2007 2017 952 +f 2017 2074 969 +f 1558 1753 1813 +f 837 2005 1517 +f 2005 2006 2130 +f 1532 1474 1528 +f 2003 1981 1948 +f 2070 2071 2069 +f 1922 919 1931 +f 2017 2085 2074 +f 2085 2104 2121 +f 2100 2099 2082 +f 2156 2110 2034 +f 505 2474 2004 +f 1903 871 1922 +f 1922 1952 919 +f 919 1952 1985 +f 1985 2001 2007 +f 2001 2036 2017 +f 2007 2001 2017 +f 2017 2036 2085 +f 2036 2047 2085 +f 2047 2075 2085 +f 2075 2104 2085 +f 1948 1993 2023 +f 2400 2422 2407 +f 2011 2070 1993 +f 2033 2043 2025 +f 2012 2015 1698 +f 1876 1338 2165 +f 871 1940 1922 +f 1985 1976 2001 +f 2121 2104 2143 +f 1051 1413 1456 +f 2358 1362 2379 +f 1859 1789 1870 +f 2090 2109 2071 +f 1405 1398 1885 +f 1886 1884 1355 +f 1922 1960 1952 +f 1952 1960 1985 +f 1960 1976 1985 +f 1956 1948 1936 +f 2135 209 2128 +f 2157 1875 1212 +f 2160 2168 2169 +f 1900 1461 1918 +f 2001 2018 2036 +f 2075 2086 2104 +f 2111 2142 2103 +f 1937 1956 1936 +f 2023 2070 2061 +f 2135 2128 2108 +f 2042 2071 2011 +f 2138 413 2383 +f 2033 2072 2043 +f 1922 1940 1960 +f 2070 2069 2061 +f 2069 2108 2061 +f 2108 2119 2135 +f 1855 1904 1889 +f 1889 1904 871 +f 871 1904 1940 +f 1976 2018 2001 +f 2036 2018 2047 +f 2122 2143 2104 +f 216 1642 489 +f 2148 984 2143 +f 1975 1974 1967 +f 2157 1683 1516 +f 1614 1593 1594 +f 2269 2270 2276 +f 1926 2147 29 +f 2082 2091 2072 +f 430 503 2059 +f 1904 1905 1940 +f 1940 1961 1960 +f 1961 1976 1960 +f 2087 2086 2075 +f 2065 2156 1390 +f 1820 1838 1900 +f 534 1308 837 +f 2167 273 1018 +f 831 1850 1855 +f 2019 2037 2018 +f 2018 2037 2047 +f 2037 2075 2047 +f 2086 2095 2104 +f 2095 2122 2104 +f 2122 2148 2143 +f 1926 1213 1995 +f 1405 1885 1761 +f 2006 2013 2012 +f 2211 2233 2216 +f 1855 1890 1904 +f 1904 1895 1905 +f 1905 1932 1940 +f 1961 1977 1976 +f 1976 1986 2018 +f 2484 2476 1518 +f 1870 1411 1859 +f 1548 2142 2111 +f 1904 1890 1895 +f 1895 1932 1905 +f 1940 1932 1961 +f 1976 1977 1986 +f 1986 2008 2018 +f 2018 2008 2019 +f 2087 2075 2037 +f 2087 2095 2086 +f 2094 1391 1860 +f 1852 1853 2006 +f 1853 2013 2006 +f 929 979 850 +f 1855 1874 1890 +f 2008 2028 2019 +f 1993 2070 2023 +f 1705 1799 1998 +f 1491 2147 206 +f 1851 1856 1855 +f 1895 1890 1874 +f 2038 2019 2028 +f 2038 2048 2037 +f 2019 2038 2037 +f 2048 2067 2087 +f 2037 2048 2087 +f 2087 2067 2095 +f 2095 2149 2122 +f 2149 2148 2122 +f 1308 2005 837 +f 209 1308 1387 +f 1601 2102 1927 +f 254 170 201 +f 1800 1403 1763 +f 1510 1346 1740 +f 870 871 1903 +f 1919 1650 1619 +f 2148 1667 1753 +f 1932 1923 1961 +f 1977 1953 1986 +f 2067 2112 2095 +f 2112 2149 2095 +f 2148 2149 1667 +f 2422 2421 2407 +f 1926 2026 1213 +f 1912 2144 543 +f 2128 1387 2153 +f 1733 1510 1740 +f 990 853 2489 +f 503 1214 803 +f 1921 431 2163 +f 2146 2145 2129 +f 2144 1921 2163 +f 1855 1856 1874 +f 1895 1923 1932 +f 1923 1941 1961 +f 1961 1941 1977 +f 2048 2076 2067 +f 2076 2113 2067 +f 2067 2113 2112 +f 1723 1900 1937 +f 1870 1900 1723 +f 1367 2163 1338 +f 520 1346 1510 +f 1698 1831 1861 +f 1984 1919 2045 +f 1895 1891 1923 +f 2008 1986 2028 +f 1948 1981 1993 +f 1883 1346 520 +f 1883 1814 1346 +f 1930 206 2147 +f 2499 2486 1447 +f 1891 1906 1923 +f 1923 1953 1941 +f 1953 1977 1941 +f 1953 1987 1986 +f 2113 2123 2112 +f 2123 2149 2112 +f 1387 1308 1226 +f 1599 1688 1346 +f 2093 1390 1537 +f 2003 2011 1981 +f 1987 2028 1986 +f 2038 2049 2048 +f 2048 2049 2076 +f 1813 1667 2149 +f 2123 1813 2149 +f 1461 1469 1964 +f 1757 1510 1743 +f 505 1930 1999 +f 2223 1784 1789 +f 1532 1522 1651 +f 1906 1913 1923 +f 1913 1943 1923 +f 1943 1942 1923 +f 1923 1942 1953 +f 1942 1987 1953 +f 1308 1852 2005 +f 2053 1814 1883 +f 1733 1740 1541 +f 2154 1886 1355 +f 1503 1528 1474 +f 1874 1879 1895 +f 1895 1879 1891 +f 2076 2124 2113 +f 2113 2124 2123 +f 1896 1891 1879 +f 1891 1896 1906 +f 1942 1962 1987 +f 1962 2009 2028 +f 1987 1962 2028 +f 2009 2038 2028 +f 2109 2119 2071 +f 1918 1956 1937 +f 1851 1864 1856 +f 1896 1897 1906 +f 1906 1897 1913 +f 1943 1962 1942 +f 2049 2077 2076 +f 2124 2125 2123 +f 1930 2147 1926 +f 1902 1894 1878 +f 482 1510 1757 +f 2129 2137 2120 +f 503 803 2059 +f 1847 1857 1851 +f 1851 1857 1864 +f 2039 2038 2009 +f 2038 2039 2049 +f 2076 2077 2124 +f 2150 1813 2123 +f 482 520 1510 +f 1994 1821 2046 +f 2044 2004 1764 +f 1864 1867 1856 +f 1867 1874 1856 +f 1897 1944 1913 +f 1943 1944 1962 +f 2124 2126 2125 +f 2150 2123 2125 +f 2099 2146 2129 +f 2041 1995 2098 +f 1605 1641 2151 +f 1847 1959 1857 +f 1874 1867 1879 +f 1913 1944 1943 +f 1944 1963 1962 +f 2077 2096 2124 +f 2096 2126 2124 +f 2126 2150 2125 +f 941 1650 1919 +f 2135 2136 209 +f 1884 1886 2014 +f 2049 2029 2077 +f 1388 2127 1389 +f 1389 2127 1566 +f 1930 1926 1995 +f 941 1919 1316 +f 2110 503 430 +f 1867 1880 1879 +f 1879 1880 1896 +f 1897 1907 1944 +f 1963 1978 1962 +f 1962 1978 2009 +f 2039 2029 2049 +f 2077 2078 2096 +f 822 823 827 +f 2166 1668 2150 +f 81 941 1316 +f 2204 2216 2203 +f 2011 2071 2070 +f 1880 1892 1896 +f 1892 1907 1897 +f 1896 1892 1897 +f 1907 1914 1944 +f 1978 2010 2009 +f 2010 2039 2009 +f 1688 1740 1346 +f 1789 1820 1870 +f 2130 1391 2094 +f 1944 1945 1963 +f 2029 2078 2077 +f 1767 2150 2126 +f 1767 2166 2150 +f 803 2022 2467 +f 1503 1927 2102 +f 1914 1954 1944 +f 1944 1954 1945 +f 1963 1970 1978 +f 2078 2105 2096 +f 2105 2126 2096 +f 1965 2011 2003 +f 192 1626 1358 +f 2101 1559 1594 +f 1930 2041 1999 +f 1698 1876 2165 +f 1398 1871 891 +f 2165 1338 1681 +f 1970 2010 1978 +f 2010 2030 2029 +f 2039 2010 2029 +f 2030 2055 2078 +f 2029 2030 2078 +f 1849 1848 2175 +f 1871 1862 891 +f 543 2015 2014 +f 1857 1858 1864 +f 1864 1858 1867 +f 1963 1945 1970 +f 2055 2088 2078 +f 2078 2088 2105 +f 2105 2131 2126 +f 2126 2131 1767 +f 2063 2083 2033 +f 2161 2171 209 +f 2032 2042 2011 +f 1813 2150 1773 +f 1914 1908 1954 +f 1970 1979 2010 +f 2088 2131 2105 +f 2015 543 1876 +f 1694 1692 1048 +f 1395 2207 1859 +f 1395 1393 2207 +f 1730 1784 1736 +f 2500 2466 2470 +f 1709 1701 1757 +f 1945 1979 1970 +f 2030 2050 2055 +f 2350 2317 2286 +f 2154 2155 1886 +f 871 860 1889 +f 2161 209 2136 +f 2497 2463 2493 +f 2190 2204 2203 +f 1800 2179 1404 +f 2477 2469 1385 +f 1385 1715 2477 +f 2128 209 1387 +f 1858 1868 1867 +f 1867 1881 1880 +f 1893 1892 1880 +f 1881 1893 1880 +f 1893 1907 1892 +f 1907 1908 1914 +f 1954 1979 1945 +f 1979 1980 2010 +f 2131 2159 1767 +f 1765 93 339 +f 1761 1877 1405 +f 523 1347 515 +f 1541 2157 1738 +f 2144 2163 1367 +f 1380 1389 1566 +f 2317 2392 2316 +f 1994 2498 1801 +f 1867 1868 1881 +f 1980 2050 2030 +f 2010 1980 2030 +f 2050 2089 2055 +f 2055 2089 2088 +f 2088 2114 2131 +f 1538 1651 1659 +f 2145 2155 2129 +f 2140 29 1928 +f 2370 2033 2025 +f 2252 2239 2240 +f 2239 2252 1862 +f 2392 2391 2316 +f 2469 2501 1385 +f 2477 1715 1710 +f 502 1614 1643 +f 2438 1227 2431 +f 1915 1907 1893 +f 1915 1908 1907 +f 1954 1908 1979 +f 1908 1988 1979 +f 1979 1988 1980 +f 2114 2159 2131 +f 2155 2154 2129 +f 508 1966 2144 +f 872 1756 1626 +f 1710 1715 1505 +f 236 1966 508 +f 2272 2284 1398 +f 2325 2355 2319 +f 1548 2121 1779 +f 1532 1528 1522 +f 1980 2056 2050 +f 2050 2056 2089 +f 2013 2015 2012 +f 1964 2003 1956 +f 2006 2012 1391 +f 1565 1927 1503 +f 2244 2243 2226 +f 5 1715 1385 +f 1858 1848 1868 +f 1915 1946 1908 +f 1946 1988 1908 +f 1980 2020 2056 +f 2115 2159 2114 +f 2092 2083 2063 +f 1398 2284 1687 +f 2162 2155 2145 +f 519 2475 2488 +f 2158 5 1385 +f 5 1505 1715 +f 1692 1694 1505 +f 1988 2020 1980 +f 2115 2169 2159 +f 2169 2168 2159 +f 2083 2082 2072 +f 1316 1984 1983 +f 1488 1619 1650 +f 2083 2072 2033 +f 2361 1210 1233 +f 1933 1946 1915 +f 2056 2079 2089 +f 2088 2115 2114 +f 2099 2091 2082 +f 2162 532 2155 +f 1852 2006 2005 +f 2023 2061 2052 +f 2176 2184 2175 +f 2162 985 532 +f 1909 1893 1881 +f 1909 1915 1893 +f 1988 2040 2020 +f 2040 2056 2020 +f 2089 2079 2088 +f 2088 2079 2115 +f 1782 1444 1882 +f 1216 1215 2320 +f 867 1939 1894 +f 867 903 1939 +f 1372 2398 1379 +f 1863 504 2027 +f 2158 1385 504 +f 1868 1782 1881 +f 1909 1933 1915 +f 2040 1988 1946 +f 1481 2024 1492 +f 2120 2136 2119 +f 1522 1528 1518 +f 1871 1398 1405 +f 1221 1408 1399 +f 1357 5 2158 +f 2179 1800 1763 +f 1868 1865 1782 +f 1882 1881 1782 +f 1882 1909 1881 +f 2040 2057 2056 +f 2106 2079 2056 +f 2057 2106 2056 +f 2106 2132 2079 +f 2132 2115 2079 +f 2115 2132 2169 +f 532 985 597 +f 2092 2100 2082 +f 1210 1221 1399 +f 1399 1233 1210 +f 2130 2002 1517 +f 1849 1865 1868 +f 1933 2040 1946 +f 52 1269 30 +f 1667 1813 1753 +f 1997 1380 1673 +f 940 1008 1088 +f 1947 1994 2046 +f 1882 1916 1909 +f 1924 1933 1909 +f 1533 2040 1933 +f 1533 1534 2040 +f 2058 2040 1534 +f 2058 2057 2040 +f 1238 191 1768 +f 1997 1389 1380 +f 1875 1541 1554 +f 1854 504 1863 +f 1854 2158 504 +f 2396 1275 2406 +f 2426 2443 153 +f 1916 1924 1909 +f 1925 1935 1934 +f 1870 1723 1426 +f 2058 2097 2057 +f 2097 2106 2057 +f 2132 2151 2169 +f 2151 2160 2169 +f 1106 1635 1562 +f 1957 1768 1681 +f 1957 2051 1768 +f 526 535 33 +f 1614 1594 1609 +f 2233 2229 2216 +f 2496 2027 2084 +f 2496 1863 2027 +f 2117 1854 1863 +f 2016 2158 1854 +f 2016 1504 1357 +f 2158 2016 1357 +f 1114 236 1661 +f 2129 2154 2137 +f 2133 2106 2097 +f 2491 1999 2041 +f 2051 1238 1768 +f 2061 2108 2081 +f 2189 2195 2186 +f 2348 2349 2362 +f 1701 192 482 +f 505 1737 1707 +f 2133 2132 2106 +f 2132 2133 2151 +f 2151 2170 2160 +f 502 1661 2162 +f 1998 1389 1997 +f 2297 2352 2329 +f 2352 2364 2329 +f 2394 2414 2364 +f 2352 2394 2364 +f 2402 512 2415 +f 2255 2254 2243 +f 2446 1365 2456 +f 2271 2282 2298 +f 846 2283 2264 +f 2293 2310 2318 +f 2254 2295 2294 +f 2283 2290 2278 +f 2270 2294 2293 +f 2423 2455 2400 +f 2281 2287 2267 +f 2190 2191 2204 +f 2271 2263 2282 +f 2334 2329 2364 +f 2424 2432 2409 +f 2282 2263 2298 +f 1409 1659 1958 +f 2263 2302 2298 +f 2297 2329 2296 +f 1256 446 2346 +f 1958 2502 2478 +f 2437 2399 2444 +f 263 2366 2359 +f 849 827 823 +f 2311 2325 2290 +f 2499 2379 2434 +f 2446 2456 2423 +f 947 2358 2379 +f 2499 947 2379 +f 2205 2195 2212 +f 2245 2237 2227 +f 2245 2256 2237 +f 2256 2263 2271 +f 556 571 2305 +f 1528 2068 1518 +f 2424 2439 2432 +f 2302 2352 2297 +f 1866 2237 826 +f 2248 2242 2211 +f 2334 2364 2363 +f 2235 2244 2226 +f 2255 2295 2254 +f 2329 2324 2296 +f 2439 2447 1973 +f 2329 2334 2324 +f 2409 2432 2414 +f 2293 2318 2276 +f 866 2425 2416 +f 1487 1493 2372 +f 2237 2231 2230 +f 2415 512 17 +f 2035 1236 26 +f 921 2138 688 +f 2491 2482 2462 +f 6 181 197 +f 2481 948 1795 +f 2138 2383 2382 +f 2377 2394 2352 +f 2377 506 2394 +f 2394 506 2402 +f 2401 2402 2415 +f 2394 2402 2401 +f 2318 2326 2276 +f 2439 2457 2432 +f 2298 2302 2297 +f 2244 2249 2243 +f 2404 1100 2382 +f 2238 2245 2227 +f 2245 2257 2256 +f 2257 2263 2256 +f 2324 2334 2328 +f 2257 2289 2263 +f 2289 2302 2263 +f 2236 2231 2250 +f 2138 2382 688 +f 2383 2404 2382 +f 1100 2404 2343 +f 2353 2352 2302 +f 2353 2377 2352 +f 2237 2230 2220 +f 2335 2355 2325 +f 2308 2340 2315 +f 2253 2269 2276 +f 2311 2335 2325 +f 2439 2424 511 +f 2268 2267 2248 +f 2383 413 2404 +f 123 971 832 +f 2234 2243 2269 +f 2225 2213 2234 +f 2219 2213 2225 +f 2195 2196 2212 +f 1544 2418 1549 +f 413 866 2404 +f 2404 866 2416 +f 2416 2417 2404 +f 2404 2417 2343 +f 2415 2409 2401 +f 2196 2219 2212 +f 2268 2248 2218 +f 2206 2214 2197 +f 2417 2332 2343 +f 2343 2332 832 +f 2330 2302 2289 +f 2330 2353 2302 +f 2453 2454 515 +f 2218 2248 2217 +f 2218 2217 2205 +f 2276 2281 2268 +f 2178 2197 2177 +f 2197 2189 2177 +f 2332 2066 832 +f 832 2066 123 +f 2231 2236 2230 +f 669 950 1144 +f 2217 2211 2199 +f 1216 1209 1217 +f 2066 2365 123 +f 2230 2226 2214 +f 2290 2325 2304 +f 2325 2319 2304 +f 2217 2248 2211 +f 2191 2192 2199 +f 510 525 2035 +f 2417 1917 2332 +f 2332 1917 2066 +f 2408 2413 2341 +f 2248 2267 2242 +f 2326 2333 2281 +f 1340 2365 2066 +f 2440 1302 1340 +f 2226 2230 2235 +f 1153 1163 1116 +f 2431 2455 2438 +f 2416 2425 2417 +f 2495 2474 2462 +f 2290 2304 2277 +f 825 2227 1872 +f 151 239 1038 +f 9 151 1038 +f 545 928 2381 +f 2440 2406 1384 +f 928 1596 2381 +f 2186 2188 2185 +f 2456 26 1888 +f 2287 2333 2262 +f 2425 2342 2417 +f 2342 1917 2417 +f 1917 877 2066 +f 2336 1340 2066 +f 2336 2440 1340 +f 2328 2351 2327 +f 825 2238 2227 +f 2351 2368 2327 +f 1222 2388 1211 +f 678 756 734 +f 428 263 1343 +f 2188 2191 2190 +f 2341 2376 2333 +f 2066 877 2336 +f 2290 2277 2278 +f 739 634 592 +f 675 304 14 +f 2384 675 14 +f 2199 2211 2204 +f 2191 2199 2204 +f 2322 2318 2310 +f 2287 2262 2233 +f 2185 2188 2184 +f 2386 2425 845 +f 2384 572 675 +f 1128 123 2365 +f 832 971 2343 +f 2188 2186 2191 +f 2185 2184 2176 +f 2345 1917 2342 +f 2345 877 1917 +f 2336 2406 2440 +f 971 1100 2343 +f 2299 2289 2257 +f 2299 2303 2289 +f 2249 2255 2243 +f 506 513 512 +f 2437 955 1219 +f 1587 2398 1324 +f 877 2396 2336 +f 2336 2396 2406 +f 2463 2479 879 +f 2376 2412 2350 +f 2281 2267 2268 +f 2303 2330 2289 +f 624 635 159 +f 1996 2356 1561 +f 2449 2436 1996 +f 2356 2054 2451 +f 928 2398 1587 +f 2333 2350 2262 +f 2035 26 2456 +f 2346 2342 2425 +f 2346 2345 2342 +f 1544 2380 2418 +f 2412 2392 2350 +f 622 509 1151 +f 2436 2054 1996 +f 545 2451 928 +f 2326 2341 2333 +f 2346 2425 2386 +f 1365 2035 2456 +f 2369 2377 2353 +f 2369 506 2377 +f 2451 900 928 +f 900 2398 928 +f 1235 1888 1244 +f 2337 2345 2346 +f 877 772 2396 +f 772 1275 2396 +f 2432 2446 2414 +f 2294 2295 2310 +f 2369 2330 828 +f 2418 2419 2436 +f 2450 2429 2436 +f 2436 2429 2054 +f 2490 2494 1656 +f 1321 155 2338 +f 1256 2346 2386 +f 2448 877 2345 +f 877 2448 772 +f 2446 2423 2414 +f 2351 2334 2363 +f 2243 2254 2269 +f 2380 2419 2418 +f 2419 2450 2436 +f 2283 2278 2264 +f 822 2197 823 +f 1008 1759 1565 +f 2448 2345 2337 +f 2270 2293 2276 +f 2323 2324 2328 +f 2429 1012 2054 +f 2226 2243 2213 +f 2395 325 772 +f 2370 2367 2380 +f 2054 2435 2451 +f 2435 2397 2451 +f 2451 2397 900 +f 1774 1974 1975 +f 2305 2290 2283 +f 846 2305 2283 +f 2320 1215 2285 +f 2139 2448 2337 +f 2448 2395 772 +f 1232 1231 1216 +f 2272 2285 2284 +f 2367 2371 2380 +f 2371 2405 2380 +f 2380 2405 2419 +f 2419 2429 2450 +f 2429 176 1012 +f 2397 2373 900 +f 2373 2398 900 +f 2373 1379 2398 +f 2372 1500 1508 +f 1133 1303 1142 +f 2252 2273 2272 +f 891 2252 2272 +f 2419 2405 2429 +f 2405 2430 2429 +f 2429 2430 176 +f 2189 2186 2181 +f 2212 2219 2218 +f 2312 2139 2337 +f 2139 2384 2448 +f 2448 2384 2395 +f 899 855 843 +f 2272 2273 2285 +f 2331 2303 2299 +f 176 2435 2054 +f 1012 176 2054 +f 2177 2185 2176 +f 2218 2219 2225 +f 1216 1220 1215 +f 2378 2139 2312 +f 2384 14 2395 +f 2324 2295 2255 +f 2240 2273 2252 +f 2371 2387 2405 +f 2410 2430 2405 +f 2430 2442 176 +f 2435 2344 2397 +f 2397 2344 2373 +f 2456 1888 2455 +f 2242 2267 2233 +f 2233 2262 2229 +f 2378 2384 2139 +f 2323 2310 2295 +f 2323 2322 2310 +f 2240 2274 2273 +f 974 841 990 +f 2490 1447 2486 +f 2387 2410 2405 +f 2442 2141 176 +f 2344 1778 2373 +f 972 1379 2373 +f 1778 972 2373 +f 1379 972 428 +f 1211 2437 1223 +f 1228 1215 1220 +f 702 2378 2312 +f 17 518 2415 +f 1888 26 1244 +f 2324 2323 2295 +f 2305 2311 2290 +f 2307 2285 2273 +f 2274 2307 2273 +f 2307 2320 2285 +f 2369 531 506 +f 2435 2258 2344 +f 2296 2324 2288 +f 1233 1217 2361 +f 2360 2371 2367 +f 2410 2442 2430 +f 176 2141 2258 +f 176 2258 2435 +f 539 2331 66 +f 2350 2392 2317 +f 2268 2225 2253 +f 1508 1500 2371 +f 2360 1508 2371 +f 2371 1500 2387 +f 972 2366 428 +f 1626 1686 1358 +f 1759 1807 1819 +f 2277 2257 2245 +f 2277 2299 2257 +f 1784 2228 1736 +f 2265 2240 1736 +f 2228 2265 1736 +f 2265 2274 2240 +f 1209 2320 2307 +f 2320 1209 1216 +f 1555 1584 1560 +f 2387 1500 2372 +f 2410 2420 2442 +f 2433 972 1778 +f 2433 2366 972 +f 955 522 1225 +f 2339 2307 2274 +f 2372 1493 2387 +f 2411 2420 2410 +f 2420 954 2442 +f 2442 954 2141 +f 2344 2433 1778 +f 2205 2212 2218 +f 2328 2334 2351 +f 2394 2401 2414 +f 2250 2256 2271 +f 2339 1209 2307 +f 2328 2322 2323 +f 866 845 2425 +f 3 316 893 +f 2387 2411 2410 +f 2441 2141 954 +f 2141 2441 2258 +f 2354 2433 2344 +f 2254 2294 2270 +f 2269 2254 2270 +f 863 2305 846 +f 2441 2354 2258 +f 2258 2354 2344 +f 2319 2355 51 +f 2223 2228 1784 +f 1493 2411 2387 +f 1560 2449 1555 +f 2288 2324 2255 +f 825 2251 2238 +f 2251 2245 2238 +f 1299 84 1312 +f 2246 2265 2228 +f 2313 2274 2265 +f 2313 2339 2274 +f 2251 2277 2245 +f 2319 51 2331 +f 891 1862 2252 +f 2443 954 2420 +f 2443 2441 954 +f 511 2447 2439 +f 2242 2233 2211 +f 188 15 814 +f 2443 2426 2441 +f 2426 2354 2441 +f 2306 2403 2433 +f 2433 2403 2366 +f 539 2303 2331 +f 2246 2228 2223 +f 1030 1819 1807 +f 2354 2306 2433 +f 2413 2412 2376 +f 2438 2455 1888 +f 1848 1857 2176 +f 2207 2208 2223 +f 2208 2246 2223 +f 1209 2339 1217 +f 2339 2361 1217 +f 1221 1210 2388 +f 554 109 78 +f 386 1375 95 +f 2327 2326 2318 +f 2179 2182 1393 +f 2182 2208 1393 +f 1393 2208 2207 +f 2361 2399 2388 +f 2388 2399 1211 +f 2306 2354 2426 +f 2403 2359 2366 +f 2214 2226 2213 +f 2268 2253 2276 +f 889 2200 2179 +f 2200 2182 2179 +f 2200 2221 2182 +f 2221 2208 2182 +f 2314 2265 2246 +f 2314 2313 2265 +f 2339 2374 2361 +f 2478 2434 2379 +f 2205 2217 2199 +f 2208 2259 2246 +f 2259 2275 2246 +f 2314 2321 2313 +f 2313 2347 2339 +f 2347 2374 2339 +f 2374 2399 2361 +f 153 154 2426 +f 154 2306 2426 +f 2385 2359 2403 +f 2221 2259 2208 +f 2306 2357 2403 +f 2357 2385 2403 +f 2237 2256 2231 +f 2172 2180 889 +f 2180 2200 889 +f 2200 2201 2221 +f 2246 2291 2314 +f 2374 2444 2399 +f 571 555 2311 +f 2192 2205 2199 +f 2173 2180 2172 +f 2279 2246 2275 +f 2279 2291 2246 +f 2292 2314 2291 +f 2321 2362 2313 +f 2362 2347 2313 +f 2347 2389 2374 +f 2444 955 2437 +f 2292 2291 2279 +f 2452 2444 2374 +f 2054 2356 1996 +f 2338 2306 154 +f 2186 2192 2191 +f 2193 2201 2200 +f 2259 2221 2201 +f 2247 2259 2201 +f 2452 955 2444 +f 2278 2277 2251 +f 2338 2357 2306 +f 2181 2186 2185 +f 2276 2326 2281 +f 2432 2457 2446 +f 2198 2201 2193 +f 2198 2232 2201 +f 2232 2247 2201 +f 2389 2452 2374 +f 2452 1630 955 +f 1403 1749 1444 +f 1555 1996 1561 +f 2357 2427 2385 +f 2385 2428 230 +f 2409 2415 2424 +f 2304 2331 2299 +f 2193 2200 2180 +f 2445 2452 2389 +f 1565 1759 1927 +f 2380 1544 2370 +f 2338 2427 2357 +f 2427 2428 2385 +f 230 222 253 +f 2202 2198 2193 +f 2202 2209 2198 +f 2209 2241 2198 +f 2241 2232 2198 +f 2266 2275 2259 +f 2365 1340 1128 +f 2415 518 2424 +f 2338 170 2427 +f 170 2428 2427 +f 2181 2185 2177 +f 2196 2195 2189 +f 2183 2193 2180 +f 2453 1630 2452 +f 2197 2214 2189 +f 2401 2409 2414 +f 822 2220 2197 +f 1210 2361 2388 +f 2187 2193 2183 +f 2187 2202 2193 +f 2266 2279 2275 +f 2279 2300 2292 +f 2375 2347 2362 +f 2375 2390 2347 +f 2390 2389 2347 +f 2453 2452 2445 +f 1347 1630 2453 +f 1630 1347 522 +f 2220 2206 2197 +f 2262 2350 2286 +f 170 254 2428 +f 2457 1973 2446 +f 1973 1365 2446 +f 2174 2183 2180 +f 2194 2202 2187 +f 2222 2241 2209 +f 2222 2260 2241 +f 2266 2259 2247 +f 2390 2445 2389 +f 2264 2251 825 +f 2363 2368 2351 +f 2326 2393 2341 +f 1855 1850 1851 +f 2210 2209 2202 +f 2210 2222 2209 +f 2261 2260 2222 +f 2280 2279 2266 +f 2280 2300 2279 +f 251 263 2359 +f 2277 2304 2299 +f 2220 2230 2206 +f 2202 2194 2210 +f 2213 2243 2234 +f 2328 2327 2322 +f 2294 2310 2293 +f 2214 2196 2189 +f 2196 2213 2219 +f 2224 2222 2210 +f 2421 2390 2375 +f 2206 2230 2214 +f 2194 2203 2210 +f 2224 2261 2222 +f 2421 2445 2390 +f 2322 2327 2318 +f 2393 2408 2341 +f 1365 1973 510 +f 2216 2210 2203 +f 2216 2224 2210 +f 2266 2308 2280 +f 2280 2308 2300 +f 2407 2421 2375 +f 2175 2183 2174 +f 2194 2190 2203 +f 2454 2445 2421 +f 522 1347 523 +f 2456 2455 2423 +f 823 2197 2178 +f 2281 2333 2287 +f 2188 2187 2183 +f 2188 2190 2194 +f 2187 2188 2194 +f 2308 2315 2300 +f 2407 2375 2362 +f 2443 2420 2503 +f 2420 2411 2503 +f 2411 1493 2503 +f 1493 1487 2503 +f 1487 1318 2503 +f 1318 1320 2503 +f 1320 2443 2503 diff --git a/A1/resources/sphere.obj b/A1/resources/sphere.obj new file mode 100644 index 0000000..698f5ce --- /dev/null +++ b/A1/resources/sphere.obj @@ -0,0 +1,204 @@ +#### +# +# OBJ File Generated by LightWave3D +# LightWave3D OBJ Export v2.2 +# +#### +# +# Vertices: 62 +# Points: 0 +# Lines: 0 +# Faces: 120 +# Materials: 1 +# +#### + +# Vertex list + +v 0 -0.5 -0 +v 0.25 -0.433013 -0 +v 0.216506 -0.433013 -0.125 +v 0.125 -0.433013 -0.216506 +v 0 -0.433013 -0.25 +v -0.125 -0.433013 -0.216506 +v -0.216506 -0.433013 -0.125 +v -0.25 -0.433013 -0 +v -0.216506 -0.433013 0.125 +v -0.125 -0.433013 0.216506 +v 0 -0.433013 0.25 +v 0.125 -0.433013 0.216506 +v 0.216506 -0.433013 0.125 +v 0.433013 -0.25 -0 +v 0.375 -0.25 -0.216506 +v 0.216506 -0.25 -0.375 +v 0 -0.25 -0.433013 +v -0.216506 -0.25 -0.375 +v -0.375 -0.25 -0.216506 +v -0.433013 -0.25 -0 +v -0.375 -0.25 0.216506 +v -0.216506 -0.25 0.375 +v 0 -0.25 0.433013 +v 0.216506 -0.25 0.375 +v 0.375 -0.25 0.216506 +v 0.5 2.55171e-12 -0 +v 0.433013 2.55171e-12 -0.25 +v 0.25 2.55171e-12 -0.433013 +v 0 2.55171e-12 -0.5 +v -0.25 2.55171e-12 -0.433013 +v -0.433013 2.55171e-12 -0.25 +v -0.5 2.55171e-12 -0 +v -0.433013 2.55171e-12 0.25 +v -0.25 2.55171e-12 0.433013 +v 0 2.55171e-12 0.5 +v 0.25 2.55171e-12 0.433013 +v 0.433013 2.55171e-12 0.25 +v 0.433013 0.25 -0 +v 0.375 0.25 -0.216506 +v 0.216506 0.25 -0.375 +v 0 0.25 -0.433013 +v -0.216506 0.25 -0.375 +v -0.375 0.25 -0.216506 +v -0.433013 0.25 -0 +v -0.375 0.25 0.216506 +v -0.216506 0.25 0.375 +v 0 0.25 0.433013 +v 0.216506 0.25 0.375 +v 0.375 0.25 0.216506 +v 0.25 0.433013 -0 +v 0.216506 0.433013 -0.125 +v 0.125 0.433013 -0.216506 +v 0 0.433013 -0.25 +v -0.125 0.433013 -0.216506 +v -0.216506 0.433013 -0.125 +v -0.25 0.433013 -0 +v -0.216506 0.433013 0.125 +v -0.125 0.433013 0.216506 +v 0 0.433013 0.25 +v 0.125 0.433013 0.216506 +v 0.216506 0.433013 0.125 +v 5.10341e-12 0.5 -0 + +# Face list + +f 3 2 1 +f 4 3 1 +f 5 4 1 +f 6 5 1 +f 7 6 1 +f 8 7 1 +f 9 8 1 +f 10 9 1 +f 11 10 1 +f 12 11 1 +f 13 12 1 +f 2 13 1 +f 3 14 2 +f 15 14 3 +f 4 15 3 +f 16 15 4 +f 17 16 4 +f 5 17 4 +f 17 5 6 +f 18 17 6 +f 18 6 7 +f 19 18 7 +f 20 7 8 +f 20 19 7 +f 20 8 9 +f 21 20 9 +f 21 9 10 +f 22 21 10 +f 23 10 11 +f 23 22 10 +f 12 23 11 +f 24 23 12 +f 13 24 12 +f 25 24 13 +f 14 25 13 +f 2 14 13 +f 15 26 14 +f 27 26 15 +f 28 27 15 +f 16 28 15 +f 29 28 16 +f 17 29 16 +f 29 17 18 +f 30 29 18 +f 31 18 19 +f 31 30 18 +f 32 19 20 +f 32 31 19 +f 32 20 21 +f 33 32 21 +f 34 21 22 +f 34 33 21 +f 35 22 23 +f 35 34 22 +f 24 35 23 +f 36 35 24 +f 37 36 24 +f 25 37 24 +f 26 37 25 +f 14 26 25 +f 39 38 26 +f 27 39 26 +f 28 39 27 +f 40 39 28 +f 29 40 28 +f 41 40 29 +f 42 29 30 +f 42 41 29 +f 43 30 31 +f 43 42 30 +f 43 31 32 +f 44 43 32 +f 45 32 33 +f 45 44 32 +f 45 33 34 +f 46 45 34 +f 46 34 35 +f 47 46 35 +f 48 47 35 +f 36 48 35 +f 49 48 36 +f 37 49 36 +f 26 49 37 +f 38 49 26 +f 39 50 38 +f 51 50 39 +f 40 51 39 +f 52 51 40 +f 53 52 40 +f 41 53 40 +f 53 41 42 +f 54 53 42 +f 55 42 43 +f 55 54 42 +f 56 43 44 +f 56 55 43 +f 56 44 45 +f 57 56 45 +f 58 45 46 +f 58 57 45 +f 58 46 47 +f 59 58 47 +f 60 59 47 +f 48 60 47 +f 49 60 48 +f 61 60 49 +f 50 61 49 +f 38 50 49 +f 51 62 50 +f 52 62 51 +f 53 62 52 +f 62 53 54 +f 62 54 55 +f 62 55 56 +f 62 56 57 +f 62 57 58 +f 62 58 59 +f 60 62 59 +f 61 62 60 +f 50 62 61 + +# End of file diff --git a/A1/resources/teapot.obj b/A1/resources/teapot.obj new file mode 100644 index 0000000..6fed453 --- /dev/null +++ b/A1/resources/teapot.obj @@ -0,0 +1,5049 @@ +# Blender v2.65 (sub 0) OBJ File +# www.blender.org +o teapot.005 +v -0.498530 0.712498 -0.039883 +v -0.501666 0.699221 -0.063813 +v -0.501255 0.717792 0.000000 +v -0.624036 0.711938 -0.039883 +v -0.526706 0.651362 -0.039883 +v -0.508714 0.682112 -0.071712 +v -0.622039 0.698704 -0.063813 +v -0.624834 0.717232 0.000000 +v -0.498530 0.712498 0.039883 +v -0.638129 0.287158 0.000000 +v -0.517593 0.664661 -0.063813 +v -0.534329 0.646030 0.000000 +v -0.614850 0.651067 -0.039883 +v -0.616848 0.664299 -0.063813 +v -0.619445 0.681503 -0.071790 +v -0.741245 0.707456 -0.039883 +v -0.744483 0.712577 0.000000 +v -0.624036 0.711938 0.039883 +v -0.501667 0.699221 0.063813 +v -0.622039 0.698704 0.063813 +v -0.712095 0.661370 -0.063813 +v -0.733150 0.694655 -0.063813 +v -0.741245 0.707456 0.039883 +v -0.733150 0.694655 0.063813 +v -0.631184 0.277569 -0.039883 +v -0.526706 0.651362 0.039883 +v -0.614053 0.645774 0.000000 +v -0.704000 0.648569 -0.039883 +v -0.722621 0.678012 -0.071790 +v -0.832523 0.695296 -0.039883 +v -0.837545 0.699948 0.000000 +v -0.832523 0.695296 0.039883 +v -0.619445 0.681503 0.071790 +v -0.508714 0.682112 0.071712 +v -0.722621 0.678012 0.071790 +v -0.517593 0.664661 0.063813 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.710066 0.328372 0.000000 +v -0.614850 0.651067 0.039883 +v -0.787321 0.653419 -0.063813 +v -0.803644 0.668539 -0.071790 +v -0.819967 0.683663 -0.063813 +v -0.819967 0.683663 0.063813 +v -0.803644 0.668539 0.071790 +v -0.711425 0.307332 -0.063813 +v -0.615553 0.216807 -0.063813 +v -0.712688 0.287795 -0.071790 +v -0.631184 0.277569 0.039883 +v -0.710455 0.322361 -0.039883 +v -0.710455 0.322361 0.039883 +v -0.700762 0.643448 0.000000 +v -0.774766 0.641786 -0.039883 +v -0.897800 0.671612 -0.039883 +v -0.904015 0.675354 0.000000 +v -0.897800 0.671612 0.039883 +v -0.882265 0.662257 0.063813 +v -0.712095 0.661370 0.063813 +v -0.787321 0.653419 0.063813 +v -0.608884 0.198682 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.766936 0.377559 0.000000 +v -0.769651 0.372307 0.039883 +v -0.616848 0.664299 0.063813 +v -0.704000 0.648569 0.039883 +v -0.841868 0.637931 -0.063813 +v -0.862065 0.650094 -0.071790 +v -0.882265 0.662257 -0.063813 +v -0.862065 0.650094 0.071790 +v -0.841868 0.637931 0.063813 +v -0.611709 0.194244 0.000000 +v -0.776434 0.359177 -0.063813 +v -0.769651 0.372307 -0.039883 +v -0.713952 0.268259 -0.063813 +v -0.711425 0.307332 0.063813 +v -0.776434 0.359177 0.063813 +v -0.769743 0.637131 0.000000 +v -0.826329 0.628576 -0.039883 +v -0.937016 0.632565 -0.039883 +v -0.943899 0.634805 0.000000 +v -0.937016 0.632565 0.039883 +v -0.919812 0.626965 0.063813 +v -0.897443 0.619684 0.071790 +v -0.774766 0.641786 0.039883 +v -0.826329 0.628576 0.039883 +v -0.714922 0.253231 -0.039883 +v -0.608883 0.198681 0.039883 +v -0.715311 0.247220 0.000000 +v -0.785253 0.342107 -0.071790 +v -0.619922 0.238069 0.071790 +v -0.712688 0.287795 0.071790 +v -0.809626 0.430737 0.000000 +v -0.814205 0.426194 0.039883 +v -0.825653 0.414838 0.063813 +v -0.875076 0.612403 -0.063813 +v -0.897443 0.619684 -0.071790 +v -0.919812 0.626965 -0.063813 +v -0.875076 0.612403 0.063813 +v -0.857869 0.606800 0.039883 +v -0.794072 0.325038 -0.063813 +v -0.800855 0.311909 -0.039883 +v -0.825653 0.414838 -0.063813 +v -0.814205 0.426194 -0.039883 +v -0.615480 0.216617 0.063578 +v -0.785253 0.342107 0.071790 +v -0.840534 0.400078 0.071790 +v -0.820114 0.624834 0.000000 +v -0.857869 0.606800 -0.039883 +v -0.950104 0.574316 -0.039883 +v -0.957194 0.574316 0.000000 +v -0.950104 0.574316 0.039883 +v -0.932377 0.574316 0.063813 +v -0.909334 0.574316 0.071790 +v -0.886292 0.574316 0.063813 +v -0.850987 0.604560 0.000000 +v -0.714922 0.253231 0.039883 +v -0.803571 0.306656 0.000000 +v -0.840534 0.400078 -0.071790 +v -0.713952 0.268259 0.063813 +v -0.794072 0.325038 0.063813 +v -0.839022 0.483916 0.000000 +v -0.844976 0.480304 0.039883 +v -0.859854 0.471278 0.063813 +v -0.879202 0.459542 0.071790 +v -0.886292 0.574316 -0.063813 +v -0.909334 0.574316 -0.071790 +v -0.932377 0.574316 -0.063813 +v -0.868564 0.574316 0.039883 +v -0.861474 0.574316 0.000000 +v -0.855419 0.385315 -0.063813 +v -0.866867 0.373960 -0.039883 +v -0.859854 0.471278 -0.063813 +v -0.844976 0.480304 -0.039883 +v -0.855419 0.385315 0.063813 +v -0.898547 0.447807 0.063813 +v -0.868564 0.574316 -0.039883 +v -0.941014 0.505765 -0.039883 +v -0.947813 0.503580 0.000000 +v -0.941014 0.505765 0.039883 +v -0.924011 0.511234 0.063813 +v -0.901913 0.518343 0.071790 +v -0.879811 0.525448 0.063813 +v -0.862808 0.530917 0.039883 +v -0.800855 0.311909 0.039883 +v -0.871445 0.369416 0.000000 +v -0.879202 0.459542 -0.071790 +v -0.866867 0.373960 0.039883 +v -0.856009 0.533103 0.000000 +v -0.879811 0.525448 -0.063813 +v -0.901913 0.518343 -0.071790 +v -0.924011 0.511234 -0.063813 +v -0.862808 0.530917 -0.039883 +v -0.898547 0.447807 -0.063813 +v -0.913428 0.438781 -0.039883 +v -0.913428 0.438781 0.039883 +v -0.919378 0.435169 0.000000 +v 0.600960 0.444810 0.085753 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.656890 0.471064 0.000000 +v 0.661223 0.454734 -0.083705 +v 0.730696 0.501576 -0.073611 +v 0.661223 0.454734 0.083705 +v 0.605101 0.399712 -0.137265 +v 0.746455 0.470391 -0.117778 +v 0.724395 0.514048 0.000000 +v 0.605100 0.399712 0.137265 +v 0.672055 0.413907 -0.133928 +v 0.613258 0.341675 -0.154354 +v 0.786583 0.544847 -0.096783 +v 0.768856 0.565896 -0.060489 +v 0.672055 0.413907 0.133928 +v 0.730696 0.501576 0.073611 +v 0.686135 0.360830 -0.150669 +v 0.809626 0.517481 -0.108881 +v 0.766935 0.429850 -0.132501 +v 0.761767 0.574316 0.000000 +v 0.613258 0.341675 0.154354 +v 0.813417 0.626247 -0.075788 +v 0.839021 0.611098 -0.085261 +v 0.793721 0.637899 -0.047367 +v 0.686135 0.360830 0.150669 +v 0.768856 0.565896 0.060489 +v 0.746455 0.470391 0.117778 +v 0.619427 0.283145 -0.137236 +v 0.864627 0.595949 -0.075788 +v 0.832669 0.490118 -0.096783 +v 0.787419 0.389310 -0.117778 +v 0.785843 0.642561 0.000000 +v 0.619427 0.283145 0.137236 +v 0.700219 0.307756 -0.133928 +v 0.847933 0.703560 -0.059638 +v 0.879938 0.698065 -0.067092 +v 0.911944 0.692571 -0.059638 +v 0.823314 0.707784 -0.037273 +v 0.766935 0.429850 0.132501 +v 0.793721 0.637899 0.047367 +v 0.786583 0.544847 0.096783 +v 0.700219 0.307756 0.133928 +v 0.617684 0.235930 -0.085941 +v 0.936563 0.688344 -0.037273 +v 0.884319 0.584297 -0.047367 +v 0.850396 0.469070 -0.060489 +v 0.803175 0.358128 -0.073611 +v 0.813468 0.709475 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v 0.711051 0.266929 -0.083705 +v 0.911107 0.765755 -0.053178 +v 0.957193 0.765755 -0.059825 +v 1.003279 0.765755 -0.053178 +v 1.038733 0.765755 -0.033236 +v 0.875654 0.765755 -0.033236 +v 0.809626 0.517481 0.108881 +v 0.787419 0.389310 0.117778 +v 0.823314 0.707784 0.037273 +v 0.813417 0.626247 0.075788 +v 0.711051 0.266929 0.083705 +v 0.715384 0.250599 0.000000 +v 1.052913 0.765755 0.000000 +v 0.946409 0.686653 0.000000 +v 0.892200 0.579635 0.000000 +v 0.857486 0.460650 0.000000 +v 0.809479 0.345652 0.000000 +v 0.861474 0.765755 0.000000 +v 0.929990 0.776479 -0.051602 +v 0.979075 0.777181 -0.058052 +v 1.028157 0.777879 -0.051602 +v 1.065915 0.778419 -0.032251 +v 1.081016 0.778632 0.000000 +v 0.892235 0.775943 -0.032251 +v 0.839021 0.611098 0.085261 +v 0.832669 0.490118 0.096783 +v 0.803175 0.358128 0.073611 +v 0.875654 0.765755 0.033236 +v 0.847933 0.703560 0.059638 +v 1.065915 0.778419 0.032174 +v 1.038733 0.765755 0.033236 +v 0.936563 0.688344 0.037273 +v 0.884319 0.584297 0.047367 +v 0.850396 0.469070 0.060489 +v 0.877131 0.775726 0.000000 +v 0.943713 0.783087 -0.047663 +v 0.992645 0.784366 -0.053621 +v 1.041577 0.785649 -0.047663 +v 1.079216 0.786631 -0.029789 +v 1.094273 0.787027 0.000000 +v 1.079216 0.786631 0.029174 +v 0.906073 0.782101 -0.029789 +v 0.879938 0.698065 0.067092 +v 0.864627 0.595949 0.075788 +v 0.892235 0.775943 0.032236 +v 0.911107 0.765755 0.053178 +v 1.041577 0.785649 0.046875 +v 1.028157 0.777879 0.051503 +v 1.003279 0.765755 0.053178 +v 0.911944 0.692571 0.059638 +v 0.891016 0.781708 0.000000 +v 0.951249 0.785448 -0.042542 +v 0.997575 0.787068 -0.047860 +v 1.043903 0.788686 -0.042542 +v 1.079539 0.789934 -0.026589 +v 1.093795 0.790431 0.000000 +v 1.079539 0.789934 0.024511 +v 1.043903 0.788686 0.039883 +v 0.915613 0.784200 -0.026589 +v 0.957193 0.765755 0.059825 +v 0.906073 0.782101 0.029666 +v 0.929990 0.776479 0.051553 +v 0.997575 0.787068 0.045616 +v 0.992645 0.784366 0.052956 +v 0.979075 0.777181 0.057969 +v 0.901357 0.783702 0.000000 +v 0.951569 0.783431 -0.037421 +v 0.993532 0.785033 -0.042099 +v 1.035492 0.786631 -0.037421 +v 1.067772 0.787863 -0.023388 +v 1.080684 0.788354 0.000000 +v 1.067772 0.787863 0.018464 +v 1.035492 0.786631 0.031119 +v 0.993532 0.785033 0.036781 +v 0.919292 0.782200 -0.023388 +v 0.915613 0.784200 0.026173 +v 0.943713 0.783087 0.047269 +v 0.951569 0.783431 0.034270 +v 0.951249 0.785448 0.041213 +v 0.906379 0.781708 0.000000 +v 0.943653 0.776909 -0.033482 +v 0.980182 0.778010 -0.037667 +v 1.016712 0.779111 -0.033482 +v 1.044812 0.779957 -0.020926 +v 1.056052 0.780295 0.000000 +v 1.044812 0.779957 0.011310 +v 1.016712 0.779111 0.021172 +v 0.980182 0.778010 0.027281 +v 0.943653 0.776909 0.027327 +v 0.915553 0.776064 -0.020926 +v 0.919292 0.782200 0.022403 +v 0.915553 0.776064 0.019003 +v 0.904312 0.775726 0.000000 +v 0.926468 0.765755 -0.031906 +v 0.957193 0.765755 -0.035895 +v 0.987920 0.765755 -0.031906 +v 1.011552 0.765755 -0.019942 +v 1.021006 0.765755 0.000000 +v 1.011552 0.765755 0.003324 +v 0.987920 0.765755 0.010635 +v 0.957193 0.765755 0.017947 +v 0.926468 0.765755 0.021271 +v 0.902834 0.765755 0.016618 +v 0.902834 0.765755 -0.019942 +v 0.893380 0.765755 0.000000 +v 0.886428 0.750924 -0.019014 +v 0.908324 0.750924 -0.030099 +v 0.936793 0.750924 -0.033795 +v 0.965261 0.750924 -0.030099 +v 0.987158 0.750924 -0.019014 +v 0.995918 0.750924 -0.000537 +v 0.987158 0.750924 0.002542 +v 0.965261 0.750924 0.009317 +v 0.936793 0.750924 0.016092 +v 0.908324 0.750924 0.019171 +v 0.886428 0.750924 0.014860 +v 0.877668 0.750924 -0.000537 +v 0.936793 0.750924 -0.007312 +v 0.440746 0.783205 0.000000 +v 0.446690 0.765755 0.000000 +v 0.430973 0.765755 0.119945 +v 0.425236 0.783205 0.118348 +v 0.425236 0.783205 -0.118348 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 0.121642 +v 0.441668 0.793673 0.000000 +v 0.386470 0.765755 0.226985 +v 0.430973 0.765755 -0.119945 +v 0.426127 0.793673 -0.118596 +v 0.437073 0.750009 -0.121642 +v 0.426127 0.793673 0.118596 +v 0.381327 0.783205 0.223964 +v 0.381327 0.783205 -0.223964 +v 0.382124 0.793673 -0.224433 +v 0.317150 0.765755 0.317150 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 0.321639 +v 0.386470 0.765755 -0.226985 +v 0.391939 0.750009 -0.230197 +v 0.447686 0.797164 0.000000 +v 0.431936 0.797164 -0.120212 +v 0.387332 0.797164 -0.227491 +v 0.230197 0.750009 0.391940 +v 0.226984 0.765755 0.386470 +v 0.317150 0.765755 -0.317150 +v 0.321638 0.750009 -0.321639 +v 0.431936 0.797164 0.120212 +v 0.382124 0.793673 0.224433 +v 0.312929 0.783205 0.312929 +v 0.313584 0.793673 -0.313584 +v 0.312929 0.783205 -0.312929 +v 0.317858 0.797164 -0.317858 +v 0.121642 0.750009 0.437072 +v 0.119944 0.765755 0.430973 +v 0.226984 0.765755 -0.386470 +v 0.230197 0.750009 -0.391940 +v 0.457031 0.793673 0.000000 +v 0.440950 0.793673 -0.122721 +v 0.395416 0.793673 -0.232239 +v 0.324491 0.793673 -0.324492 +v -0.000000 0.750009 0.453012 +v -0.000000 0.765755 0.446690 +v 0.223963 0.783205 0.381327 +v 0.223963 0.783205 -0.381327 +v 0.119944 0.765755 -0.430973 +v 0.121642 0.750009 -0.437072 +v 0.440950 0.793673 0.122721 +v 0.387332 0.797164 0.227491 +v 0.313584 0.793673 0.313584 +v 0.227491 0.797164 -0.387332 +v 0.224433 0.793673 -0.382125 +v 0.232239 0.793673 -0.395417 +v -0.119945 0.765755 0.430973 +v -0.121642 0.750009 0.437072 +v 0.118348 0.783205 0.425237 +v 0.118348 0.783205 -0.425237 +v -0.000000 0.750009 -0.453012 +v -0.000000 0.765755 -0.446690 +v 0.467924 0.783205 0.000000 +v 0.451460 0.783205 -0.125646 +v 0.404842 0.783205 -0.237775 +v 0.332226 0.783205 -0.332226 +v 0.237775 0.783205 -0.404842 +v -0.226985 0.765755 0.386470 +v -0.000000 0.783205 0.440746 +v 0.224433 0.793673 0.382125 +v 0.118596 0.793673 -0.426127 +v -0.000000 0.783205 -0.440746 +v -0.119945 0.765755 -0.430973 +v -0.121642 0.750009 -0.437072 +v 0.451460 0.783205 0.125646 +v 0.395416 0.793673 0.232239 +v 0.317858 0.797164 0.317858 +v 0.122721 0.793673 -0.440950 +v 0.120212 0.797164 -0.431937 +v 0.125646 0.783205 -0.451460 +v -0.317150 0.765755 0.317150 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.118348 0.783205 0.425237 +v 0.118596 0.793673 0.426127 +v -0.000000 0.793673 -0.441668 +v -0.118348 0.783205 -0.425237 +v -0.226985 0.765755 -0.386470 +v 0.478596 0.765755 0.000000 +v 0.461756 0.765755 -0.128512 +v 0.414076 0.765755 -0.243198 +v 0.339803 0.765755 -0.339804 +v 0.243198 0.765755 -0.414076 +v 0.128512 0.765755 -0.461757 +v -0.391940 0.750009 0.230197 +v -0.386470 0.765755 0.226985 +v -0.223964 0.783205 0.381327 +v -0.000000 0.793673 0.441668 +v 0.227491 0.797164 0.387332 +v -0.000000 0.797164 -0.447686 +v -0.118596 0.793673 -0.426127 +v -0.223964 0.783205 -0.381327 +v -0.317150 0.765755 -0.317150 +v -0.230198 0.750009 -0.391939 +v -0.321639 0.750009 -0.321639 +v 0.461756 0.765755 0.128512 +v 0.404842 0.783205 0.237775 +v 0.324491 0.793673 0.324492 +v -0.000000 0.783205 -0.467924 +v -0.000000 0.793673 -0.457031 +v -0.000000 0.765755 -0.478597 +v -0.437073 0.750009 0.121642 +v -0.430974 0.765755 0.119945 +v -0.312929 0.783205 0.312929 +v -0.118596 0.793673 0.426127 +v 0.120212 0.797164 0.431937 +v -0.120212 0.797164 -0.431937 +v -0.224433 0.793673 -0.382125 +v -0.312929 0.783205 -0.312929 +v -0.386470 0.765755 -0.226985 +v -0.391940 0.750009 -0.230197 +v 0.518110 0.682112 0.000000 +v 0.499881 0.682112 -0.139122 +v 0.448260 0.682112 -0.263277 +v 0.367859 0.682112 -0.367859 +v 0.263277 0.682112 -0.448260 +v 0.139122 0.682112 -0.499882 +v -0.000000 0.682112 -0.518110 +v -0.453012 0.750009 0.000000 +v -0.446690 0.765755 0.000000 +v -0.381327 0.783205 0.223964 +v -0.224433 0.793673 0.382125 +v -0.000000 0.797164 0.447686 +v 0.232239 0.793673 0.395417 +v -0.122721 0.793673 -0.440950 +v -0.227491 0.797164 -0.387332 +v -0.313584 0.793673 -0.313584 +v -0.381327 0.783205 -0.223964 +v -0.430974 0.765755 -0.119945 +v 0.499881 0.682112 0.139122 +v 0.414076 0.765755 0.243198 +v 0.332226 0.783205 0.332226 +v -0.128513 0.765755 -0.461757 +v -0.125646 0.783205 -0.451460 +v -0.139123 0.682112 -0.499882 +v -0.437073 0.750009 -0.121642 +v -0.425237 0.783205 0.118348 +v -0.313584 0.793673 0.313584 +v -0.120212 0.797164 0.431937 +v 0.122721 0.793673 0.440950 +v -0.232240 0.793673 -0.395417 +v -0.317859 0.797164 -0.317858 +v -0.382125 0.793673 -0.224433 +v -0.425237 0.783205 -0.118348 +v 0.555408 0.599133 0.000000 +v 0.535865 0.599133 -0.149137 +v 0.480530 0.599133 -0.282230 +v 0.394341 0.599133 -0.394341 +v 0.282230 0.599133 -0.480530 +v 0.149137 0.599133 -0.535866 +v -0.000000 0.599133 -0.555408 +v -0.149138 0.599133 -0.535866 +v -0.440746 0.783205 0.000000 +v -0.382125 0.793673 0.224433 +v -0.227491 0.797164 0.387332 +v -0.000000 0.793673 0.457031 +v 0.237775 0.783205 0.404842 +v -0.237775 0.783205 -0.404842 +v -0.324492 0.793673 -0.324492 +v -0.387332 0.797164 -0.227491 +v -0.426127 0.793673 -0.118596 +v 0.535865 0.599133 0.149137 +v 0.448260 0.682112 0.263277 +v 0.339803 0.765755 0.339804 +v -0.263278 0.682112 -0.448260 +v -0.243198 0.765755 -0.414076 +v -0.282230 0.599133 -0.480530 +v -0.426127 0.793673 0.118596 +v -0.317859 0.797164 0.317858 +v -0.122721 0.793673 0.440950 +v 0.125646 0.783205 0.451460 +v -0.332226 0.783205 -0.332226 +v -0.395417 0.793673 -0.232239 +v -0.431937 0.797164 -0.120212 +v -0.441668 0.793673 0.000000 +v 0.588275 0.517481 0.000000 +v 0.567578 0.517481 -0.157963 +v 0.508969 0.517485 -0.298931 +v 0.417675 0.517481 -0.417675 +v 0.298931 0.517485 -0.508969 +v 0.157963 0.517485 -0.567578 +v -0.000000 0.517481 -0.588275 +v -0.157963 0.517481 -0.567578 +v -0.298931 0.517485 -0.508969 +v -0.387332 0.797164 0.227491 +v -0.232240 0.793673 0.395417 +v -0.000000 0.783205 0.467924 +v 0.243198 0.765755 0.414076 +v -0.339804 0.765755 -0.339804 +v -0.404842 0.783205 -0.237775 +v -0.440950 0.793673 -0.122721 +v -0.447686 0.797164 0.000000 +v 0.567578 0.517485 0.157963 +v 0.480530 0.599133 0.282230 +v 0.367859 0.682112 0.367859 +v -0.394341 0.599133 -0.394341 +v -0.367859 0.682112 -0.367859 +v -0.417675 0.517481 -0.417675 +v -0.431937 0.797164 0.120212 +v -0.324492 0.793673 0.324492 +v -0.125646 0.783205 0.451460 +v 0.128512 0.765755 0.461757 +v -0.414076 0.765755 -0.243198 +v -0.451461 0.783205 -0.125646 +v -0.457031 0.793673 0.000000 +v 0.592873 0.437827 -0.165003 +v 0.531651 0.437827 -0.312254 +v 0.436292 0.437827 -0.436292 +v 0.312254 0.437827 -0.531651 +v 0.165003 0.437827 -0.592873 +v -0.000000 0.437827 -0.614496 +v -0.165004 0.437827 -0.592873 +v -0.312255 0.437827 -0.531651 +v -0.436292 0.437827 -0.436292 +v -0.395417 0.793673 0.232239 +v -0.237775 0.783205 0.404842 +v -0.000000 0.765755 0.478597 +v 0.263277 0.682112 0.448260 +v -0.448260 0.682112 -0.263277 +v -0.461757 0.765755 -0.128512 +v -0.467924 0.783205 0.000000 +v -0.440950 0.793673 0.122721 +v 0.592873 0.437827 0.165003 +v 0.508969 0.517485 0.298931 +v 0.394341 0.599133 0.394341 +v -0.508969 0.517485 -0.298931 +v -0.480530 0.599133 -0.282230 +v -0.531651 0.437827 -0.312254 +v -0.332226 0.783205 0.332226 +v -0.128513 0.765755 0.461757 +v 0.139122 0.682112 0.499882 +v -0.499882 0.682112 -0.139122 +v -0.478597 0.765755 0.000000 +v -0.451461 0.783205 0.125646 +v 0.546669 0.360830 -0.321075 +v 0.448614 0.360830 -0.448614 +v 0.321074 0.360830 -0.546669 +v 0.169664 0.360830 -0.609621 +v -0.000000 0.360830 -0.631850 +v -0.169664 0.360830 -0.609621 +v -0.321075 0.360830 -0.546669 +v -0.448615 0.360830 -0.448614 +v -0.546669 0.360830 -0.321075 +v -0.404842 0.783205 0.237775 +v -0.243198 0.765755 0.414076 +v -0.000000 0.682112 0.518110 +v 0.282230 0.599133 0.480530 +v -0.535866 0.599133 -0.149137 +v -0.461757 0.765755 0.128512 +v 0.531651 0.437827 0.312254 +v 0.417675 0.517481 0.417675 +v 0.609621 0.360830 -0.169664 +v -0.592873 0.437827 -0.165003 +v -0.567578 0.517485 -0.157963 +v -0.609621 0.360830 -0.169664 +v -0.339804 0.765755 0.339804 +v -0.139123 0.682112 0.499882 +v 0.149137 0.599133 0.535866 +v -0.555408 0.599133 0.000000 +v -0.499882 0.682112 0.139122 +v -0.414076 0.765755 0.243198 +v 0.609621 0.360830 0.169664 +v 0.552100 0.287158 -0.324265 +v 0.453072 0.287158 -0.453072 +v 0.324265 0.287158 -0.552100 +v 0.171349 0.287158 -0.615677 +v -0.000000 0.287158 -0.638129 +v -0.171350 0.287158 -0.615677 +v -0.324265 0.287158 -0.552100 +v -0.453072 0.287158 -0.453072 +v -0.552100 0.287158 -0.324265 +v -0.615677 0.287158 -0.171349 +v -0.263278 0.682112 0.448260 +v -0.000000 0.599133 0.555408 +v 0.298931 0.517485 0.508969 +v -0.588275 0.517481 0.000000 +v -0.448260 0.682112 0.263277 +v 0.546669 0.360830 0.321075 +v 0.436292 0.437827 0.436292 +v 0.615677 0.287158 -0.171349 +v -0.631850 0.360830 0.000000 +v -0.614496 0.437827 0.000000 +v -0.367859 0.682112 0.367859 +v -0.149138 0.599133 0.535866 +v 0.157963 0.517481 0.567578 +v -0.567578 0.517481 0.157963 +v -0.480530 0.599133 0.282230 +v 0.615677 0.287158 0.171349 +v 0.541877 0.221240 -0.318259 +v 0.444680 0.221240 -0.444680 +v 0.318259 0.221240 -0.541877 +v 0.168176 0.221240 -0.604276 +v -0.000000 0.221240 -0.626311 +v -0.168177 0.221240 -0.604276 +v -0.318259 0.221240 -0.541877 +v -0.444680 0.221240 -0.444680 +v -0.541877 0.221240 -0.318259 +v -0.604277 0.221240 -0.168176 +v -0.282230 0.599133 0.480530 +v -0.000000 0.517481 0.588275 +v 0.312254 0.437827 0.531651 +v -0.592873 0.437827 0.165003 +v -0.535866 0.599133 0.149137 +v -0.394341 0.599133 0.394341 +v 0.552100 0.287158 0.324265 +v 0.448614 0.360830 0.448614 +v 0.604276 0.221240 -0.168176 +v -0.615677 0.287158 0.171349 +v -0.609621 0.360830 0.169664 +v -0.157963 0.517485 0.567578 +v 0.165003 0.437827 0.592873 +v -0.531651 0.437827 0.312254 +v -0.508969 0.517485 0.298931 +v -0.417675 0.517481 0.417675 +v 0.604276 0.221240 0.168176 +v 0.516317 0.166623 -0.303247 +v 0.423705 0.166623 -0.423705 +v 0.303247 0.166623 -0.516317 +v 0.160243 0.166623 -0.575771 +v -0.000000 0.166623 -0.596769 +v -0.160244 0.166623 -0.575771 +v -0.303247 0.166623 -0.516317 +v -0.423705 0.166623 -0.423705 +v -0.516317 0.166623 -0.303247 +v -0.575771 0.166623 -0.160243 +v -0.298931 0.517485 0.508969 +v -0.000000 0.437827 0.614496 +v 0.321074 0.360830 0.546669 +v -0.546669 0.360830 0.321075 +v 0.541877 0.221240 0.318259 +v 0.453072 0.287158 0.453072 +v 0.575771 0.166623 -0.160243 +v -0.596769 0.166623 0.000000 +v -0.604277 0.221240 0.168176 +v -0.552100 0.287158 0.324265 +v -0.165004 0.437827 0.592873 +v 0.169664 0.360830 0.609621 +v -0.448615 0.360830 0.448614 +v -0.436292 0.437827 0.436292 +v -0.312255 0.437827 0.531651 +v 0.575771 0.166623 0.160243 +v 0.483086 0.122640 -0.283731 +v 0.396438 0.122640 -0.396438 +v 0.283731 0.122640 -0.483086 +v 0.149931 0.122640 -0.538718 +v -0.000000 0.122640 -0.558363 +v -0.149931 0.122640 -0.538718 +v -0.283731 0.122640 -0.483086 +v -0.396438 0.122640 -0.396438 +v -0.483087 0.122640 -0.283731 +v -0.538718 0.122640 -0.149931 +v -0.558363 0.122640 0.000000 +v -0.541877 0.221240 0.318259 +v -0.000000 0.360830 0.631850 +v 0.324265 0.287158 0.552100 +v -0.453072 0.287158 0.453072 +v 0.516317 0.166623 0.303247 +v 0.596768 0.166623 0.000000 +v 0.444680 0.221240 0.444680 +v 0.538718 0.122640 -0.149931 +v -0.538718 0.122640 0.149931 +v -0.516317 0.166623 0.303247 +v -0.444680 0.221240 0.444680 +v -0.169664 0.360830 0.609621 +v 0.171349 0.287158 0.615677 +v -0.324265 0.287158 0.552100 +v -0.321075 0.360830 0.546669 +v 0.538718 0.122640 0.149931 +v 0.558363 0.122640 0.000000 +v 0.449858 0.088629 -0.264215 +v 0.369171 0.088629 -0.369171 +v 0.264215 0.088629 -0.449859 +v 0.139618 0.088629 -0.501662 +v -0.000000 0.088629 -0.519957 +v -0.139618 0.088629 -0.501662 +v -0.264215 0.088629 -0.449859 +v -0.369171 0.088629 -0.369171 +v -0.449859 0.088629 -0.264215 +v -0.501662 0.088629 -0.139618 +v -0.519957 0.088629 0.000000 +v -0.501662 0.088629 0.139618 +v -0.575771 0.166623 0.160243 +v -0.423705 0.166623 0.423705 +v -0.000000 0.287158 0.638129 +v 0.318259 0.221240 0.541877 +v -0.318259 0.221240 0.541877 +v 0.483086 0.122640 0.283731 +v 0.423705 0.166623 0.423705 +v 0.501662 0.088629 -0.139618 +v -0.449859 0.088629 0.264215 +v -0.483087 0.122640 0.283731 +v -0.396438 0.122640 0.396438 +v -0.303247 0.166623 0.516317 +v -0.171350 0.287158 0.615677 +v 0.168176 0.221240 0.604276 +v -0.168177 0.221240 0.604276 +v 0.501662 0.088629 0.139618 +v 0.519957 0.088629 0.000000 +v 0.424299 0.063924 -0.249203 +v 0.348195 0.063924 -0.348195 +v 0.249203 0.063924 -0.424298 +v 0.131685 0.063924 -0.473160 +v -0.000000 0.063924 -0.490415 +v -0.131686 0.063924 -0.473160 +v -0.249203 0.063924 -0.424298 +v -0.348196 0.063924 -0.348195 +v -0.424299 0.063924 -0.249203 +v -0.473160 0.063924 -0.131685 +v -0.490415 0.063924 0.000000 +v -0.473160 0.063924 0.131685 +v -0.424299 0.063924 0.249203 +v -0.283731 0.122640 0.483086 +v -0.000000 0.221240 0.626311 +v 0.303247 0.166623 0.516317 +v -0.160244 0.166623 0.575771 +v 0.449858 0.088629 0.264215 +v 0.396438 0.122640 0.396438 +v 0.473160 0.063924 -0.131685 +v -0.348196 0.063924 0.348195 +v -0.369171 0.088629 0.369171 +v -0.264215 0.088629 0.449859 +v -0.149931 0.122640 0.538718 +v 0.160243 0.166623 0.575771 +v -0.000000 0.166623 0.596769 +v 0.473160 0.063924 0.131685 +v 0.490415 0.063924 0.000000 +v 0.414076 0.047860 -0.243198 +v 0.339803 0.047860 -0.339804 +v 0.243198 0.047860 -0.414076 +v 0.128512 0.047860 -0.461757 +v -0.000000 0.047860 -0.478597 +v -0.128513 0.047860 -0.461757 +v -0.243198 0.047860 -0.414076 +v -0.339804 0.047860 -0.339804 +v -0.414076 0.047860 -0.243198 +v -0.461757 0.047860 -0.128512 +v -0.478597 0.047860 0.000000 +v -0.461757 0.047860 0.128512 +v -0.414076 0.047860 0.243198 +v -0.339804 0.047860 0.339804 +v -0.139618 0.088629 0.501662 +v 0.283731 0.122640 0.483086 +v -0.000000 0.122640 0.558363 +v 0.424299 0.063924 0.249203 +v 0.369171 0.088629 0.369171 +v 0.461756 0.047860 -0.128512 +v -0.243198 0.047860 0.414076 +v -0.249203 0.063924 0.424298 +v -0.131686 0.063924 0.473160 +v -0.000000 0.088629 0.519957 +v 0.149931 0.122640 0.538718 +v 0.461756 0.047860 0.128512 +v 0.478596 0.047860 0.000000 +v 0.410719 0.036005 -0.241228 +v 0.337050 0.036005 -0.337050 +v 0.241227 0.036005 -0.410719 +v 0.127471 0.036005 -0.458017 +v -0.000000 0.036005 -0.474720 +v -0.127471 0.036005 -0.458017 +v -0.241228 0.036005 -0.410719 +v -0.337051 0.036005 -0.337050 +v -0.410719 0.036005 -0.241228 +v -0.458017 0.036005 -0.127471 +v -0.474721 0.036005 0.000000 +v -0.458017 0.036005 0.127471 +v -0.410719 0.036005 0.241228 +v -0.337051 0.036005 0.337050 +v -0.241228 0.036005 0.410719 +v -0.000000 0.063924 0.490415 +v 0.264215 0.088629 0.449859 +v 0.139618 0.088629 0.501662 +v 0.414076 0.047860 0.243198 +v 0.348195 0.063924 0.348195 +v 0.458017 0.036005 -0.127471 +v -0.127471 0.036005 0.458017 +v -0.128513 0.047860 0.461757 +v -0.000000 0.047860 0.478597 +v 0.131685 0.063924 0.473160 +v 0.458017 0.036005 0.127471 +v 0.474720 0.036005 0.000000 +v 0.394137 0.024816 -0.231489 +v 0.323442 0.024816 -0.323442 +v 0.231489 0.024816 -0.394137 +v 0.122324 0.024816 -0.439524 +v -0.000000 0.024816 -0.455554 +v -0.122325 0.024816 -0.439524 +v -0.231489 0.024816 -0.394137 +v -0.323442 0.024816 -0.323442 +v -0.394137 0.024816 -0.231489 +v -0.439524 0.024816 -0.122325 +v -0.455554 0.024816 0.000000 +v -0.439524 0.024816 0.122325 +v -0.394137 0.024816 0.231489 +v -0.323442 0.024816 0.323442 +v -0.231489 0.024816 0.394137 +v -0.122325 0.024816 0.439524 +v 0.128512 0.047860 0.461757 +v 0.249203 0.063924 0.424298 +v 0.410719 0.036005 0.241228 +v 0.339803 0.047860 0.339804 +v 0.439524 0.024816 -0.122325 +v -0.000000 0.036005 0.474720 +v -0.000000 0.024816 0.455554 +v 0.127471 0.036005 0.458017 +v 0.243198 0.047860 0.414076 +v 0.439524 0.024816 0.122325 +v 0.455554 0.024816 0.000000 +v 0.354551 0.014956 -0.208238 +v 0.290957 0.014956 -0.290957 +v 0.208238 0.014956 -0.354551 +v 0.110038 0.014956 -0.395378 +v -0.000000 0.014956 -0.409797 +v -0.110038 0.014956 -0.395378 +v -0.208239 0.014956 -0.354551 +v -0.290957 0.014956 -0.290957 +v -0.354551 0.014956 -0.208238 +v -0.395378 0.014956 -0.110038 +v -0.409797 0.014956 0.000000 +v -0.395378 0.014956 0.110038 +v -0.354551 0.014956 0.208238 +v -0.290957 0.014956 0.290957 +v -0.208239 0.014956 0.354551 +v -0.110038 0.014956 0.395378 +v -0.000000 0.014956 0.409797 +v 0.241227 0.036005 0.410719 +v 0.337050 0.036005 0.337050 +v 0.394137 0.024816 0.231489 +v 0.395378 0.014956 -0.110038 +v 0.122324 0.024816 0.439524 +v 0.110038 0.014956 0.395378 +v 0.231489 0.024816 0.394137 +v 0.395378 0.014956 0.110038 +v 0.409797 0.014956 0.000000 +v 0.282184 0.007090 -0.165735 +v 0.231570 0.007090 -0.231570 +v 0.165735 0.007090 -0.282185 +v 0.087579 0.007090 -0.314679 +v -0.000000 0.007090 -0.326154 +v -0.087579 0.007090 -0.314679 +v -0.165735 0.007090 -0.282185 +v -0.231570 0.007090 -0.231570 +v -0.282184 0.007090 -0.165735 +v -0.314679 0.007090 -0.087579 +v -0.326155 0.007090 0.000000 +v -0.314679 0.007090 0.087579 +v -0.282184 0.007090 0.165735 +v -0.231570 0.007090 0.231570 +v -0.165735 0.007090 0.282185 +v -0.087579 0.007090 0.314679 +v -0.000000 0.007090 0.326154 +v 0.087579 0.007090 0.314679 +v 0.323442 0.024816 0.323442 +v 0.354551 0.014956 0.208238 +v 0.314679 0.007090 -0.087579 +v 0.208238 0.014956 0.354551 +v 0.165735 0.007090 0.282185 +v 0.290957 0.014956 0.290957 +v 0.314679 0.007090 0.087579 +v 0.326154 0.007090 0.000000 +v 0.167259 0.001883 -0.098236 +v 0.137258 0.001883 -0.137259 +v 0.098236 0.001883 -0.167259 +v 0.051910 0.001883 -0.186520 +v -0.000000 0.001883 -0.193322 +v -0.051911 0.001883 -0.186520 +v -0.098237 0.001883 -0.167259 +v -0.137259 0.001883 -0.137259 +v -0.167259 0.001883 -0.098236 +v -0.186520 0.001883 -0.051911 +v -0.193323 0.001883 0.000000 +v -0.186520 0.001883 0.051911 +v -0.167259 0.001883 0.098236 +v -0.137259 0.001883 0.137259 +v -0.098237 0.001883 0.167259 +v -0.051911 0.001883 0.186520 +v -0.000000 0.001883 0.193322 +v 0.051910 0.001883 0.186520 +v 0.098236 0.001883 0.167259 +v 0.282184 0.007090 0.165735 +v 0.186520 0.001883 -0.051911 +v 0.231570 0.007090 0.231570 +v 0.137258 0.001883 0.137259 +v 0.186520 0.001883 0.051911 +v 0.193322 0.001883 0.000000 +v -0.000000 0.000000 0.000000 +v 0.167259 0.001883 0.098236 +v 0.063813 0.861474 0.000000 +v 0.054654 0.888729 0.000000 +v 0.052734 0.888729 0.014691 +v 0.061568 0.861474 0.017135 +v 0.061568 0.861474 -0.017135 +v 0.072979 0.919969 0.020357 +v 0.111968 0.841089 0.000000 +v 0.047296 0.888729 0.027792 +v 0.052734 0.888729 -0.014691 +v 0.108028 0.841089 -0.030065 +v 0.075630 0.919969 0.000000 +v 0.065466 0.919969 0.038494 +v 0.108028 0.841089 0.030065 +v 0.055210 0.861474 0.032427 +v 0.055210 0.861474 -0.032427 +v 0.096873 0.841089 -0.056896 +v 0.100064 0.951211 0.027927 +v 0.089769 0.951211 0.052799 +v 0.183167 0.826023 0.000000 +v 0.176722 0.826023 -0.049184 +v 0.038821 0.888729 0.038821 +v 0.053751 0.919969 0.053751 +v 0.047296 0.888729 -0.027792 +v 0.072979 0.919969 -0.020357 +v 0.158473 0.826023 -0.093076 +v 0.103696 0.951211 0.000000 +v 0.073714 0.951211 0.073714 +v 0.176722 0.826023 0.049184 +v 0.096873 0.841089 0.056896 +v 0.045307 0.861474 0.045307 +v 0.079497 0.841089 -0.079497 +v 0.045307 0.861474 -0.045307 +v 0.130048 0.826023 -0.130048 +v 0.111754 0.978466 0.031195 +v 0.100259 0.978466 0.058974 +v 0.082330 0.978466 0.082330 +v 0.263228 0.813615 0.000000 +v 0.253966 0.813615 -0.070682 +v 0.227741 0.813615 -0.133759 +v 0.027792 0.888729 0.047296 +v 0.038494 0.919969 0.065466 +v 0.052799 0.951211 0.089769 +v 0.038821 0.888729 -0.038821 +v 0.065466 0.919969 -0.038494 +v 0.100064 0.951211 -0.027927 +v 0.186892 0.813615 -0.186892 +v 0.115809 0.978466 0.000000 +v 0.058974 0.978466 0.100259 +v 0.253966 0.813615 0.070682 +v 0.158473 0.826023 0.093076 +v 0.079497 0.841089 0.079497 +v 0.032426 0.861474 0.055210 +v 0.093076 0.826023 -0.158473 +v 0.056896 0.841089 -0.096873 +v 0.032426 0.861474 -0.055210 +v 0.133759 0.813615 -0.227741 +v 0.085811 0.997741 0.023955 +v 0.076985 0.997741 0.045285 +v 0.063219 0.997741 0.063219 +v 0.045285 0.997741 0.076986 +v 0.337972 0.801206 0.000000 +v 0.326081 0.801206 -0.090752 +v 0.292408 0.801206 -0.171740 +v 0.239960 0.801206 -0.239960 +v 0.014691 0.888729 0.052735 +v 0.020357 0.919969 0.072979 +v 0.027927 0.951211 0.100064 +v 0.031195 0.978466 0.111754 +v 0.027792 0.888729 -0.047296 +v 0.053751 0.919969 -0.053751 +v 0.089769 0.951211 -0.052799 +v 0.111754 0.978466 -0.031195 +v 0.171740 0.801206 -0.292408 +v 0.088924 0.997741 0.000000 +v 0.023955 0.997741 0.085811 +v 0.326081 0.801206 0.090752 +v 0.227741 0.813615 0.133759 +v 0.130048 0.826023 0.130048 +v 0.056896 0.841089 0.096873 +v 0.017135 0.861474 0.061568 +v 0.070682 0.813615 -0.253966 +v 0.049184 0.826023 -0.176722 +v 0.030065 0.841089 -0.108029 +v 0.017135 0.861474 -0.061568 +v 0.090752 0.801206 -0.326081 +v -0.000000 1.005054 0.000000 +v 0.393218 0.786140 0.000000 +v 0.379380 0.786140 -0.105586 +v 0.340206 0.786140 -0.199813 +v 0.279184 0.786140 -0.279184 +v 0.199813 0.786140 -0.340206 +v -0.000000 0.888729 0.054654 +v -0.000000 0.919969 0.075630 +v -0.000000 0.951211 0.103696 +v -0.000000 0.978466 0.115809 +v -0.000000 0.997741 0.088925 +v 0.014691 0.888729 -0.052735 +v 0.038494 0.919969 -0.065466 +v 0.073714 0.951211 -0.073714 +v 0.100259 0.978466 -0.058974 +v 0.085811 0.997741 -0.023955 +v 0.105586 0.786140 -0.379381 +v 0.379380 0.786140 0.105586 +v 0.292408 0.801206 0.171740 +v 0.186892 0.813615 0.186892 +v 0.093076 0.826023 0.158473 +v 0.030065 0.841089 0.108029 +v -0.000000 0.861474 0.063813 +v -0.000000 0.801206 -0.337972 +v -0.000000 0.813615 -0.263228 +v -0.000000 0.826023 -0.183167 +v -0.000000 0.841089 -0.111968 +v -0.000000 0.861474 -0.063813 +v -0.000000 0.786140 -0.393218 +v 0.076985 0.997741 -0.045285 +v -0.023955 0.997741 0.085811 +v 0.414784 0.765755 0.000000 +v 0.400190 0.765755 -0.111377 +v 0.358865 0.765755 -0.210772 +v 0.294497 0.765755 -0.294497 +v 0.210772 0.765755 -0.358865 +v 0.111377 0.765755 -0.400190 +v -0.014691 0.888729 0.052735 +v -0.020357 0.919969 0.072979 +v -0.027927 0.951211 0.100064 +v -0.031195 0.978466 0.111754 +v -0.000000 0.888729 -0.054654 +v 0.020357 0.919969 -0.072979 +v 0.052799 0.951211 -0.089769 +v 0.082330 0.978466 -0.082330 +v -0.000000 0.765755 -0.414784 +v 0.063219 0.997741 -0.063219 +v -0.045285 0.997741 0.076986 +v 0.400190 0.765755 0.111377 +v 0.340206 0.786140 0.199813 +v 0.239960 0.801206 0.239960 +v 0.133759 0.813615 0.227741 +v 0.049184 0.826023 0.176722 +v -0.000000 0.841089 0.111968 +v -0.017135 0.861474 0.061568 +v -0.105586 0.786140 -0.379381 +v -0.090752 0.801206 -0.326081 +v -0.070682 0.813615 -0.253966 +v -0.049184 0.826023 -0.176722 +v -0.030066 0.841089 -0.108029 +v -0.017135 0.861474 -0.061568 +v -0.111377 0.765755 -0.400190 +v 0.045285 0.997741 -0.076986 +v -0.063220 0.997741 0.063219 +v 0.414952 0.750806 0.115486 +v 0.430085 0.750806 0.000000 +v 0.414952 0.750806 -0.115486 +v 0.372103 0.750806 -0.218547 +v 0.305360 0.750806 -0.305360 +v 0.218547 0.750806 -0.372103 +v 0.115486 0.750806 -0.414952 +v -0.000000 0.750806 -0.430085 +v -0.027793 0.888729 0.047296 +v -0.038494 0.919969 0.065466 +v -0.052799 0.951211 0.089769 +v -0.058974 0.978466 0.100259 +v -0.014691 0.888729 -0.052735 +v -0.000000 0.919969 -0.075630 +v 0.027927 0.951211 -0.100064 +v 0.058974 0.978466 -0.100259 +v -0.115486 0.750806 -0.414952 +v 0.023955 0.997741 -0.085811 +v -0.076986 0.997741 0.045285 +v 0.372103 0.750806 0.218547 +v 0.358865 0.765755 0.210772 +v 0.279184 0.786140 0.279184 +v 0.171740 0.801206 0.292408 +v 0.070682 0.813615 0.253966 +v -0.000000 0.826023 0.183167 +v -0.030066 0.841089 0.108029 +v -0.032427 0.861474 0.055210 +v -0.210772 0.765755 -0.358865 +v -0.199813 0.786140 -0.340206 +v -0.171740 0.801206 -0.292408 +v -0.133759 0.813615 -0.227741 +v -0.093076 0.826023 -0.158473 +v -0.056896 0.841089 -0.096873 +v -0.032427 0.861474 -0.055210 +v -0.218547 0.750806 -0.372103 +v 0.031195 0.978466 -0.111754 +v -0.000000 0.997741 -0.088925 +v -0.082331 0.978466 0.082330 +v -0.085811 0.997741 0.023955 +v 0.305360 0.750806 0.305360 +v 0.294497 0.765755 0.294497 +v -0.038821 0.888729 0.038821 +v -0.053751 0.919969 0.053751 +v -0.073714 0.951211 0.073714 +v -0.027793 0.888729 -0.047296 +v -0.020357 0.919969 -0.072979 +v -0.000000 0.951211 -0.103696 +v -0.305360 0.750806 -0.305360 +v -0.294497 0.765755 -0.294497 +v -0.000000 0.978466 -0.115809 +v -0.023955 0.997741 -0.085811 +v -0.100259 0.978466 0.058974 +v -0.088925 0.997741 0.000000 +v 0.210772 0.765755 0.358865 +v 0.218547 0.750806 0.372103 +v 0.199813 0.786140 0.340206 +v 0.090752 0.801206 0.326081 +v -0.000000 0.813615 0.263228 +v -0.049184 0.826023 0.176722 +v -0.056896 0.841089 0.096873 +v -0.045307 0.861474 0.045307 +v -0.279185 0.786140 -0.279184 +v -0.239960 0.801206 -0.239960 +v -0.186892 0.813615 -0.186892 +v -0.130049 0.826023 -0.130048 +v -0.079497 0.841089 -0.079497 +v -0.045307 0.861474 -0.045307 +v -0.372103 0.750806 -0.218547 +v -0.358865 0.765755 -0.210772 +v -0.031195 0.978466 -0.111754 +v -0.045285 0.997741 -0.076986 +v -0.111754 0.978466 0.031195 +v -0.085811 0.997741 -0.023955 +v 0.111377 0.765755 0.400190 +v 0.115486 0.750806 0.414952 +v -0.047296 0.888729 0.027792 +v -0.065466 0.919969 0.038494 +v -0.089770 0.951211 0.052799 +v -0.038821 0.888729 -0.038821 +v -0.038494 0.919969 -0.065466 +v -0.027927 0.951211 -0.100064 +v -0.414952 0.750806 -0.115486 +v -0.400190 0.765755 -0.111377 +v -0.058974 0.978466 -0.100259 +v -0.063220 0.997741 -0.063219 +v -0.115809 0.978466 0.000000 +v -0.076986 0.997741 -0.045285 +v 0.105586 0.786140 0.379381 +v -0.000000 0.765755 0.414784 +v -0.000000 0.750806 0.430085 +v -0.000000 0.801206 0.337972 +v -0.070682 0.813615 0.253966 +v -0.093076 0.826023 0.158473 +v -0.079497 0.841089 0.079497 +v -0.055210 0.861474 0.032427 +v -0.340206 0.786140 -0.199813 +v -0.292408 0.801206 -0.171740 +v -0.227741 0.813615 -0.133759 +v -0.158473 0.826023 -0.093076 +v -0.096873 0.841089 -0.056896 +v -0.055210 0.861474 -0.032427 +v -0.430085 0.750806 0.000000 +v -0.414784 0.765755 0.000000 +v -0.052799 0.951211 -0.089769 +v -0.082331 0.978466 -0.082330 +v -0.100064 0.951211 0.027927 +v -0.111754 0.978466 -0.031195 +v -0.000000 0.786140 0.393218 +v -0.115486 0.750806 0.414952 +v -0.111377 0.765755 0.400190 +v -0.052735 0.888729 0.014691 +v -0.072979 0.919969 0.020357 +v -0.047296 0.888729 -0.027792 +v -0.053751 0.919969 -0.053751 +v -0.414952 0.750806 0.115486 +v -0.400190 0.765755 0.111377 +v -0.379381 0.786140 -0.105586 +v -0.073714 0.951211 -0.073714 +v -0.100259 0.978466 -0.058974 +v -0.103696 0.951211 0.000000 +v -0.105586 0.786140 0.379381 +v -0.218547 0.750806 0.372103 +v -0.210772 0.765755 0.358865 +v -0.090752 0.801206 0.326081 +v -0.133759 0.813615 0.227741 +v -0.130049 0.826023 0.130048 +v -0.096873 0.841089 0.056896 +v -0.061568 0.861474 0.017135 +v -0.326081 0.801206 -0.090752 +v -0.253966 0.813615 -0.070682 +v -0.176722 0.826023 -0.049184 +v -0.108029 0.841089 -0.030065 +v -0.061568 0.861474 -0.017135 +v -0.372103 0.750806 0.218547 +v -0.358865 0.765755 0.210772 +v -0.393219 0.786140 0.000000 +v -0.089770 0.951211 -0.052799 +v -0.100064 0.951211 -0.027927 +v -0.199813 0.786140 0.340206 +v -0.305360 0.750806 0.305360 +v -0.294497 0.765755 0.294497 +v -0.054655 0.888729 0.000000 +v -0.075630 0.919969 0.000000 +v -0.052735 0.888729 -0.014691 +v -0.065466 0.919969 -0.038494 +v -0.379381 0.786140 0.105586 +v -0.171740 0.801206 0.292408 +v -0.279185 0.786140 0.279184 +v -0.186892 0.813615 0.186892 +v -0.158473 0.826023 0.093076 +v -0.108029 0.841089 0.030065 +v -0.063813 0.861474 0.000000 +v -0.337972 0.801206 0.000000 +v -0.263228 0.813615 0.000000 +v -0.183167 0.826023 0.000000 +v -0.111968 0.841089 0.000000 +v -0.340206 0.786140 0.199813 +v -0.072979 0.919969 -0.020357 +v -0.239960 0.801206 0.239960 +v -0.326081 0.801206 0.090752 +v -0.292408 0.801206 0.171740 +v -0.227741 0.813615 0.133759 +v -0.176722 0.826023 0.049184 +v -0.253966 0.813615 0.070682 +v -0.526706 0.651362 -0.039883 +v -0.534329 0.646030 0.000000 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.638129 0.287158 0.000000 +v -0.631184 0.277569 0.039883 +v -0.501666 0.699221 -0.063813 +v -0.508714 0.682112 -0.071712 +v -0.611709 0.194244 0.000000 +v -0.608883 0.198681 0.039883 +v -0.517593 0.664661 0.063813 +v -0.508714 0.682112 0.071712 +v -0.631184 0.277569 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.615480 0.216617 0.063578 +v -0.615553 0.216807 -0.063813 +v -0.517593 0.664661 -0.063813 +v -0.498530 0.712498 -0.039883 +v -0.619922 0.238069 0.071790 +v -0.526706 0.651362 0.039883 +v -0.608884 0.198682 -0.039883 +v 0.605100 0.399712 0.137265 +v 0.613258 0.341675 0.154354 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.613258 0.341675 -0.154354 +v 0.605101 0.399712 -0.137265 +v 0.600960 0.444810 0.085753 +v 0.121642 0.750009 -0.437072 +v -0.000000 0.750009 -0.453012 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 -0.121642 +v -0.453012 0.750009 0.000000 +v -0.437073 0.750009 -0.121642 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.391940 0.750009 0.230197 +v -0.437073 0.750009 0.121642 +v 0.121642 0.750009 0.437072 +v -0.000000 0.750009 0.453012 +v -0.121642 0.750009 0.437072 +v 0.437073 0.750009 0.121642 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 -0.321639 +v 0.230197 0.750009 -0.391940 +v -0.121642 0.750009 -0.437072 +v 0.391939 0.750009 -0.230197 +v 0.321638 0.750009 0.321639 +v 0.230197 0.750009 0.391940 +v -0.230198 0.750009 -0.391939 +v -0.501255 0.717792 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v -0.321639 0.750009 -0.321639 +v -0.391940 0.750009 -0.230197 +v -0.498530 0.712498 0.039883 +v -0.501667 0.699221 0.063813 +v 0.617684 0.235930 -0.085941 +v 0.619427 0.283145 -0.137236 +v 0.619427 0.283145 0.137236 +vn -0.901883 0.415418 0.118168 +vn -0.905637 0.407056 0.118656 +vn -0.877041 0.418744 0.235298 +vn 0.058443 -0.998260 0.000732 +vn 0.015107 -0.999878 0.000183 +vn 0.014557 -0.949278 0.314035 +vn 0.056703 -0.947539 0.314524 +vn 0.162053 -0.986755 0.002014 +vn 0.157933 -0.933592 0.321604 +vn 0.392376 -0.919767 0.004334 +vn 0.378307 -0.856655 0.350688 +vn 0.783776 -0.620991 0.005249 +vn 0.726829 -0.553880 0.406079 +vn 0.994812 -0.101627 0.001984 +vn 0.908139 -0.082766 0.410321 +vn 0.003082 -0.939787 0.341685 +vn 0.002167 -0.619495 0.784967 +vn 0.011536 -0.679403 0.733634 +vn 0.044679 -0.675588 0.735923 +vn 0.123325 -0.652272 0.747856 +vn 0.275399 -0.556871 0.783593 +vn 0.460067 -0.316263 0.829615 +vn 0.563036 -0.041200 0.825373 +vn -0.000427 0.122166 0.992492 +vn 0.000397 0.003632 0.999969 +vn 0.002869 0.011841 0.999908 +vn 0.004852 0.029298 0.999542 +vn -0.008179 0.053499 0.998505 +vn -0.046510 0.041536 0.998047 +vn -0.039155 0.003113 0.999207 +vn -0.850551 0.473769 -0.228217 +vn -0.897885 0.424177 -0.117649 +vn -0.880886 0.473281 0.000000 +vn -0.013611 0.682394 0.730827 +vn -0.053896 0.680441 0.730796 +vn -0.147557 0.656789 0.739464 +vn -0.325968 0.560564 0.761223 +vn -0.537645 0.315806 0.781762 +vn -0.611530 0.029939 0.790613 +vn -0.904172 0.427137 0.000000 +vn -0.897885 0.424146 0.117618 +vn -0.020112 0.949461 0.313150 +vn -0.081820 0.945433 0.315287 +vn -0.227699 0.916379 0.329173 +vn -0.504196 0.785302 0.359203 +vn -0.810633 0.443220 0.382611 +vn -0.921232 0.039705 0.386944 +vn -0.020569 0.949400 -0.313334 +vn -0.021729 0.999756 -0.000092 +vn -0.004242 0.950468 -0.310770 +vn -0.088260 0.996094 -0.000488 +vn -0.246895 0.969024 -0.001343 +vn -0.549730 0.835322 -0.002350 +vn -0.880673 0.473647 -0.001984 +vn -0.999084 0.042146 -0.000610 +vn -0.877041 0.418744 -0.235298 +vn -0.920286 0.391156 0.000000 +vn -0.905637 0.407056 -0.118656 +vn -0.083132 0.945006 -0.316202 +vn -0.230201 0.914823 -0.331797 +vn -0.505570 0.782800 -0.362743 +vn -0.808710 0.444960 -0.384625 +vn -0.920835 0.042055 -0.387646 +vn -0.897885 0.424146 -0.117618 +vn -0.901883 0.415448 -0.118168 +vn -0.014161 0.682394 -0.730796 +vn -0.055361 0.680074 -0.731010 +vn -0.150029 0.655660 -0.739982 +vn -0.327616 0.560594 -0.760491 +vn -0.537431 0.320933 -0.779809 +vn -0.611988 0.033387 -0.790155 +vn 0.015168 -0.949339 -0.313852 +vn 0.011902 -0.679403 -0.733634 +vn 0.003265 -0.939817 -0.341594 +vn 0.000183 0.004212 -0.999969 +vn 0.003510 0.014008 -0.999878 +vn 0.005921 0.035951 -0.999329 +vn -0.010132 0.064333 -0.997864 +vn -0.051576 0.048463 -0.997467 +vn -0.041597 0.003998 -0.999115 +vn 0.003082 -0.620106 -0.784478 +vn -0.000031 0.122440 -0.992462 +vn -0.897885 0.424177 0.117649 +vn 0.046449 -0.674398 -0.736869 +vn 0.125980 -0.648946 -0.750298 +vn 0.275430 -0.552477 -0.786676 +vn 0.455519 -0.320536 -0.830500 +vn 0.561693 -0.046480 -0.826014 +vn -0.888668 0.391644 0.238441 +vn 0.058046 -0.947630 -0.314005 +vn 0.159948 -0.933836 -0.319865 +vn 0.380169 -0.857753 -0.345927 +vn 0.725547 -0.560930 -0.398602 +vn 0.908597 -0.089236 -0.407971 +vn 0.003235 -0.999969 0.000031 +vn 0.973144 0.230110 0.000824 +vn 0.890896 0.211737 0.401776 +vn 0.912900 0.408094 0.002533 +vn 0.836970 0.380932 0.392834 +vn 0.829035 0.559160 0.003784 +vn 0.764519 0.528550 0.368969 +vn 0.718650 0.695334 0.003937 +vn 0.668294 0.663717 0.335917 +vn 0.579577 0.814905 0.002838 +vn 0.542650 0.779687 0.312357 +vn 0.495163 0.868770 0.002258 +vn 0.458052 0.820643 0.341624 +vn 0.561205 0.137028 0.816218 +vn 0.532029 0.253456 0.807886 +vn 0.497543 0.363445 0.787591 +vn 0.449538 0.472060 0.758293 +vn 0.373669 0.563555 0.736686 +vn 0.289041 0.531114 0.796442 +vn -0.023225 -0.005249 0.999695 +vn -0.016785 -0.010254 0.999786 +vn -0.011444 -0.012940 0.999847 +vn -0.009796 -0.013276 0.999847 +vn -0.014801 -0.013916 0.999786 +vn -0.089755 -0.176122 0.980255 +vn -0.585772 -0.152379 0.795984 +vn -0.538896 -0.288766 0.791314 +vn -0.484146 -0.407910 0.774071 +vn -0.424635 -0.509781 0.748161 +vn -0.355907 -0.584765 0.728935 +vn -0.889828 -0.237159 0.389782 +vn -0.808740 -0.446852 0.382366 +vn -0.702475 -0.613269 0.361095 +vn -0.590625 -0.734855 0.333293 +vn -0.483291 -0.816767 0.315104 +vn -0.912076 0.409955 0.000000 +vn -0.965606 -0.259987 -0.000458 +vn -0.872433 -0.488693 -0.001465 +vn -0.748436 -0.663167 -0.002197 +vn -0.621601 -0.783288 -0.002136 +vn -0.507065 -0.861873 -0.001251 +vn -0.438215 -0.854366 0.279183 +vn -0.456130 -0.889889 -0.000732 +vn -0.889126 -0.238868 -0.390332 +vn -0.807001 -0.448531 -0.384075 +vn -0.700980 -0.613392 -0.363750 +vn -0.590442 -0.733757 -0.336039 +vn -0.484787 -0.815332 -0.316477 +vn -0.440962 -0.852931 -0.279305 +vn -0.359691 -0.584185 -0.727531 +vn -0.358074 -0.682241 -0.637410 +vn -0.585467 -0.154668 -0.795770 +vn -0.538499 -0.291696 -0.790490 +vn -0.484512 -0.409772 -0.772851 +vn -0.426496 -0.510056 -0.746910 +vn -0.909543 -0.399274 -0.115207 +vn -0.971191 -0.204688 -0.121891 +vn -0.912931 -0.326609 -0.244606 +vn -0.020478 -0.017853 -0.999603 +vn -0.024537 -0.005737 -0.999664 +vn -0.020844 -0.012207 -0.999695 +vn -0.017548 -0.016846 -0.999695 +vn -0.016724 -0.018097 -0.999695 +vn -0.909116 -0.400311 0.115055 +vn -0.873775 -0.472610 0.114475 +vn -0.795892 -0.566485 0.213538 +vn -0.353069 -0.684103 0.638203 +vn 0.559679 0.139714 -0.816828 +vn 0.528581 0.255501 -0.809473 +vn 0.494217 0.362987 -0.789911 +vn 0.449049 0.469283 -0.760308 +vn 0.378246 0.560869 -0.736412 +vn -0.091983 -0.174383 -0.980346 +vn 0.295267 0.530625 -0.794488 +vn 0.890500 0.214759 -0.401044 +vn 0.836634 0.384075 -0.390515 +vn 0.765191 0.530198 -0.365123 +vn 0.671041 0.663228 -0.331339 +vn 0.547929 0.777642 -0.308206 +vn 0.464522 0.818842 -0.337199 +vn 0.931486 0.265572 -0.248543 +vn 0.939543 0.342357 0.000000 +vn 0.947539 0.295114 -0.122684 +vn -0.351421 0.936186 0.001953 +vn -0.144444 0.989502 0.003174 +vn -0.126743 0.878811 0.459975 +vn -0.716758 0.697287 -0.000946 +vn -0.299997 0.838313 0.455214 +vn -0.621876 0.660207 0.421155 +vn -0.901822 0.432081 -0.004517 +vn -0.807031 0.443434 0.389904 +vn -0.930204 0.366863 -0.008484 +vn -0.824549 0.383312 0.416059 +vn -0.850673 0.525529 -0.011628 +vn -0.722465 0.508988 0.467910 +vn -0.668447 0.743645 -0.011139 +vn -0.531449 0.686514 0.496170 +vn -0.116459 0.505448 0.854946 +vn -0.258400 0.470656 0.843593 +vn -0.407605 0.396985 0.822321 +vn -0.450270 0.352367 0.820399 +vn -0.385876 0.395734 0.833338 +vn -0.270669 0.487838 0.829890 +vn 0.141606 -0.001190 0.989898 +vn -0.067690 0.525346 0.848170 +vn 0.989593 0.100253 0.103122 +vn 0.970244 0.213324 0.114475 +vn 0.960418 0.152654 0.232917 +vn 0.241829 0.092502 0.965880 +vn 0.209296 0.170660 0.962828 +vn 0.096194 0.178625 0.979186 +vn 0.009552 0.154332 0.987945 +vn -0.000122 0.151952 0.988372 +vn 0.361248 -0.477279 0.801019 +vn 0.607929 -0.282540 0.741997 +vn 0.679220 -0.106754 0.726096 +vn 0.583911 -0.078524 0.807978 +vn 0.402722 -0.205237 0.891995 +vn 0.279519 -0.338694 0.898404 +vn 0.488601 -0.768700 0.412671 +vn 0.784570 -0.501511 0.364544 +vn 0.893918 -0.279611 0.350291 +vn 0.861415 -0.285287 0.420179 +vn 0.679373 -0.540452 0.496323 +vn 0.458327 -0.754540 0.469588 +vn 0.524155 -0.851588 -0.000153 +vn 0.827143 -0.561968 0.001679 +vn 0.943205 -0.332133 0.003479 +vn 0.933256 -0.359081 0.005737 +vn 0.756859 -0.653493 0.006470 +vn 0.492843 -0.870083 0.004120 +vn 0.322489 -0.946562 -0.001129 +vn 0.912839 -0.326609 0.244942 +vn 0.824396 -0.565996 0.000000 +vn 0.894162 -0.447676 0.000000 +vn 0.486557 -0.770501 -0.411756 +vn 0.783990 -0.504074 -0.362285 +vn 0.895199 -0.281899 -0.345134 +vn 0.863735 -0.289010 -0.412824 +vn 0.682119 -0.544267 -0.488296 +vn 0.461928 -0.758202 -0.460128 +vn 0.357463 -0.479141 -0.801599 +vn 0.605884 -0.285867 -0.742393 +vn 0.679739 -0.108646 -0.725333 +vn 0.583636 -0.077883 -0.808222 +vn 0.401440 -0.199225 -0.893918 +vn 0.281961 -0.330638 -0.900632 +vn 0.135228 -0.002380 -0.990783 +vn 0.235755 0.091128 -0.967498 +vn 0.200720 0.170629 -0.964660 +vn 0.086123 0.184576 -0.979003 +vn 0.000671 0.174322 -0.984680 +vn -0.007141 0.169012 -0.985565 +vn 0.966613 -0.042848 -0.252602 +vn 0.960418 0.152654 -0.232917 +vn 0.989593 0.100223 -0.103092 +vn -0.119297 0.503342 -0.855770 +vn -0.261269 0.472793 -0.841517 +vn -0.414075 0.399792 -0.817713 +vn -0.459700 0.357036 -0.813105 +vn -0.394024 0.408490 -0.823298 +vn -0.277871 0.487381 -0.827754 +vn -0.072207 0.520127 -0.851009 +vn -0.298654 0.840297 -0.452376 +vn -0.617512 0.663961 -0.421613 +vn -0.801324 0.450209 -0.393872 +vn -0.819422 0.389691 -0.420270 +vn -0.721274 0.506912 -0.471969 +vn -0.538347 0.670644 -0.510239 +vn -0.482009 0.876125 -0.005127 +vn -0.394635 0.815363 0.423536 +vn -0.321909 0.946745 -0.002594 +vn -0.255287 0.921995 0.291086 +vn 0.004242 0.999969 0.000397 +vn -0.002960 0.999939 -0.010102 +vn 0.853450 0.521073 -0.007050 +vn 0.392041 0.688986 -0.609546 +vn 0.805170 -0.592517 -0.023621 +vn 0.588763 -0.206122 -0.781579 +vn 0.681478 -0.731040 -0.033296 +vn 0.485031 -0.441237 -0.754967 +vn -0.206824 0.638203 0.741539 +vn -0.129490 0.862056 0.489944 +vn -0.033418 0.999176 0.022340 +vn 0.047700 0.864040 -0.501114 +vn 0.099307 0.538743 -0.836573 +vn 0.053560 0.251839 -0.966277 +vn 0.020112 0.322611 0.946287 +vn 0.021943 0.748894 0.662282 +vn -0.025941 0.995605 0.089908 +vn -0.059175 0.930876 -0.360424 +vn -0.080172 0.784448 -0.614948 +vn -0.142582 0.557604 -0.817743 +vn 0.281747 -0.174993 0.943388 +vn 0.303903 0.444136 0.842830 +vn 0.034333 0.983764 0.175970 +vn -0.113865 0.956420 -0.268777 +vn -0.155339 0.858852 -0.488021 +vn -0.207404 0.641865 -0.738182 +vn 0.467238 -0.683187 0.561144 +vn 0.699515 0.004364 0.714560 +vn 0.355296 0.891934 0.279641 +vn -0.170354 0.971465 -0.164861 +vn -0.245552 0.901181 -0.357097 +vn -0.248726 0.651082 -0.717063 +vn 0.494430 -0.869167 0.006317 +vn 0.933134 -0.358898 0.019868 +vn 0.703146 0.710685 0.021790 +vn -0.203650 0.978942 -0.012574 +vn -0.326456 0.942869 -0.066073 +vn -0.397595 0.857082 -0.327525 +vn 0.460616 -0.712546 -0.529221 +vn 0.695486 -0.098544 -0.711722 +vn 0.397534 0.853816 -0.336070 +vn -0.198248 0.963439 0.180151 +vn -0.306833 0.888516 0.341075 +vn -0.393689 0.807672 0.438887 +vn 0.276559 -0.211951 -0.937315 +vn 0.294626 0.366161 -0.882656 +vn 0.046632 0.973235 -0.224982 +vn -0.146733 0.912168 0.382611 +vn -0.202643 0.700797 0.683950 +vn -0.232673 0.506485 0.830226 +vn 0.011689 0.309397 -0.950835 +vn 0.013245 0.708640 -0.705435 +vn -0.027589 0.995758 -0.087680 +vn -0.047395 0.829371 0.556658 +vn -0.015259 0.386608 0.922086 +vn 0.004639 0.119510 0.992798 +vn -0.211035 0.631001 -0.746513 +vn -0.138768 0.848781 -0.510147 +vn -0.024995 0.999664 -0.001190 +vn 0.120426 0.724570 0.678579 +vn 0.260750 0.006531 0.965361 +vn 0.272500 -0.255898 0.927488 +vn -0.395581 0.809961 -0.432905 +vn -0.258827 0.918851 -0.297800 +vn 0.004730 0.999878 0.013031 +vn 0.466628 0.599780 0.649983 +vn 0.621937 -0.400861 0.672628 +vn 0.551042 -0.592181 0.587878 +vn 0.649068 0.384991 -0.656087 +vn 0.055971 0.691214 0.720450 +vn -0.115940 0.804590 0.582354 +vn -0.262185 0.897946 0.353435 +vn -0.341655 0.885006 -0.316263 +vn -0.081423 0.793085 -0.603626 +vn -0.155675 0.857753 -0.489883 +vn 0.728690 0.365978 0.578784 +vn 0.318674 0.539384 0.779382 +vn 0.953551 0.300150 -0.024415 +vn -0.133976 0.836818 -0.530808 +vn 0.095401 0.667959 -0.738029 +vn 0.000000 0.999969 0.000000 +vn -0.992523 -0.122013 0.000000 +vn -0.937346 -0.348338 0.000000 +vn -0.905148 -0.348827 -0.242836 +vn -0.958617 -0.122227 -0.257057 +vn -0.832057 0.554674 0.000000 +vn -0.803217 0.555376 -0.215339 +vn -0.048616 0.998810 0.000000 +vn -0.046236 0.998840 -0.012726 +vn 0.544267 0.838893 0.000000 +vn 0.525376 0.839106 0.140843 +vn 0.783471 0.621387 0.000000 +vn 0.756371 0.621845 0.202918 +vn 0.880886 0.473281 0.000000 +vn 0.850551 0.473769 0.228217 +vn -0.810907 -0.349376 -0.469375 +vn -0.859004 -0.122410 -0.497085 +vn -0.719657 0.555559 -0.416425 +vn -0.041749 0.998810 -0.024415 +vn 0.470077 0.839625 0.272011 +vn 0.677236 0.622608 0.391980 +vn 0.761803 0.474471 0.440962 +vn -0.662465 -0.349620 -0.662465 +vn -0.701773 -0.122440 -0.701773 +vn -0.587878 0.555650 -0.587878 +vn -0.034272 0.998810 -0.034272 +vn 0.383831 0.839808 0.383831 +vn 0.553148 0.622913 0.553148 +vn 0.622303 0.474776 0.622303 +vn -0.469375 -0.349376 -0.810907 +vn -0.497085 -0.122379 -0.859004 +vn -0.416425 0.555559 -0.719657 +vn -0.024415 0.998810 -0.041749 +vn 0.272011 0.839625 0.470077 +vn 0.391980 0.622608 0.677236 +vn 0.440962 0.474471 0.761834 +vn -0.242836 -0.348827 -0.905148 +vn -0.257057 -0.122227 -0.958617 +vn -0.215339 0.555376 -0.803217 +vn -0.012726 0.998840 -0.046205 +vn 0.140843 0.839106 0.525376 +vn 0.202918 0.621845 0.756371 +vn 0.228217 0.473769 0.850551 +vn 0.000000 -0.348338 -0.937346 +vn 0.000000 -0.122013 -0.992523 +vn 0.000000 0.554674 -0.832057 +vn 0.000000 0.998810 -0.048616 +vn 0.000000 0.838893 0.544267 +vn 0.000000 0.621387 0.783471 +vn 0.000000 0.473281 0.880886 +vn 0.242836 -0.348827 -0.905148 +vn 0.257057 -0.122227 -0.958617 +vn 0.215308 0.555376 -0.803217 +vn 0.012726 0.998840 -0.046205 +vn -0.140843 0.839106 0.525376 +vn -0.202918 0.621845 0.756340 +vn -0.228217 0.473769 0.850551 +vn 0.469375 -0.349376 -0.810907 +vn 0.497085 -0.122379 -0.859004 +vn 0.416425 0.555559 -0.719657 +vn 0.024415 0.998810 -0.041749 +vn -0.272011 0.839625 0.470077 +vn -0.391980 0.622608 0.677236 +vn -0.440962 0.474502 0.761803 +vn 0.662465 -0.349620 -0.662465 +vn 0.701773 -0.122471 -0.701773 +vn 0.587878 0.555650 -0.587878 +vn 0.034272 0.998810 -0.034272 +vn -0.383831 0.839808 0.383831 +vn -0.553148 0.622913 0.553148 +vn -0.622303 0.474776 0.622303 +vn 0.810907 -0.349406 -0.469375 +vn 0.859004 -0.122379 -0.497085 +vn 0.719657 0.555559 -0.416425 +vn 0.041749 0.998810 -0.024415 +vn -0.470077 0.839625 0.272011 +vn -0.677236 0.622608 0.391980 +vn -0.761803 0.474471 0.440962 +vn 0.905148 -0.348827 -0.242836 +vn 0.958617 -0.122227 -0.257057 +vn 0.803217 0.555376 -0.215339 +vn 0.046205 0.998840 -0.012726 +vn -0.525376 0.839106 0.140843 +vn -0.756340 0.621876 0.202918 +vn -0.850551 0.473769 0.228217 +vn 0.937346 -0.348338 0.000000 +vn 0.992523 -0.122013 0.000000 +vn 0.832026 0.554674 0.000000 +vn 0.048616 0.998810 0.000000 +vn -0.544267 0.838893 0.000000 +vn -0.783471 0.621387 0.000000 +vn 0.905148 -0.348827 0.242836 +vn 0.958617 -0.122227 0.257057 +vn 0.803217 0.555376 0.215308 +vn 0.046205 0.998840 0.012726 +vn -0.525376 0.839106 -0.140843 +vn -0.756340 0.621876 -0.202918 +vn 0.810907 -0.349406 0.469375 +vn 0.859004 -0.122379 0.497085 +vn 0.719657 0.555559 0.416425 +vn 0.041749 0.998810 0.024415 +vn -0.470077 0.839625 -0.272011 +vn -0.677236 0.622608 -0.391980 +vn -0.761803 0.474471 -0.440962 +vn 0.662465 -0.349620 0.662465 +vn 0.701773 -0.122471 0.701773 +vn 0.587878 0.555650 0.587878 +vn 0.034272 0.998810 0.034272 +vn -0.383831 0.839808 -0.383831 +vn -0.553148 0.622913 -0.553148 +vn -0.622303 0.474776 -0.622303 +vn 0.469375 -0.349376 0.810907 +vn 0.497085 -0.122379 0.859004 +vn 0.416425 0.555559 0.719657 +vn 0.024415 0.998810 0.041749 +vn -0.272011 0.839625 -0.470077 +vn -0.391980 0.622608 -0.677236 +vn -0.440962 0.474471 -0.761803 +vn 0.242836 -0.348827 0.905148 +vn 0.257057 -0.122227 0.958617 +vn 0.215339 0.555376 0.803217 +vn 0.012726 0.998840 0.046205 +vn -0.140843 0.839106 -0.525376 +vn -0.202918 0.621845 -0.756371 +vn -0.228217 0.473769 -0.850551 +vn 0.000000 -0.348338 0.937346 +vn 0.000000 -0.122013 0.992523 +vn 0.000000 0.554674 0.832057 +vn 0.000000 0.998810 0.048616 +vn 0.000000 0.838893 -0.544267 +vn 0.000000 0.621387 -0.783471 +vn 0.000000 0.473281 -0.880886 +vn -0.242836 -0.348827 0.905148 +vn -0.257057 -0.122227 0.958617 +vn -0.215308 0.555376 0.803217 +vn -0.012726 0.998840 0.046205 +vn 0.140843 0.839106 -0.525376 +vn 0.202918 0.621845 -0.756371 +vn 0.228217 0.473769 -0.850551 +vn -0.469375 -0.349376 0.810907 +vn -0.497085 -0.122379 0.859004 +vn -0.416425 0.555559 0.719657 +vn -0.024415 0.998810 0.041749 +vn 0.272011 0.839625 -0.470077 +vn 0.391980 0.622608 -0.677236 +vn 0.440962 0.474471 -0.761803 +vn -0.662465 -0.349620 0.662465 +vn -0.701773 -0.122440 0.701773 +vn -0.587878 0.555650 0.587878 +vn -0.034272 0.998810 0.034272 +vn 0.383831 0.839808 -0.383831 +vn 0.553148 0.622913 -0.553148 +vn 0.622303 0.474776 -0.622303 +vn -0.810907 -0.349376 0.469375 +vn -0.859004 -0.122410 0.497085 +vn -0.719657 0.555528 0.416425 +vn -0.041749 0.998810 0.024415 +vn 0.470077 0.839625 -0.272011 +vn 0.677236 0.622639 -0.391980 +vn 0.761803 0.474471 -0.440962 +vn -0.905148 -0.348827 0.242836 +vn -0.958617 -0.122227 0.257057 +vn -0.803217 0.555376 0.215339 +vn -0.046236 0.998840 0.012726 +vn 0.525376 0.839106 -0.140843 +vn 0.756371 0.621845 -0.202918 +vn 0.850551 0.473769 -0.228217 +vn 0.908292 0.418256 0.000000 +vn 0.877041 0.418744 0.235298 +vn 0.920286 0.391156 0.000000 +vn 0.888668 0.391644 0.238441 +vn 0.907315 0.342753 0.243446 +vn 0.785638 0.419416 0.454756 +vn 0.796075 0.392285 0.460799 +vn 0.812830 0.343333 0.470504 +vn 0.931486 0.265542 0.248543 +vn 0.834162 0.266366 0.482864 +vn 0.855312 0.152379 0.495132 +vn 0.966613 -0.042848 0.252602 +vn 0.864498 -0.045808 0.500504 +vn 0.641804 0.419691 0.641804 +vn 0.650349 0.392499 0.650349 +vn 0.664052 0.343577 0.664052 +vn 0.681509 0.266579 0.681509 +vn 0.698813 0.152501 0.698813 +vn 0.706351 -0.045869 0.706351 +vn 0.454756 0.419416 0.785638 +vn 0.460799 0.392285 0.796075 +vn 0.470504 0.343333 0.812830 +vn 0.482864 0.266366 0.834162 +vn 0.495132 0.152409 0.855312 +vn 0.500504 -0.045808 0.864498 +vn 0.235298 0.418744 0.877041 +vn 0.238441 0.391644 0.888668 +vn 0.243446 0.342753 0.907315 +vn 0.249855 0.265908 0.931028 +vn 0.256172 0.152104 0.954558 +vn 0.258980 -0.045717 0.964782 +vn 0.000000 0.418256 0.908292 +vn 0.000000 0.391156 0.920286 +vn 0.000000 0.342357 0.939543 +vn 0.000000 0.265542 0.964080 +vn 0.000000 0.151891 0.988372 +vn 0.000000 -0.045656 0.998932 +vn -0.235298 0.418744 0.877041 +vn -0.238441 0.391644 0.888668 +vn -0.243446 0.342753 0.907315 +vn -0.249855 0.265877 0.931028 +vn -0.256172 0.152104 0.954558 +vn -0.258980 -0.045717 0.964782 +vn -0.454756 0.419416 0.785638 +vn -0.460799 0.392285 0.796075 +vn -0.470504 0.343333 0.812830 +vn -0.482864 0.266366 0.834162 +vn -0.495132 0.152379 0.855312 +vn -0.500504 -0.045808 0.864498 +vn -0.641804 0.419691 0.641804 +vn -0.650349 0.392499 0.650349 +vn -0.664052 0.343577 0.664052 +vn -0.681509 0.266579 0.681509 +vn -0.698813 0.152501 0.698813 +vn -0.706351 -0.045869 0.706351 +vn -0.785638 0.419416 0.454756 +vn -0.796075 0.392285 0.460799 +vn -0.812830 0.343364 0.470504 +vn -0.834162 0.266366 0.482864 +vn -0.855312 0.152379 0.495132 +vn -0.864498 -0.045808 0.500504 +vn -0.907315 0.342753 0.243446 +vn -0.931028 0.265908 0.249855 +vn -0.954558 0.152104 0.256172 +vn -0.964782 -0.045717 0.258980 +vn -0.939543 0.342357 0.000000 +vn -0.964080 0.265542 0.000000 +vn -0.988372 0.151891 0.000000 +vn -0.888668 0.391644 -0.238441 +vn -0.907315 0.342753 -0.243446 +vn -0.931028 0.265877 -0.249855 +vn -0.954558 0.152104 -0.256172 +vn -0.785638 0.419416 -0.454756 +vn -0.796075 0.392285 -0.460799 +vn -0.812830 0.343333 -0.470504 +vn -0.834162 0.266366 -0.482864 +vn -0.855312 0.152379 -0.495132 +vn -0.964782 -0.045717 -0.258980 +vn -0.864498 -0.045808 -0.500504 +vn -0.641804 0.419691 -0.641804 +vn -0.650349 0.392499 -0.650349 +vn -0.664052 0.343577 -0.664052 +vn -0.681509 0.266579 -0.681509 +vn -0.698813 0.152501 -0.698813 +vn -0.706351 -0.045869 -0.706351 +vn -0.454756 0.419416 -0.785638 +vn -0.460799 0.392285 -0.796075 +vn -0.470504 0.343333 -0.812830 +vn -0.482864 0.266366 -0.834162 +vn -0.495132 0.152379 -0.855312 +vn -0.500504 -0.045808 -0.864498 +vn -0.235298 0.418744 -0.877041 +vn -0.238441 0.391644 -0.888668 +vn -0.243446 0.342753 -0.907315 +vn -0.249855 0.265908 -0.931028 +vn -0.256172 0.152104 -0.954558 +vn -0.258980 -0.045717 -0.964782 +vn 0.000000 0.418256 -0.908292 +vn 0.000000 0.391156 -0.920286 +vn 0.000000 0.342357 -0.939543 +vn 0.000000 0.265542 -0.964080 +vn 0.000000 0.151891 -0.988372 +vn 0.000000 -0.045656 -0.998932 +vn 0.235298 0.418744 -0.877041 +vn 0.238441 0.391644 -0.888668 +vn 0.243446 0.342753 -0.907315 +vn 0.249855 0.265877 -0.931028 +vn 0.256172 0.152104 -0.954558 +vn 0.258980 -0.045717 -0.964782 +vn 0.454756 0.419416 -0.785638 +vn 0.460799 0.392285 -0.796075 +vn 0.470504 0.343333 -0.812830 +vn 0.482864 0.266366 -0.834162 +vn 0.495132 0.152379 -0.855312 +vn 0.500504 -0.045808 -0.864498 +vn 0.641804 0.419691 -0.641804 +vn 0.650349 0.392499 -0.650349 +vn 0.664052 0.343577 -0.664052 +vn 0.681509 0.266579 -0.681509 +vn 0.698813 0.152501 -0.698813 +vn 0.706351 -0.045869 -0.706351 +vn 0.785638 0.419416 -0.454756 +vn 0.796075 0.392285 -0.460799 +vn 0.812830 0.343364 -0.470504 +vn 0.834162 0.266366 -0.482864 +vn 0.855312 0.152379 -0.495132 +vn 0.864498 -0.045808 -0.500504 +vn 0.877041 0.418744 -0.235298 +vn 0.888668 0.391644 -0.238441 +vn 0.907315 0.342753 -0.243446 +vn 0.795892 -0.566485 0.213538 +vn 0.712180 -0.701987 0.000000 +vn 0.687399 -0.702445 0.184393 +vn 0.652974 -0.757347 0.000000 +vn 0.630146 -0.757805 0.169012 +vn 0.724021 -0.689749 0.000000 +vn 0.698752 -0.690329 0.187414 +vn 0.886410 -0.462874 0.000000 +vn 0.855861 -0.463454 0.229530 +vn 0.817774 -0.327158 0.473434 +vn 0.712729 -0.567248 0.412549 +vn 0.615345 -0.703146 0.356151 +vn 0.564043 -0.758446 0.326456 +vn 0.625660 -0.690939 0.362102 +vn 0.766625 -0.464125 0.443678 +vn 0.668111 -0.327403 0.668111 +vn 0.582171 -0.567522 0.582171 +vn 0.502579 -0.703421 0.502579 +vn 0.460646 -0.758660 0.460646 +vn 0.510971 -0.691183 0.510971 +vn 0.626209 -0.464370 0.626240 +vn 0.473434 -0.327158 0.817774 +vn 0.412549 -0.567248 0.712729 +vn 0.356151 -0.703146 0.615375 +vn 0.326456 -0.758446 0.564043 +vn 0.362102 -0.690939 0.625660 +vn 0.443678 -0.464125 0.766625 +vn 0.245003 -0.326609 0.912839 +vn 0.213538 -0.566485 0.795892 +vn 0.184393 -0.702445 0.687399 +vn 0.169012 -0.757805 0.630146 +vn 0.187414 -0.690329 0.698752 +vn 0.229530 -0.463454 0.855831 +vn 0.000000 -0.326243 0.945250 +vn 0.000000 -0.565996 0.824396 +vn 0.000000 -0.701987 0.712180 +vn 0.000000 -0.757347 0.652974 +vn 0.000000 -0.689749 0.724021 +vn 0.000000 -0.462905 0.886380 +vn -0.245003 -0.326609 0.912839 +vn -0.213538 -0.566485 0.795892 +vn -0.184393 -0.702445 0.687399 +vn -0.169012 -0.757805 0.630146 +vn -0.187414 -0.690329 0.698752 +vn -0.229530 -0.463454 0.855861 +vn -0.473434 -0.327158 0.817774 +vn -0.412549 -0.567248 0.712729 +vn -0.356151 -0.703146 0.615375 +vn -0.326456 -0.758446 0.564043 +vn -0.362102 -0.690939 0.625660 +vn -0.443678 -0.464125 0.766625 +vn -0.668111 -0.327403 0.668111 +vn -0.582171 -0.567522 0.582171 +vn -0.502579 -0.703421 0.502579 +vn -0.460646 -0.758660 0.460646 +vn -0.510971 -0.691183 0.510971 +vn -0.626209 -0.464370 0.626209 +vn -0.817774 -0.327158 0.473434 +vn -0.712729 -0.567248 0.412549 +vn -0.615375 -0.703146 0.356151 +vn -0.564043 -0.758446 0.326456 +vn -0.625660 -0.690939 0.362102 +vn -0.766625 -0.464125 0.443678 +vn -0.912931 -0.326609 0.244575 +vn -0.687399 -0.702445 0.184393 +vn -0.630146 -0.757805 0.169012 +vn -0.698752 -0.690329 0.187414 +vn -0.855831 -0.463485 0.229530 +vn -0.824396 -0.565996 0.000000 +vn -0.712180 -0.701987 0.000000 +vn -0.652974 -0.757347 0.000000 +vn -0.724021 -0.689749 0.000000 +vn -0.886410 -0.462874 0.000000 +vn -0.795892 -0.566485 -0.213538 +vn -0.687399 -0.702445 -0.184393 +vn -0.630146 -0.757805 -0.169012 +vn -0.698752 -0.690329 -0.187414 +vn -0.855831 -0.463454 -0.229530 +vn -0.817774 -0.327158 -0.473434 +vn -0.712729 -0.567217 -0.412549 +vn -0.615375 -0.703146 -0.356151 +vn -0.564043 -0.758446 -0.326456 +vn -0.625660 -0.690939 -0.362102 +vn -0.766625 -0.464125 -0.443678 +vn -0.668111 -0.327403 -0.668111 +vn -0.582171 -0.567522 -0.582171 +vn -0.502579 -0.703421 -0.502579 +vn -0.460646 -0.758660 -0.460646 +vn -0.510971 -0.691183 -0.510971 +vn -0.626209 -0.464370 -0.626209 +vn -0.473434 -0.327158 -0.817774 +vn -0.412549 -0.567248 -0.712729 +vn -0.356151 -0.703146 -0.615375 +vn -0.326456 -0.758446 -0.564043 +vn -0.362102 -0.690939 -0.625660 +vn -0.443678 -0.464125 -0.766625 +vn -0.245003 -0.326609 -0.912839 +vn -0.213538 -0.566485 -0.795892 +vn -0.184393 -0.702445 -0.687399 +vn -0.169012 -0.757805 -0.630146 +vn -0.187414 -0.690329 -0.698752 +vn -0.229530 -0.463454 -0.855831 +vn 0.000000 -0.326243 -0.945250 +vn 0.000000 -0.565996 -0.824396 +vn 0.000000 -0.701987 -0.712180 +vn 0.000000 -0.757347 -0.652974 +vn 0.000000 -0.689749 -0.724021 +vn 0.000000 -0.462905 -0.886380 +vn 0.245003 -0.326609 -0.912839 +vn 0.213538 -0.566485 -0.795892 +vn 0.184393 -0.702445 -0.687399 +vn 0.169012 -0.757805 -0.630146 +vn 0.187445 -0.690329 -0.698752 +vn 0.229530 -0.463454 -0.855861 +vn 0.473434 -0.327158 -0.817774 +vn 0.412549 -0.567248 -0.712729 +vn 0.356151 -0.703146 -0.615375 +vn 0.326456 -0.758446 -0.564043 +vn 0.362102 -0.690939 -0.625660 +vn 0.443678 -0.464125 -0.766625 +vn 0.668111 -0.327403 -0.668111 +vn 0.582171 -0.567522 -0.582171 +vn 0.502579 -0.703421 -0.502579 +vn 0.460646 -0.758660 -0.460646 +vn 0.510971 -0.691183 -0.510971 +vn 0.626209 -0.464370 -0.626209 +vn 0.817774 -0.327158 -0.473434 +vn 0.712729 -0.567248 -0.412549 +vn 0.615375 -0.703146 -0.356151 +vn 0.564043 -0.758446 -0.326456 +vn 0.625660 -0.690939 -0.362102 +vn 0.766625 -0.464125 -0.443678 +vn 0.912839 -0.326609 -0.244942 +vn 0.795892 -0.566485 -0.213538 +vn 0.687399 -0.702445 -0.184393 +vn 0.630146 -0.757805 -0.169012 +vn 0.698752 -0.690329 -0.187414 +vn 0.855861 -0.463454 -0.229530 +vn 0.025666 -0.999664 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.024781 -0.999664 -0.006623 +vn 0.068667 -0.997620 0.000000 +vn 0.066256 -0.997620 -0.017731 +vn 0.157170 -0.987548 0.000000 +vn 0.151677 -0.987579 -0.040620 +vn 0.373150 -0.927763 0.000000 +vn 0.360118 -0.927885 -0.096469 +vn 0.789148 -0.614154 0.000000 +vn 0.762017 -0.614399 -0.204505 +vn 0.022156 -0.999664 -0.012787 +vn 0.059236 -0.997650 -0.034272 +vn 0.135624 -0.987640 -0.078463 +vn 0.322153 -0.928129 -0.186377 +vn 0.682333 -0.615131 -0.394971 +vn 0.018067 -0.999664 -0.018067 +vn 0.048341 -0.997650 -0.048341 +vn 0.110691 -0.987640 -0.110691 +vn 0.262947 -0.928251 -0.262947 +vn 0.557329 -0.615375 -0.557329 +vn 0.012787 -0.999664 -0.022156 +vn 0.034272 -0.997650 -0.059236 +vn 0.078463 -0.987640 -0.135624 +vn 0.186377 -0.928129 -0.322153 +vn 0.394971 -0.615131 -0.682302 +vn 0.006623 -0.999664 -0.024781 +vn 0.017731 -0.997620 -0.066256 +vn 0.040620 -0.987579 -0.151677 +vn 0.096469 -0.927885 -0.360118 +vn 0.204474 -0.614399 -0.762017 +vn 0.000000 -0.999664 -0.025666 +vn 0.000000 -0.997620 -0.068667 +vn 0.000000 -0.987548 -0.157170 +vn 0.000000 -0.927763 -0.373150 +vn 0.000000 -0.614154 -0.789148 +vn -0.006623 -0.999664 -0.024781 +vn -0.017731 -0.997620 -0.066256 +vn -0.040620 -0.987579 -0.151677 +vn -0.096469 -0.927885 -0.360118 +vn -0.204474 -0.614399 -0.762017 +vn -0.012787 -0.999664 -0.022156 +vn -0.034272 -0.997650 -0.059236 +vn -0.078463 -0.987640 -0.135624 +vn -0.186377 -0.928129 -0.322153 +vn -0.394971 -0.615131 -0.682333 +vn -0.018067 -0.999664 -0.018067 +vn -0.048341 -0.997650 -0.048341 +vn -0.110691 -0.987640 -0.110691 +vn -0.262947 -0.928251 -0.262947 +vn -0.557329 -0.615375 -0.557329 +vn -0.022156 -0.999664 -0.012787 +vn -0.059236 -0.997650 -0.034272 +vn -0.135624 -0.987640 -0.078463 +vn -0.322153 -0.928129 -0.186377 +vn -0.682302 -0.615131 -0.394971 +vn -0.024781 -0.999664 -0.006623 +vn -0.066256 -0.997620 -0.017731 +vn -0.151677 -0.987579 -0.040620 +vn -0.360118 -0.927885 -0.096469 +vn -0.762017 -0.614399 -0.204474 +vn -0.025666 -0.999664 0.000000 +vn -0.068667 -0.997620 0.000000 +vn -0.157170 -0.987548 0.000000 +vn -0.373150 -0.927763 0.000000 +vn -0.789148 -0.614154 0.000000 +vn -0.024781 -0.999664 0.006623 +vn -0.066256 -0.997620 0.017731 +vn -0.151677 -0.987579 0.040620 +vn -0.360149 -0.927885 0.096469 +vn -0.762017 -0.614399 0.204474 +vn -0.022156 -0.999664 0.012787 +vn -0.059236 -0.997650 0.034272 +vn -0.135624 -0.987640 0.078463 +vn -0.322153 -0.928129 0.186377 +vn -0.682333 -0.615131 0.394971 +vn -0.018067 -0.999664 0.018067 +vn -0.048341 -0.997650 0.048341 +vn -0.110691 -0.987640 0.110691 +vn -0.262947 -0.928251 0.262947 +vn -0.557329 -0.615375 0.557329 +vn -0.012787 -0.999664 0.022156 +vn -0.034272 -0.997650 0.059236 +vn -0.078463 -0.987640 0.135624 +vn -0.186377 -0.928129 0.322153 +vn -0.394971 -0.615131 0.682302 +vn -0.006623 -0.999664 0.024781 +vn -0.017731 -0.997620 0.066256 +vn -0.040620 -0.987579 0.151677 +vn -0.096469 -0.927885 0.360118 +vn -0.204474 -0.614399 0.762017 +vn 0.000000 -0.999664 0.025666 +vn 0.000000 -0.997620 0.068667 +vn 0.000000 -0.987548 0.157170 +vn 0.000000 -0.927763 0.373150 +vn 0.000000 -0.614154 0.789148 +vn 0.006623 -0.999664 0.024781 +vn 0.017731 -0.997620 0.066256 +vn 0.040620 -0.987579 0.151677 +vn 0.096469 -0.927885 0.360149 +vn 0.204474 -0.614399 0.762017 +vn 0.012787 -0.999664 0.022156 +vn 0.034272 -0.997650 0.059236 +vn 0.078463 -0.987640 0.135624 +vn 0.186377 -0.928129 0.322153 +vn 0.394971 -0.615131 0.682333 +vn 0.018067 -0.999664 0.018067 +vn 0.048341 -0.997650 0.048341 +vn 0.110691 -0.987640 0.110691 +vn 0.262947 -0.928251 0.262947 +vn 0.557329 -0.615375 0.557329 +vn 0.022156 -0.999664 0.012787 +vn 0.059236 -0.997650 0.034272 +vn 0.135624 -0.987640 0.078463 +vn 0.322153 -0.928129 0.186346 +vn 0.682302 -0.615131 0.394971 +vn 0.024781 -0.999664 0.006623 +vn 0.066256 -0.997620 0.017731 +vn 0.151677 -0.987579 0.040620 +vn 0.360118 -0.927885 0.096469 +vn 0.762017 -0.614399 0.204474 +vn 0.464827 -0.373638 -0.802667 +vn 0.655812 -0.373882 -0.655812 +vn 0.000000 -0.372539 0.927976 +vn -0.240699 -0.373028 0.896023 +vn -0.802667 -0.373608 0.464827 +vn 0.896023 -0.372997 -0.240699 +vn -0.927976 -0.372539 0.000000 +vn 0.927976 -0.372539 0.000000 +vn 0.717063 0.696982 0.000000 +vn 0.990387 -0.138310 -0.000061 +vn 0.956694 -0.138737 0.255806 +vn 0.692129 0.697470 0.185583 +vn 0.857326 -0.139317 0.495529 +vn 0.620045 0.697653 0.358837 +vn 0.700125 -0.139531 0.700217 +vn 0.506516 0.697714 0.506546 +vn 0.495468 -0.139286 0.857356 +vn 0.358776 0.697714 0.620014 +vn 0.255867 -0.138737 0.956694 +vn 0.185583 0.697531 0.692068 +vn 0.000061 -0.138310 0.990387 +vn 0.000000 0.696982 0.717063 +vn -0.255806 -0.138737 0.956694 +vn -0.185583 0.697470 0.692129 +vn -0.495529 -0.139317 0.857326 +vn -0.358837 0.697653 0.620045 +vn -0.700217 -0.139531 0.700156 +vn -0.506546 0.697714 0.506516 +vn -0.857356 -0.139286 0.495468 +vn -0.620014 0.697714 0.358776 +vn -0.956694 -0.138737 0.255867 +vn -0.692068 0.697531 0.185583 +vn -0.990387 -0.138310 0.000061 +vn -0.717063 0.696982 0.000000 +vn -0.956694 -0.138737 -0.255806 +vn -0.692129 0.697470 -0.185583 +vn -0.857326 -0.139317 -0.495529 +vn -0.620045 0.697653 -0.358837 +vn -0.700125 -0.139531 -0.700217 +vn -0.506516 0.697714 -0.506546 +vn -0.495468 -0.139286 -0.857356 +vn -0.358776 0.697714 -0.620014 +vn -0.255867 -0.138737 -0.956694 +vn -0.185583 0.697531 -0.692068 +vn -0.000061 -0.138310 -0.990387 +vn 0.000000 0.696982 -0.717063 +vn 0.255806 -0.138737 -0.956694 +vn 0.185583 0.697470 -0.692129 +vn 0.495529 -0.139317 -0.857326 +vn 0.358837 0.697653 -0.620045 +vn 0.700217 -0.139531 -0.700156 +vn 0.506546 0.697714 -0.506516 +vn 0.857356 -0.139286 -0.495468 +vn 0.620014 0.697714 -0.358776 +vn 0.956694 -0.138737 -0.255867 +vn 0.692068 0.697531 -0.185583 +vn 0.292520 0.956236 0.000000 +vn 0.282083 0.956389 0.075686 +vn 0.177953 0.984008 0.000000 +vn 0.171606 0.984069 0.046022 +vn 0.158879 0.987274 0.000000 +vn 0.153264 0.987304 0.041078 +vn 0.217719 0.975982 0.000000 +vn 0.210059 0.976043 0.056276 +vn 0.504715 0.863277 0.000000 +vn 0.487197 0.863460 0.130558 +vn 0.693258 0.720664 0.000000 +vn 0.669057 0.721183 0.179449 +vn 0.252388 0.956511 0.146092 +vn 0.153508 0.984130 0.088839 +vn 0.137059 0.987365 0.079318 +vn 0.187872 0.976135 0.108676 +vn 0.435926 0.863887 0.252205 +vn 0.598956 0.721824 0.346660 +vn 0.206091 0.956572 0.206091 +vn 0.125340 0.984161 0.125340 +vn 0.111911 0.987396 0.111911 +vn 0.153356 0.976196 0.153356 +vn 0.355907 0.864071 0.355907 +vn 0.489151 0.722098 0.489151 +vn 0.146092 0.956511 0.252388 +vn 0.088839 0.984130 0.153508 +vn 0.079318 0.987365 0.137059 +vn 0.108676 0.976135 0.187872 +vn 0.252205 0.863887 0.435926 +vn 0.346660 0.721824 0.598956 +vn 0.075686 0.956389 0.282083 +vn 0.046022 0.984069 0.171606 +vn 0.041078 0.987304 0.153264 +vn 0.056276 0.976043 0.210059 +vn 0.130558 0.863460 0.487197 +vn 0.179449 0.721183 0.669057 +vn 0.000000 0.956236 0.292520 +vn 0.000000 0.984008 0.177953 +vn 0.000000 0.987274 0.158879 +vn 0.000000 0.975982 0.217719 +vn 0.000000 0.863277 0.504715 +vn 0.000000 0.720664 0.693258 +vn -0.075686 0.956389 0.282083 +vn -0.046022 0.984069 0.171606 +vn -0.041078 0.987304 0.153264 +vn -0.056276 0.976043 0.210059 +vn -0.130558 0.863460 0.487197 +vn -0.179449 0.721183 0.669057 +vn -0.146092 0.956511 0.252388 +vn -0.088839 0.984130 0.153508 +vn -0.079318 0.987365 0.137059 +vn -0.108676 0.976135 0.187872 +vn -0.252205 0.863887 0.435926 +vn -0.346660 0.721824 0.598956 +vn -0.206091 0.956572 0.206091 +vn -0.125340 0.984161 0.125340 +vn -0.111911 0.987396 0.111911 +vn -0.153356 0.976196 0.153356 +vn -0.355907 0.864071 0.355907 +vn -0.489151 0.722098 0.489151 +vn -0.252388 0.956511 0.146092 +vn -0.153508 0.984130 0.088839 +vn -0.137059 0.987365 0.079318 +vn -0.187872 0.976135 0.108676 +vn -0.435926 0.863887 0.252205 +vn -0.598956 0.721824 0.346660 +vn -0.282083 0.956389 0.075686 +vn -0.171606 0.984069 0.046022 +vn -0.153264 0.987304 0.041078 +vn -0.210059 0.976043 0.056276 +vn -0.487197 0.863460 0.130558 +vn -0.669057 0.721183 0.179449 +vn -0.292520 0.956236 0.000000 +vn -0.177953 0.984008 0.000000 +vn -0.158879 0.987274 0.000000 +vn -0.217719 0.975982 0.000000 +vn -0.504715 0.863277 0.000000 +vn -0.693258 0.720664 0.000000 +vn -0.282083 0.956389 -0.075686 +vn -0.171606 0.984069 -0.046022 +vn -0.153264 0.987304 -0.041078 +vn -0.210059 0.976043 -0.056276 +vn -0.487197 0.863460 -0.130558 +vn -0.669057 0.721183 -0.179449 +vn -0.252388 0.956511 -0.146092 +vn -0.153508 0.984130 -0.088839 +vn -0.137059 0.987365 -0.079318 +vn -0.187872 0.976135 -0.108676 +vn -0.435926 0.863887 -0.252205 +vn -0.598956 0.721824 -0.346660 +vn -0.206091 0.956572 -0.206091 +vn -0.125340 0.984161 -0.125340 +vn -0.111911 0.987396 -0.111911 +vn -0.153356 0.976196 -0.153356 +vn -0.355907 0.864071 -0.355907 +vn -0.489151 0.722098 -0.489151 +vn -0.146092 0.956511 -0.252388 +vn -0.088839 0.984130 -0.153508 +vn -0.079318 0.987365 -0.137059 +vn -0.108676 0.976135 -0.187872 +vn -0.252205 0.863887 -0.435926 +vn -0.346660 0.721824 -0.598956 +vn -0.075686 0.956389 -0.282083 +vn -0.046022 0.984069 -0.171606 +vn -0.041078 0.987304 -0.153264 +vn -0.056276 0.976043 -0.210059 +vn -0.130558 0.863460 -0.487197 +vn -0.179449 0.721183 -0.669057 +vn 0.000000 0.956236 -0.292520 +vn 0.000000 0.984008 -0.177953 +vn 0.000000 0.987274 -0.158879 +vn 0.000000 0.975982 -0.217719 +vn 0.000000 0.863277 -0.504715 +vn 0.000000 0.720664 -0.693258 +vn 0.075686 0.956389 -0.282083 +vn 0.046022 0.984069 -0.171606 +vn 0.041078 0.987304 -0.153264 +vn 0.056276 0.976043 -0.210059 +vn 0.130558 0.863460 -0.487197 +vn 0.179449 0.721183 -0.669057 +vn 0.146092 0.956511 -0.252388 +vn 0.088839 0.984130 -0.153508 +vn 0.079318 0.987365 -0.137059 +vn 0.108676 0.976135 -0.187872 +vn 0.252205 0.863887 -0.435926 +vn 0.346660 0.721824 -0.598956 +vn 0.206091 0.956572 -0.206091 +vn 0.125340 0.984161 -0.125340 +vn 0.111911 0.987396 -0.111911 +vn 0.153356 0.976196 -0.153356 +vn 0.355907 0.864071 -0.355907 +vn 0.489151 0.722098 -0.489151 +vn 0.252388 0.956511 -0.146092 +vn 0.153508 0.984130 -0.088839 +vn 0.137059 0.987365 -0.079318 +vn 0.187872 0.976135 -0.108676 +vn 0.435926 0.863887 -0.252205 +vn 0.598956 0.721824 -0.346660 +vn 0.282083 0.956389 -0.075686 +vn 0.171606 0.984069 -0.046022 +vn 0.153264 0.987304 -0.041078 +vn 0.210059 0.976043 -0.056276 +vn 0.487197 0.863460 -0.130558 +vn 0.669057 0.721183 -0.179449 +vn 0.363842 0.931455 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.351451 0.931516 0.093509 +vn 0.968261 0.249916 0.000000 +vn 0.935423 0.249763 0.250130 +vn 0.842860 -0.538102 0.000000 +vn 0.813959 -0.538713 0.217292 +vn 0.786767 -0.617206 -0.000031 +vn 0.759514 -0.618000 0.202857 +vn 0.314432 0.931791 0.181280 +vn 0.838404 0.249855 0.484359 +vn 0.729026 -0.539720 0.420911 +vn 0.680013 -0.619068 0.392743 +vn 0.256386 0.931913 0.256417 +vn 0.684652 0.249886 0.684652 +vn 0.595050 -0.540147 0.595050 +vn 0.555010 -0.619526 0.555040 +vn 0.181280 0.931791 0.314432 +vn 0.484359 0.249825 0.838404 +vn 0.420881 -0.539720 0.729026 +vn 0.392712 -0.619098 0.680013 +vn 0.093509 0.931516 0.351451 +vn 0.250160 0.249763 0.935423 +vn 0.217322 -0.538713 0.813959 +vn 0.202887 -0.618030 0.759484 +vn 0.000000 0.931455 0.363842 +vn 0.000000 0.249916 0.968261 +vn 0.000000 -0.538102 0.842860 +vn 0.000031 -0.617206 0.786767 +vn -0.093509 0.931516 0.351451 +vn -0.250130 0.249763 0.935423 +vn -0.217292 -0.538682 0.813959 +vn -0.202857 -0.618000 0.759514 +vn -0.181280 0.931791 0.314432 +vn -0.484359 0.249855 0.838404 +vn -0.420911 -0.539720 0.729026 +vn -0.392743 -0.619068 0.680013 +vn -0.256417 0.931913 0.256386 +vn -0.684652 0.249886 0.684652 +vn -0.595050 -0.540147 0.595050 +vn -0.555040 -0.619526 0.555010 +vn -0.314432 0.931791 0.181280 +vn -0.838404 0.249825 0.484359 +vn -0.729026 -0.539720 0.420881 +vn -0.680013 -0.619098 0.392712 +vn -0.351451 0.931516 0.093509 +vn -0.935423 0.249763 0.250160 +vn -0.813959 -0.538713 0.217292 +vn -0.759484 -0.618030 0.202887 +vn -0.363842 0.931455 0.000000 +vn -0.968261 0.249916 0.000000 +vn -0.842860 -0.538102 0.000000 +vn -0.786767 -0.617206 0.000031 +vn -0.351451 0.931516 -0.093509 +vn -0.935423 0.249763 -0.250130 +vn -0.813959 -0.538713 -0.217292 +vn -0.759514 -0.618000 -0.202857 +vn -0.314432 0.931791 -0.181280 +vn -0.838404 0.249855 -0.484359 +vn -0.729026 -0.539720 -0.420911 +vn -0.680013 -0.619068 -0.392743 +vn -0.256386 0.931913 -0.256417 +vn -0.684652 0.249886 -0.684652 +vn -0.595050 -0.540147 -0.595050 +vn -0.555010 -0.619526 -0.555040 +vn -0.181280 0.931791 -0.314432 +vn -0.484359 0.249825 -0.838404 +vn -0.420881 -0.539720 -0.729026 +vn -0.392712 -0.619098 -0.680013 +vn -0.093509 0.931516 -0.351451 +vn -0.250160 0.249763 -0.935423 +vn -0.217322 -0.538713 -0.813959 +vn -0.202887 -0.618030 -0.759484 +vn 0.000000 0.931455 -0.363842 +vn 0.000000 0.249916 -0.968261 +vn 0.000000 -0.538102 -0.842860 +vn -0.000031 -0.617206 -0.786767 +vn 0.093509 0.931516 -0.351451 +vn 0.250130 0.249763 -0.935423 +vn 0.217292 -0.538682 -0.813959 +vn 0.202857 -0.618000 -0.759514 +vn 0.181280 0.931791 -0.314432 +vn 0.484359 0.249855 -0.838404 +vn 0.420911 -0.539720 -0.729026 +vn 0.392743 -0.619068 -0.680013 +vn 0.256417 0.931913 -0.256386 +vn 0.684652 0.249886 -0.684652 +vn 0.595050 -0.540147 -0.595050 +vn 0.555040 -0.619526 -0.555010 +vn 0.314432 0.931791 -0.181280 +vn 0.838404 0.249825 -0.484359 +vn 0.729026 -0.539720 -0.420881 +vn 0.680013 -0.619098 -0.392712 +vn 0.351451 0.931516 -0.093509 +vn 0.935423 0.249763 -0.250160 +vn 0.813959 -0.538713 -0.217292 +vn 0.759484 -0.618030 -0.202887 +vn -0.354198 0.930296 -0.095187 +vn 0.095187 0.930296 0.354198 +vn 0.354198 0.930296 0.095187 +vn 0.183721 0.930387 0.317179 +vn -0.183721 0.930387 -0.317179 +vn -0.367443 0.930021 0.000000 +vn -0.183721 0.930387 0.317179 +vn 0.367412 0.930021 0.000000 +vn -0.317179 0.930387 0.183721 +vn -0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 -0.367443 +vn -0.354198 0.930296 0.095187 +vn 0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 0.367443 +vn -0.317179 0.930387 -0.183721 +vn 0.317179 0.930387 -0.183721 +vn -0.095187 0.930296 0.354198 +vn 0.317179 0.930387 0.183721 +vn 0.354198 0.930296 -0.095187 +vn 0.183721 0.930387 -0.317179 +vn -0.034730 0.999390 0.000000 +vn 0.033479 0.999390 -0.009003 +vn 0.034730 0.999390 0.000000 +vn 0.009003 0.999390 -0.033479 +vn 0.000000 0.999390 -0.034730 +vn -0.259163 0.930387 0.259163 +vn -0.017335 0.999390 0.029939 +vn 0.947539 0.295083 0.122654 +vn -0.004486 0.999969 0.000000 +vn -0.004151 0.950468 0.310739 +vn -0.003021 0.719291 0.694662 +vn -0.998688 0.050722 0.000000 +vn -0.003143 0.719321 -0.694632 +vn 0.970214 0.213324 -0.114505 +vn -0.136235 0.879482 -0.455947 +vn 0.949858 0.312662 0.000000 +vn 0.055757 -0.017579 -0.998260 +vn 0.201300 -0.540880 -0.816645 +vn 0.974456 -0.186071 -0.125645 +vn 0.988098 -0.096286 0.119938 +vn 0.974456 -0.186041 0.125614 +vn -0.879574 -0.475723 0.000000 +vn -0.873775 -0.472610 -0.114475 +vn 0.988067 -0.096286 -0.119938 +vn 0.295480 -0.855464 -0.425214 +vn -0.976196 -0.174993 -0.127903 +vn -0.971007 -0.205725 0.121677 +vn -0.976196 -0.174963 0.127903 +vn -0.976196 -0.174993 0.127903 +vn 0.896054 -0.372997 0.240699 +vn -0.802667 -0.373638 -0.464827 +vn -0.655812 -0.373852 -0.655812 +vn -0.240699 -0.373028 -0.896023 +vn -0.464827 -0.373638 -0.802667 +vn -0.896023 -0.373028 0.240699 +vn 0.000000 -0.372539 -0.927976 +vn -0.655812 -0.373852 0.655812 +vn 0.240699 -0.373028 0.896023 +vn -0.896023 -0.373028 -0.240699 +vn 0.802667 -0.373638 -0.464827 +vn 0.655812 -0.373882 0.655812 +vn 0.464827 -0.373638 0.802667 +vn -0.464827 -0.373638 0.802667 +vn 0.240699 -0.373028 -0.896023 +vn 0.802667 -0.373638 0.464827 +vn -0.033479 0.999390 0.009003 +vn -0.259163 0.930387 -0.259163 +vn -0.024445 0.999390 -0.024445 +vn -0.029939 0.999390 -0.017335 +vn 0.259163 0.930387 -0.259163 +vn 0.024445 0.999390 -0.024445 +vn 0.017335 0.999390 -0.029939 +vn 0.029939 0.999390 -0.017335 +vn 0.033479 0.999390 0.009003 +vn -0.009003 0.999390 0.033479 +vn 0.000000 0.999390 0.034730 +vn -0.017335 0.999390 -0.029939 +vn 0.259163 0.930387 0.259163 +vn 0.029939 0.999390 0.017335 +vn -0.009003 0.999390 -0.033479 +vn 0.024445 0.999390 0.024445 +vn 0.017335 0.999390 0.029939 +vn 0.009003 0.999390 0.033479 +vn -0.033479 0.999390 -0.009003 +vn -0.024445 0.999390 0.024445 +vn -0.029939 0.999390 0.017335 +vn 0.055757 -0.017579 0.998260 +vn 0.294198 -0.855403 0.426252 +vn 0.201300 -0.540880 0.816614 +s 1 +f 34//1 1243//2 593//3 +f 52//4 27//5 40//6 +f 52//4 40//6 65//7 +f 77//8 52//4 65//7 +f 77//8 65//7 84//9 +f 107//10 77//8 84//9 +f 107//10 84//9 85//11 +f 115//12 107//10 85//11 +f 115//12 85//11 99//13 +f 129//14 115//12 99//13 +f 129//14 99//13 128//15 +f 1252//16 36//17 40//6 +f 65//7 40//6 64//18 +f 65//7 64//18 58//19 +f 84//9 65//7 58//19 +f 84//9 58//19 59//20 +f 85//11 84//9 59//20 +f 85//11 59//20 70//21 +f 99//13 85//11 70//21 +f 99//13 70//21 98//22 +f 128//15 99//13 98//22 +f 128//15 98//22 114//23 +f 1244//24 33//25 64//18 +f 58//19 64//18 33//25 +f 58//19 33//25 35//26 +f 59//20 58//19 35//26 +f 59//20 35//26 45//27 +f 70//21 59//20 45//27 +f 70//21 45//27 69//28 +f 98//22 70//21 69//28 +f 98//22 69//28 83//29 +f 114//23 98//22 83//29 +f 114//23 83//29 113//30 +f 553//31 1//32 566//33 +f 35//26 33//25 20//34 +f 35//26 20//34 24//35 +f 45//27 35//26 24//35 +f 45//27 24//35 44//36 +f 69//28 45//27 44//36 +f 69//28 44//36 57//37 +f 83//29 69//28 57//37 +f 83//29 57//37 82//38 +f 113//30 83//29 82//38 +f 113//30 82//38 112//39 +f 566//33 1283//40 9//41 +f 24//35 20//34 18//42 +f 24//35 18//42 23//43 +f 44//36 24//35 23//43 +f 44//36 23//43 32//44 +f 57//37 44//36 32//44 +f 57//37 32//44 56//45 +f 82//38 57//37 56//45 +f 82//38 56//45 81//46 +f 112//39 82//38 81//46 +f 112//39 81//46 111//47 +f 4//48 8//49 1250//50 +f 23//43 18//42 8//49 +f 23//43 8//49 17//51 +f 32//44 23//43 17//51 +f 32//44 17//51 31//52 +f 56//45 32//44 31//52 +f 56//45 31//52 55//53 +f 81//46 56//45 55//53 +f 81//46 55//53 80//54 +f 111//47 81//46 80//54 +f 111//47 80//54 110//55 +f 565//56 592//57 1233//58 +f 17//51 8//49 4//48 +f 17//51 4//48 16//59 +f 31//52 17//51 16//59 +f 31//52 16//59 30//60 +f 55//53 31//52 30//60 +f 55//53 30//60 54//61 +f 80//54 55//53 54//61 +f 80//54 54//61 79//62 +f 110//55 80//54 79//62 +f 110//55 79//62 109//63 +f 1//32 565//56 2//64 +f 6//65 2//64 565//56 +f 16//59 4//48 7//66 +f 16//59 7//66 22//67 +f 30//60 16//59 22//67 +f 30//60 22//67 43//68 +f 54//61 30//60 43//68 +f 54//61 43//68 68//69 +f 79//62 54//61 68//69 +f 79//62 68//69 97//70 +f 109//63 79//62 97//70 +f 109//63 97//70 127//71 +f 565//56 1233//58 1249//58 +f 13//72 14//73 5//74 +f 22//67 7//66 15//75 +f 22//67 15//75 29//76 +f 43//68 22//67 29//76 +f 43//68 29//76 42//77 +f 68//69 43//68 42//77 +f 68//69 42//77 67//78 +f 97//70 68//69 67//78 +f 97//70 67//78 96//79 +f 127//71 97//70 96//79 +f 127//71 96//79 126//80 +f 11//81 15//75 1240//82 +f 1289//83 34//1 593//3 +f 29//76 15//75 14//73 +f 29//76 14//73 21//84 +f 42//77 29//76 21//84 +f 42//77 21//84 41//85 +f 67//78 42//77 41//85 +f 67//78 41//85 66//86 +f 96//79 67//78 66//86 +f 96//79 66//86 95//87 +f 126//80 96//79 95//87 +f 126//80 95//87 125//88 +f 636//89 1243//2 26//2 +f 636//89 26//2 592//57 +f 21//84 14//73 13//72 +f 21//84 13//72 28//90 +f 41//85 21//84 28//90 +f 41//85 28//90 53//91 +f 66//86 41//85 53//91 +f 66//86 53//91 78//92 +f 95//87 66//86 78//92 +f 95//87 78//92 108//93 +f 125//88 95//87 108//93 +f 125//88 108//93 136//94 +f 12//95 13//72 5//74 +f 28//90 13//72 27//5 +f 28//90 27//5 52//4 +f 53//91 28//90 52//4 +f 53//91 52//4 77//8 +f 78//92 53//91 77//8 +f 78//92 77//8 107//10 +f 108//93 78//92 107//10 +f 108//93 107//10 115//12 +f 136//94 108//93 115//12 +f 136//94 115//12 129//14 +f 148//96 129//14 128//15 +f 148//96 128//15 143//97 +f 121//98 148//96 143//97 +f 121//98 143//97 122//99 +f 92//100 121//98 122//99 +f 92//100 122//99 93//101 +f 62//102 92//100 93//101 +f 62//102 93//101 63//103 +f 39//104 62//102 63//103 +f 39//104 63//103 51//105 +f 10//106 39//104 51//105 +f 10//106 51//105 49//107 +f 143//97 128//15 114//23 +f 143//97 114//23 142//108 +f 122//99 143//97 142//108 +f 122//99 142//108 123//109 +f 93//101 122//99 123//109 +f 93//101 123//109 94//110 +f 63//103 93//101 94//110 +f 63//103 94//110 76//111 +f 51//105 63//103 76//111 +f 51//105 76//111 75//112 +f 49//107 51//105 75//112 +f 49//107 75//112 61//113 +f 142//108 114//23 113//30 +f 142//108 113//30 141//114 +f 123//109 142//108 141//114 +f 123//109 141//114 124//115 +f 94//110 123//109 124//115 +f 94//110 124//115 106//116 +f 76//111 94//110 106//116 +f 76//111 106//116 105//117 +f 75//112 76//111 105//117 +f 75//112 105//117 91//118 +f 61//113 75//112 91//118 +f 61//113 91//118 90//119 +f 141//114 113//30 112//39 +f 141//114 112//39 140//120 +f 124//115 141//114 140//120 +f 124//115 140//120 135//121 +f 106//116 124//115 135//121 +f 106//116 135//121 134//122 +f 105//117 106//116 134//122 +f 105//117 134//122 120//123 +f 91//118 105//117 120//123 +f 91//118 120//123 119//124 +f 90//119 91//118 119//124 +f 140//120 112//39 111//47 +f 140//120 111//47 139//125 +f 135//121 140//120 139//125 +f 135//121 139//125 155//126 +f 134//122 135//121 155//126 +f 134//122 155//126 147//127 +f 120//123 134//122 147//127 +f 120//123 147//127 144//128 +f 119//124 120//123 144//128 +f 119//124 144//128 116//129 +f 26//2 1234//130 592//57 +f 139//125 111//47 110//55 +f 139//125 110//55 138//131 +f 155//126 139//125 138//131 +f 155//126 138//131 156//132 +f 147//127 155//126 156//132 +f 147//127 156//132 145//133 +f 144//128 147//127 145//133 +f 144//128 145//133 117//134 +f 116//129 144//128 117//134 +f 116//129 117//134 88//135 +f 27//5 13//72 12//95 +f 1242//136 88//135 71//137 +f 138//131 110//55 109//63 +f 138//131 109//63 137//138 +f 156//132 138//131 137//138 +f 156//132 137//138 154//139 +f 145//133 156//132 154//139 +f 145//133 154//139 131//140 +f 117//134 145//133 131//140 +f 117//134 131//140 101//141 +f 88//135 117//134 101//141 +f 88//135 101//141 86//142 +f 60//143 74//144 1248//145 +f 137//138 109//63 127//71 +f 137//138 127//71 151//146 +f 154//139 137//138 151//146 +f 154//139 151//146 153//147 +f 131//140 154//139 153//147 +f 131//140 153//147 130//148 +f 101//141 131//140 130//148 +f 101//141 130//148 100//149 +f 86//142 101//141 100//149 +f 86//142 100//149 74//144 +f 47//150 1235//151 631//152 +f 74//144 48//153 1248//145 +f 151//146 127//71 126//80 +f 151//146 126//80 150//154 +f 153//147 151//146 150//154 +f 153//147 150//154 146//155 +f 130//148 153//147 146//155 +f 130//148 146//155 118//156 +f 100//149 130//148 118//156 +f 100//149 118//156 89//157 +f 74//144 100//149 89//157 +f 74//144 89//157 48//153 +f 1247//158 87//159 715//160 +f 104//161 116//129 1242//136 +f 150//154 126//80 125//88 +f 150//154 125//88 149//162 +f 146//155 150//154 149//162 +f 146//155 149//162 132//163 +f 118//156 146//155 132//163 +f 118//156 132//163 102//164 +f 89//157 118//156 102//164 +f 89//157 102//164 72//165 +f 48//153 89//157 72//165 +f 48//153 72//165 46//166 +f 37//167 48//153 46//166 +f 37//167 46//166 38//168 +f 149//162 125//88 136//94 +f 149//162 136//94 152//169 +f 132//163 149//162 152//169 +f 132//163 152//169 133//170 +f 102//164 132//163 133//170 +f 102//164 133//170 103//171 +f 72//165 102//164 103//171 +f 72//165 103//171 73//172 +f 46//166 72//165 73//172 +f 46//166 73//172 50//173 +f 38//168 46//166 50//173 +f 38//168 50//173 25//174 +f 152//169 136//94 129//14 +f 152//169 129//14 148//96 +f 133//170 152//169 148//96 +f 133//170 148//96 121//98 +f 103//171 133//170 121//98 +f 103//171 121//98 92//100 +f 73//172 103//171 92//100 +f 73//172 92//100 62//102 +f 50//173 73//172 62//102 +f 50//173 62//102 39//104 +f 25//174 50//173 39//104 +f 39//104 10//106 25//174 +f 539//175 509//176 159//177 +f 160//178 158//179 157//180 +f 166//181 160//178 163//182 +f 166//181 163//182 173//183 +f 177//184 166//181 173//183 +f 177//184 173//183 183//185 +f 189//186 177//184 183//185 +f 189//186 183//185 197//187 +f 205//188 189//186 197//187 +f 205//188 197//187 216//189 +f 225//190 205//188 216//189 +f 225//190 216//189 235//191 +f 173//183 163//182 172//192 +f 173//183 172//192 184//193 +f 183//185 173//183 184//193 +f 183//185 184//193 198//194 +f 197//187 183//185 198//194 +f 197//187 198//194 217//195 +f 216//189 197//187 217//195 +f 216//189 217//195 236//196 +f 235//191 216//189 236//196 +f 235//191 236//196 253//197 +f 182//198 172//192 1254//199 +f 1255//200 167//201 595//202 +f 184//193 172//192 182//198 +f 184//193 182//198 196//203 +f 198//194 184//193 196//203 +f 198//194 196//203 214//204 +f 217//195 198//194 214//204 +f 217//195 214//204 232//205 +f 236//196 217//195 232//205 +f 236//196 232//205 250//206 +f 253//197 236//196 250//206 +f 253//197 250//206 267//207 +f 196//203 182//198 199//208 +f 196//203 199//208 215//209 +f 214//204 196//203 215//209 +f 214//204 215//209 233//210 +f 232//205 214//204 233//210 +f 232//205 233//210 251//211 +f 250//206 232//205 251//211 +f 250//206 251//211 257//212 +f 267//207 250//206 257//212 +f 267//207 257//212 256//213 +f 215//209 199//208 218//214 +f 215//209 218//214 234//215 +f 233//210 215//209 234//215 +f 233//210 234//215 241//216 +f 251//211 233//210 241//216 +f 251//211 241//216 240//217 +f 257//212 251//211 240//217 +f 257//212 240//217 239//218 +f 256//213 257//212 239//218 +f 256//213 239//218 238//219 +f 234//215 218//214 219//220 +f 234//215 219//220 224//221 +f 241//216 234//215 224//221 +f 241//216 224//221 223//222 +f 240//217 241//216 223//222 +f 240//217 223//222 222//223 +f 239//218 240//217 222//223 +f 239//218 222//223 221//224 +f 238//219 239//218 221//224 +f 238//219 221//224 220//225 +f 219//220 218//214 1285//226 +f 648//227 691//228 207//229 +f 224//221 219//220 208//230 +f 224//221 208//230 204//231 +f 223//222 224//221 204//231 +f 223//222 204//231 203//232 +f 222//223 223//222 203//232 +f 222//223 203//232 202//233 +f 221//224 222//223 202//233 +f 221//224 202//233 201//234 +f 220//225 221//224 201//234 +f 220//225 201//234 212//235 +f 204//231 208//230 191//236 +f 204//231 191//236 188//237 +f 203//232 204//231 188//237 +f 203//232 188//237 187//238 +f 202//233 203//232 187//238 +f 202//233 187//238 186//239 +f 201//234 202//233 186//239 +f 201//234 186//239 194//240 +f 212//235 201//234 194//240 +f 212//235 194//240 211//241 +f 188//237 191//236 174//242 +f 188//237 174//242 176//243 +f 187//238 188//237 176//243 +f 187//238 176//243 175//244 +f 186//239 187//238 175//244 +f 186//239 175//244 180//245 +f 194//240 186//239 180//245 +f 194//240 180//245 193//246 +f 211//241 194//240 193//246 +f 211//241 193//246 210//247 +f 613//248 585//249 1258//250 +f 176//243 174//242 168//251 +f 176//243 168//251 165//252 +f 175//244 176//243 165//252 +f 175//244 165//252 170//253 +f 180//245 175//244 170//253 +f 180//245 170//253 179//254 +f 193//246 180//245 179//254 +f 193//246 179//254 192//255 +f 210//247 193//246 192//255 +f 210//247 192//255 209//256 +f 168//251 174//242 164//257 +f 165//252 168//251 161//258 +f 165//252 161//258 162//259 +f 170//253 165//252 162//259 +f 170//253 162//259 171//260 +f 179//254 170//253 171//260 +f 179//254 171//260 181//261 +f 192//255 179//254 181//261 +f 192//255 181//261 195//262 +f 209//256 192//255 195//262 +f 209//256 195//262 213//263 +f 160//178 161//258 158//179 +f 161//258 160//178 162//259 +f 162//259 160//178 166//181 +f 171//260 162//259 166//181 +f 171//260 166//181 177//184 +f 181//261 171//260 177//184 +f 181//261 177//184 189//186 +f 195//262 181//261 189//186 +f 195//262 189//186 205//188 +f 213//263 195//262 205//188 +f 213//263 205//188 225//190 +f 242//264 225//190 235//191 +f 242//264 235//191 252//265 +f 258//266 242//264 252//265 +f 258//266 252//265 268//267 +f 273//268 258//266 268//267 +f 273//268 268//267 283//269 +f 287//270 273//268 283//269 +f 287//270 283//269 298//271 +f 300//272 287//270 298//271 +f 300//272 298//271 299//273 +f 312//274 300//272 299//273 +f 312//274 299//273 310//275 +f 252//265 235//191 253//197 +f 252//265 253//197 269//276 +f 268//267 252//265 269//276 +f 268//267 269//276 284//277 +f 283//269 268//267 284//277 +f 283//269 284//277 286//278 +f 298//271 283//269 286//278 +f 298//271 286//278 285//279 +f 299//273 298//271 285//279 +f 299//273 285//279 296//280 +f 310//275 299//273 296//280 +f 310//275 296//280 309//281 +f 269//276 253//197 267//207 +f 269//276 267//207 272//282 +f 284//277 269//276 272//282 +f 284//277 272//282 271//283 +f 286//278 284//277 271//283 +f 286//278 271//283 270//284 +f 285//279 286//278 270//284 +f 285//279 270//284 281//285 +f 296//280 285//279 281//285 +f 296//280 281//285 295//286 +f 309//281 296//280 295//286 +f 309//281 295//286 308//287 +f 272//282 267//207 256//213 +f 272//282 256//213 255//288 +f 271//283 272//282 255//288 +f 271//283 255//288 254//289 +f 270//284 271//283 254//289 +f 270//284 254//289 265//290 +f 281//285 270//284 265//290 +f 281//285 265//290 280//291 +f 295//286 281//285 280//291 +f 295//286 280//291 294//292 +f 308//287 295//286 294//292 +f 308//287 294//292 307//293 +f 255//288 256//213 238//219 +f 255//288 238//219 237//294 +f 254//289 255//288 237//294 +f 254//289 237//294 248//295 +f 265//290 254//289 248//295 +f 265//290 248//295 264//296 +f 280//291 265//290 264//296 +f 280//291 264//296 279//297 +f 294//292 280//291 279//297 +f 294//292 279//297 293//298 +f 307//293 294//292 293//298 +f 307//293 293//298 306//299 +f 237//294 238//219 220//225 +f 237//294 220//225 230//300 +f 248//295 237//294 230//300 +f 248//295 230//300 247//301 +f 264//296 248//295 247//301 +f 264//296 247//301 263//302 +f 279//297 264//296 263//302 +f 279//297 263//302 278//303 +f 293//298 279//297 278//303 +f 293//298 278//303 292//304 +f 306//299 293//298 292//304 +f 306//299 292//304 305//305 +f 230//300 220//225 212//235 +f 230//300 212//235 229//306 +f 247//301 230//300 229//306 +f 247//301 229//306 246//307 +f 263//302 247//301 246//307 +f 263//302 246//307 262//308 +f 278//303 263//302 262//308 +f 278//303 262//308 277//309 +f 292//304 278//303 277//309 +f 292//304 277//309 291//310 +f 305//305 292//304 291//310 +f 305//305 291//310 304//311 +f 229//306 212//235 211//241 +f 229//306 211//241 228//312 +f 246//307 229//306 228//312 +f 246//307 228//312 245//313 +f 262//308 246//307 245//313 +f 262//308 245//313 261//314 +f 277//309 262//308 261//314 +f 277//309 261//314 276//315 +f 291//310 277//309 276//315 +f 291//310 276//315 290//316 +f 304//311 291//310 290//316 +f 304//311 290//316 303//317 +f 228//312 211//241 210//247 +f 228//312 210//247 227//318 +f 245//313 228//312 227//318 +f 245//313 227//318 244//319 +f 261//314 245//313 244//319 +f 261//314 244//319 260//320 +f 276//315 261//314 260//320 +f 276//315 260//320 275//321 +f 290//316 276//315 275//321 +f 290//316 275//321 289//322 +f 303//317 290//316 289//322 +f 303//317 289//322 302//323 +f 227//318 210//247 209//256 +f 227//318 209//256 226//324 +f 244//319 227//318 226//324 +f 244//319 226//324 243//325 +f 260//320 244//319 243//325 +f 260//320 243//325 259//326 +f 275//321 260//320 259//326 +f 275//321 259//326 274//327 +f 289//322 275//321 274//327 +f 289//322 274//327 288//328 +f 302//323 289//322 288//328 +f 302//323 288//328 301//329 +f 226//324 209//256 213//263 +f 226//324 213//263 231//330 +f 243//325 226//324 231//330 +f 243//325 231//330 249//331 +f 259//326 243//325 249//331 +f 259//326 249//331 266//332 +f 274//327 259//326 266//332 +f 274//327 266//332 282//333 +f 288//328 274//327 282//333 +f 288//328 282//333 297//334 +f 301//329 288//328 297//334 +f 301//329 297//334 311//335 +f 231//330 213//263 225//190 +f 231//330 225//190 242//264 +f 249//331 231//330 242//264 +f 249//331 242//264 258//266 +f 266//332 249//331 258//266 +f 266//332 258//266 273//268 +f 282//333 266//332 273//268 +f 282//333 273//268 287//270 +f 297//334 282//333 287//270 +f 297//334 287//270 300//272 +f 311//335 297//334 300//272 +f 311//335 300//272 312//274 +f 312//274 310//275 323//336 +f 302//323 315//337 316//338 +f 304//311 317//339 318//340 +f 303//317 316//338 317//339 +f 309//281 308//287 321//341 +f 307//293 306//299 319//342 +f 311//335 313//343 314//344 +f 301//329 314//344 315//337 +f 312//274 324//345 313//343 +f 306//299 305//305 318//340 +f 308//287 307//293 320//346 +f 310//275 309//281 322//347 +f 322//347 321//341 325//348 +f 314//344 313//343 325//348 +f 323//336 322//347 325//348 +f 319//342 318//340 325//348 +f 315//337 314//344 325//348 +f 321//341 320//346 325//348 +f 324//345 323//336 325//348 +f 320//346 319//342 325//348 +f 317//339 316//338 325//348 +f 316//338 315//337 325//348 +f 313//343 324//345 325//348 +f 318//340 317//339 325//348 +f 326//349 327//350 328//351 +f 326//349 328//351 329//352 +f 333//353 326//349 329//352 +f 333//353 329//352 338//354 +f 347//355 333//353 338//354 +f 347//355 338//354 354//356 +f 364//357 347//355 354//356 +f 364//357 354//356 374//358 +f 386//359 364//357 374//358 +f 386//359 374//358 398//360 +f 412//361 386//359 398//360 +f 412//361 398//360 429//362 +f 329//352 328//351 334//363 +f 329//352 334//363 339//364 +f 338//354 329//352 339//364 +f 338//354 339//364 355//365 +f 354//356 338//354 355//365 +f 354//356 355//365 375//366 +f 374//358 354//356 375//366 +f 374//358 375//366 399//367 +f 398//360 374//358 399//367 +f 398//360 399//367 430//368 +f 429//362 398//360 430//368 +f 429//362 430//368 464//369 +f 339//364 334//363 342//370 +f 339//364 342//370 356//371 +f 355//365 339//364 356//371 +f 355//365 356//371 376//372 +f 375//366 355//365 376//372 +f 375//366 376//372 400//373 +f 399//367 375//366 400//373 +f 399//367 400//373 431//374 +f 430//368 399//367 431//374 +f 430//368 431//374 465//375 +f 464//369 430//368 465//375 +f 464//369 465//375 497//376 +f 356//371 342//370 351//377 +f 356//371 351//377 370//378 +f 376//372 356//371 370//378 +f 376//372 370//378 393//379 +f 400//373 376//372 393//379 +f 400//373 393//379 422//380 +f 431//374 400//373 422//380 +f 431//374 422//380 457//381 +f 465//375 431//374 457//381 +f 465//375 457//381 490//382 +f 497//376 465//375 490//382 +f 497//376 490//382 521//383 +f 370//378 351//377 361//384 +f 370//378 361//384 382//385 +f 393//379 370//378 382//385 +f 393//379 382//385 408//386 +f 422//380 393//379 408//386 +f 422//380 408//386 439//387 +f 457//381 422//380 439//387 +f 457//381 439//387 473//388 +f 490//382 457//381 473//388 +f 490//382 473//388 504//389 +f 521//383 490//382 504//389 +f 521//383 504//389 535//390 +f 382//385 361//384 369//391 +f 382//385 369//391 392//392 +f 408//386 382//385 392//392 +f 408//386 392//392 421//393 +f 439//387 408//386 421//393 +f 439//387 421//393 456//394 +f 473//388 439//387 456//394 +f 473//388 456//394 489//395 +f 504//389 473//388 489//395 +f 504//389 489//395 520//396 +f 535//390 504//389 520//396 +f 535//390 520//396 550//397 +f 392//392 369//391 380//398 +f 392//392 380//398 407//399 +f 421//393 392//392 407//399 +f 421//393 407//399 438//400 +f 456//394 421//393 438//400 +f 456//394 438//400 472//401 +f 489//395 456//394 472//401 +f 489//395 472//401 503//402 +f 520//396 489//395 503//402 +f 520//396 503//402 534//403 +f 550//397 520//396 534//403 +f 550//397 534//403 563//404 +f 407//399 380//398 391//405 +f 407//399 391//405 420//406 +f 438//400 407//399 420//406 +f 438//400 420//406 455//407 +f 472//401 438//400 455//407 +f 472//401 455//407 488//408 +f 503//402 472//401 488//408 +f 503//402 488//408 519//409 +f 534//403 503//402 519//409 +f 534//403 519//409 549//410 +f 563//404 534//403 549//410 +f 563//404 549//410 578//411 +f 420//406 391//405 404//412 +f 420//406 404//412 437//413 +f 455//407 420//406 437//413 +f 455//407 437//413 471//414 +f 488//408 455//407 471//414 +f 488//408 471//414 502//415 +f 519//409 488//408 502//415 +f 519//409 502//415 533//416 +f 549//410 519//409 533//416 +f 549//410 533//416 562//417 +f 578//411 549//410 562//417 +f 578//411 562//417 589//418 +f 437//413 404//412 419//419 +f 437//413 419//419 454//420 +f 471//414 437//413 454//420 +f 471//414 454//420 487//421 +f 502//415 471//414 487//421 +f 502//415 487//421 518//422 +f 533//416 502//415 518//422 +f 533//416 518//422 548//423 +f 562//417 533//416 548//423 +f 562//417 548//423 577//424 +f 589//418 562//417 577//424 +f 589//418 577//424 594//425 +f 454//420 419//419 436//426 +f 454//420 436//426 470//427 +f 487//421 454//420 470//427 +f 487//421 470//427 501//428 +f 518//422 487//421 501//428 +f 518//422 501//428 532//429 +f 548//423 518//422 532//429 +f 548//423 532//429 555//430 +f 577//424 548//423 555//430 +f 577//424 555//430 567//431 +f 594//425 577//424 567//431 +f 594//425 567//431 582//432 +f 470//427 436//426 453//433 +f 470//427 453//433 486//434 +f 501//428 470//427 486//434 +f 501//428 486//434 508//435 +f 532//429 501//428 508//435 +f 532//429 508//435 525//436 +f 555//430 532//429 525//436 +f 555//430 525//436 538//437 +f 567//431 555//430 538//437 +f 567//431 538//437 554//438 +f 582//432 567//431 554//438 +f 582//432 554//438 566//33 +f 486//434 453//433 462//439 +f 486//434 462//439 477//440 +f 508//435 486//434 477//440 +f 508//435 477//440 494//441 +f 525//436 508//435 494//441 +f 525//436 494//441 507//442 +f 538//437 525//436 507//442 +f 538//437 507//442 524//443 +f 554//438 538//437 524//443 +f 554//438 524//443 537//444 +f 566//33 554//438 537//444 +f 566//33 537//444 553//31 +f 477//440 462//439 443//445 +f 477//440 443//445 461//446 +f 494//441 477//440 461//446 +f 494//441 461//446 476//447 +f 507//442 494//441 476//447 +f 507//442 476//447 493//448 +f 524//443 507//442 493//448 +f 524//443 493//448 506//449 +f 537//444 524//443 506//449 +f 537//444 506//449 523//450 +f 553//31 537//444 523//450 +f 553//31 523//450 536//451 +f 461//446 443//445 426//452 +f 461//446 426//452 442//453 +f 476//447 461//446 442//453 +f 476//447 442//453 460//454 +f 493//448 476//447 460//454 +f 493//448 460//454 475//455 +f 506//449 493//448 475//455 +f 506//449 475//455 492//456 +f 523//450 506//449 492//456 +f 523//450 492//456 505//457 +f 536//451 523//450 505//457 +f 536//451 505//457 522//458 +f 442//453 426//452 411//459 +f 442//453 411//459 425//460 +f 460//454 442//453 425//460 +f 460//454 425//460 441//461 +f 475//455 460//454 441//461 +f 475//455 441//461 459//462 +f 492//456 475//455 459//462 +f 492//456 459//462 474//463 +f 505//457 492//456 474//463 +f 505//457 474//463 491//464 +f 522//458 505//457 491//464 +f 522//458 491//464 499//465 +f 425//460 411//459 396//466 +f 425//460 396//466 410//467 +f 441//461 425//460 410//467 +f 441//461 410//467 424//468 +f 459//462 441//461 424//468 +f 459//462 424//468 440//469 +f 474//463 459//462 440//469 +f 474//463 440//469 458//470 +f 491//464 474//463 458//470 +f 491//464 458//470 467//471 +f 499//465 491//464 467//471 +f 499//465 467//471 466//472 +f 410//467 396//466 385//473 +f 410//467 385//473 395//474 +f 424//468 410//467 395//474 +f 424//468 395//474 409//475 +f 440//469 424//468 409//475 +f 440//469 409//475 423//476 +f 458//470 440//469 423//476 +f 458//470 423//476 433//477 +f 467//471 458//470 433//477 +f 467//471 433//477 432//478 +f 466//472 467//471 432//478 +f 466//472 432//478 434//479 +f 395//474 385//473 372//480 +f 395//474 372//480 383//481 +f 409//475 395//474 383//481 +f 409//475 383//481 394//482 +f 423//476 409//475 394//482 +f 423//476 394//482 402//483 +f 433//477 423//476 402//483 +f 433//477 402//483 401//484 +f 432//478 433//477 401//484 +f 432//478 401//484 403//485 +f 434//479 432//478 403//485 +f 434//479 403//485 417//486 +f 383//481 372//480 362//487 +f 383//481 362//487 371//488 +f 394//482 383//481 371//488 +f 394//482 371//488 378//489 +f 402//483 394//482 378//489 +f 402//483 378//489 377//490 +f 401//484 402//483 377//490 +f 401//484 377//490 379//491 +f 403//485 401//484 379//491 +f 403//485 379//491 390//492 +f 417//486 403//485 390//492 +f 417//486 390//492 416//493 +f 371//488 362//487 352//494 +f 371//488 352//494 358//495 +f 378//489 371//488 358//495 +f 378//489 358//495 357//496 +f 377//490 378//489 357//496 +f 377//490 357//496 359//497 +f 379//491 377//490 359//497 +f 379//491 359//497 367//498 +f 390//492 379//491 367//498 +f 390//492 367//498 389//499 +f 416//493 390//492 389//499 +f 416//493 389//499 415//500 +f 358//495 352//494 345//501 +f 358//495 345//501 340//502 +f 357//496 358//495 340//502 +f 357//496 340//502 341//503 +f 359//497 357//496 341//503 +f 359//497 341//503 349//504 +f 367//498 359//497 349//504 +f 367//498 349//504 366//505 +f 389//499 367//498 366//505 +f 389//499 366//505 388//506 +f 415//500 389//499 388//506 +f 415//500 388//506 414//507 +f 340//502 345//501 335//508 +f 340//502 335//508 330//509 +f 341//503 340//502 330//509 +f 341//503 330//509 336//510 +f 349//504 341//503 336//510 +f 349//504 336//510 348//511 +f 366//505 349//504 348//511 +f 366//505 348//511 365//512 +f 388//506 366//505 365//512 +f 388//506 365//512 387//513 +f 414//507 388//506 387//513 +f 414//507 387//513 413//514 +f 330//509 335//508 327//350 +f 327//350 326//349 330//509 +f 330//509 326//349 336//510 +f 336//510 326//349 333//353 +f 348//511 336//510 333//353 +f 348//511 333//353 347//355 +f 365//512 348//511 347//355 +f 365//512 347//355 364//357 +f 387//513 365//512 364//357 +f 387//513 364//357 386//359 +f 413//514 387//513 386//359 +f 413//514 386//359 412//361 +f 445//515 412//361 429//362 +f 445//515 429//362 463//516 +f 478//517 445//515 463//516 +f 478//517 463//516 495//518 +f 509//176 478//517 495//518 +f 509//176 495//518 526//519 +f 463//516 429//362 464//369 +f 463//516 464//369 496//520 +f 495//518 463//516 496//520 +f 495//518 496//520 527//521 +f 526//519 495//518 527//521 +f 526//519 527//521 557//522 +f 556//523 526//519 557//522 +f 556//523 557//522 583//524 +f 595//202 556//523 583//524 +f 595//202 583//524 611//525 +f 621//526 595//202 611//525 +f 621//526 611//525 638//527 +f 496//520 464//369 497//376 +f 496//520 497//376 528//528 +f 527//521 496//520 528//528 +f 527//521 528//528 558//529 +f 557//522 527//521 558//529 +f 557//522 558//529 584//530 +f 583//524 557//522 584//530 +f 583//524 584//530 612//531 +f 611//525 583//524 612//531 +f 611//525 612//531 639//532 +f 638//527 611//525 639//532 +f 638//527 639//532 664//533 +f 528//528 497//376 521//383 +f 528//528 521//383 551//534 +f 558//529 528//528 551//534 +f 558//529 551//534 580//535 +f 584//530 558//529 580//535 +f 584//530 580//535 608//536 +f 612//531 584//530 608//536 +f 612//531 608//536 634//537 +f 639//532 612//531 634//537 +f 639//532 634//537 661//538 +f 664//533 639//532 661//538 +f 664//533 661//538 688//539 +f 551//534 521//383 535//390 +f 551//534 535//390 564//540 +f 580//535 551//534 564//540 +f 580//535 564//540 591//541 +f 608//536 580//535 591//541 +f 608//536 591//541 618//542 +f 634//537 608//536 618//542 +f 634//537 618//542 644//543 +f 661//538 634//537 644//543 +f 661//538 644//543 670//544 +f 688//539 661//538 670//544 +f 688//539 670//544 698//545 +f 564//540 535//390 550//397 +f 564//540 550//397 579//546 +f 591//541 564//540 579//546 +f 591//541 579//546 607//547 +f 618//542 591//541 607//547 +f 618//542 607//547 633//548 +f 644//543 618//542 633//548 +f 644//543 633//548 660//549 +f 670//544 644//543 660//549 +f 670//544 660//549 687//550 +f 698//545 670//544 687//550 +f 698//545 687//550 717//551 +f 579//546 550//397 563//404 +f 579//546 563//404 590//552 +f 607//547 579//546 590//552 +f 607//547 590//552 617//553 +f 633//548 607//547 617//553 +f 633//548 617//553 643//554 +f 660//549 633//548 643//554 +f 660//549 643//554 669//555 +f 687//550 660//549 669//555 +f 687//550 669//555 697//556 +f 717//551 687//550 697//556 +f 717//551 697//556 727//557 +f 590//552 563//404 578//411 +f 590//552 578//411 606//558 +f 617//553 590//552 606//558 +f 617//553 606//558 632//559 +f 643//554 617//553 632//559 +f 643//554 632//559 659//560 +f 669//555 643//554 659//560 +f 669//555 659//560 673//561 +f 697//556 669//555 673//561 +f 697//556 673//561 700//562 +f 727//557 697//556 700//562 +f 727//557 700//562 699//563 +f 606//558 578//411 589//418 +f 606//558 589//418 616//564 +f 632//559 606//558 616//564 +f 632//559 616//564 637//565 +f 659//560 632//559 637//565 +f 659//560 637//565 647//566 +f 673//561 659//560 647//566 +f 673//561 647//566 672//567 +f 700//562 673//561 672//567 +f 700//562 672//567 671//568 +f 699//563 700//562 671//568 +f 699//563 671//568 689//569 +f 616//564 589//418 594//425 +f 616//564 594//425 610//570 +f 637//565 616//564 610//570 +f 637//565 610//570 620//571 +f 647//566 637//565 620//571 +f 647//566 620//571 646//572 +f 672//567 647//566 646//572 +f 672//567 646//572 645//573 +f 671//568 672//567 645//573 +f 671//568 645//573 662//574 +f 689//569 671//568 662//574 +f 689//569 662//574 668//575 +f 610//570 594//425 582//432 +f 610//570 582//432 593//3 +f 620//571 610//570 593//3 +f 620//571 593//3 636//89 +f 646//572 620//571 636//89 +f 646//572 636//89 619//576 +f 645//573 646//572 619//576 +f 645//573 619//576 635//577 +f 662//574 645//573 635//577 +f 662//574 635//577 642//578 +f 668//575 662//574 642//578 +f 668//575 642//578 641//579 +f 593//3 582//432 566//33 +f 619//576 636//89 592//57 +f 619//576 592//57 609//580 +f 635//577 619//576 609//580 +f 635//577 609//580 615//581 +f 642//578 635//577 615//581 +f 642//578 615//581 614//582 +f 641//579 642//578 614//582 +f 592//57 565//56 581//583 +f 609//580 592//57 581//583 +f 609//580 581//583 587//584 +f 615//581 609//580 587//584 +f 615//581 587//584 586//585 +f 614//582 615//581 586//585 +f 614//582 586//585 588//586 +f 565//56 553//31 536//451 +f 565//56 536//451 552//587 +f 581//583 565//56 552//587 +f 581//583 552//587 560//588 +f 587//584 581//583 560//588 +f 587//584 560//588 559//589 +f 586//585 587//584 559//589 +f 586//585 559//589 561//590 +f 588//586 586//585 561//590 +f 588//586 561//590 576//591 +f 605//592 588//586 576//591 +f 605//592 576//591 604//593 +f 552//587 536//451 522//458 +f 552//587 522//458 530//594 +f 560//588 552//587 530//594 +f 560//588 530//594 529//595 +f 559//589 560//588 529//595 +f 559//589 529//595 531//596 +f 561//590 559//589 531//596 +f 561//590 531//596 547//597 +f 576//591 561//590 547//597 +f 576//591 547//597 575//598 +f 604//593 576//591 575//598 +f 604//593 575//598 603//599 +f 530//594 522//458 499//465 +f 530//594 499//465 498//600 +f 529//595 530//594 498//600 +f 529//595 498//600 500//601 +f 531//596 529//595 500//601 +f 531//596 500//601 517//602 +f 547//597 531//596 517//602 +f 547//597 517//602 546//603 +f 575//598 547//597 546//603 +f 575//598 546//603 574//604 +f 603//599 575//598 574//604 +f 603//599 574//604 602//605 +f 498//600 499//465 466//472 +f 498//600 466//472 468//606 +f 500//601 498//600 468//606 +f 500//601 468//606 485//607 +f 517//602 500//601 485//607 +f 517//602 485//607 516//608 +f 546//603 517//602 516//608 +f 546//603 516//608 545//609 +f 574//604 546//603 545//609 +f 574//604 545//609 573//610 +f 602//605 574//604 573//610 +f 602//605 573//610 601//611 +f 468//606 466//472 434//479 +f 468//606 434//479 451//612 +f 485//607 468//606 451//612 +f 485//607 451//612 484//613 +f 516//608 485//607 484//613 +f 516//608 484//613 515//614 +f 545//609 516//608 515//614 +f 545//609 515//614 544//615 +f 573//610 545//609 544//615 +f 573//610 544//615 572//616 +f 601//611 573//610 572//616 +f 601//611 572//616 600//617 +f 451//612 434//479 417//486 +f 451//612 417//486 450//618 +f 484//613 451//612 450//618 +f 484//613 450//618 483//619 +f 515//614 484//613 483//619 +f 515//614 483//619 514//620 +f 544//615 515//614 514//620 +f 544//615 514//620 543//621 +f 572//616 544//615 543//621 +f 572//616 543//621 571//622 +f 600//617 572//616 571//622 +f 600//617 571//622 599//623 +f 450//618 417//486 416//493 +f 450//618 416//493 449//624 +f 483//619 450//618 449//624 +f 483//619 449//624 482//625 +f 514//620 483//619 482//625 +f 514//620 482//625 513//626 +f 543//621 514//620 513//626 +f 543//621 513//626 542//627 +f 571//622 543//621 542//627 +f 571//622 542//627 570//628 +f 599//623 571//622 570//628 +f 599//623 570//628 598//629 +f 449//624 416//493 415//500 +f 449//624 415//500 448//630 +f 482//625 449//624 448//630 +f 482//625 448//630 481//631 +f 513//626 482//625 481//631 +f 513//626 481//631 512//632 +f 542//627 513//626 512//632 +f 542//627 512//632 541//633 +f 570//628 542//627 541//633 +f 570//628 541//633 569//634 +f 598//629 570//628 569//634 +f 598//629 569//634 597//635 +f 448//630 415//500 414//507 +f 448//630 414//507 447//636 +f 481//631 448//630 447//636 +f 481//631 447//636 480//637 +f 512//632 481//631 480//637 +f 512//632 480//637 511//638 +f 541//633 512//632 511//638 +f 541//633 511//638 540//639 +f 569//634 541//633 540//639 +f 569//634 540//639 568//640 +f 597//635 569//634 568//640 +f 597//635 568//640 596//641 +f 447//636 414//507 413//514 +f 447//636 413//514 446//642 +f 480//637 447//636 446//642 +f 480//637 446//642 479//643 +f 511//638 480//637 479//643 +f 511//638 479//643 510//644 +f 540//639 511//638 510//644 +f 540//639 510//644 539//175 +f 568//640 540//639 539//175 +f 568//640 539//175 585//249 +f 596//641 568//640 585//249 +f 596//641 585//249 613//248 +f 446//642 413//514 412//361 +f 446//642 412//361 445//515 +f 479//643 446//642 445//515 +f 479//643 445//515 478//517 +f 510//644 479//643 478//517 +f 510//644 478//517 509//176 +f 539//175 510//644 509//176 +f 691//228 648//227 674//645 +f 702//646 691//228 674//645 +f 702//646 674//645 701//647 +f 731//648 702//646 701//647 +f 731//648 701//647 730//649 +f 759//650 731//648 730//649 +f 759//650 730//649 758//651 +f 786//652 759//650 758//651 +f 786//652 758//651 785//653 +f 648//227 621//526 638//527 +f 648//227 638//527 663//654 +f 674//645 648//227 663//654 +f 674//645 663//654 690//655 +f 701//647 674//645 690//655 +f 701//647 690//655 720//656 +f 730//649 701//647 720//656 +f 730//649 720//656 749//657 +f 758//651 730//649 749//657 +f 758//651 749//657 777//658 +f 785//653 758//651 777//658 +f 785//653 777//658 805//659 +f 663//654 638//527 664//533 +f 663//654 664//533 692//660 +f 690//655 663//654 692//660 +f 690//655 692//660 721//661 +f 720//656 690//655 721//661 +f 720//656 721//661 750//662 +f 749//657 720//656 750//662 +f 749//657 750//662 778//663 +f 777//658 749//657 778//663 +f 777//658 778//663 806//664 +f 805//659 777//658 806//664 +f 805//659 806//664 833//665 +f 692//660 664//533 688//539 +f 692//660 688//539 718//666 +f 721//661 692//660 718//666 +f 721//661 718//666 747//667 +f 750//662 721//661 747//667 +f 750//662 747//667 775//668 +f 778//663 750//662 775//668 +f 778//663 775//668 803//669 +f 806//664 778//663 803//669 +f 806//664 803//669 831//670 +f 833//665 806//664 831//670 +f 833//665 831//670 838//671 +f 718//666 688//539 698//545 +f 718//666 698//545 728//672 +f 747//667 718//666 728//672 +f 747//667 728//672 756//673 +f 775//668 747//667 756//673 +f 775//668 756//673 784//674 +f 803//669 775//668 784//674 +f 803//669 784//674 804//675 +f 831//670 803//669 804//675 +f 831//670 804//675 811//676 +f 838//671 831//670 811//676 +f 838//671 811//676 830//677 +f 728//672 698//545 717//551 +f 728//672 717//551 746//678 +f 756//673 728//672 746//678 +f 756//673 746//678 757//679 +f 784//674 756//673 757//679 +f 784//674 757//679 776//680 +f 804//675 784//674 776//680 +f 804//675 776//680 783//681 +f 811//676 804//675 783//681 +f 811//676 783//681 802//682 +f 830//677 811//676 802//682 +f 830//677 802//682 810//683 +f 746//678 717//551 727//557 +f 746//678 727//557 729//684 +f 757//679 746//678 729//684 +f 757//679 729//684 748//685 +f 776//680 757//679 748//685 +f 776//680 748//685 755//686 +f 783//681 776//680 755//686 +f 783//681 755//686 774//687 +f 802//682 783//681 774//687 +f 802//682 774//687 782//688 +f 810//683 802//682 782//688 +f 810//683 782//688 809//689 +f 729//684 727//557 699//563 +f 729//684 699//563 719//690 +f 748//685 729//684 719//690 +f 748//685 719//690 726//691 +f 755//686 748//685 726//691 +f 755//686 726//691 745//692 +f 774//687 755//686 745//692 +f 774//687 745//692 754//693 +f 782//688 774//687 754//693 +f 782//688 754//693 781//694 +f 809//689 782//688 781//694 +f 809//689 781//694 780//695 +f 719//690 699//563 689//569 +f 719//690 689//569 696//696 +f 726//691 719//690 696//696 +f 726//691 696//696 716//697 +f 745//692 726//691 716//697 +f 745//692 716//697 725//698 +f 754//693 745//692 725//698 +f 754//693 725//698 753//699 +f 781//694 754//693 753//699 +f 781//694 753//699 752//700 +f 780//695 781//694 752//700 +f 780//695 752//700 773//701 +f 696//696 689//569 668//575 +f 696//696 668//575 686//702 +f 716//697 696//696 686//702 +f 716//697 686//702 695//703 +f 725//698 716//697 695//703 +f 725//698 695//703 724//704 +f 753//699 725//698 724//704 +f 753//699 724//704 723//705 +f 752//700 753//699 723//705 +f 752//700 723//705 744//706 +f 773//701 752//700 744//706 +f 773//701 744//706 772//707 +f 686//702 668//575 641//579 +f 686//702 641//579 667//708 +f 695//703 686//702 667//708 +f 695//703 667//708 715//160 +f 724//704 695//703 715//160 +f 724//704 715//160 694//709 +f 723//705 724//704 694//709 +f 723//705 694//709 714//710 +f 744//706 723//705 714//710 +f 744//706 714//710 743//711 +f 772//707 744//706 743//711 +f 772//707 743//711 771//712 +f 694//709 715//160 666//713 +f 694//709 666//713 685//714 +f 714//710 694//709 685//714 +f 714//710 685//714 713//715 +f 743//711 714//710 713//715 +f 743//711 713//715 742//716 +f 771//712 743//711 742//716 +f 771//712 742//716 770//717 +f 666//713 631//152 658//718 +f 685//714 666//713 658//718 +f 685//714 658//718 684//719 +f 713//715 685//714 684//719 +f 713//715 684//719 712//720 +f 742//716 713//715 712//720 +f 742//716 712//720 741//721 +f 770//717 742//716 741//721 +f 770//717 741//721 769//722 +f 631//152 605//592 604//593 +f 631//152 604//593 630//723 +f 658//718 631//152 630//723 +f 658//718 630//723 657//724 +f 684//719 658//718 657//724 +f 684//719 657//724 683//725 +f 712//720 684//719 683//725 +f 712//720 683//725 711//726 +f 741//721 712//720 711//726 +f 741//721 711//726 740//727 +f 769//722 741//721 740//727 +f 769//722 740//727 768//728 +f 630//723 604//593 603//599 +f 630//723 603//599 629//729 +f 657//724 630//723 629//729 +f 657//724 629//729 656//730 +f 683//725 657//724 656//730 +f 683//725 656//730 682//731 +f 711//726 683//725 682//731 +f 711//726 682//731 710//732 +f 740//727 711//726 710//732 +f 740//727 710//732 739//733 +f 768//728 740//727 739//733 +f 768//728 739//733 767//734 +f 629//729 603//599 602//605 +f 629//729 602//605 628//735 +f 656//730 629//729 628//735 +f 656//730 628//735 655//736 +f 682//731 656//730 655//736 +f 682//731 655//736 681//737 +f 710//732 682//731 681//737 +f 710//732 681//737 709//738 +f 739//733 710//732 709//738 +f 739//733 709//738 738//739 +f 767//734 739//733 738//739 +f 767//734 738//739 766//740 +f 628//735 602//605 601//611 +f 628//735 601//611 627//741 +f 655//736 628//735 627//741 +f 655//736 627//741 654//742 +f 681//737 655//736 654//742 +f 681//737 654//742 680//743 +f 709//738 681//737 680//743 +f 709//738 680//743 708//744 +f 738//739 709//738 708//744 +f 738//739 708//744 737//745 +f 766//740 738//739 737//745 +f 766//740 737//745 765//746 +f 627//741 601//611 600//617 +f 627//741 600//617 626//747 +f 654//742 627//741 626//747 +f 654//742 626//747 653//748 +f 680//743 654//742 653//748 +f 680//743 653//748 679//749 +f 708//744 680//743 679//749 +f 708//744 679//749 707//750 +f 737//745 708//744 707//750 +f 737//745 707//750 736//751 +f 765//746 737//745 736//751 +f 765//746 736//751 764//752 +f 626//747 600//617 599//623 +f 626//747 599//623 625//753 +f 653//748 626//747 625//753 +f 653//748 625//753 652//754 +f 679//749 653//748 652//754 +f 679//749 652//754 678//755 +f 707//750 679//749 678//755 +f 707//750 678//755 706//756 +f 736//751 707//750 706//756 +f 736//751 706//756 735//757 +f 764//752 736//751 735//757 +f 764//752 735//757 763//758 +f 625//753 599//623 598//629 +f 625//753 598//629 624//759 +f 652//754 625//753 624//759 +f 652//754 624//759 651//760 +f 678//755 652//754 651//760 +f 678//755 651//760 677//761 +f 706//756 678//755 677//761 +f 706//756 677//761 705//762 +f 735//757 706//756 705//762 +f 735//757 705//762 734//763 +f 763//758 735//757 734//763 +f 763//758 734//763 762//764 +f 624//759 598//629 597//635 +f 624//759 597//635 623//765 +f 651//760 624//759 623//765 +f 651//760 623//765 650//766 +f 677//761 651//760 650//766 +f 677//761 650//766 676//767 +f 705//762 677//761 676//767 +f 705//762 676//767 704//768 +f 734//763 705//762 704//768 +f 734//763 704//768 733//769 +f 762//764 734//763 733//769 +f 762//764 733//769 761//770 +f 623//765 597//635 596//641 +f 623//765 596//641 622//771 +f 650//766 623//765 622//771 +f 650//766 622//771 649//772 +f 676//767 650//766 649//772 +f 676//767 649//772 675//773 +f 704//768 676//767 675//773 +f 704//768 675//773 703//774 +f 733//769 704//768 703//774 +f 733//769 703//774 732//775 +f 761//770 733//769 732//775 +f 761//770 732//775 760//776 +f 622//771 596//641 613//248 +f 622//771 613//248 640//777 +f 649//772 622//771 640//777 +f 649//772 640//777 665//778 +f 675//773 649//772 665//778 +f 675//773 665//778 693//779 +f 703//774 675//773 693//779 +f 703//774 693//779 722//780 +f 732//775 703//774 722//780 +f 732//775 722//780 751//781 +f 760//776 732//775 751//781 +f 760//776 751//781 779//782 +f 693//779 665//778 691//228 +f 693//779 691//228 702//646 +f 722//780 693//779 702//646 +f 722//780 702//646 731//648 +f 751//781 722//780 731//648 +f 751//781 731//648 759//650 +f 779//782 751//781 759//650 +f 779//782 759//650 786//652 +f 917//783 918//784 913//785 +f 892//786 917//783 913//785 +f 892//786 913//785 887//787 +f 866//788 892//786 887//787 +f 866//788 887//787 861//789 +f 840//790 866//788 861//789 +f 840//790 861//789 834//791 +f 813//792 840//790 834//791 +f 813//792 834//791 807//793 +f 786//652 813//792 807//793 +f 786//652 807//793 779//782 +f 913//785 918//784 893//794 +f 887//787 913//785 893//794 +f 887//787 893//794 867//795 +f 861//789 887//787 867//795 +f 861//789 867//795 841//796 +f 834//791 861//789 841//796 +f 834//791 841//796 814//797 +f 807//793 834//791 814//797 +f 807//793 814//797 787//798 +f 779//782 807//793 787//798 +f 779//782 787//798 760//776 +f 893//794 918//784 894//799 +f 867//795 893//794 894//799 +f 867//795 894//799 868//800 +f 841//796 867//795 868//800 +f 841//796 868//800 842//801 +f 814//797 841//796 842//801 +f 814//797 842//801 815//802 +f 787//798 814//797 815//802 +f 787//798 815//802 788//803 +f 760//776 787//798 788//803 +f 760//776 788//803 761//770 +f 894//799 918//784 895//804 +f 868//800 894//799 895//804 +f 868//800 895//804 869//805 +f 842//801 868//800 869//805 +f 842//801 869//805 843//806 +f 815//802 842//801 843//806 +f 815//802 843//806 816//807 +f 788//803 815//802 816//807 +f 788//803 816//807 789//808 +f 761//770 788//803 789//808 +f 761//770 789//808 762//764 +f 895//804 918//784 896//809 +f 869//805 895//804 896//809 +f 869//805 896//809 870//810 +f 843//806 869//805 870//810 +f 843//806 870//810 844//811 +f 816//807 843//806 844//811 +f 816//807 844//811 817//812 +f 789//808 816//807 817//812 +f 789//808 817//812 790//813 +f 762//764 789//808 790//813 +f 762//764 790//813 763//758 +f 896//809 918//784 897//814 +f 870//810 896//809 897//814 +f 870//810 897//814 871//815 +f 844//811 870//810 871//815 +f 844//811 871//815 845//816 +f 817//812 844//811 845//816 +f 817//812 845//816 818//817 +f 790//813 817//812 818//817 +f 790//813 818//817 791//818 +f 763//758 790//813 791//818 +f 763//758 791//818 764//752 +f 897//814 918//784 898//819 +f 871//815 897//814 898//819 +f 871//815 898//819 872//820 +f 845//816 871//815 872//820 +f 845//816 872//820 846//821 +f 818//817 845//816 846//821 +f 818//817 846//821 819//822 +f 791//818 818//817 819//822 +f 791//818 819//822 792//823 +f 764//752 791//818 792//823 +f 764//752 792//823 765//746 +f 898//819 918//784 899//824 +f 872//820 898//819 899//824 +f 872//820 899//824 873//825 +f 846//821 872//820 873//825 +f 846//821 873//825 847//826 +f 819//822 846//821 847//826 +f 819//822 847//826 820//827 +f 792//823 819//822 820//827 +f 792//823 820//827 793//828 +f 765//746 792//823 793//828 +f 765//746 793//828 766//740 +f 899//824 918//784 900//829 +f 873//825 899//824 900//829 +f 873//825 900//829 874//830 +f 847//826 873//825 874//830 +f 847//826 874//830 848//831 +f 820//827 847//826 848//831 +f 820//827 848//831 821//832 +f 793//828 820//827 821//832 +f 793//828 821//832 794//833 +f 766//740 793//828 794//833 +f 766//740 794//833 767//734 +f 900//829 918//784 901//834 +f 874//830 900//829 901//834 +f 874//830 901//834 875//835 +f 848//831 874//830 875//835 +f 848//831 875//835 849//836 +f 821//832 848//831 849//836 +f 821//832 849//836 822//837 +f 794//833 821//832 822//837 +f 794//833 822//837 795//838 +f 767//734 794//833 795//838 +f 767//734 795//838 768//728 +f 901//834 918//784 902//839 +f 875//835 901//834 902//839 +f 875//835 902//839 876//840 +f 849//836 875//835 876//840 +f 849//836 876//840 850//841 +f 822//837 849//836 850//841 +f 822//837 850//841 823//842 +f 795//838 822//837 823//842 +f 795//838 823//842 796//843 +f 768//728 795//838 796//843 +f 768//728 796//843 769//722 +f 902//839 918//784 903//844 +f 876//840 902//839 903//844 +f 876//840 903//844 877//845 +f 850//841 876//840 877//845 +f 850//841 877//845 851//846 +f 823//842 850//841 851//846 +f 823//842 851//846 824//847 +f 796//843 823//842 824//847 +f 796//843 824//847 797//848 +f 769//722 796//843 797//848 +f 769//722 797//848 770//717 +f 903//844 918//784 904//849 +f 877//845 903//844 904//849 +f 877//845 904//849 878//850 +f 851//846 877//845 878//850 +f 851//846 878//850 852//851 +f 824//847 851//846 852//851 +f 824//847 852//851 825//852 +f 797//848 824//847 825//852 +f 797//848 825//852 798//853 +f 770//717 797//848 798//853 +f 770//717 798//853 771//712 +f 904//849 918//784 905//854 +f 878//850 904//849 905//854 +f 878//850 905//854 879//855 +f 852//851 878//850 879//855 +f 852//851 879//855 853//856 +f 825//852 852//851 853//856 +f 825//852 853//856 826//857 +f 798//853 825//852 826//857 +f 798//853 826//857 799//858 +f 771//712 798//853 799//858 +f 771//712 799//858 772//707 +f 905//854 918//784 906//859 +f 879//855 905//854 906//859 +f 879//855 906//859 880//860 +f 853//856 879//855 880//860 +f 853//856 880//860 854//861 +f 826//857 853//856 854//861 +f 826//857 854//861 827//862 +f 799//858 826//857 827//862 +f 799//858 827//862 800//863 +f 772//707 799//858 800//863 +f 772//707 800//863 773//701 +f 906//859 918//784 907//864 +f 880//860 906//859 907//864 +f 880//860 907//864 881//865 +f 854//861 880//860 881//865 +f 854//861 881//865 855//866 +f 827//862 854//861 855//866 +f 827//862 855//866 828//867 +f 800//863 827//862 828//867 +f 800//863 828//867 801//868 +f 773//701 800//863 801//868 +f 773//701 801//868 780//695 +f 907//864 918//784 908//869 +f 881//865 907//864 908//869 +f 881//865 908//869 882//870 +f 855//866 881//865 882//870 +f 855//866 882//870 856//871 +f 828//867 855//866 856//871 +f 828//867 856//871 829//872 +f 801//868 828//867 829//872 +f 801//868 829//872 808//873 +f 780//695 801//868 808//873 +f 780//695 808//873 809//689 +f 908//869 918//784 909//874 +f 882//870 908//869 909//874 +f 882//870 909//874 883//875 +f 856//871 882//870 883//875 +f 856//871 883//875 857//876 +f 829//872 856//871 857//876 +f 829//872 857//876 836//877 +f 808//873 829//872 836//877 +f 808//873 836//877 835//878 +f 809//689 808//873 835//878 +f 809//689 835//878 810//683 +f 909//874 918//784 910//879 +f 883//875 909//874 910//879 +f 883//875 910//879 884//880 +f 857//876 883//875 884//880 +f 857//876 884//880 863//881 +f 836//877 857//876 863//881 +f 836//877 863//881 862//882 +f 835//878 836//877 862//882 +f 835//878 862//882 837//883 +f 810//683 835//878 837//883 +f 810//683 837//883 830//677 +f 910//879 918//784 911//884 +f 884//880 910//879 911//884 +f 884//880 911//884 889//885 +f 863//881 884//880 889//885 +f 863//881 889//885 888//886 +f 862//882 863//881 888//886 +f 862//882 888//886 864//887 +f 837//883 862//882 864//887 +f 837//883 864//887 858//888 +f 830//677 837//883 858//888 +f 830//677 858//888 838//671 +f 911//884 918//784 915//889 +f 889//885 911//884 915//889 +f 889//885 915//889 914//890 +f 888//886 889//885 914//890 +f 888//886 914//890 890//891 +f 864//887 888//886 890//891 +f 864//887 890//891 885//892 +f 858//888 864//887 885//892 +f 858//888 885//892 859//893 +f 838//671 858//888 859//893 +f 838//671 859//893 833//665 +f 915//889 918//784 919//894 +f 914//890 915//889 919//894 +f 914//890 919//894 912//895 +f 890//891 914//890 912//895 +f 890//891 912//895 886//896 +f 885//892 890//891 886//896 +f 885//892 886//896 860//897 +f 859//893 885//892 860//897 +f 859//893 860//897 832//898 +f 833//665 859//893 832//898 +f 833//665 832//898 805//659 +f 919//894 918//784 916//899 +f 912//895 919//894 916//899 +f 912//895 916//899 891//900 +f 886//896 912//895 891//900 +f 886//896 891//900 865//901 +f 860//897 886//896 865//901 +f 860//897 865//901 839//902 +f 832//898 860//897 839//902 +f 832//898 839//902 812//903 +f 805//659 832//898 812//903 +f 805//659 812//903 785//653 +f 916//899 918//784 917//783 +f 891//900 916//899 917//783 +f 891//900 917//783 892//786 +f 865//901 891//900 892//786 +f 865//901 892//786 866//788 +f 839//902 865//901 866//788 +f 839//902 866//788 840//790 +f 812//903 839//902 840//790 +f 812//903 840//790 813//792 +f 785//653 812//903 813//792 +f 785//653 813//792 786//652 +f 404//412 1267//904 1268//905 +f 384//906 373//907 372//480 +f 346//908 345//501 352//494 +f 435//909 436//426 419//419 +f 331//910 327//350 335//508 +f 462//439 453//433 1265//911 +f 920//912 921//913 922//914 +f 920//912 922//914 923//915 +f 923//915 922//914 927//916 +f 923//915 927//916 933//917 +f 933//917 927//916 940//918 +f 933//917 940//918 949//919 +f 949//919 940//918 959//920 +f 949//919 959//920 971//921 +f 971//921 959//920 984//922 +f 971//921 984//922 999//923 +f 999//923 984//922 1011//924 +f 999//923 1011//924 1027//925 +f 1027//925 1011//924 1042//926 +f 1027//925 1042//926 1059//927 +f 1059//927 1042//926 1077//928 +f 1059//927 1077//928 1095//929 +f 1095//929 1077//928 1110//930 +f 1095//929 1110//930 1129//931 +f 1129//931 1110//930 1144//932 +f 1129//931 1144//932 1163//933 +f 1163//933 1144//932 1179//934 +f 1163//933 1179//934 1196//935 +f 1196//935 1179//934 1210//936 +f 1196//935 1210//936 1220//937 +f 1220//937 1210//936 1212//938 +f 1220//937 1212//938 1201//939 +f 1201//939 1212//938 1181//940 +f 1201//939 1181//940 1169//941 +f 1169//941 1181//940 1147//942 +f 1169//941 1147//942 1135//943 +f 1135//943 1147//942 1113//944 +f 1135//943 1113//944 1102//945 +f 1102//945 1113//944 1081//946 +f 1102//945 1081//946 1065//947 +f 1065//947 1081//946 1046//948 +f 1065//947 1046//948 1032//949 +f 1032//949 1046//948 1016//950 +f 1032//949 1016//950 1003//951 +f 1003//951 1016//950 988//952 +f 1003//951 988//952 974//953 +f 974//953 988//952 962//954 +f 974//953 962//954 951//955 +f 951//955 962//954 942//956 +f 951//955 942//956 934//957 +f 934//957 942//956 928//958 +f 934//957 928//958 924//959 +f 924//959 928//958 921//913 +f 921//913 920//912 924//959 +f 926//960 920//912 923//915 +f 926//960 923//915 932//961 +f 938//962 926//960 932//961 +f 938//962 932//961 947//963 +f 956//964 938//962 947//963 +f 956//964 947//963 968//965 +f 980//966 956//964 968//965 +f 980//966 968//965 995//967 +f 1006//968 980//966 995//967 +f 1006//968 995//967 1022//969 +f 1036//970 1006//968 1022//969 +f 1036//970 1022//969 1053//971 +f 932//961 923//915 933//917 +f 932//961 933//917 948//972 +f 947//963 932//961 948//972 +f 947//963 948//972 969//973 +f 968//965 947//963 969//973 +f 968//965 969//973 996//974 +f 995//967 968//965 996//974 +f 995//967 996//974 1023//975 +f 1022//969 995//967 1023//975 +f 1022//969 1023//975 1054//976 +f 1053//971 1022//969 1054//976 +f 1053//971 1054//976 1089//977 +f 948//972 933//917 949//919 +f 948//972 949//919 970//978 +f 969//973 948//972 970//978 +f 969//973 970//978 997//979 +f 996//974 969//973 997//979 +f 996//974 997//979 1024//980 +f 1023//975 996//974 1024//980 +f 1023//975 1024//980 1055//981 +f 1054//976 1023//975 1055//981 +f 1054//976 1055//981 1090//982 +f 1089//977 1054//976 1090//982 +f 1089//977 1090//982 1109//983 +f 970//978 949//919 971//921 +f 970//978 971//921 998//984 +f 997//979 970//978 998//984 +f 997//979 998//984 1025//985 +f 1024//980 997//979 1025//985 +f 1024//980 1025//985 1056//986 +f 1055//981 1024//980 1056//986 +f 1055//981 1056//986 1091//987 +f 1090//982 1055//981 1091//987 +f 1090//982 1091//987 1124//988 +f 1109//983 1090//982 1124//988 +f 1109//983 1124//988 1122//989 +f 998//984 971//921 999//923 +f 998//984 999//923 1026//990 +f 1025//985 998//984 1026//990 +f 1025//985 1026//990 1057//991 +f 1056//986 1025//985 1057//991 +f 1056//986 1057//991 1092//992 +f 1091//987 1056//986 1092//992 +f 1091//987 1092//992 1125//993 +f 1124//988 1091//987 1125//993 +f 1124//988 1125//993 1156//994 +f 1122//989 1124//988 1156//994 +f 1122//989 1156//994 1142//995 +f 1026//990 999//923 1027//925 +f 1026//990 1027//925 1058//996 +f 1057//991 1026//990 1058//996 +f 1057//991 1058//996 1093//997 +f 1092//992 1057//991 1093//997 +f 1092//992 1093//997 1126//998 +f 1125//993 1092//992 1126//998 +f 1125//993 1126//998 1159//999 +f 1156//994 1125//993 1159//999 +f 1156//994 1159//999 1176//1000 +f 1142//995 1156//994 1176//1000 +f 1142//995 1176//1000 1157//1001 +f 1058//996 1027//925 1059//927 +f 1058//996 1059//927 1094//1002 +f 1093//997 1058//996 1094//1002 +f 1093//997 1094//1002 1127//1003 +f 1126//998 1093//997 1127//1003 +f 1126//998 1127//1003 1160//1004 +f 1159//999 1126//998 1160//1004 +f 1159//999 1160//1004 1192//1005 +f 1176//1000 1159//999 1192//1005 +f 1176//1000 1192//1005 1189//1006 +f 1157//1001 1176//1000 1189//1006 +f 1157//1001 1189//1006 1178//1007 +f 1094//1002 1059//927 1095//929 +f 1094//1002 1095//929 1128//1008 +f 1127//1003 1094//1002 1128//1008 +f 1127//1003 1128//1008 1161//1009 +f 1160//1004 1127//1003 1161//1009 +f 1160//1004 1161//1009 1193//1010 +f 1192//1005 1160//1004 1193//1010 +f 1192//1005 1193//1010 1215//1011 +f 1189//1006 1192//1005 1215//1011 +f 1189//1006 1215//1011 1207//1012 +f 1178//1007 1189//1006 1207//1012 +f 1178//1007 1207//1012 1191//1013 +f 1128//1008 1095//929 1129//931 +f 1128//1008 1129//931 1162//1014 +f 1161//1009 1128//1008 1162//1014 +f 1161//1009 1162//1014 1194//1015 +f 1193//1010 1161//1009 1194//1015 +f 1193//1010 1194//1015 1217//1016 +f 1215//1011 1193//1010 1217//1016 +f 1215//1011 1217//1016 1227//1017 +f 1207//1012 1215//1011 1227//1017 +f 1207//1012 1227//1017 1216//1018 +f 1191//1013 1207//1012 1216//1018 +f 1191//1013 1216//1018 1209//1019 +f 1162//1014 1129//931 1163//933 +f 1162//1014 1163//933 1195//1020 +f 1194//1015 1162//1014 1195//1020 +f 1194//1015 1195//1020 1218//1021 +f 1217//1016 1194//1015 1218//1021 +f 1217//1016 1218//1021 1230//1022 +f 1227//1017 1217//1016 1230//1022 +f 1227//1017 1230//1022 1229//1023 +f 1216//1018 1227//1017 1229//1023 +f 1216//1018 1229//1023 1225//1024 +f 1209//1019 1216//1018 1225//1024 +f 1209//1019 1225//1024 1203//1025 +f 1195//1020 1163//933 1196//935 +f 1195//1020 1196//935 1219//1026 +f 1218//1021 1195//1020 1219//1026 +f 1218//1021 1219//1026 1231//1027 +f 1230//1022 1218//1021 1231//1027 +f 1230//1022 1231//1027 1232//1028 +f 1229//1023 1230//1022 1232//1028 +f 1229//1023 1232//1028 1228//1029 +f 1225//1024 1229//1023 1228//1029 +f 1225//1024 1228//1029 1214//1030 +f 1203//1025 1225//1024 1214//1030 +f 1203//1025 1214//1030 1184//1031 +f 1219//1026 1196//935 1220//937 +f 1219//1026 1220//937 1224//1032 +f 1231//1027 1219//1026 1224//1032 +f 1231//1027 1224//1032 1223//1033 +f 1232//1028 1231//1027 1223//1033 +f 1232//1028 1223//1033 1222//1034 +f 1228//1029 1232//1028 1222//1034 +f 1228//1029 1222//1034 1221//1035 +f 1214//1030 1228//1029 1221//1035 +f 1214//1030 1221//1035 1204//1036 +f 1184//1031 1214//1030 1204//1036 +f 1184//1031 1204//1036 1171//1037 +f 1224//1032 1220//937 1201//939 +f 1224//1032 1201//939 1200//1038 +f 1223//1033 1224//1032 1200//1038 +f 1223//1033 1200//1038 1199//1039 +f 1222//1034 1223//1033 1199//1039 +f 1222//1034 1199//1039 1198//1040 +f 1221//1035 1222//1034 1198//1040 +f 1221//1035 1198//1040 1197//1041 +f 1204//1036 1221//1035 1197//1041 +f 1204//1036 1197//1041 1185//1042 +f 1171//1037 1204//1036 1185//1042 +f 1171//1037 1185//1042 1151//1043 +f 1200//1038 1201//939 1169//941 +f 1200//1038 1169//941 1168//1044 +f 1199//1039 1200//1038 1168//1044 +f 1199//1039 1168//1044 1167//1045 +f 1198//1040 1199//1039 1167//1045 +f 1198//1040 1167//1045 1166//1046 +f 1197//1041 1198//1040 1166//1046 +f 1197//1041 1166//1046 1165//1047 +f 1185//1042 1197//1041 1165//1047 +f 1185//1042 1165//1047 1164//1048 +f 1151//1043 1185//1042 1164//1048 +f 1151//1043 1164//1048 1137//1049 +f 1168//1044 1169//941 1135//943 +f 1168//1044 1135//943 1134//1050 +f 1167//1045 1168//1044 1134//1050 +f 1167//1045 1134//1050 1133//1051 +f 1166//1046 1167//1045 1133//1051 +f 1166//1046 1133//1051 1132//1052 +f 1165//1047 1166//1046 1132//1052 +f 1165//1047 1132//1052 1131//1053 +f 1164//1048 1165//1047 1131//1053 +f 1164//1048 1131//1053 1130//1054 +f 1137//1049 1164//1048 1130//1054 +f 1137//1049 1130//1054 1117//1055 +f 1134//1050 1135//943 1102//945 +f 1134//1050 1102//945 1101//1056 +f 1133//1051 1134//1050 1101//1056 +f 1133//1051 1101//1056 1100//1057 +f 1132//1052 1133//1051 1100//1057 +f 1132//1052 1100//1057 1099//1058 +f 1131//1053 1132//1052 1099//1058 +f 1131//1053 1099//1058 1098//1059 +f 1130//1054 1131//1053 1098//1059 +f 1130//1054 1098//1059 1097//1060 +f 1117//1055 1130//1054 1097//1060 +f 1117//1055 1097//1060 1096//1061 +f 1101//1056 1102//945 1065//947 +f 1101//1056 1065//947 1064//1062 +f 1100//1057 1101//1056 1064//1062 +f 1100//1057 1064//1062 1063//1063 +f 1099//1058 1100//1057 1063//1063 +f 1099//1058 1063//1063 1062//1064 +f 1098//1059 1099//1058 1062//1064 +f 1098//1059 1062//1064 1061//1065 +f 1097//1060 1098//1059 1061//1065 +f 1097//1060 1061//1065 1060//1066 +f 1096//1061 1097//1060 1060//1066 +f 1096//1061 1060//1066 1066//1067 +f 1064//1062 1065//947 1032//949 +f 1064//1062 1032//949 1031//1068 +f 1063//1063 1064//1062 1031//1068 +f 1063//1063 1031//1068 1030//1069 +f 1062//1064 1063//1063 1030//1069 +f 1062//1064 1030//1069 1029//1070 +f 1061//1065 1062//1064 1029//1070 +f 1061//1065 1029//1070 1028//1071 +f 1060//1066 1061//1065 1028//1071 +f 1060//1066 1028//1071 1033//1072 +f 1066//1067 1060//1066 1033//1072 +f 1066//1067 1033//1072 1050//1073 +f 1031//1068 1032//949 1003//951 +f 1031//1068 1003//951 1002//1074 +f 1030//1069 1031//1068 1002//1074 +f 1030//1069 1002//1074 1001//1075 +f 1029//1070 1030//1069 1001//1075 +f 1029//1070 1001//1075 1000//1076 +f 1028//1071 1029//1070 1000//1076 +f 1028//1071 1000//1076 1004//1077 +f 1033//1072 1028//1071 1004//1077 +f 1033//1072 1004//1077 1021//1078 +f 1050//1073 1033//1072 1021//1078 +f 1050//1073 1021//1078 1041//1079 +f 1002//1074 1003//951 974//953 +f 1002//1074 974//953 973//1080 +f 1001//1075 1002//1074 973//1080 +f 1001//1075 973//1080 972//1081 +f 1000//1076 1001//1075 972//1081 +f 1000//1076 972//1081 975//1082 +f 1004//1077 1000//1076 975//1082 +f 1004//1077 975//1082 992//1083 +f 1021//1078 1004//1077 992//1083 +f 1021//1078 992//1083 1010//1084 +f 1041//1079 1021//1078 1010//1084 +f 1041//1079 1010//1084 1040//1085 +f 973//1080 974//953 951//955 +f 973//1080 951//955 950//1086 +f 972//1081 973//1080 950//1086 +f 972//1081 950//1086 952//1087 +f 975//1082 972//1081 952//1087 +f 975//1082 952//1087 965//1088 +f 992//1083 975//1082 965//1088 +f 992//1083 965//1088 983//1089 +f 1010//1084 992//1083 983//1089 +f 1010//1084 983//1089 1009//1090 +f 1040//1085 1010//1084 1009//1090 +f 1040//1085 1009//1090 1039//1091 +f 950//1086 951//955 934//957 +f 950//1086 934//957 935//1092 +f 952//1087 950//1086 935//1092 +f 952//1087 935//1092 944//1093 +f 965//1088 952//1087 944//1093 +f 965//1088 944//1093 958//1094 +f 983//1089 965//1088 958//1094 +f 983//1089 958//1094 982//1095 +f 1009//1090 983//1089 982//1095 +f 1009//1090 982//1095 1008//1096 +f 1039//1091 1009//1090 1008//1096 +f 1039//1091 1008//1096 1038//1097 +f 935//1092 934//957 924//959 +f 935//1092 924//959 929//1098 +f 944//1093 935//1092 929//1098 +f 944//1093 929//1098 939//1099 +f 958//1094 944//1093 939//1099 +f 958//1094 939//1099 957//1100 +f 982//1095 958//1094 957//1100 +f 982//1095 957//1100 981//1101 +f 1008//1096 982//1095 981//1101 +f 1008//1096 981//1101 1007//1102 +f 1038//1097 1008//1096 1007//1102 +f 1038//1097 1007//1102 1037//1103 +f 924//959 920//912 929//1098 +f 929//1098 920//912 926//960 +f 939//1099 929//1098 926//960 +f 939//1099 926//960 938//962 +f 957//1100 939//1099 938//962 +f 957//1100 938//962 956//964 +f 981//1101 957//1100 956//964 +f 981//1101 956//964 980//966 +f 1007//1102 981//1101 980//966 +f 1007//1102 980//966 1006//968 +f 1037//1103 1007//1102 1006//968 +f 1037//1103 1006//968 1036//970 +f 993//1104 1005//1105 976//1106 +f 966//1107 993//1104 976//1106 +f 966//1107 976//1106 953//1108 +f 945//1109 966//1107 953//1108 +f 945//1109 953//1108 936//1110 +f 930//1111 945//1109 936//1110 +f 930//1111 936//1110 925//1112 +f 921//913 930//1111 925//1112 +f 921//913 925//1112 922//914 +f 976//1106 1005//1105 977//1113 +f 953//1108 976//1106 977//1113 +f 953//1108 977//1113 954//1114 +f 936//1110 953//1108 954//1114 +f 936//1110 954//1114 937//1115 +f 925//1112 936//1110 937//1115 +f 925//1112 937//1115 931//1116 +f 922//914 925//1112 931//1116 +f 922//914 931//1116 927//916 +f 977//1113 1005//1105 978//1117 +f 954//1114 977//1113 978//1117 +f 954//1114 978//1117 955//1118 +f 937//1115 954//1114 955//1118 +f 937//1115 955//1118 946//1119 +f 931//1116 937//1115 946//1119 +f 931//1116 946//1119 941//1120 +f 927//916 931//1116 941//1120 +f 927//916 941//1120 940//918 +f 978//1117 1005//1105 979//1121 +f 955//1118 978//1117 979//1121 +f 955//1118 979//1121 967//1122 +f 946//1119 955//1118 967//1122 +f 946//1119 967//1122 961//1123 +f 941//1120 946//1119 961//1123 +f 941//1120 961//1123 960//1124 +f 940//918 941//1120 960//1124 +f 940//918 960//1124 959//920 +f 979//1121 1005//1105 994//1125 +f 967//1122 979//1121 994//1125 +f 967//1122 994//1125 987//1126 +f 961//1123 967//1122 987//1126 +f 961//1123 987//1126 986//1127 +f 960//1124 961//1123 986//1127 +f 960//1124 986//1127 985//1128 +f 959//920 960//1124 985//1128 +f 959//920 985//1128 984//922 +f 994//1125 1005//1105 1015//1129 +f 987//1126 994//1125 1015//1129 +f 987//1126 1015//1129 1014//1130 +f 986//1127 987//1126 1014//1130 +f 986//1127 1014//1130 1013//1131 +f 985//1128 986//1127 1013//1131 +f 985//1128 1013//1131 1012//1132 +f 984//922 985//1128 1012//1132 +f 984//922 1012//1132 1011//924 +f 1015//1129 1005//1105 1035//1133 +f 1014//1130 1015//1129 1035//1133 +f 1014//1130 1035//1133 1045//1134 +f 1013//1131 1014//1130 1045//1134 +f 1013//1131 1045//1134 1044//1135 +f 1012//1132 1013//1131 1044//1135 +f 1012//1132 1044//1135 1043//1136 +f 1011//924 1012//1132 1043//1136 +f 1011//924 1043//1136 1042//926 +f 1035//1133 1005//1105 1052//1137 +f 1045//1134 1035//1133 1052//1137 +f 1045//1134 1052//1137 1080//1138 +f 1044//1135 1045//1134 1080//1138 +f 1044//1135 1080//1138 1079//1139 +f 1043//1136 1044//1135 1079//1139 +f 1043//1136 1079//1139 1078//1140 +f 1042//926 1043//1136 1078//1140 +f 1042//926 1078//1140 1077//928 +f 1052//1137 1005//1105 1068//1141 +f 1080//1138 1052//1137 1068//1141 +f 1080//1138 1068//1141 1106//1142 +f 1079//1139 1080//1138 1106//1142 +f 1079//1139 1106//1142 1112//1143 +f 1078//1140 1079//1139 1112//1143 +f 1078//1140 1112//1143 1111//1144 +f 1077//928 1078//1140 1111//1144 +f 1077//928 1111//1144 1110//930 +f 1068//1141 1005//1105 1087//1145 +f 1106//1142 1068//1141 1087//1145 +f 1106//1142 1087//1145 1120//1146 +f 1112//1143 1106//1142 1120//1146 +f 1112//1143 1120//1146 1146//1147 +f 1111//1144 1112//1143 1146//1147 +f 1111//1144 1146//1147 1145//1148 +f 1110//930 1111//1144 1145//1148 +f 1110//930 1145//1148 1144//932 +f 1087//1145 1005//1105 1107//1149 +f 1120//1146 1087//1145 1107//1149 +f 1120//1146 1107//1149 1140//1150 +f 1146//1147 1120//1146 1140//1150 +f 1146//1147 1140//1150 1174//1151 +f 1145//1148 1146//1147 1174//1151 +f 1145//1148 1174//1151 1180//1152 +f 1144//932 1145//1148 1180//1152 +f 1144//932 1180//1152 1179//934 +f 1107//1149 1005//1105 1121//1153 +f 1140//1150 1107//1149 1121//1153 +f 1140//1150 1121//1153 1154//1154 +f 1174//1151 1140//1150 1154//1154 +f 1174//1151 1154//1154 1188//1155 +f 1180//1152 1174//1151 1188//1155 +f 1180//1152 1188//1155 1211//1156 +f 1179//934 1180//1152 1211//1156 +f 1179//934 1211//1156 1210//936 +f 1121//1153 1005//1105 1141//1157 +f 1154//1154 1121//1153 1141//1157 +f 1154//1154 1141//1157 1175//1158 +f 1188//1155 1154//1154 1175//1158 +f 1188//1155 1175//1158 1206//1159 +f 1211//1156 1188//1155 1206//1159 +f 1211//1156 1206//1159 1226//1160 +f 1210//936 1211//1156 1226//1160 +f 1210//936 1226//1160 1212//938 +f 1141//1157 1005//1105 1155//1161 +f 1175//1158 1141//1157 1155//1161 +f 1175//1158 1155//1161 1187//1162 +f 1206//1159 1175//1158 1187//1162 +f 1206//1159 1187//1162 1205//1163 +f 1226//1160 1206//1159 1205//1163 +f 1226//1160 1205//1163 1213//1164 +f 1212//938 1226//1160 1213//1164 +f 1212//938 1213//1164 1181//940 +f 1155//1161 1005//1105 1153//1165 +f 1187//1162 1155//1161 1153//1165 +f 1187//1162 1153//1165 1173//1166 +f 1205//1163 1187//1162 1173//1166 +f 1205//1163 1173//1166 1186//1167 +f 1213//1164 1205//1163 1186//1167 +f 1213//1164 1186//1167 1182//1168 +f 1181//940 1213//1164 1182//1168 +f 1181//940 1182//1168 1147//942 +f 1153//1165 1005//1105 1139//1169 +f 1173//1166 1153//1165 1139//1169 +f 1173//1166 1139//1169 1152//1170 +f 1186//1167 1173//1166 1152//1170 +f 1186//1167 1152//1170 1172//1171 +f 1182//1168 1186//1167 1172//1171 +f 1182//1168 1172//1171 1148//1172 +f 1147//942 1182//1168 1148//1172 +f 1147//942 1148//1172 1113//944 +f 1139//1169 1005//1105 1119//1173 +f 1152//1170 1139//1169 1119//1173 +f 1152//1170 1119//1173 1138//1174 +f 1172//1171 1152//1170 1138//1174 +f 1172//1171 1138//1174 1149//1175 +f 1148//1172 1172//1171 1149//1175 +f 1148//1172 1149//1175 1114//1176 +f 1113//944 1148//1172 1114//1176 +f 1113//944 1114//1176 1081//946 +f 1119//1173 1005//1105 1105//1177 +f 1138//1174 1119//1173 1105//1177 +f 1138//1174 1105//1177 1118//1178 +f 1149//1175 1138//1174 1118//1178 +f 1149//1175 1118//1178 1115//1179 +f 1114//1176 1149//1175 1115//1179 +f 1114//1176 1115//1179 1082//1180 +f 1081//946 1114//1176 1082//1180 +f 1081//946 1082//1180 1046//948 +f 1105//1177 1005//1105 1086//1181 +f 1118//1178 1105//1177 1086//1181 +f 1118//1178 1086//1181 1104//1182 +f 1115//1179 1118//1178 1104//1182 +f 1115//1179 1104//1182 1083//1183 +f 1082//1180 1115//1179 1083//1183 +f 1082//1180 1083//1183 1047//1184 +f 1046//948 1082//1180 1047//1184 +f 1046//948 1047//1184 1016//950 +f 1086//1181 1005//1105 1067//1185 +f 1104//1182 1086//1181 1067//1185 +f 1104//1182 1067//1185 1084//1186 +f 1083//1183 1104//1182 1084//1186 +f 1083//1183 1084//1186 1048//1187 +f 1047//1184 1083//1183 1048//1187 +f 1047//1184 1048//1187 1017//1188 +f 1016//950 1047//1184 1017//1188 +f 1016//950 1017//1188 988//952 +f 1067//1185 1005//1105 1051//1189 +f 1084//1186 1067//1185 1051//1189 +f 1084//1186 1051//1189 1049//1190 +f 1048//1187 1084//1186 1049//1190 +f 1048//1187 1049//1190 1018//1191 +f 1017//1188 1048//1187 1018//1191 +f 1017//1188 1018//1191 989//1192 +f 988//952 1017//1188 989//1192 +f 988//952 989//1192 962//954 +f 1051//1189 1005//1105 1034//1193 +f 1049//1190 1051//1189 1034//1193 +f 1049//1190 1034//1193 1019//1194 +f 1018//1191 1049//1190 1019//1194 +f 1018//1191 1019//1194 990//1195 +f 989//1192 1018//1191 990//1195 +f 989//1192 990//1195 963//1196 +f 962//954 989//1192 963//1196 +f 962//954 963//1196 942//956 +f 1034//1193 1005//1105 1020//1197 +f 1019//1194 1034//1193 1020//1197 +f 1019//1194 1020//1197 991//1198 +f 990//1195 1019//1194 991//1198 +f 990//1195 991//1198 964//1199 +f 963//1196 990//1195 964//1199 +f 963//1196 964//1199 943//1200 +f 942//956 963//1196 943//1200 +f 942//956 943//1200 928//958 +f 1020//1197 1005//1105 993//1104 +f 991//1198 1020//1197 993//1104 +f 991//1198 993//1104 966//1107 +f 964//1199 991//1198 966//1107 +f 964//1199 966//1107 945//1109 +f 943//1200 964//1199 945//1109 +f 943//1200 945//1109 930//1111 +f 928//958 943//1200 930//1111 +f 928//958 930//1111 921//913 +f 1151//1043 1137//1049 1150//1201 +f 1142//995 1143//1202 1122//989 +f 1053//971 1089//977 1069//1203 +f 1122//989 1123//1204 1109//983 +f 1096//1061 1103//1205 1117//1055 +f 1171//1037 1170//1206 1184//1031 +f 1191//1013 1209//1019 1190//1207 +f 1036//970 1053//971 1070//1208 +f 1036//970 1070//1208 1037//1103 +f 1203//1025 1202//1209 1209//1019 +f 1066//1067 1085//1210 1096//1061 +f 1050//1073 1076//1211 1066//1067 +f 1184//1031 1183//1212 1203//1025 +f 1041//1079 1040//1085 1075//1213 +f 1171//1037 1151//1043 1170//1206 +f 1157//1001 1158//1214 1142//995 +f 1137//1049 1117//1055 1136//1215 +f 1038//1097 1072//1216 1039//1091 +f 1178//1007 1191//1013 1177//1217 +f 1089//977 1109//983 1088//1218 +f 1037//1103 1071//1219 1038//1097 +f 1050//1073 1041//1079 1076//1211 +f 1157//1001 1178//1007 1158//1214 +f 1040//1085 1039//1091 1074//1220 +f 1170//1206 1150//1201 452//1221 +f 1264//1222 1071//1219 1263//1223 +f 1261//1224 1262//1225 1076//1211 +f 1085//1210 1076//1211 1262//1225 +f 1190//1207 1208//1226 405//1227 +f 509//176 526//519 1260//1228 +f 1260//1228 526//519 556//523 +f 167//201 556//523 595//202 +f 595//202 621//526 1255//200 +f 172//192 163//182 1254//199 +f 8//49 18//42 3//1229 +f 3//1229 18//42 1288//1230 +f 15//75 7//66 1240//82 +f 1250//50 8//49 3//1229 +f 1//32 1283//40 566//33 +f 593//3 566//33 9//41 +f 19//1231 20//34 33//25 +f 1243//2 636//89 593//3 +f 64//18 40//6 36//17 +f 1244//24 64//18 36//17 +f 641//579 614//582 1237//1232 +f 1250//50 1239//1233 4//48 +f 7//66 4//48 1239//1233 +f 5//74 14//73 11//81 +f 1240//82 7//66 1239//1233 +f 1//32 553//31 565//56 +f 593//3 9//41 1289//83 +f 18//42 20//34 1288//1230 +f 40//6 27//5 1252//16 +f 1249//58 6//65 565//56 +f 14//73 15//75 11//81 +f 592//57 1234//130 1233//58 +f 1237//1232 614//582 588//586 +f 1237//1232 588//586 605//592 +f 539//175 159//177 1259//1234 +f 164//257 1257//1235 168//251 +f 509//176 1256//1236 159//177 +f 1258//250 585//249 1259//1234 +f 169//1237 164//257 174//242 +f 191//236 208//230 185//1238 +f 1290//1239 207//229 640//777 +f 621//526 1292//1240 1255//200 +f 163//182 160//178 157//180 +f 1284//1241 1292//1240 648//227 +f 1252//16 27//5 12//95 +f 119//124 116//129 104//161 +f 116//129 88//135 1242//136 +f 87//159 666//713 715//160 +f 87//159 1241//1242 666//713 +f 1253//1243 47//150 631//152 +f 631//152 666//713 1253//1243 +f 86//142 74//144 60//143 +f 640//777 1291//1244 1290//1239 +f 1291//1244 640//777 613//248 +f 208//230 219//220 200//1245 +f 665//778 640//777 207//229 +f 1285//226 200//1245 219//220 +f 648//227 207//229 1284//1241 +f 691//228 665//778 207//229 +f 605//592 1236//1246 1245//1246 +f 1235//151 605//592 631//152 +f 1248//145 48//153 37//167 +f 667//708 1251//1247 1247//158 +f 605//592 1235//151 1236//1246 +f 641//579 1238//1248 1246//1249 +f 641//579 1237//1232 1238//1248 +f 404//412 391//405 1267//904 +f 1265//911 453//433 436//426 +f 328//351 327//350 331//910 +f 443//445 462//439 469//1250 +f 342//370 1275//1251 344//1252 +f 342//370 334//363 1275//1251 +f 372//480 385//473 384//906 +f 351//377 1271//1253 361//384 +f 351//377 350//1254 1271//1253 +f 337//1255 335//508 345//501 +f 384//906 385//473 396//466 +f 361//384 368//1256 369//391 +f 361//384 1271//1253 368//1256 +f 352//494 1276//1257 346//908 +f 397//1258 396//466 411//459 +f 342//370 350//1254 351//377 +f 342//370 344//1252 350//1254 +f 380//398 369//391 368//1256 +f 334//363 328//351 332//1259 +f 404//412 418//1260 419//419 +f 404//412 1268//905 418//1260 +f 426//452 1286//1261 1282//1262 +f 1282//1262 411//459 426//452 +f 352//494 362//487 1277//1263 +f 1277//1263 1276//1257 352//494 +f 391//405 380//398 381//1264 +f 426//452 443//445 444//1265 +f 444//1265 1286//1261 426//452 +f 362//487 372//480 373//907 +f 373//907 1277//1263 362//487 +f 1202//1209 1183//1212 1270//1266 +f 1116//1267 428//1268 1136//1215 +f 428//1268 1287//1269 1136//1215 +f 1073//1270 353//1271 1074//1220 +f 353//1271 363//1272 1074//1220 +f 353//1271 1073//1270 1279//1273 +f 1070//1208 1069//1203 1263//1223 +f 1274//1274 1069//1203 1088//1218 +f 1177//1217 1273//1275 1272//1276 +f 1272//1276 1158//1214 1177//1217 +f 428//1268 1116//1267 427//1277 +f 1088//1218 1108//1278 343//1279 +f 1103//1205 1085//1210 1278//1280 +f 1108//1278 1123//1204 1280//1281 +f 1123//1204 1281//1282 1280//1281 +f 1143//1202 1158//1214 360//1283 +f 1158//1214 1272//1276 360//1283 +f 1075//1213 1261//1224 1076//1211 +f 1085//1210 1262//1225 1278//1280 +f 1123//1204 1143//1202 1281//1282 +f 1143//1202 360//1283 1281//1282 +f 1074//1220 363//1272 1075//1213 +f 363//1272 1261//1224 1075//1213 +f 1270//1266 1183//1212 452//1221 +f 1266//1284 1150//1201 1136//1215 +f 1273//1275 1177//1217 1190//1207 +f 1208//1226 1202//1209 406//1285 +f 1202//1209 1269//1286 406//1285 +f 1072//1216 1071//1219 1264//1222 +f 1241//1242 1253//1243 666//713 +f 71//137 86//142 60//143 +f 88//135 86//142 71//137 +f 1245//1246 1237//1232 605//592 +f 119//124 104//161 90//119 +f 667//708 1246//1249 1251//1247 +f 621//526 648//227 1292//1240 +f 208//230 200//1245 185//1238 +f 174//242 191//236 169//1237 +f 1258//250 1291//1244 613//248 +f 1244//24 19//1231 33//25 +f 1288//1230 20//34 19//1231 +f 199//208 182//198 178//1287 +f 206//1288 218//214 190//1289 +f 1260//1228 556//523 167//201 +f 157//180 1254//199 163//182 +f 178//1287 182//198 1254//199 +f 218//214 206//1288 1285//226 +f 161//258 1257//1235 158//179 +f 324//345 312//274 323//336 +f 303//317 302//323 316//338 +f 305//305 304//311 318//340 +f 304//311 303//317 317//339 +f 322//347 309//281 321//341 +f 320//346 307//293 319//342 +f 301//329 311//335 314//344 +f 302//323 301//329 315//337 +f 311//335 312//274 313//343 +f 319//342 306//299 318//340 +f 321//341 308//287 320//346 +f 323//336 310//275 322//347 +f 418//1260 435//909 419//419 +f 337//1255 331//910 335//508 +f 469//1250 462//439 1265//911 +f 1137//1049 1136//1215 1150//1201 +f 1143//1202 1123//1204 1122//989 +f 1089//977 1088//1218 1069//1203 +f 1123//1204 1108//1278 1109//983 +f 1103//1205 1116//1267 1117//1055 +f 1170//1206 1183//1212 1184//1031 +f 1209//1019 1208//1226 1190//1207 +f 1053//971 1069//1203 1070//1208 +f 1070//1208 1071//1219 1037//1103 +f 1202//1209 1208//1226 1209//1019 +f 1085//1210 1103//1205 1096//1061 +f 1076//1211 1085//1210 1066//1067 +f 1183//1212 1202//1209 1203//1025 +f 1040//1085 1074//1220 1075//1213 +f 1151//1043 1150//1201 1170//1206 +f 1158//1214 1143//1202 1142//995 +f 1117//1055 1116//1267 1136//1215 +f 1072//1216 1073//1270 1039//1091 +f 1191//1013 1190//1207 1177//1217 +f 1109//983 1108//1278 1088//1218 +f 1071//1219 1072//1216 1038//1097 +f 1041//1079 1075//1213 1076//1211 +f 1178//1007 1177//1217 1158//1214 +f 1039//1091 1073//1270 1074//1220 +f 1150//1201 1266//1284 452//1221 +f 1071//1219 1070//1208 1263//1223 +f 1208//1226 406//1285 405//1227 +f 1256//1236 509//176 1260//1228 +f 1257//1235 161//258 168//251 +f 585//249 539//175 1259//1234 +f 715//160 667//708 1247//158 +f 667//708 641//579 1246//1249 +f 435//909 1265//911 436//426 +f 332//1259 328//351 331//910 +f 444//1265 443//445 469//1250 +f 346//908 337//1255 345//501 +f 397//1258 384//906 396//466 +f 1282//1262 397//1258 411//459 +f 381//1264 380//398 368//1256 +f 1275//1251 334//363 332//1259 +f 1267//904 391//405 381//1264 +f 1269//1286 1202//1209 1270//1266 +f 1073//1270 1072//1216 1279//1273 +f 1069//1203 1274//1274 1263//1223 +f 343//1279 1274//1274 1088//1218 +f 1116//1267 1103//1205 427//1277 +f 1108//1278 1280//1281 343//1279 +f 427//1277 1103//1205 1278//1280 +f 1183//1212 1170//1206 452//1221 +f 1287//1269 1266//1284 1136//1215 +f 405//1227 1273//1275 1190//1207 +f 1279//1273 1072//1216 1264//1222 +f 191//236 185//1238 169//1237 +f 190//1289 199//208 178//1287 +f 218//214 199//208 190//1289 diff --git a/A1/resources/tri.obj b/A1/resources/tri.obj new file mode 100644 index 0000000..0373bf9 --- /dev/null +++ b/A1/resources/tri.obj @@ -0,0 +1,4 @@ +v 0 0 0 +v 10 0 0 +v 5 5 5 +f 1 2 3 diff --git a/A1/resources/tri2.obj b/A1/resources/tri2.obj new file mode 100644 index 0000000..78273e0 --- /dev/null +++ b/A1/resources/tri2.obj @@ -0,0 +1,8 @@ +v 0 0 0 +v 10 0 0 +v 5 5 5 +v 0 5 0 +v 5 0 5 +v 10 5 0 +f 1 2 3 +f 4 5 6 diff --git a/A1/shadow8t4.zip b/A1/shadow8t4.zip new file mode 100644 index 0000000..e70344d Binary files /dev/null and b/A1/shadow8t4.zip differ diff --git a/A1/shadow8t4/shadow8t4/CMakeLists.txt b/A1/shadow8t4/shadow8t4/CMakeLists.txt new file mode 100644 index 0000000..5deaf8f --- /dev/null +++ b/A1/shadow8t4/shadow8t4/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(A1) + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS}) + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") +ENDIF() diff --git a/A1/shadow8t4/shadow8t4/README.txt b/A1/shadow8t4/shadow8t4/README.txt new file mode 100644 index 0000000..2f808ed --- /dev/null +++ b/A1/shadow8t4/shadow8t4/README.txt @@ -0,0 +1,7 @@ +1) Alexander Huddleston + +2) The last coloring mode goes from blue to green, top to bottom respectively. + +3) http://www.mathopenref.com/coordtrianglearea.html + +4) This was written and compiled on Arch Linux on a 64-bit machine. There should not be any errors when run on another machine, but I am making note here just in case. diff --git a/A1/shadow8t4/shadow8t4/src/Image.cpp b/A1/shadow8t4/shadow8t4/src/Image.cpp new file mode 100644 index 0000000..298edfb --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/Image.cpp @@ -0,0 +1,61 @@ +#include +#include +#include "Image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +using namespace std; + +Image::Image(int w, int h) : + width(w), + height(h), + comp(3), + pixels(width*height*comp, 0) +{ +} + +Image::~Image() +{ +} + +void Image::setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) +{ + // The pixel data is laid out row by row. Each row consists of 'width' + // columns, and each column consists of 3 unsigned chars. + + // First check for bounds + if(y < 0 || y >= height) { + cout << "Row " << y << " is out of bounds" << endl; + return; + } + if(x < 0 || x >= width) { + cout << "Col " << x << " is out of bounds" << endl; + return; + } + + // Since the origin (0, 0) of the image is the upper left corner, we need + // to flip the row to make the origin be the lower left corner. + y = height - y - 1; + // index corresponding to row and col, (assuming single component image) + int index = y*width + x; + // Multiply by 3 to get the index for the rgb components. + assert(index >= 0); + assert(3*index + 2 < (int)pixels.size()); + pixels[3*index + 0] = r; + pixels[3*index + 1] = g; + pixels[3*index + 2] = b; +} + +void Image::writeToFile(const string &filename) +{ + // The distance in bytes from the first byte of a row of pixels to the + // first byte of the next row of pixels + int stride_in_bytes = width*comp*sizeof(unsigned char); + int rc = stbi_write_png(filename.c_str(), width, height, comp, &pixels[0], stride_in_bytes); + if(rc) { + cout << "Wrote to " << filename << endl; + } else { + cout << "Couldn't write to " << filename << endl; + } +} diff --git a/A1/shadow8t4/shadow8t4/src/Image.h b/A1/shadow8t4/shadow8t4/src/Image.h new file mode 100644 index 0000000..2f27d46 --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/Image.h @@ -0,0 +1,25 @@ +#pragma once +#ifndef _IMAGE_H_ +#define _IMAGE_H_ + +#include +#include + +class Image +{ +public: + Image(int width, int height); + virtual ~Image(); + void setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b); + void writeToFile(const std::string &filename); + int getWidth() const { return width; } + int getHeight() const { return height; } + +private: + int width; + int height; + int comp; + std::vector pixels; +}; + +#endif diff --git a/A1/shadow8t4/shadow8t4/src/Triangle.cpp b/A1/shadow8t4/shadow8t4/src/Triangle.cpp new file mode 100644 index 0000000..46fd23c --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/Triangle.cpp @@ -0,0 +1,45 @@ +#include "Triangle.h" + +using namespace std; + +Tri::Tri() +{ + vertex v1; + v1.x = 0.0; + v1.y = 0.0; + v1.z = 0.0; + vertex v2; + v2.x = 0.0; + v2.y = 0.0; + v2.z = 0.0; + vertex v3; + v3.x = 0.0; + v3.y = 0.0; + v3.z = 0.0; + v.push_back(v1); + v.push_back(v2); + v.push_back(v3); + xmin = 0; + xmax = 0; + ymin = 0; + ymax = 0; + area = 0.0; +} + +float findArea(vertex &one, vertex &two, vertex &three) +{ + return abs(one.x*two.y + two.x*three.y + three.x*one.y - one.y*two.x - two.y*three.x - three.y*one.x)/2.0; +} + +Tri::Tri(vertex &one, vertex &two, vertex &three) +{ + v.push_back(one); + v.push_back(two); + v.push_back(three); + xmin = one.x; + xmax = one.x; + ymin = one.y; + ymax = one.y; + area = findArea(one, two, three); +} + diff --git a/A1/shadow8t4/shadow8t4/src/Triangle.h b/A1/shadow8t4/shadow8t4/src/Triangle.h new file mode 100644 index 0000000..e366b09 --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/Triangle.h @@ -0,0 +1,34 @@ +#pragma once +#ifndef _TRIANGLE_H_ +#define _TRIANGLE_H_ + +#include +#include +#include + +struct vertex +{ + float x = 0.0; + float y = 0.0; + float z = 0.0; + float r = 0.0; + float g = 0.0; + float b = 0.0; +}; + +class Tri +{ + public: + Tri(); + Tri(vertex &one, vertex &two, vertex &three); + std::vector v; + float xmin; + float xmax; + float ymin; + float ymax; + float area; +}; + +float findArea(vertex &one, vertex &two, vertex &three); + +#endif diff --git a/A1/shadow8t4/shadow8t4/src/main.cpp b/A1/shadow8t4/shadow8t4/src/main.cpp new file mode 100644 index 0000000..3b64734 --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/main.cpp @@ -0,0 +1,347 @@ +#include +#include +#include +#include + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +#include "Image.h" +#include "Triangle.h" + +// This allows you to skip the `std::` in front of C++ standard library +// functions. You can also say `using std::cout` to be more selective. +// You should never do this in a header file. +using namespace std; + +int main(int argc, char **argv) +{ + if(argc < 6) { + cout << "Usage: A1 meshfile image width height colormode" << endl; + return 0; + } + + srand(743298); + string meshName(argv[1]); + string filename(argv[2]); + int width = atoi(argv[3]); + int height = atoi(argv[4]); + int colormode = atoi(argv[5]); + + // Load geometry + vector posBuf; // list of vertex positions + + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + + } + index_offset += fv; + + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } + cout << "Number of vertices: " << posBuf.size()/3 << endl; + + vector> zbuf; + + std::vector tris; + + // Split posBuf into triangles. + for(int i = 0; i < (int)posBuf.size()/9; i++) + { + vertex v1; + v1.x = posBuf[i*9]; + v1.y = posBuf[i*9 + 1]; + v1.z = posBuf[i*9 + 2]; + vertex v2; + v2.x = posBuf[i*9 + 3]; + v2.y = posBuf[i*9 + 4]; + v2.z = posBuf[i*9 + 5]; + vertex v3; + v3.x = posBuf[i*9 + 6]; + v3.y = posBuf[i*9 + 7]; + v3.z = posBuf[i*9 + 8]; + Tri t(v1, v2, v3); + tris.push_back(t); + } + + // Initialize min/max variables. + float xmin = posBuf[0]; + float xmax = xmin; + float ymin = posBuf[1]; + float ymax = ymin; + float zmin = tris[0].v[0].z; + float zmax = zmin; + + // First time finding max and min. + // Also, initializing r,g,b per triangle. + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + + int temp1 = rand()%255; + int temp2 = rand()%255; + int temp3 = rand()%255; + tris[i].v[j].r = temp1; + tris[i].v[j].g = temp2; + tris[i].v[j].b = temp3; + } + } + + unsigned char r = rand()%255; + unsigned char b = rand()%255; + unsigned char g = rand()%255; + + + // Create the image. We're using a `shared_ptr`, a C++11 feature. + auto image = make_shared(width, height); + + // Find scaling ratio. + float xratio = (1.0*width/(xmax - xmin)); + float yratio = (1.0*height/(ymax - ymin)); + float zratio = (255.0/(zmax-zmin)); + + float aratio = 1.0; + + // Determine and assign smaller ratio. + if(xratio < yratio) + { + aratio = xratio; + } + else + { + aratio = yratio; + } + + + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + tris[i].v[j].x *= aratio; + tris[i].v[j].y *= aratio; + tris[i].v[j].z *= zratio; + } + } + + xmin = tris[0].v[0].x; + xmax = xmin; + ymin = tris[0].v[0].y; + ymax = ymin; + zmin = tris[0].v[0].z; + zmax = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + } + } + + float xoffset = ((width)/2 - (xmax + xmin)/2); + float yoffset = ((height)/2 - (ymax + ymin)/2); + float zoffset = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size();j++) + { + tris[i].v[j].x += xoffset; + tris[i].v[j].y += yoffset; + tris[i].v[j].z -= zoffset; + } + } + + xmin = tris[0].v[0].x; + xmax = xmin; + ymin = tris[0].v[0].y; + ymax = ymin; + zmin = tris[0].v[0].z; + zmax = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + tris[i].xmin = tris[i].v[0].x; + tris[i].xmax = tris[i].v[0].x; + tris[i].ymin = tris[i].v[0].y; + tris[i].ymax = tris[i].v[0].y; + + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + + if(tris[i].xmin > tris[i].v[j].x) + tris[i].xmin = tris[i].v[j].x; + if(tris[i].xmax < tris[i].v[j].x) + tris[i].xmax = tris[i].v[j].x; + if(tris[i].ymin > tris[i].v[j].y) + tris[i].ymin = tris[i].v[j].y; + if(tris[i].ymax < tris[i].v[j].y) + tris[i].ymax = tris[i].v[j].y; + } + } + + + for(int r = 0; r < width; r++) + { + vector temp; + zbuf.push_back(temp); + for(int c = 0; c < height; c++) + { + zbuf.at(r).push_back(zmin); + } + } + + // Initialize variables for the three + // Barycentric areas. + float a1 = 0.0; + float a2 = 0.0; + float a3 = 0.0; + + // Initialize variables for the three + // Barycentric coordinates. + float l1 = 0.0; + float l2 = 0.0; + float l3 = 0.0; + + // Variable to hold current z coordinate. + float z = 0.0; + + // I had each triangle hold a variable which was its area, + // Here, I make sure they all have their areas set correctly. + for(int i = 0; i < (int)tris.size(); i++) + { + tris[i].area = findArea(tris[i].v[0], tris[i].v[1], tris[i].v[2]); + } + for(int i = 0; i < (int)tris.size(); i++) + { + for(int x = tris[i].xmin; x < tris[i].xmax; x++) + { + for(int y = tris[i].ymin; y < tris[i].ymax; y++) + { + // Temporary vertex so we can utilize findArea. + vertex tempv; + tempv.x = x; + tempv.y = y; + + a3 = findArea(tris[i].v[0], tris[i].v[1], tempv); + a2 = findArea(tris[i].v[0], tempv, tris[i].v[2]); + a1 = findArea(tempv, tris[i].v[1], tris[i].v[2]); + + l1 = a1/tris[i].area; + l2 = a2/tris[i].area; + l3 = a3/tris[i].area; + + r = (a1*tris[i].v[0].r + a2*tris[i].v[1].r + a3*tris[i].v[2].r)/tris[i].area; + g = (a1*tris[i].v[0].g + a2*tris[i].v[1].g + a3*tris[i].v[2].g)/tris[i].area; + b = (a1*tris[i].v[0].b + a2*tris[i].v[1].b + a3*tris[i].v[2].b)/tris[i].area; + + if(colormode == 0) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, r, g ,b); + zbuf.at(x).at(y) = z; + } + } + + float z1 = tris[i].v[0].z; + float z2 = tris[i].v[1].z; + float z3 = tris[i].v[2].z; + + z = (a1*z1 + a2*z2 + a3*z3)/tris[i].area; + if(colormode == 1) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, z, 0, 0); + zbuf.at(x).at(y) = z; + } + } + else if(colormode == 2) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, 0, (255/(ymax - ymin)) - (y - ymin)*(255/(ymax - ymin)), (y - ymin)*(255/(ymax - ymin))); + zbuf.at(x).at(y) = z; + } + } + } + } + } + + // Write image to file + image->writeToFile(filename); + return 0; +} diff --git a/A1/shadow8t4/shadow8t4/src/stb_image_write.h b/A1/shadow8t4/shadow8t4/src/stb_image_write.h new file mode 100644 index 0000000..f07b625 --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/stb_image_write.h @@ -0,0 +1,1048 @@ +/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio. It could be + adapted to write to memory or a general streaming interface; let me know. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation. This library is designed + for source code compactness and simplicity, not optimal image file size + or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can define STBIW_MEMMOVE() to replace memmove() + +USAGE: + + There are four functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + There are also four equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + +CREDITS: + + PNG/BMP/TGA + Sean Barrett + HDR + Baldur Karlsson + TGA monochrome: + Jean-Sebastien Guay + misc enhancements: + Tim Kelsey + TGA RLE + Alan Hickman + initial file IO callback implementation + Emmanuel Julien + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + +LICENSE + +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#define STBIWDEF extern +extern int stbi_write_tga_with_rle; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + +#ifdef __cplusplus +} +#endif + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_tga_with_rle = 1; +#else +int stbi_write_tga_with_rle = 1; +#endif + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a, arr[1] = b, arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 1: + s->func(s->context,d,1); + break; + case 2: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + for (j = y - 1; j >= 0; --j) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson +#ifndef STBI_WRITE_NO_STDIO + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); + STBIW_FREE(scratch); + return 1; + } +} + +int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) best=d,bestloc=hlist[j]; + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; + s1 %= 65521, s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int i,j,k,p,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = j ? mapping : firstmap; + int best = 0, bestval = 0x7fffffff; + for (p=0; p < 2; ++p) { + for (k= p?best:0; k < 5; ++k) { + int type = mymap[k],est=0; + unsigned char *z = pixels + stride_bytes*j; + for (i=0; i < n; ++i) + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + for (i=n; i < x*n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i] - z[i-n]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; + case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } + } + if (p) break; + for (i=0; i < x*n; ++i) + est += abs((signed char) line_buffer[i]); + if (est < bestval) { bestval = est; best = k; } + } + } + // when we get here, best contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) best; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + f = fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ diff --git a/A1/shadow8t4/shadow8t4/src/tiny_obj_loader.h b/A1/shadow8t4/shadow8t4/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/A1/src/Image.cpp b/A1/src/Image.cpp new file mode 100644 index 0000000..298edfb --- /dev/null +++ b/A1/src/Image.cpp @@ -0,0 +1,61 @@ +#include +#include +#include "Image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +using namespace std; + +Image::Image(int w, int h) : + width(w), + height(h), + comp(3), + pixels(width*height*comp, 0) +{ +} + +Image::~Image() +{ +} + +void Image::setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) +{ + // The pixel data is laid out row by row. Each row consists of 'width' + // columns, and each column consists of 3 unsigned chars. + + // First check for bounds + if(y < 0 || y >= height) { + cout << "Row " << y << " is out of bounds" << endl; + return; + } + if(x < 0 || x >= width) { + cout << "Col " << x << " is out of bounds" << endl; + return; + } + + // Since the origin (0, 0) of the image is the upper left corner, we need + // to flip the row to make the origin be the lower left corner. + y = height - y - 1; + // index corresponding to row and col, (assuming single component image) + int index = y*width + x; + // Multiply by 3 to get the index for the rgb components. + assert(index >= 0); + assert(3*index + 2 < (int)pixels.size()); + pixels[3*index + 0] = r; + pixels[3*index + 1] = g; + pixels[3*index + 2] = b; +} + +void Image::writeToFile(const string &filename) +{ + // The distance in bytes from the first byte of a row of pixels to the + // first byte of the next row of pixels + int stride_in_bytes = width*comp*sizeof(unsigned char); + int rc = stbi_write_png(filename.c_str(), width, height, comp, &pixels[0], stride_in_bytes); + if(rc) { + cout << "Wrote to " << filename << endl; + } else { + cout << "Couldn't write to " << filename << endl; + } +} diff --git a/A1/src/Image.h b/A1/src/Image.h new file mode 100644 index 0000000..2f27d46 --- /dev/null +++ b/A1/src/Image.h @@ -0,0 +1,25 @@ +#pragma once +#ifndef _IMAGE_H_ +#define _IMAGE_H_ + +#include +#include + +class Image +{ +public: + Image(int width, int height); + virtual ~Image(); + void setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b); + void writeToFile(const std::string &filename); + int getWidth() const { return width; } + int getHeight() const { return height; } + +private: + int width; + int height; + int comp; + std::vector pixels; +}; + +#endif diff --git a/A1/src/Triangle.cpp b/A1/src/Triangle.cpp new file mode 100644 index 0000000..46fd23c --- /dev/null +++ b/A1/src/Triangle.cpp @@ -0,0 +1,45 @@ +#include "Triangle.h" + +using namespace std; + +Tri::Tri() +{ + vertex v1; + v1.x = 0.0; + v1.y = 0.0; + v1.z = 0.0; + vertex v2; + v2.x = 0.0; + v2.y = 0.0; + v2.z = 0.0; + vertex v3; + v3.x = 0.0; + v3.y = 0.0; + v3.z = 0.0; + v.push_back(v1); + v.push_back(v2); + v.push_back(v3); + xmin = 0; + xmax = 0; + ymin = 0; + ymax = 0; + area = 0.0; +} + +float findArea(vertex &one, vertex &two, vertex &three) +{ + return abs(one.x*two.y + two.x*three.y + three.x*one.y - one.y*two.x - two.y*three.x - three.y*one.x)/2.0; +} + +Tri::Tri(vertex &one, vertex &two, vertex &three) +{ + v.push_back(one); + v.push_back(two); + v.push_back(three); + xmin = one.x; + xmax = one.x; + ymin = one.y; + ymax = one.y; + area = findArea(one, two, three); +} + diff --git a/A1/src/Triangle.h b/A1/src/Triangle.h new file mode 100644 index 0000000..e366b09 --- /dev/null +++ b/A1/src/Triangle.h @@ -0,0 +1,34 @@ +#pragma once +#ifndef _TRIANGLE_H_ +#define _TRIANGLE_H_ + +#include +#include +#include + +struct vertex +{ + float x = 0.0; + float y = 0.0; + float z = 0.0; + float r = 0.0; + float g = 0.0; + float b = 0.0; +}; + +class Tri +{ + public: + Tri(); + Tri(vertex &one, vertex &two, vertex &three); + std::vector v; + float xmin; + float xmax; + float ymin; + float ymax; + float area; +}; + +float findArea(vertex &one, vertex &two, vertex &three); + +#endif diff --git a/A1/src/main.cpp b/A1/src/main.cpp new file mode 100644 index 0000000..3b64734 --- /dev/null +++ b/A1/src/main.cpp @@ -0,0 +1,347 @@ +#include +#include +#include +#include + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +#include "Image.h" +#include "Triangle.h" + +// This allows you to skip the `std::` in front of C++ standard library +// functions. You can also say `using std::cout` to be more selective. +// You should never do this in a header file. +using namespace std; + +int main(int argc, char **argv) +{ + if(argc < 6) { + cout << "Usage: A1 meshfile image width height colormode" << endl; + return 0; + } + + srand(743298); + string meshName(argv[1]); + string filename(argv[2]); + int width = atoi(argv[3]); + int height = atoi(argv[4]); + int colormode = atoi(argv[5]); + + // Load geometry + vector posBuf; // list of vertex positions + + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + + } + index_offset += fv; + + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } + cout << "Number of vertices: " << posBuf.size()/3 << endl; + + vector> zbuf; + + std::vector tris; + + // Split posBuf into triangles. + for(int i = 0; i < (int)posBuf.size()/9; i++) + { + vertex v1; + v1.x = posBuf[i*9]; + v1.y = posBuf[i*9 + 1]; + v1.z = posBuf[i*9 + 2]; + vertex v2; + v2.x = posBuf[i*9 + 3]; + v2.y = posBuf[i*9 + 4]; + v2.z = posBuf[i*9 + 5]; + vertex v3; + v3.x = posBuf[i*9 + 6]; + v3.y = posBuf[i*9 + 7]; + v3.z = posBuf[i*9 + 8]; + Tri t(v1, v2, v3); + tris.push_back(t); + } + + // Initialize min/max variables. + float xmin = posBuf[0]; + float xmax = xmin; + float ymin = posBuf[1]; + float ymax = ymin; + float zmin = tris[0].v[0].z; + float zmax = zmin; + + // First time finding max and min. + // Also, initializing r,g,b per triangle. + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + + int temp1 = rand()%255; + int temp2 = rand()%255; + int temp3 = rand()%255; + tris[i].v[j].r = temp1; + tris[i].v[j].g = temp2; + tris[i].v[j].b = temp3; + } + } + + unsigned char r = rand()%255; + unsigned char b = rand()%255; + unsigned char g = rand()%255; + + + // Create the image. We're using a `shared_ptr`, a C++11 feature. + auto image = make_shared(width, height); + + // Find scaling ratio. + float xratio = (1.0*width/(xmax - xmin)); + float yratio = (1.0*height/(ymax - ymin)); + float zratio = (255.0/(zmax-zmin)); + + float aratio = 1.0; + + // Determine and assign smaller ratio. + if(xratio < yratio) + { + aratio = xratio; + } + else + { + aratio = yratio; + } + + + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + tris[i].v[j].x *= aratio; + tris[i].v[j].y *= aratio; + tris[i].v[j].z *= zratio; + } + } + + xmin = tris[0].v[0].x; + xmax = xmin; + ymin = tris[0].v[0].y; + ymax = ymin; + zmin = tris[0].v[0].z; + zmax = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + } + } + + float xoffset = ((width)/2 - (xmax + xmin)/2); + float yoffset = ((height)/2 - (ymax + ymin)/2); + float zoffset = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size();j++) + { + tris[i].v[j].x += xoffset; + tris[i].v[j].y += yoffset; + tris[i].v[j].z -= zoffset; + } + } + + xmin = tris[0].v[0].x; + xmax = xmin; + ymin = tris[0].v[0].y; + ymax = ymin; + zmin = tris[0].v[0].z; + zmax = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + tris[i].xmin = tris[i].v[0].x; + tris[i].xmax = tris[i].v[0].x; + tris[i].ymin = tris[i].v[0].y; + tris[i].ymax = tris[i].v[0].y; + + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + + if(tris[i].xmin > tris[i].v[j].x) + tris[i].xmin = tris[i].v[j].x; + if(tris[i].xmax < tris[i].v[j].x) + tris[i].xmax = tris[i].v[j].x; + if(tris[i].ymin > tris[i].v[j].y) + tris[i].ymin = tris[i].v[j].y; + if(tris[i].ymax < tris[i].v[j].y) + tris[i].ymax = tris[i].v[j].y; + } + } + + + for(int r = 0; r < width; r++) + { + vector temp; + zbuf.push_back(temp); + for(int c = 0; c < height; c++) + { + zbuf.at(r).push_back(zmin); + } + } + + // Initialize variables for the three + // Barycentric areas. + float a1 = 0.0; + float a2 = 0.0; + float a3 = 0.0; + + // Initialize variables for the three + // Barycentric coordinates. + float l1 = 0.0; + float l2 = 0.0; + float l3 = 0.0; + + // Variable to hold current z coordinate. + float z = 0.0; + + // I had each triangle hold a variable which was its area, + // Here, I make sure they all have their areas set correctly. + for(int i = 0; i < (int)tris.size(); i++) + { + tris[i].area = findArea(tris[i].v[0], tris[i].v[1], tris[i].v[2]); + } + for(int i = 0; i < (int)tris.size(); i++) + { + for(int x = tris[i].xmin; x < tris[i].xmax; x++) + { + for(int y = tris[i].ymin; y < tris[i].ymax; y++) + { + // Temporary vertex so we can utilize findArea. + vertex tempv; + tempv.x = x; + tempv.y = y; + + a3 = findArea(tris[i].v[0], tris[i].v[1], tempv); + a2 = findArea(tris[i].v[0], tempv, tris[i].v[2]); + a1 = findArea(tempv, tris[i].v[1], tris[i].v[2]); + + l1 = a1/tris[i].area; + l2 = a2/tris[i].area; + l3 = a3/tris[i].area; + + r = (a1*tris[i].v[0].r + a2*tris[i].v[1].r + a3*tris[i].v[2].r)/tris[i].area; + g = (a1*tris[i].v[0].g + a2*tris[i].v[1].g + a3*tris[i].v[2].g)/tris[i].area; + b = (a1*tris[i].v[0].b + a2*tris[i].v[1].b + a3*tris[i].v[2].b)/tris[i].area; + + if(colormode == 0) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, r, g ,b); + zbuf.at(x).at(y) = z; + } + } + + float z1 = tris[i].v[0].z; + float z2 = tris[i].v[1].z; + float z3 = tris[i].v[2].z; + + z = (a1*z1 + a2*z2 + a3*z3)/tris[i].area; + if(colormode == 1) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, z, 0, 0); + zbuf.at(x).at(y) = z; + } + } + else if(colormode == 2) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, 0, (255/(ymax - ymin)) - (y - ymin)*(255/(ymax - ymin)), (y - ymin)*(255/(ymax - ymin))); + zbuf.at(x).at(y) = z; + } + } + } + } + } + + // Write image to file + image->writeToFile(filename); + return 0; +} diff --git a/A1/src/stb_image_write.h b/A1/src/stb_image_write.h new file mode 100644 index 0000000..f07b625 --- /dev/null +++ b/A1/src/stb_image_write.h @@ -0,0 +1,1048 @@ +/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio. It could be + adapted to write to memory or a general streaming interface; let me know. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation. This library is designed + for source code compactness and simplicity, not optimal image file size + or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can define STBIW_MEMMOVE() to replace memmove() + +USAGE: + + There are four functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + There are also four equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + +CREDITS: + + PNG/BMP/TGA + Sean Barrett + HDR + Baldur Karlsson + TGA monochrome: + Jean-Sebastien Guay + misc enhancements: + Tim Kelsey + TGA RLE + Alan Hickman + initial file IO callback implementation + Emmanuel Julien + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + +LICENSE + +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#define STBIWDEF extern +extern int stbi_write_tga_with_rle; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + +#ifdef __cplusplus +} +#endif + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_tga_with_rle = 1; +#else +int stbi_write_tga_with_rle = 1; +#endif + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a, arr[1] = b, arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 1: + s->func(s->context,d,1); + break; + case 2: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + for (j = y - 1; j >= 0; --j) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson +#ifndef STBI_WRITE_NO_STDIO + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); + STBIW_FREE(scratch); + return 1; + } +} + +int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) best=d,bestloc=hlist[j]; + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; + s1 %= 65521, s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int i,j,k,p,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = j ? mapping : firstmap; + int best = 0, bestval = 0x7fffffff; + for (p=0; p < 2; ++p) { + for (k= p?best:0; k < 5; ++k) { + int type = mymap[k],est=0; + unsigned char *z = pixels + stride_bytes*j; + for (i=0; i < n; ++i) + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + for (i=n; i < x*n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i] - z[i-n]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; + case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } + } + if (p) break; + for (i=0; i < x*n; ++i) + est += abs((signed char) line_buffer[i]); + if (est < bestval) { bestval = est; best = k; } + } + } + // when we get here, best contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) best; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + f = fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ diff --git a/A1/src/tiny_obj_loader.h b/A1/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/A1/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/A2/.gitignore b/A2/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/A2/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/A2/CMakeLists.txt b/A2/CMakeLists.txt new file mode 100644 index 0000000..e451276 --- /dev/null +++ b/A2/CMakeLists.txt @@ -0,0 +1,126 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(A2) + +# FOR LAB MACHINES ONLY! +# DO NOT EDIT +SET(DEF_DIR_GLM "C:\\c++\\glm") +SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1") +SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0") + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() +FILE(GLOB_RECURSE GLSL "resources/*.glsl") + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL}) + +# Get the GLM environment variable. Since GLM is a header-only library, we +# just need to add it to the include directory. +SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}") +IF(NOT GLM_INCLUDE_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}") + IF(IS_DIRECTORY ${DEF_DIR_GLM}) + MESSAGE(STATUS "Found!") + SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR}) + +# Get the GLFW environment variable. There should be a CMakeLists.txt in the +# specified directory. +SET(GLFW_DIR "$ENV{GLFW_DIR}") +IF(NOT GLFW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}") + IF(IS_DIRECTORY ${DEF_DIR_GLFW}) + MESSAGE(STATUS "Found!") + SET(GLFW_DIR ${DEF_DIR_GLFW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF) +OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF) +OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF) +IF(CMAKE_BUILD_TYPE MATCHES Release) + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release) +ELSE() + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug) +ENDIF() +INCLUDE_DIRECTORIES(${GLFW_DIR}/include) +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES}) + +# Get the GLEW environment variable. +SET(GLEW_DIR "$ENV{GLEW_DIR}") +IF(NOT GLEW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}") + IF(IS_DIRECTORY ${DEF_DIR_GLEW}) + MESSAGE(STATUS "Found!") + SET(GLEW_DIR ${DEF_DIR_GLEW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLEW_DIR}/include) +IF(WIN32) + # With prebuilt binaries + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib) +ELSE() + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a) +ENDIF() + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib) +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") + IF(APPLE) + # Add required frameworks for GLFW. + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo") + ELSE() + #Link the Linux OpenGL library + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL") + ENDIF() +ENDIF() diff --git a/A2/resources/cube.obj b/A2/resources/cube.obj new file mode 100644 index 0000000..e81edd5 --- /dev/null +++ b/A2/resources/cube.obj @@ -0,0 +1,29 @@ +# Blender v2.71 (sub 0) OBJ File: '' +# www.blender.org +v 0.500000 0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 0.500000 -0.500000 +v 0.500000 0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 0.500000 +v -0.500000 0.500000 0.500000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 1.000000 +vn 1.000000 -0.000000 -0.000000 +vn -0.000000 -1.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 1.000000 0.000000 +s off +f 2//1 3//1 4//1 +f 8//2 7//2 6//2 +f 1//3 5//3 6//3 +f 2//4 6//4 7//4 +f 7//5 8//5 4//5 +f 1//6 4//6 8//6 +f 1//1 2//1 4//1 +f 5//2 8//2 6//2 +f 2//3 1//3 6//3 +f 3//4 2//4 7//4 +f 3//5 7//5 4//5 +f 5//6 1//6 8//6 diff --git a/A2/resources/frag.glsl b/A2/resources/frag.glsl new file mode 100644 index 0000000..9d07efa --- /dev/null +++ b/A2/resources/frag.glsl @@ -0,0 +1,8 @@ +#version 120 + +varying vec3 vCol; + +void main() +{ + gl_FragColor = vec4(vCol.r, vCol.g, vCol.b, 1.0); +} diff --git a/A2/resources/vert.glsl b/A2/resources/vert.glsl new file mode 100644 index 0000000..3ecb3f4 --- /dev/null +++ b/A2/resources/vert.glsl @@ -0,0 +1,13 @@ +#version 120 + +attribute vec4 aPos; +attribute vec3 aNor; +uniform mat4 P; +uniform mat4 MV; +varying vec3 vCol; + +void main() +{ + gl_Position = P * MV * aPos; + vCol = 0.5*(aNor + 1.0); +} diff --git a/A2/src/Body.h b/A2/src/Body.h new file mode 100644 index 0000000..9d0f5a8 --- /dev/null +++ b/A2/src/Body.h @@ -0,0 +1,43 @@ +// Create Body Class + +/* +Class Body +{ + Head h; + Shoulder sl; + Shoulder sr; + Leg ull; + Leg ulr; + bool selected = true; + + draw(MatrixStack MV); +} +*/ + +/* + +static void renderA(MatrixStack MV) +{ + MV.pushMatrix(); + MV.translate(-1, 0, 0); + MV.rotate(-(2*PI)/16, 0, 0, 1); + MV.scale(0.5, 4, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #1 + MV.pushMatrix(); + MV.scale(2, 0.5, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #2 + MV.pushMatrix(); + MV.translate(1, 0, 0); + MV.rotate((2*PI)/16, 0, 0, 1); + MV.scale(0.5, 4, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #3 +} + + +*/ diff --git a/A2/src/GLSL.cpp b/A2/src/GLSL.cpp new file mode 100644 index 0000000..2969872 --- /dev/null +++ b/A2/src/GLSL.cpp @@ -0,0 +1,152 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#include "GLSL.h" +#include +#include +#include +#include + +using namespace std; + +namespace GLSL { + +const char * errorString(GLenum err) +{ + switch(err) { + case GL_NO_ERROR: + return "No error"; + case GL_INVALID_ENUM: + return "Invalid enum"; + case GL_INVALID_VALUE: + return "Invalid value"; + case GL_INVALID_OPERATION: + return "Invalid operation"; + case GL_STACK_OVERFLOW: + return "Stack overflow"; + case GL_STACK_UNDERFLOW: + return "Stack underflow"; + case GL_OUT_OF_MEMORY: + return "Out of memory"; + default: + return "No error"; + } +} + +void checkVersion() +{ + int major, minor; + major = minor = 0; + const char *verstr = (const char *)glGetString(GL_VERSION); + + if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) { + printf("Invalid GL_VERSION format %d.%d\n", major, minor); + } + if(major < 2) { + printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor); + exit(0); + } +} + +void checkError(const char *str) +{ + GLenum glErr = glGetError(); + if(glErr != GL_NO_ERROR) { + if(str) { + printf("%s: ", str); + } + printf("GL_ERROR = %s.\n", errorString(glErr)); + assert(false); + } +} + +void printShaderInfoLog(GLuint shader) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Shader InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +void printProgramInfoLog(GLuint program) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Program InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +char *textFileRead(const char *fn) +{ + FILE *fp; + char *content = NULL; + int count = 0; + if(fn != NULL) { + fp = fopen(fn,"rt"); + if(fp != NULL) { + fseek(fp, 0, SEEK_END); + count = (int)ftell(fp); + rewind(fp); + if(count > 0) { + content = (char *)malloc(sizeof(char) * (count+1)); + count = (int)fread(content,sizeof(char),count,fp); + content[count] = '\0'; + } + fclose(fp); + } else { + printf("error loading %s\n", fn); + } + } + return content; +} + +int textFileWrite(const char *fn, const char *s) +{ + FILE *fp; + int status = 0; + if(fn != NULL) { + fp = fopen(fn,"w"); + if(fp != NULL) { + if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) { + status = 1; + } + fclose(fp); + } + } + return(status); +} + +} diff --git a/A2/src/GLSL.h b/A2/src/GLSL.h new file mode 100644 index 0000000..f945fdd --- /dev/null +++ b/A2/src/GLSL.h @@ -0,0 +1,40 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#pragma once +#ifndef __GLSL__ +#define __GLSL__ + +#define GLEW_STATIC +#include + +/////////////////////////////////////////////////////////////////////////////// +// For printing out the current file and line number // +/////////////////////////////////////////////////////////////////////////////// +#include + +template +std::string NumberToString(T x) +{ + std::ostringstream ss; + ss << x; + return ss.str(); +} + +#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str() +/////////////////////////////////////////////////////////////////////////////// + +namespace GLSL { + + void checkVersion(); + void checkError(const char *str = 0); + void printProgramInfoLog(GLuint program); + void printShaderInfoLog(GLuint shader); + int textFileWrite(const char *filename, const char *s); + char *textFileRead(const char *filename); +} + +#endif diff --git a/A2/src/MatrixStack.cpp b/A2/src/MatrixStack.cpp new file mode 100644 index 0000000..eaa6e6c --- /dev/null +++ b/A2/src/MatrixStack.cpp @@ -0,0 +1,114 @@ +#include "MatrixStack.h" + +#include +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +using namespace std; + +MatrixStack::MatrixStack() +{ + mstack = make_shared< stack >(); + mstack->push(glm::mat4(1.0)); +} + +MatrixStack::~MatrixStack() +{ +} + +void MatrixStack::pushMatrix() +{ + const glm::mat4 &top = mstack->top(); + mstack->push(top); + assert(mstack->size() < 100); +} + +void MatrixStack::popMatrix() +{ + assert(!mstack->empty()); + mstack->pop(); + // There should always be one matrix left. + assert(!mstack->empty()); +} + +void MatrixStack::loadIdentity() +{ + glm::mat4 &top = mstack->top(); + top = glm::mat4(1.0); +} + +void MatrixStack::translate(const glm::vec3 &t) +{ + glm::mat4 &top = mstack->top(); + top *= glm::translate(t); +} + +void MatrixStack::translate(float x, float y, float z) +{ + translate(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(const glm::vec3 &s) +{ + glm::mat4 &top = mstack->top(); + top *= glm::scale(s); +} + +void MatrixStack::scale(float x, float y, float z) +{ + scale(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(float s) +{ + scale(glm::vec3(s, s, s)); +} + +void MatrixStack::rotate(float angle, const glm::vec3 &axis) +{ + glm::mat4 &top = mstack->top(); + top *= glm::rotate(angle, axis); +} + +void MatrixStack::rotate(float angle, float x, float y, float z) +{ + rotate(angle, glm::vec3(x, y, z)); +} + +void MatrixStack::multMatrix(const glm::mat4 &matrix) +{ + glm::mat4 &top = mstack->top(); + top *= matrix; +} + +const glm::mat4 &MatrixStack::topMatrix() const +{ + return mstack->top(); +} + +void MatrixStack::print(const glm::mat4 &mat, const char *name) +{ + if(name) { + printf("%s = [\n", name); + } + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + // mat[j] returns the jth column + printf("%- 5.2f ", mat[j][i]); + } + printf("\n"); + } + if(name) { + printf("];"); + } + printf("\n"); +} + +void MatrixStack::print(const char *name) const +{ + print(mstack->top(), name); +} diff --git a/A2/src/MatrixStack.h b/A2/src/MatrixStack.h new file mode 100644 index 0000000..66278ce --- /dev/null +++ b/A2/src/MatrixStack.h @@ -0,0 +1,50 @@ +#pragma once +#ifndef _MatrixStack_H_ +#define _MatrixStack_H_ + +#include +#include +#include + +class MatrixStack +{ +public: + MatrixStack(); + virtual ~MatrixStack(); + + // glPushMatrix(): Copies the current matrix and adds it to the top of the stack + void pushMatrix(); + // glPopMatrix(): Removes the top of the stack and sets the current matrix to be the matrix that is now on top + void popMatrix(); + + // glLoadIdentity(): Sets the top matrix to be the identity + void loadIdentity(); + // glMultMatrix(): Right multiplies the top matrix + void multMatrix(const glm::mat4 &matrix); + + // glTranslate(): Right multiplies the top matrix by a translation matrix + void translate(const glm::vec3 &trans); + void translate(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(const glm::vec3 &scale); + void scale(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(float size); + // glRotate(): Right multiplies the top matrix by a rotation matrix (angle in radians) + void rotate(float angle, const glm::vec3 &axis); + void rotate(float angle, float x, float y, float z); + + // glGet(GL_MODELVIEW_MATRIX): Gets the top matrix + const glm::mat4 &topMatrix() const; + + // Prints out the specified matrix + static void print(const glm::mat4 &mat, const char *name = 0); + // Prints out the top matrix + void print(const char *name = 0) const; + +private: + std::shared_ptr< std::stack > mstack; + +}; + +#endif diff --git a/A2/src/Program.cpp b/A2/src/Program.cpp new file mode 100644 index 0000000..1e85538 --- /dev/null +++ b/A2/src/Program.cpp @@ -0,0 +1,126 @@ +#include "Program.h" + +#include +#include + +#include "GLSL.h" + +using namespace std; + +Program::Program() : + vShaderName(""), + fShaderName(""), + pid(0), + verbose(true) +{ + +} + +Program::~Program() +{ + +} + +void Program::setShaderNames(const string &v, const string &f) +{ + vShaderName = v; + fShaderName = f; +} + +bool Program::init() +{ + GLint rc; + + // Create shader handles + GLuint VS = glCreateShader(GL_VERTEX_SHADER); + GLuint FS = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + const char *vshader = GLSL::textFileRead(vShaderName.c_str()); + const char *fshader = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(VS, 1, &vshader, NULL); + glShaderSource(FS, 1, &fshader, NULL); + + // Compile vertex shader + glCompileShader(VS); + glGetShaderiv(VS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(VS); + cout << "Error compiling vertex shader " << vShaderName << endl; + } + return false; + } + + // Compile fragment shader + glCompileShader(FS); + glGetShaderiv(FS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(FS); + cout << "Error compiling fragment shader " << fShaderName << endl; + } + return false; + } + + // Create the program and link + pid = glCreateProgram(); + glAttachShader(pid, VS); + glAttachShader(pid, FS); + glLinkProgram(pid); + glGetProgramiv(pid, GL_LINK_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printProgramInfoLog(pid); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + } + return false; + } + + GLSL::checkError(GET_FILE_LINE); + return true; +} + +void Program::bind() +{ + glUseProgram(pid); +} + +void Program::unbind() +{ + glUseProgram(0); +} + +void Program::addAttribute(const string &name) +{ + attributes[name] = glGetAttribLocation(pid, name.c_str()); +} + +void Program::addUniform(const string &name) +{ + uniforms[name] = glGetUniformLocation(pid, name.c_str()); +} + +GLint Program::getAttribute(const string &name) const +{ + map::const_iterator attribute = attributes.find(name.c_str()); + if(attribute == attributes.end()) { + if(isVerbose()) { + cout << name << " is not an attribute variable" << endl; + } + return -1; + } + return attribute->second; +} + +GLint Program::getUniform(const string &name) const +{ + map::const_iterator uniform = uniforms.find(name.c_str()); + if(uniform == uniforms.end()) { + if(isVerbose()) { + cout << name << " is not a uniform variable" << endl; + } + return -1; + } + return uniform->second; +} diff --git a/A2/src/Program.h b/A2/src/Program.h new file mode 100644 index 0000000..51e58bb --- /dev/null +++ b/A2/src/Program.h @@ -0,0 +1,44 @@ +#pragma once +#ifndef __Program__ +#define __Program__ + +#include +#include + +#define GLEW_STATIC +#include + +/** + * An OpenGL Program (vertex and fragment shaders) + */ +class Program +{ +public: + Program(); + virtual ~Program(); + + void setVerbose(bool v) { verbose = v; } + bool isVerbose() const { return verbose; } + + void setShaderNames(const std::string &v, const std::string &f); + virtual bool init(); + virtual void bind(); + virtual void unbind(); + + void addAttribute(const std::string &name); + void addUniform(const std::string &name); + GLint getAttribute(const std::string &name) const; + GLint getUniform(const std::string &name) const; + +protected: + std::string vShaderName; + std::string fShaderName; + +private: + GLuint pid; + std::map attributes; + std::map uniforms; + bool verbose; +}; + +#endif diff --git a/A2/src/Shape.cpp b/A2/src/Shape.cpp new file mode 100644 index 0000000..cf80379 --- /dev/null +++ b/A2/src/Shape.cpp @@ -0,0 +1,135 @@ +#include "Shape.h" +#include + +#include "GLSL.h" +#include "Program.h" + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +using namespace std; + +Shape::Shape() : + posBufID(0), + norBufID(0), + texBufID(0) +{ +} + +Shape::~Shape() +{ +} + +void Shape::loadMesh(const string &meshName) +{ + // Load geometry + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + if(!attrib.texcoords.empty()) { + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+0]); + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+1]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } +} + +void Shape::init() +{ + // Send the position array to the GPU + glGenBuffers(1, &posBufID); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + // Send the normal array to the GPU + if(!norBuf.empty()) { + glGenBuffers(1, &norBufID); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + } + + // Send the texture array to the GPU + if(!texBuf.empty()) { + glGenBuffers(1, &texBufID); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glBufferData(GL_ARRAY_BUFFER, texBuf.size()*sizeof(float), &texBuf[0], GL_STATIC_DRAW); + } + + // Unbind the arrays + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} + +void Shape::draw(const shared_ptr prog) const +{ + // Bind position buffer + int h_pos = prog->getAttribute("aPos"); + glEnableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glVertexAttribPointer(h_pos, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + + // Bind normal buffer + int h_nor = prog->getAttribute("aNor"); + if(h_nor != -1 && norBufID != 0) { + glEnableVertexAttribArray(h_nor); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glVertexAttribPointer(h_nor, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Bind texcoords buffer + int h_tex = prog->getAttribute("aTex"); + if(h_tex != -1 && texBufID != 0) { + glEnableVertexAttribArray(h_tex); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glVertexAttribPointer(h_tex, 2, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Draw + int count = posBuf.size()/3; // number of indices to be rendered + glDrawArrays(GL_TRIANGLES, 0, count); + + // Disable and unbind + if(h_tex != -1) { + glDisableVertexAttribArray(h_tex); + } + if(h_nor != -1) { + glDisableVertexAttribArray(h_nor); + } + glDisableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} diff --git a/A2/src/Shape.h b/A2/src/Shape.h new file mode 100644 index 0000000..df2aea3 --- /dev/null +++ b/A2/src/Shape.h @@ -0,0 +1,36 @@ +#pragma once +#ifndef _SHAPE_H_ +#define _SHAPE_H_ + +#include +#include +#include + +class Program; + +/** + * A shape defined by a list of triangles + * - posBuf should be of length 3*ntris + * - norBuf should be of length 3*ntris (if normals are available) + * - texBuf should be of length 2*ntris (if texture coords are available) + * posBufID, norBufID, and texBufID are OpenGL buffer identifiers. + */ +class Shape +{ +public: + Shape(); + virtual ~Shape(); + void loadMesh(const std::string &meshName); + void init(); + void draw(const std::shared_ptr prog) const; + +private: + std::vector posBuf; + std::vector norBuf; + std::vector texBuf; + unsigned posBufID; + unsigned norBufID; + unsigned texBufID; +}; + +#endif diff --git a/A2/src/main.cpp b/A2/src/main.cpp new file mode 100644 index 0000000..0985a74 --- /dev/null +++ b/A2/src/main.cpp @@ -0,0 +1,187 @@ +#include +#include +#define _USE_MATH_DEFINES +#include +#include +#include +#include + +#define GLEW_STATIC +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include +#include + +#include "tiny_obj_loader.h" + +#include "GLSL.h" +#include "MatrixStack.h" +#include "Shape.h" +#include "Program.h" + +#define PI 3.14159 + +using namespace std; +using namespace glm; + +GLFWwindow *window; // Main application window +string RESOURCE_DIR = "./"; // Where the resources are loaded from +shared_ptr prog; +shared_ptr shape; + + +GLuint progID; +map attrIDs; +map unifIDs; +map bufIDs; +int indCount; +// This function is called when a GLFW error occurs +static void error_callback(int error, const char *description) +{ + cerr << description << endl; +} + +// This function is called when a key is pressed +static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GL_TRUE); + } +} + +// This function is called when the mouse is clicked +static void mouse_callback(GLFWwindow *window, int button, int action, int mods) +{ + // Do nothing +} + +// If the window is resized, capture the new size and reset the viewport +static void resize_callback(GLFWwindow *window, int width, int height) +{ + glViewport(0, 0, width, height); +} + +static void init() +{ + GLSL::checkVersion(); + + // Set background color. + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + // Enable z-buffer test. + glEnable(GL_DEPTH_TEST); + + // Initialize mesh. + shape = make_shared(); + shape->loadMesh(RESOURCE_DIR + "teapot.obj"); + shape->init(); + + // Initialize the GLSL program. + prog = make_shared(); + prog->setVerbose(false); // Set this to true when debugging. + prog->setShaderNames(RESOURCE_DIR + "simple_vert.glsl", RESOURCE_DIR + "simple_frag.glsl"); + prog->init(); + prog->addUniform("P"); + prog->addUniform("MV"); + prog->addAttribute("aPos"); + prog->addAttribute("aNor"); + + // If there were any OpenGL errors, this will print something. + // You can intersperse this line in your code to find the exact location + // of your OpenGL error. + GLSL::checkError(GET_FILE_LINE); +} + +static void render() +{ + // Get current frame buffer size. + int width, height; + glfwGetFramebufferSize(window, &width, &height); + float aspect = width/(float)height; + glViewport(0, 0, width, height); + + // Clear framebuffer. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Create matrix stacks. + auto P = make_shared(); + auto MV = make_shared(); + // Apply projection. + P->pushMatrix(); + P->multMatrix(glm::perspective((float)(45.0*M_PI/180.0), aspect, 0.01f, 100.0f)); + // Apply camera transform. + MV->pushMatrix(); + MV->translate(glm::vec3(0, -0.5, -3)); + + // Draw mesh using GLSL. + prog->bind(); + glUniformMatrix4fv(prog->getUniform("P"), 1, GL_FALSE, &P->topMatrix()[0][0]); + glUniformMatrix4fv(prog->getUniform("MV"), 1, GL_FALSE, &MV->topMatrix()[0][0]); + shape->draw(prog); + prog->unbind(); + + // Pop matrix stacks. + MV->popMatrix(); + P->popMatrix(); + + GLSL::checkError(GET_FILE_LINE); +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + cout << "Please specify the resource directory." << endl; + return 0; + } + RESOURCE_DIR = argv[1] + string("/"); + + // Set error callback. + glfwSetErrorCallback(error_callback); + // Initialize the library. + if(!glfwInit()) { + return -1; + } + // Create a windowed mode window and its OpenGL context. + window = glfwCreateWindow(640, 480, "Alexander Huddleston", NULL, NULL); + if(!window) { + glfwTerminate(); + return -1; + } + // Make the window's context current. + glfwMakeContextCurrent(window); + // Initialize GLEW. + glewExperimental = true; + if(glewInit() != GLEW_OK) { + cerr << "Failed to initialize GLEW" << endl; + return -1; + } + glGetError(); // A bug in glewInit() causes an error that we can safely ignore. + cout << "OpenGL version: " << glGetString(GL_VERSION) << endl; + cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; + GLSL::checkVersion(); + // Set vsync. + glfwSwapInterval(1); + // Set keyboard callback. + glfwSetKeyCallback(window, key_callback); + // Set the mouse call back. + glfwSetMouseButtonCallback(window, mouse_callback); + // Set the window resize call back. + glfwSetFramebufferSizeCallback(window, resize_callback); + // Initialize scene. + init(); + // Loop until the user closes the window. + while(!glfwWindowShouldClose(window)) { + // Render scene. + render(); + // Swap front and back buffers. + glfwSwapBuffers(window); + // Poll for and process events. + glfwPollEvents(); + } + // Quit program. + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/A2/src/tiny_obj_loader.h b/A2/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/A2/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/L00(old)/.gitignore b/L00(old)/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L00(old)/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L00(old)/CMakeLists.txt b/L00(old)/CMakeLists.txt new file mode 100644 index 0000000..f6a10e7 --- /dev/null +++ b/L00(old)/CMakeLists.txt @@ -0,0 +1,118 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L00) + +# FOR LAB MACHINES ONLY! +# DO NOT EDIT +SET(DEF_DIR_GLM "C:\\c++\\glm") +SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1") +SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0") + +# Use glob to get the list of all source files. +FILE(GLOB_RECURSE SOURCES "src/*.cpp") + +# We don't really need to include header and resource files to build, but it's +# nice to have them show up in IDEs. +FILE(GLOB_RECURSE HEADERS "src/*.h") +FILE(GLOB_RECURSE GLSL "resources/*.glsl") + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL}) + +# Get the GLM environment variable. Since GLM is a header-only library, we +# just need to add it to the include directory. +SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}") +IF(NOT GLM_INCLUDE_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}") + IF(IS_DIRECTORY ${DEF_DIR_GLM}) + MESSAGE(STATUS "Found!") + SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR}) + +# Get the GLFW environment variable. There should be a CMakeLists.txt in the +# specified directory. +SET(GLFW_DIR "$ENV{GLFW_DIR}") +IF(NOT GLFW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}") + IF(IS_DIRECTORY ${DEF_DIR_GLFW}) + MESSAGE(STATUS "Found!") + SET(GLFW_DIR ${DEF_DIR_GLFW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF) +OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF) +OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF) +IF(CMAKE_BUILD_TYPE MATCHES Release) + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release) +ELSE() + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug) +ENDIF() +INCLUDE_DIRECTORIES(${GLFW_DIR}/include) +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES}) + +# Get the GLEW environment variable. +SET(GLEW_DIR "$ENV{GLEW_DIR}") +IF(NOT GLEW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}") + IF(IS_DIRECTORY ${DEF_DIR_GLEW}) + MESSAGE(STATUS "Found!") + SET(GLEW_DIR ${DEF_DIR_GLEW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLEW_DIR}/include) +IF(WIN32) + # With prebuilt binaries + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib) +ELSE() + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a) +ENDIF() + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib) +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") + IF(APPLE) + # Add required frameworks for GLFW. + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo") + ELSE() + #Link the Linux OpenGL library + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL") + ENDIF() +ENDIF() diff --git a/L00(old)/resources/simple_frag.glsl b/L00(old)/resources/simple_frag.glsl new file mode 100644 index 0000000..14d1353 --- /dev/null +++ b/L00(old)/resources/simple_frag.glsl @@ -0,0 +1,11 @@ +#version 120 + +varying vec3 fragNor; + +void main() +{ + vec3 normal = normalize(fragNor); + // Map normal in the range [-1, 1] to color in range [0, 1]; + vec3 color = 0.5*normal + 0.5; + gl_FragColor = vec4(color, 1.0); +} diff --git a/L00(old)/resources/simple_vert.glsl b/L00(old)/resources/simple_vert.glsl new file mode 100644 index 0000000..059c4b3 --- /dev/null +++ b/L00(old)/resources/simple_vert.glsl @@ -0,0 +1,12 @@ +#version 120 +attribute vec4 vertPos; +attribute vec3 vertNor; +uniform mat4 P; +uniform mat4 MV; +varying vec3 fragNor; + +void main() +{ + gl_Position = P * MV * vertPos; + fragNor = (MV * vec4(vertNor, 0.0)).xyz; +} diff --git a/L00(old)/resources/teapot.obj b/L00(old)/resources/teapot.obj new file mode 100644 index 0000000..6fed453 --- /dev/null +++ b/L00(old)/resources/teapot.obj @@ -0,0 +1,5049 @@ +# Blender v2.65 (sub 0) OBJ File +# www.blender.org +o teapot.005 +v -0.498530 0.712498 -0.039883 +v -0.501666 0.699221 -0.063813 +v -0.501255 0.717792 0.000000 +v -0.624036 0.711938 -0.039883 +v -0.526706 0.651362 -0.039883 +v -0.508714 0.682112 -0.071712 +v -0.622039 0.698704 -0.063813 +v -0.624834 0.717232 0.000000 +v -0.498530 0.712498 0.039883 +v -0.638129 0.287158 0.000000 +v -0.517593 0.664661 -0.063813 +v -0.534329 0.646030 0.000000 +v -0.614850 0.651067 -0.039883 +v -0.616848 0.664299 -0.063813 +v -0.619445 0.681503 -0.071790 +v -0.741245 0.707456 -0.039883 +v -0.744483 0.712577 0.000000 +v -0.624036 0.711938 0.039883 +v -0.501667 0.699221 0.063813 +v -0.622039 0.698704 0.063813 +v -0.712095 0.661370 -0.063813 +v -0.733150 0.694655 -0.063813 +v -0.741245 0.707456 0.039883 +v -0.733150 0.694655 0.063813 +v -0.631184 0.277569 -0.039883 +v -0.526706 0.651362 0.039883 +v -0.614053 0.645774 0.000000 +v -0.704000 0.648569 -0.039883 +v -0.722621 0.678012 -0.071790 +v -0.832523 0.695296 -0.039883 +v -0.837545 0.699948 0.000000 +v -0.832523 0.695296 0.039883 +v -0.619445 0.681503 0.071790 +v -0.508714 0.682112 0.071712 +v -0.722621 0.678012 0.071790 +v -0.517593 0.664661 0.063813 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.710066 0.328372 0.000000 +v -0.614850 0.651067 0.039883 +v -0.787321 0.653419 -0.063813 +v -0.803644 0.668539 -0.071790 +v -0.819967 0.683663 -0.063813 +v -0.819967 0.683663 0.063813 +v -0.803644 0.668539 0.071790 +v -0.711425 0.307332 -0.063813 +v -0.615553 0.216807 -0.063813 +v -0.712688 0.287795 -0.071790 +v -0.631184 0.277569 0.039883 +v -0.710455 0.322361 -0.039883 +v -0.710455 0.322361 0.039883 +v -0.700762 0.643448 0.000000 +v -0.774766 0.641786 -0.039883 +v -0.897800 0.671612 -0.039883 +v -0.904015 0.675354 0.000000 +v -0.897800 0.671612 0.039883 +v -0.882265 0.662257 0.063813 +v -0.712095 0.661370 0.063813 +v -0.787321 0.653419 0.063813 +v -0.608884 0.198682 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.766936 0.377559 0.000000 +v -0.769651 0.372307 0.039883 +v -0.616848 0.664299 0.063813 +v -0.704000 0.648569 0.039883 +v -0.841868 0.637931 -0.063813 +v -0.862065 0.650094 -0.071790 +v -0.882265 0.662257 -0.063813 +v -0.862065 0.650094 0.071790 +v -0.841868 0.637931 0.063813 +v -0.611709 0.194244 0.000000 +v -0.776434 0.359177 -0.063813 +v -0.769651 0.372307 -0.039883 +v -0.713952 0.268259 -0.063813 +v -0.711425 0.307332 0.063813 +v -0.776434 0.359177 0.063813 +v -0.769743 0.637131 0.000000 +v -0.826329 0.628576 -0.039883 +v -0.937016 0.632565 -0.039883 +v -0.943899 0.634805 0.000000 +v -0.937016 0.632565 0.039883 +v -0.919812 0.626965 0.063813 +v -0.897443 0.619684 0.071790 +v -0.774766 0.641786 0.039883 +v -0.826329 0.628576 0.039883 +v -0.714922 0.253231 -0.039883 +v -0.608883 0.198681 0.039883 +v -0.715311 0.247220 0.000000 +v -0.785253 0.342107 -0.071790 +v -0.619922 0.238069 0.071790 +v -0.712688 0.287795 0.071790 +v -0.809626 0.430737 0.000000 +v -0.814205 0.426194 0.039883 +v -0.825653 0.414838 0.063813 +v -0.875076 0.612403 -0.063813 +v -0.897443 0.619684 -0.071790 +v -0.919812 0.626965 -0.063813 +v -0.875076 0.612403 0.063813 +v -0.857869 0.606800 0.039883 +v -0.794072 0.325038 -0.063813 +v -0.800855 0.311909 -0.039883 +v -0.825653 0.414838 -0.063813 +v -0.814205 0.426194 -0.039883 +v -0.615480 0.216617 0.063578 +v -0.785253 0.342107 0.071790 +v -0.840534 0.400078 0.071790 +v -0.820114 0.624834 0.000000 +v -0.857869 0.606800 -0.039883 +v -0.950104 0.574316 -0.039883 +v -0.957194 0.574316 0.000000 +v -0.950104 0.574316 0.039883 +v -0.932377 0.574316 0.063813 +v -0.909334 0.574316 0.071790 +v -0.886292 0.574316 0.063813 +v -0.850987 0.604560 0.000000 +v -0.714922 0.253231 0.039883 +v -0.803571 0.306656 0.000000 +v -0.840534 0.400078 -0.071790 +v -0.713952 0.268259 0.063813 +v -0.794072 0.325038 0.063813 +v -0.839022 0.483916 0.000000 +v -0.844976 0.480304 0.039883 +v -0.859854 0.471278 0.063813 +v -0.879202 0.459542 0.071790 +v -0.886292 0.574316 -0.063813 +v -0.909334 0.574316 -0.071790 +v -0.932377 0.574316 -0.063813 +v -0.868564 0.574316 0.039883 +v -0.861474 0.574316 0.000000 +v -0.855419 0.385315 -0.063813 +v -0.866867 0.373960 -0.039883 +v -0.859854 0.471278 -0.063813 +v -0.844976 0.480304 -0.039883 +v -0.855419 0.385315 0.063813 +v -0.898547 0.447807 0.063813 +v -0.868564 0.574316 -0.039883 +v -0.941014 0.505765 -0.039883 +v -0.947813 0.503580 0.000000 +v -0.941014 0.505765 0.039883 +v -0.924011 0.511234 0.063813 +v -0.901913 0.518343 0.071790 +v -0.879811 0.525448 0.063813 +v -0.862808 0.530917 0.039883 +v -0.800855 0.311909 0.039883 +v -0.871445 0.369416 0.000000 +v -0.879202 0.459542 -0.071790 +v -0.866867 0.373960 0.039883 +v -0.856009 0.533103 0.000000 +v -0.879811 0.525448 -0.063813 +v -0.901913 0.518343 -0.071790 +v -0.924011 0.511234 -0.063813 +v -0.862808 0.530917 -0.039883 +v -0.898547 0.447807 -0.063813 +v -0.913428 0.438781 -0.039883 +v -0.913428 0.438781 0.039883 +v -0.919378 0.435169 0.000000 +v 0.600960 0.444810 0.085753 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.656890 0.471064 0.000000 +v 0.661223 0.454734 -0.083705 +v 0.730696 0.501576 -0.073611 +v 0.661223 0.454734 0.083705 +v 0.605101 0.399712 -0.137265 +v 0.746455 0.470391 -0.117778 +v 0.724395 0.514048 0.000000 +v 0.605100 0.399712 0.137265 +v 0.672055 0.413907 -0.133928 +v 0.613258 0.341675 -0.154354 +v 0.786583 0.544847 -0.096783 +v 0.768856 0.565896 -0.060489 +v 0.672055 0.413907 0.133928 +v 0.730696 0.501576 0.073611 +v 0.686135 0.360830 -0.150669 +v 0.809626 0.517481 -0.108881 +v 0.766935 0.429850 -0.132501 +v 0.761767 0.574316 0.000000 +v 0.613258 0.341675 0.154354 +v 0.813417 0.626247 -0.075788 +v 0.839021 0.611098 -0.085261 +v 0.793721 0.637899 -0.047367 +v 0.686135 0.360830 0.150669 +v 0.768856 0.565896 0.060489 +v 0.746455 0.470391 0.117778 +v 0.619427 0.283145 -0.137236 +v 0.864627 0.595949 -0.075788 +v 0.832669 0.490118 -0.096783 +v 0.787419 0.389310 -0.117778 +v 0.785843 0.642561 0.000000 +v 0.619427 0.283145 0.137236 +v 0.700219 0.307756 -0.133928 +v 0.847933 0.703560 -0.059638 +v 0.879938 0.698065 -0.067092 +v 0.911944 0.692571 -0.059638 +v 0.823314 0.707784 -0.037273 +v 0.766935 0.429850 0.132501 +v 0.793721 0.637899 0.047367 +v 0.786583 0.544847 0.096783 +v 0.700219 0.307756 0.133928 +v 0.617684 0.235930 -0.085941 +v 0.936563 0.688344 -0.037273 +v 0.884319 0.584297 -0.047367 +v 0.850396 0.469070 -0.060489 +v 0.803175 0.358128 -0.073611 +v 0.813468 0.709475 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v 0.711051 0.266929 -0.083705 +v 0.911107 0.765755 -0.053178 +v 0.957193 0.765755 -0.059825 +v 1.003279 0.765755 -0.053178 +v 1.038733 0.765755 -0.033236 +v 0.875654 0.765755 -0.033236 +v 0.809626 0.517481 0.108881 +v 0.787419 0.389310 0.117778 +v 0.823314 0.707784 0.037273 +v 0.813417 0.626247 0.075788 +v 0.711051 0.266929 0.083705 +v 0.715384 0.250599 0.000000 +v 1.052913 0.765755 0.000000 +v 0.946409 0.686653 0.000000 +v 0.892200 0.579635 0.000000 +v 0.857486 0.460650 0.000000 +v 0.809479 0.345652 0.000000 +v 0.861474 0.765755 0.000000 +v 0.929990 0.776479 -0.051602 +v 0.979075 0.777181 -0.058052 +v 1.028157 0.777879 -0.051602 +v 1.065915 0.778419 -0.032251 +v 1.081016 0.778632 0.000000 +v 0.892235 0.775943 -0.032251 +v 0.839021 0.611098 0.085261 +v 0.832669 0.490118 0.096783 +v 0.803175 0.358128 0.073611 +v 0.875654 0.765755 0.033236 +v 0.847933 0.703560 0.059638 +v 1.065915 0.778419 0.032174 +v 1.038733 0.765755 0.033236 +v 0.936563 0.688344 0.037273 +v 0.884319 0.584297 0.047367 +v 0.850396 0.469070 0.060489 +v 0.877131 0.775726 0.000000 +v 0.943713 0.783087 -0.047663 +v 0.992645 0.784366 -0.053621 +v 1.041577 0.785649 -0.047663 +v 1.079216 0.786631 -0.029789 +v 1.094273 0.787027 0.000000 +v 1.079216 0.786631 0.029174 +v 0.906073 0.782101 -0.029789 +v 0.879938 0.698065 0.067092 +v 0.864627 0.595949 0.075788 +v 0.892235 0.775943 0.032236 +v 0.911107 0.765755 0.053178 +v 1.041577 0.785649 0.046875 +v 1.028157 0.777879 0.051503 +v 1.003279 0.765755 0.053178 +v 0.911944 0.692571 0.059638 +v 0.891016 0.781708 0.000000 +v 0.951249 0.785448 -0.042542 +v 0.997575 0.787068 -0.047860 +v 1.043903 0.788686 -0.042542 +v 1.079539 0.789934 -0.026589 +v 1.093795 0.790431 0.000000 +v 1.079539 0.789934 0.024511 +v 1.043903 0.788686 0.039883 +v 0.915613 0.784200 -0.026589 +v 0.957193 0.765755 0.059825 +v 0.906073 0.782101 0.029666 +v 0.929990 0.776479 0.051553 +v 0.997575 0.787068 0.045616 +v 0.992645 0.784366 0.052956 +v 0.979075 0.777181 0.057969 +v 0.901357 0.783702 0.000000 +v 0.951569 0.783431 -0.037421 +v 0.993532 0.785033 -0.042099 +v 1.035492 0.786631 -0.037421 +v 1.067772 0.787863 -0.023388 +v 1.080684 0.788354 0.000000 +v 1.067772 0.787863 0.018464 +v 1.035492 0.786631 0.031119 +v 0.993532 0.785033 0.036781 +v 0.919292 0.782200 -0.023388 +v 0.915613 0.784200 0.026173 +v 0.943713 0.783087 0.047269 +v 0.951569 0.783431 0.034270 +v 0.951249 0.785448 0.041213 +v 0.906379 0.781708 0.000000 +v 0.943653 0.776909 -0.033482 +v 0.980182 0.778010 -0.037667 +v 1.016712 0.779111 -0.033482 +v 1.044812 0.779957 -0.020926 +v 1.056052 0.780295 0.000000 +v 1.044812 0.779957 0.011310 +v 1.016712 0.779111 0.021172 +v 0.980182 0.778010 0.027281 +v 0.943653 0.776909 0.027327 +v 0.915553 0.776064 -0.020926 +v 0.919292 0.782200 0.022403 +v 0.915553 0.776064 0.019003 +v 0.904312 0.775726 0.000000 +v 0.926468 0.765755 -0.031906 +v 0.957193 0.765755 -0.035895 +v 0.987920 0.765755 -0.031906 +v 1.011552 0.765755 -0.019942 +v 1.021006 0.765755 0.000000 +v 1.011552 0.765755 0.003324 +v 0.987920 0.765755 0.010635 +v 0.957193 0.765755 0.017947 +v 0.926468 0.765755 0.021271 +v 0.902834 0.765755 0.016618 +v 0.902834 0.765755 -0.019942 +v 0.893380 0.765755 0.000000 +v 0.886428 0.750924 -0.019014 +v 0.908324 0.750924 -0.030099 +v 0.936793 0.750924 -0.033795 +v 0.965261 0.750924 -0.030099 +v 0.987158 0.750924 -0.019014 +v 0.995918 0.750924 -0.000537 +v 0.987158 0.750924 0.002542 +v 0.965261 0.750924 0.009317 +v 0.936793 0.750924 0.016092 +v 0.908324 0.750924 0.019171 +v 0.886428 0.750924 0.014860 +v 0.877668 0.750924 -0.000537 +v 0.936793 0.750924 -0.007312 +v 0.440746 0.783205 0.000000 +v 0.446690 0.765755 0.000000 +v 0.430973 0.765755 0.119945 +v 0.425236 0.783205 0.118348 +v 0.425236 0.783205 -0.118348 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 0.121642 +v 0.441668 0.793673 0.000000 +v 0.386470 0.765755 0.226985 +v 0.430973 0.765755 -0.119945 +v 0.426127 0.793673 -0.118596 +v 0.437073 0.750009 -0.121642 +v 0.426127 0.793673 0.118596 +v 0.381327 0.783205 0.223964 +v 0.381327 0.783205 -0.223964 +v 0.382124 0.793673 -0.224433 +v 0.317150 0.765755 0.317150 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 0.321639 +v 0.386470 0.765755 -0.226985 +v 0.391939 0.750009 -0.230197 +v 0.447686 0.797164 0.000000 +v 0.431936 0.797164 -0.120212 +v 0.387332 0.797164 -0.227491 +v 0.230197 0.750009 0.391940 +v 0.226984 0.765755 0.386470 +v 0.317150 0.765755 -0.317150 +v 0.321638 0.750009 -0.321639 +v 0.431936 0.797164 0.120212 +v 0.382124 0.793673 0.224433 +v 0.312929 0.783205 0.312929 +v 0.313584 0.793673 -0.313584 +v 0.312929 0.783205 -0.312929 +v 0.317858 0.797164 -0.317858 +v 0.121642 0.750009 0.437072 +v 0.119944 0.765755 0.430973 +v 0.226984 0.765755 -0.386470 +v 0.230197 0.750009 -0.391940 +v 0.457031 0.793673 0.000000 +v 0.440950 0.793673 -0.122721 +v 0.395416 0.793673 -0.232239 +v 0.324491 0.793673 -0.324492 +v -0.000000 0.750009 0.453012 +v -0.000000 0.765755 0.446690 +v 0.223963 0.783205 0.381327 +v 0.223963 0.783205 -0.381327 +v 0.119944 0.765755 -0.430973 +v 0.121642 0.750009 -0.437072 +v 0.440950 0.793673 0.122721 +v 0.387332 0.797164 0.227491 +v 0.313584 0.793673 0.313584 +v 0.227491 0.797164 -0.387332 +v 0.224433 0.793673 -0.382125 +v 0.232239 0.793673 -0.395417 +v -0.119945 0.765755 0.430973 +v -0.121642 0.750009 0.437072 +v 0.118348 0.783205 0.425237 +v 0.118348 0.783205 -0.425237 +v -0.000000 0.750009 -0.453012 +v -0.000000 0.765755 -0.446690 +v 0.467924 0.783205 0.000000 +v 0.451460 0.783205 -0.125646 +v 0.404842 0.783205 -0.237775 +v 0.332226 0.783205 -0.332226 +v 0.237775 0.783205 -0.404842 +v -0.226985 0.765755 0.386470 +v -0.000000 0.783205 0.440746 +v 0.224433 0.793673 0.382125 +v 0.118596 0.793673 -0.426127 +v -0.000000 0.783205 -0.440746 +v -0.119945 0.765755 -0.430973 +v -0.121642 0.750009 -0.437072 +v 0.451460 0.783205 0.125646 +v 0.395416 0.793673 0.232239 +v 0.317858 0.797164 0.317858 +v 0.122721 0.793673 -0.440950 +v 0.120212 0.797164 -0.431937 +v 0.125646 0.783205 -0.451460 +v -0.317150 0.765755 0.317150 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.118348 0.783205 0.425237 +v 0.118596 0.793673 0.426127 +v -0.000000 0.793673 -0.441668 +v -0.118348 0.783205 -0.425237 +v -0.226985 0.765755 -0.386470 +v 0.478596 0.765755 0.000000 +v 0.461756 0.765755 -0.128512 +v 0.414076 0.765755 -0.243198 +v 0.339803 0.765755 -0.339804 +v 0.243198 0.765755 -0.414076 +v 0.128512 0.765755 -0.461757 +v -0.391940 0.750009 0.230197 +v -0.386470 0.765755 0.226985 +v -0.223964 0.783205 0.381327 +v -0.000000 0.793673 0.441668 +v 0.227491 0.797164 0.387332 +v -0.000000 0.797164 -0.447686 +v -0.118596 0.793673 -0.426127 +v -0.223964 0.783205 -0.381327 +v -0.317150 0.765755 -0.317150 +v -0.230198 0.750009 -0.391939 +v -0.321639 0.750009 -0.321639 +v 0.461756 0.765755 0.128512 +v 0.404842 0.783205 0.237775 +v 0.324491 0.793673 0.324492 +v -0.000000 0.783205 -0.467924 +v -0.000000 0.793673 -0.457031 +v -0.000000 0.765755 -0.478597 +v -0.437073 0.750009 0.121642 +v -0.430974 0.765755 0.119945 +v -0.312929 0.783205 0.312929 +v -0.118596 0.793673 0.426127 +v 0.120212 0.797164 0.431937 +v -0.120212 0.797164 -0.431937 +v -0.224433 0.793673 -0.382125 +v -0.312929 0.783205 -0.312929 +v -0.386470 0.765755 -0.226985 +v -0.391940 0.750009 -0.230197 +v 0.518110 0.682112 0.000000 +v 0.499881 0.682112 -0.139122 +v 0.448260 0.682112 -0.263277 +v 0.367859 0.682112 -0.367859 +v 0.263277 0.682112 -0.448260 +v 0.139122 0.682112 -0.499882 +v -0.000000 0.682112 -0.518110 +v -0.453012 0.750009 0.000000 +v -0.446690 0.765755 0.000000 +v -0.381327 0.783205 0.223964 +v -0.224433 0.793673 0.382125 +v -0.000000 0.797164 0.447686 +v 0.232239 0.793673 0.395417 +v -0.122721 0.793673 -0.440950 +v -0.227491 0.797164 -0.387332 +v -0.313584 0.793673 -0.313584 +v -0.381327 0.783205 -0.223964 +v -0.430974 0.765755 -0.119945 +v 0.499881 0.682112 0.139122 +v 0.414076 0.765755 0.243198 +v 0.332226 0.783205 0.332226 +v -0.128513 0.765755 -0.461757 +v -0.125646 0.783205 -0.451460 +v -0.139123 0.682112 -0.499882 +v -0.437073 0.750009 -0.121642 +v -0.425237 0.783205 0.118348 +v -0.313584 0.793673 0.313584 +v -0.120212 0.797164 0.431937 +v 0.122721 0.793673 0.440950 +v -0.232240 0.793673 -0.395417 +v -0.317859 0.797164 -0.317858 +v -0.382125 0.793673 -0.224433 +v -0.425237 0.783205 -0.118348 +v 0.555408 0.599133 0.000000 +v 0.535865 0.599133 -0.149137 +v 0.480530 0.599133 -0.282230 +v 0.394341 0.599133 -0.394341 +v 0.282230 0.599133 -0.480530 +v 0.149137 0.599133 -0.535866 +v -0.000000 0.599133 -0.555408 +v -0.149138 0.599133 -0.535866 +v -0.440746 0.783205 0.000000 +v -0.382125 0.793673 0.224433 +v -0.227491 0.797164 0.387332 +v -0.000000 0.793673 0.457031 +v 0.237775 0.783205 0.404842 +v -0.237775 0.783205 -0.404842 +v -0.324492 0.793673 -0.324492 +v -0.387332 0.797164 -0.227491 +v -0.426127 0.793673 -0.118596 +v 0.535865 0.599133 0.149137 +v 0.448260 0.682112 0.263277 +v 0.339803 0.765755 0.339804 +v -0.263278 0.682112 -0.448260 +v -0.243198 0.765755 -0.414076 +v -0.282230 0.599133 -0.480530 +v -0.426127 0.793673 0.118596 +v -0.317859 0.797164 0.317858 +v -0.122721 0.793673 0.440950 +v 0.125646 0.783205 0.451460 +v -0.332226 0.783205 -0.332226 +v -0.395417 0.793673 -0.232239 +v -0.431937 0.797164 -0.120212 +v -0.441668 0.793673 0.000000 +v 0.588275 0.517481 0.000000 +v 0.567578 0.517481 -0.157963 +v 0.508969 0.517485 -0.298931 +v 0.417675 0.517481 -0.417675 +v 0.298931 0.517485 -0.508969 +v 0.157963 0.517485 -0.567578 +v -0.000000 0.517481 -0.588275 +v -0.157963 0.517481 -0.567578 +v -0.298931 0.517485 -0.508969 +v -0.387332 0.797164 0.227491 +v -0.232240 0.793673 0.395417 +v -0.000000 0.783205 0.467924 +v 0.243198 0.765755 0.414076 +v -0.339804 0.765755 -0.339804 +v -0.404842 0.783205 -0.237775 +v -0.440950 0.793673 -0.122721 +v -0.447686 0.797164 0.000000 +v 0.567578 0.517485 0.157963 +v 0.480530 0.599133 0.282230 +v 0.367859 0.682112 0.367859 +v -0.394341 0.599133 -0.394341 +v -0.367859 0.682112 -0.367859 +v -0.417675 0.517481 -0.417675 +v -0.431937 0.797164 0.120212 +v -0.324492 0.793673 0.324492 +v -0.125646 0.783205 0.451460 +v 0.128512 0.765755 0.461757 +v -0.414076 0.765755 -0.243198 +v -0.451461 0.783205 -0.125646 +v -0.457031 0.793673 0.000000 +v 0.592873 0.437827 -0.165003 +v 0.531651 0.437827 -0.312254 +v 0.436292 0.437827 -0.436292 +v 0.312254 0.437827 -0.531651 +v 0.165003 0.437827 -0.592873 +v -0.000000 0.437827 -0.614496 +v -0.165004 0.437827 -0.592873 +v -0.312255 0.437827 -0.531651 +v -0.436292 0.437827 -0.436292 +v -0.395417 0.793673 0.232239 +v -0.237775 0.783205 0.404842 +v -0.000000 0.765755 0.478597 +v 0.263277 0.682112 0.448260 +v -0.448260 0.682112 -0.263277 +v -0.461757 0.765755 -0.128512 +v -0.467924 0.783205 0.000000 +v -0.440950 0.793673 0.122721 +v 0.592873 0.437827 0.165003 +v 0.508969 0.517485 0.298931 +v 0.394341 0.599133 0.394341 +v -0.508969 0.517485 -0.298931 +v -0.480530 0.599133 -0.282230 +v -0.531651 0.437827 -0.312254 +v -0.332226 0.783205 0.332226 +v -0.128513 0.765755 0.461757 +v 0.139122 0.682112 0.499882 +v -0.499882 0.682112 -0.139122 +v -0.478597 0.765755 0.000000 +v -0.451461 0.783205 0.125646 +v 0.546669 0.360830 -0.321075 +v 0.448614 0.360830 -0.448614 +v 0.321074 0.360830 -0.546669 +v 0.169664 0.360830 -0.609621 +v -0.000000 0.360830 -0.631850 +v -0.169664 0.360830 -0.609621 +v -0.321075 0.360830 -0.546669 +v -0.448615 0.360830 -0.448614 +v -0.546669 0.360830 -0.321075 +v -0.404842 0.783205 0.237775 +v -0.243198 0.765755 0.414076 +v -0.000000 0.682112 0.518110 +v 0.282230 0.599133 0.480530 +v -0.535866 0.599133 -0.149137 +v -0.461757 0.765755 0.128512 +v 0.531651 0.437827 0.312254 +v 0.417675 0.517481 0.417675 +v 0.609621 0.360830 -0.169664 +v -0.592873 0.437827 -0.165003 +v -0.567578 0.517485 -0.157963 +v -0.609621 0.360830 -0.169664 +v -0.339804 0.765755 0.339804 +v -0.139123 0.682112 0.499882 +v 0.149137 0.599133 0.535866 +v -0.555408 0.599133 0.000000 +v -0.499882 0.682112 0.139122 +v -0.414076 0.765755 0.243198 +v 0.609621 0.360830 0.169664 +v 0.552100 0.287158 -0.324265 +v 0.453072 0.287158 -0.453072 +v 0.324265 0.287158 -0.552100 +v 0.171349 0.287158 -0.615677 +v -0.000000 0.287158 -0.638129 +v -0.171350 0.287158 -0.615677 +v -0.324265 0.287158 -0.552100 +v -0.453072 0.287158 -0.453072 +v -0.552100 0.287158 -0.324265 +v -0.615677 0.287158 -0.171349 +v -0.263278 0.682112 0.448260 +v -0.000000 0.599133 0.555408 +v 0.298931 0.517485 0.508969 +v -0.588275 0.517481 0.000000 +v -0.448260 0.682112 0.263277 +v 0.546669 0.360830 0.321075 +v 0.436292 0.437827 0.436292 +v 0.615677 0.287158 -0.171349 +v -0.631850 0.360830 0.000000 +v -0.614496 0.437827 0.000000 +v -0.367859 0.682112 0.367859 +v -0.149138 0.599133 0.535866 +v 0.157963 0.517481 0.567578 +v -0.567578 0.517481 0.157963 +v -0.480530 0.599133 0.282230 +v 0.615677 0.287158 0.171349 +v 0.541877 0.221240 -0.318259 +v 0.444680 0.221240 -0.444680 +v 0.318259 0.221240 -0.541877 +v 0.168176 0.221240 -0.604276 +v -0.000000 0.221240 -0.626311 +v -0.168177 0.221240 -0.604276 +v -0.318259 0.221240 -0.541877 +v -0.444680 0.221240 -0.444680 +v -0.541877 0.221240 -0.318259 +v -0.604277 0.221240 -0.168176 +v -0.282230 0.599133 0.480530 +v -0.000000 0.517481 0.588275 +v 0.312254 0.437827 0.531651 +v -0.592873 0.437827 0.165003 +v -0.535866 0.599133 0.149137 +v -0.394341 0.599133 0.394341 +v 0.552100 0.287158 0.324265 +v 0.448614 0.360830 0.448614 +v 0.604276 0.221240 -0.168176 +v -0.615677 0.287158 0.171349 +v -0.609621 0.360830 0.169664 +v -0.157963 0.517485 0.567578 +v 0.165003 0.437827 0.592873 +v -0.531651 0.437827 0.312254 +v -0.508969 0.517485 0.298931 +v -0.417675 0.517481 0.417675 +v 0.604276 0.221240 0.168176 +v 0.516317 0.166623 -0.303247 +v 0.423705 0.166623 -0.423705 +v 0.303247 0.166623 -0.516317 +v 0.160243 0.166623 -0.575771 +v -0.000000 0.166623 -0.596769 +v -0.160244 0.166623 -0.575771 +v -0.303247 0.166623 -0.516317 +v -0.423705 0.166623 -0.423705 +v -0.516317 0.166623 -0.303247 +v -0.575771 0.166623 -0.160243 +v -0.298931 0.517485 0.508969 +v -0.000000 0.437827 0.614496 +v 0.321074 0.360830 0.546669 +v -0.546669 0.360830 0.321075 +v 0.541877 0.221240 0.318259 +v 0.453072 0.287158 0.453072 +v 0.575771 0.166623 -0.160243 +v -0.596769 0.166623 0.000000 +v -0.604277 0.221240 0.168176 +v -0.552100 0.287158 0.324265 +v -0.165004 0.437827 0.592873 +v 0.169664 0.360830 0.609621 +v -0.448615 0.360830 0.448614 +v -0.436292 0.437827 0.436292 +v -0.312255 0.437827 0.531651 +v 0.575771 0.166623 0.160243 +v 0.483086 0.122640 -0.283731 +v 0.396438 0.122640 -0.396438 +v 0.283731 0.122640 -0.483086 +v 0.149931 0.122640 -0.538718 +v -0.000000 0.122640 -0.558363 +v -0.149931 0.122640 -0.538718 +v -0.283731 0.122640 -0.483086 +v -0.396438 0.122640 -0.396438 +v -0.483087 0.122640 -0.283731 +v -0.538718 0.122640 -0.149931 +v -0.558363 0.122640 0.000000 +v -0.541877 0.221240 0.318259 +v -0.000000 0.360830 0.631850 +v 0.324265 0.287158 0.552100 +v -0.453072 0.287158 0.453072 +v 0.516317 0.166623 0.303247 +v 0.596768 0.166623 0.000000 +v 0.444680 0.221240 0.444680 +v 0.538718 0.122640 -0.149931 +v -0.538718 0.122640 0.149931 +v -0.516317 0.166623 0.303247 +v -0.444680 0.221240 0.444680 +v -0.169664 0.360830 0.609621 +v 0.171349 0.287158 0.615677 +v -0.324265 0.287158 0.552100 +v -0.321075 0.360830 0.546669 +v 0.538718 0.122640 0.149931 +v 0.558363 0.122640 0.000000 +v 0.449858 0.088629 -0.264215 +v 0.369171 0.088629 -0.369171 +v 0.264215 0.088629 -0.449859 +v 0.139618 0.088629 -0.501662 +v -0.000000 0.088629 -0.519957 +v -0.139618 0.088629 -0.501662 +v -0.264215 0.088629 -0.449859 +v -0.369171 0.088629 -0.369171 +v -0.449859 0.088629 -0.264215 +v -0.501662 0.088629 -0.139618 +v -0.519957 0.088629 0.000000 +v -0.501662 0.088629 0.139618 +v -0.575771 0.166623 0.160243 +v -0.423705 0.166623 0.423705 +v -0.000000 0.287158 0.638129 +v 0.318259 0.221240 0.541877 +v -0.318259 0.221240 0.541877 +v 0.483086 0.122640 0.283731 +v 0.423705 0.166623 0.423705 +v 0.501662 0.088629 -0.139618 +v -0.449859 0.088629 0.264215 +v -0.483087 0.122640 0.283731 +v -0.396438 0.122640 0.396438 +v -0.303247 0.166623 0.516317 +v -0.171350 0.287158 0.615677 +v 0.168176 0.221240 0.604276 +v -0.168177 0.221240 0.604276 +v 0.501662 0.088629 0.139618 +v 0.519957 0.088629 0.000000 +v 0.424299 0.063924 -0.249203 +v 0.348195 0.063924 -0.348195 +v 0.249203 0.063924 -0.424298 +v 0.131685 0.063924 -0.473160 +v -0.000000 0.063924 -0.490415 +v -0.131686 0.063924 -0.473160 +v -0.249203 0.063924 -0.424298 +v -0.348196 0.063924 -0.348195 +v -0.424299 0.063924 -0.249203 +v -0.473160 0.063924 -0.131685 +v -0.490415 0.063924 0.000000 +v -0.473160 0.063924 0.131685 +v -0.424299 0.063924 0.249203 +v -0.283731 0.122640 0.483086 +v -0.000000 0.221240 0.626311 +v 0.303247 0.166623 0.516317 +v -0.160244 0.166623 0.575771 +v 0.449858 0.088629 0.264215 +v 0.396438 0.122640 0.396438 +v 0.473160 0.063924 -0.131685 +v -0.348196 0.063924 0.348195 +v -0.369171 0.088629 0.369171 +v -0.264215 0.088629 0.449859 +v -0.149931 0.122640 0.538718 +v 0.160243 0.166623 0.575771 +v -0.000000 0.166623 0.596769 +v 0.473160 0.063924 0.131685 +v 0.490415 0.063924 0.000000 +v 0.414076 0.047860 -0.243198 +v 0.339803 0.047860 -0.339804 +v 0.243198 0.047860 -0.414076 +v 0.128512 0.047860 -0.461757 +v -0.000000 0.047860 -0.478597 +v -0.128513 0.047860 -0.461757 +v -0.243198 0.047860 -0.414076 +v -0.339804 0.047860 -0.339804 +v -0.414076 0.047860 -0.243198 +v -0.461757 0.047860 -0.128512 +v -0.478597 0.047860 0.000000 +v -0.461757 0.047860 0.128512 +v -0.414076 0.047860 0.243198 +v -0.339804 0.047860 0.339804 +v -0.139618 0.088629 0.501662 +v 0.283731 0.122640 0.483086 +v -0.000000 0.122640 0.558363 +v 0.424299 0.063924 0.249203 +v 0.369171 0.088629 0.369171 +v 0.461756 0.047860 -0.128512 +v -0.243198 0.047860 0.414076 +v -0.249203 0.063924 0.424298 +v -0.131686 0.063924 0.473160 +v -0.000000 0.088629 0.519957 +v 0.149931 0.122640 0.538718 +v 0.461756 0.047860 0.128512 +v 0.478596 0.047860 0.000000 +v 0.410719 0.036005 -0.241228 +v 0.337050 0.036005 -0.337050 +v 0.241227 0.036005 -0.410719 +v 0.127471 0.036005 -0.458017 +v -0.000000 0.036005 -0.474720 +v -0.127471 0.036005 -0.458017 +v -0.241228 0.036005 -0.410719 +v -0.337051 0.036005 -0.337050 +v -0.410719 0.036005 -0.241228 +v -0.458017 0.036005 -0.127471 +v -0.474721 0.036005 0.000000 +v -0.458017 0.036005 0.127471 +v -0.410719 0.036005 0.241228 +v -0.337051 0.036005 0.337050 +v -0.241228 0.036005 0.410719 +v -0.000000 0.063924 0.490415 +v 0.264215 0.088629 0.449859 +v 0.139618 0.088629 0.501662 +v 0.414076 0.047860 0.243198 +v 0.348195 0.063924 0.348195 +v 0.458017 0.036005 -0.127471 +v -0.127471 0.036005 0.458017 +v -0.128513 0.047860 0.461757 +v -0.000000 0.047860 0.478597 +v 0.131685 0.063924 0.473160 +v 0.458017 0.036005 0.127471 +v 0.474720 0.036005 0.000000 +v 0.394137 0.024816 -0.231489 +v 0.323442 0.024816 -0.323442 +v 0.231489 0.024816 -0.394137 +v 0.122324 0.024816 -0.439524 +v -0.000000 0.024816 -0.455554 +v -0.122325 0.024816 -0.439524 +v -0.231489 0.024816 -0.394137 +v -0.323442 0.024816 -0.323442 +v -0.394137 0.024816 -0.231489 +v -0.439524 0.024816 -0.122325 +v -0.455554 0.024816 0.000000 +v -0.439524 0.024816 0.122325 +v -0.394137 0.024816 0.231489 +v -0.323442 0.024816 0.323442 +v -0.231489 0.024816 0.394137 +v -0.122325 0.024816 0.439524 +v 0.128512 0.047860 0.461757 +v 0.249203 0.063924 0.424298 +v 0.410719 0.036005 0.241228 +v 0.339803 0.047860 0.339804 +v 0.439524 0.024816 -0.122325 +v -0.000000 0.036005 0.474720 +v -0.000000 0.024816 0.455554 +v 0.127471 0.036005 0.458017 +v 0.243198 0.047860 0.414076 +v 0.439524 0.024816 0.122325 +v 0.455554 0.024816 0.000000 +v 0.354551 0.014956 -0.208238 +v 0.290957 0.014956 -0.290957 +v 0.208238 0.014956 -0.354551 +v 0.110038 0.014956 -0.395378 +v -0.000000 0.014956 -0.409797 +v -0.110038 0.014956 -0.395378 +v -0.208239 0.014956 -0.354551 +v -0.290957 0.014956 -0.290957 +v -0.354551 0.014956 -0.208238 +v -0.395378 0.014956 -0.110038 +v -0.409797 0.014956 0.000000 +v -0.395378 0.014956 0.110038 +v -0.354551 0.014956 0.208238 +v -0.290957 0.014956 0.290957 +v -0.208239 0.014956 0.354551 +v -0.110038 0.014956 0.395378 +v -0.000000 0.014956 0.409797 +v 0.241227 0.036005 0.410719 +v 0.337050 0.036005 0.337050 +v 0.394137 0.024816 0.231489 +v 0.395378 0.014956 -0.110038 +v 0.122324 0.024816 0.439524 +v 0.110038 0.014956 0.395378 +v 0.231489 0.024816 0.394137 +v 0.395378 0.014956 0.110038 +v 0.409797 0.014956 0.000000 +v 0.282184 0.007090 -0.165735 +v 0.231570 0.007090 -0.231570 +v 0.165735 0.007090 -0.282185 +v 0.087579 0.007090 -0.314679 +v -0.000000 0.007090 -0.326154 +v -0.087579 0.007090 -0.314679 +v -0.165735 0.007090 -0.282185 +v -0.231570 0.007090 -0.231570 +v -0.282184 0.007090 -0.165735 +v -0.314679 0.007090 -0.087579 +v -0.326155 0.007090 0.000000 +v -0.314679 0.007090 0.087579 +v -0.282184 0.007090 0.165735 +v -0.231570 0.007090 0.231570 +v -0.165735 0.007090 0.282185 +v -0.087579 0.007090 0.314679 +v -0.000000 0.007090 0.326154 +v 0.087579 0.007090 0.314679 +v 0.323442 0.024816 0.323442 +v 0.354551 0.014956 0.208238 +v 0.314679 0.007090 -0.087579 +v 0.208238 0.014956 0.354551 +v 0.165735 0.007090 0.282185 +v 0.290957 0.014956 0.290957 +v 0.314679 0.007090 0.087579 +v 0.326154 0.007090 0.000000 +v 0.167259 0.001883 -0.098236 +v 0.137258 0.001883 -0.137259 +v 0.098236 0.001883 -0.167259 +v 0.051910 0.001883 -0.186520 +v -0.000000 0.001883 -0.193322 +v -0.051911 0.001883 -0.186520 +v -0.098237 0.001883 -0.167259 +v -0.137259 0.001883 -0.137259 +v -0.167259 0.001883 -0.098236 +v -0.186520 0.001883 -0.051911 +v -0.193323 0.001883 0.000000 +v -0.186520 0.001883 0.051911 +v -0.167259 0.001883 0.098236 +v -0.137259 0.001883 0.137259 +v -0.098237 0.001883 0.167259 +v -0.051911 0.001883 0.186520 +v -0.000000 0.001883 0.193322 +v 0.051910 0.001883 0.186520 +v 0.098236 0.001883 0.167259 +v 0.282184 0.007090 0.165735 +v 0.186520 0.001883 -0.051911 +v 0.231570 0.007090 0.231570 +v 0.137258 0.001883 0.137259 +v 0.186520 0.001883 0.051911 +v 0.193322 0.001883 0.000000 +v -0.000000 0.000000 0.000000 +v 0.167259 0.001883 0.098236 +v 0.063813 0.861474 0.000000 +v 0.054654 0.888729 0.000000 +v 0.052734 0.888729 0.014691 +v 0.061568 0.861474 0.017135 +v 0.061568 0.861474 -0.017135 +v 0.072979 0.919969 0.020357 +v 0.111968 0.841089 0.000000 +v 0.047296 0.888729 0.027792 +v 0.052734 0.888729 -0.014691 +v 0.108028 0.841089 -0.030065 +v 0.075630 0.919969 0.000000 +v 0.065466 0.919969 0.038494 +v 0.108028 0.841089 0.030065 +v 0.055210 0.861474 0.032427 +v 0.055210 0.861474 -0.032427 +v 0.096873 0.841089 -0.056896 +v 0.100064 0.951211 0.027927 +v 0.089769 0.951211 0.052799 +v 0.183167 0.826023 0.000000 +v 0.176722 0.826023 -0.049184 +v 0.038821 0.888729 0.038821 +v 0.053751 0.919969 0.053751 +v 0.047296 0.888729 -0.027792 +v 0.072979 0.919969 -0.020357 +v 0.158473 0.826023 -0.093076 +v 0.103696 0.951211 0.000000 +v 0.073714 0.951211 0.073714 +v 0.176722 0.826023 0.049184 +v 0.096873 0.841089 0.056896 +v 0.045307 0.861474 0.045307 +v 0.079497 0.841089 -0.079497 +v 0.045307 0.861474 -0.045307 +v 0.130048 0.826023 -0.130048 +v 0.111754 0.978466 0.031195 +v 0.100259 0.978466 0.058974 +v 0.082330 0.978466 0.082330 +v 0.263228 0.813615 0.000000 +v 0.253966 0.813615 -0.070682 +v 0.227741 0.813615 -0.133759 +v 0.027792 0.888729 0.047296 +v 0.038494 0.919969 0.065466 +v 0.052799 0.951211 0.089769 +v 0.038821 0.888729 -0.038821 +v 0.065466 0.919969 -0.038494 +v 0.100064 0.951211 -0.027927 +v 0.186892 0.813615 -0.186892 +v 0.115809 0.978466 0.000000 +v 0.058974 0.978466 0.100259 +v 0.253966 0.813615 0.070682 +v 0.158473 0.826023 0.093076 +v 0.079497 0.841089 0.079497 +v 0.032426 0.861474 0.055210 +v 0.093076 0.826023 -0.158473 +v 0.056896 0.841089 -0.096873 +v 0.032426 0.861474 -0.055210 +v 0.133759 0.813615 -0.227741 +v 0.085811 0.997741 0.023955 +v 0.076985 0.997741 0.045285 +v 0.063219 0.997741 0.063219 +v 0.045285 0.997741 0.076986 +v 0.337972 0.801206 0.000000 +v 0.326081 0.801206 -0.090752 +v 0.292408 0.801206 -0.171740 +v 0.239960 0.801206 -0.239960 +v 0.014691 0.888729 0.052735 +v 0.020357 0.919969 0.072979 +v 0.027927 0.951211 0.100064 +v 0.031195 0.978466 0.111754 +v 0.027792 0.888729 -0.047296 +v 0.053751 0.919969 -0.053751 +v 0.089769 0.951211 -0.052799 +v 0.111754 0.978466 -0.031195 +v 0.171740 0.801206 -0.292408 +v 0.088924 0.997741 0.000000 +v 0.023955 0.997741 0.085811 +v 0.326081 0.801206 0.090752 +v 0.227741 0.813615 0.133759 +v 0.130048 0.826023 0.130048 +v 0.056896 0.841089 0.096873 +v 0.017135 0.861474 0.061568 +v 0.070682 0.813615 -0.253966 +v 0.049184 0.826023 -0.176722 +v 0.030065 0.841089 -0.108029 +v 0.017135 0.861474 -0.061568 +v 0.090752 0.801206 -0.326081 +v -0.000000 1.005054 0.000000 +v 0.393218 0.786140 0.000000 +v 0.379380 0.786140 -0.105586 +v 0.340206 0.786140 -0.199813 +v 0.279184 0.786140 -0.279184 +v 0.199813 0.786140 -0.340206 +v -0.000000 0.888729 0.054654 +v -0.000000 0.919969 0.075630 +v -0.000000 0.951211 0.103696 +v -0.000000 0.978466 0.115809 +v -0.000000 0.997741 0.088925 +v 0.014691 0.888729 -0.052735 +v 0.038494 0.919969 -0.065466 +v 0.073714 0.951211 -0.073714 +v 0.100259 0.978466 -0.058974 +v 0.085811 0.997741 -0.023955 +v 0.105586 0.786140 -0.379381 +v 0.379380 0.786140 0.105586 +v 0.292408 0.801206 0.171740 +v 0.186892 0.813615 0.186892 +v 0.093076 0.826023 0.158473 +v 0.030065 0.841089 0.108029 +v -0.000000 0.861474 0.063813 +v -0.000000 0.801206 -0.337972 +v -0.000000 0.813615 -0.263228 +v -0.000000 0.826023 -0.183167 +v -0.000000 0.841089 -0.111968 +v -0.000000 0.861474 -0.063813 +v -0.000000 0.786140 -0.393218 +v 0.076985 0.997741 -0.045285 +v -0.023955 0.997741 0.085811 +v 0.414784 0.765755 0.000000 +v 0.400190 0.765755 -0.111377 +v 0.358865 0.765755 -0.210772 +v 0.294497 0.765755 -0.294497 +v 0.210772 0.765755 -0.358865 +v 0.111377 0.765755 -0.400190 +v -0.014691 0.888729 0.052735 +v -0.020357 0.919969 0.072979 +v -0.027927 0.951211 0.100064 +v -0.031195 0.978466 0.111754 +v -0.000000 0.888729 -0.054654 +v 0.020357 0.919969 -0.072979 +v 0.052799 0.951211 -0.089769 +v 0.082330 0.978466 -0.082330 +v -0.000000 0.765755 -0.414784 +v 0.063219 0.997741 -0.063219 +v -0.045285 0.997741 0.076986 +v 0.400190 0.765755 0.111377 +v 0.340206 0.786140 0.199813 +v 0.239960 0.801206 0.239960 +v 0.133759 0.813615 0.227741 +v 0.049184 0.826023 0.176722 +v -0.000000 0.841089 0.111968 +v -0.017135 0.861474 0.061568 +v -0.105586 0.786140 -0.379381 +v -0.090752 0.801206 -0.326081 +v -0.070682 0.813615 -0.253966 +v -0.049184 0.826023 -0.176722 +v -0.030066 0.841089 -0.108029 +v -0.017135 0.861474 -0.061568 +v -0.111377 0.765755 -0.400190 +v 0.045285 0.997741 -0.076986 +v -0.063220 0.997741 0.063219 +v 0.414952 0.750806 0.115486 +v 0.430085 0.750806 0.000000 +v 0.414952 0.750806 -0.115486 +v 0.372103 0.750806 -0.218547 +v 0.305360 0.750806 -0.305360 +v 0.218547 0.750806 -0.372103 +v 0.115486 0.750806 -0.414952 +v -0.000000 0.750806 -0.430085 +v -0.027793 0.888729 0.047296 +v -0.038494 0.919969 0.065466 +v -0.052799 0.951211 0.089769 +v -0.058974 0.978466 0.100259 +v -0.014691 0.888729 -0.052735 +v -0.000000 0.919969 -0.075630 +v 0.027927 0.951211 -0.100064 +v 0.058974 0.978466 -0.100259 +v -0.115486 0.750806 -0.414952 +v 0.023955 0.997741 -0.085811 +v -0.076986 0.997741 0.045285 +v 0.372103 0.750806 0.218547 +v 0.358865 0.765755 0.210772 +v 0.279184 0.786140 0.279184 +v 0.171740 0.801206 0.292408 +v 0.070682 0.813615 0.253966 +v -0.000000 0.826023 0.183167 +v -0.030066 0.841089 0.108029 +v -0.032427 0.861474 0.055210 +v -0.210772 0.765755 -0.358865 +v -0.199813 0.786140 -0.340206 +v -0.171740 0.801206 -0.292408 +v -0.133759 0.813615 -0.227741 +v -0.093076 0.826023 -0.158473 +v -0.056896 0.841089 -0.096873 +v -0.032427 0.861474 -0.055210 +v -0.218547 0.750806 -0.372103 +v 0.031195 0.978466 -0.111754 +v -0.000000 0.997741 -0.088925 +v -0.082331 0.978466 0.082330 +v -0.085811 0.997741 0.023955 +v 0.305360 0.750806 0.305360 +v 0.294497 0.765755 0.294497 +v -0.038821 0.888729 0.038821 +v -0.053751 0.919969 0.053751 +v -0.073714 0.951211 0.073714 +v -0.027793 0.888729 -0.047296 +v -0.020357 0.919969 -0.072979 +v -0.000000 0.951211 -0.103696 +v -0.305360 0.750806 -0.305360 +v -0.294497 0.765755 -0.294497 +v -0.000000 0.978466 -0.115809 +v -0.023955 0.997741 -0.085811 +v -0.100259 0.978466 0.058974 +v -0.088925 0.997741 0.000000 +v 0.210772 0.765755 0.358865 +v 0.218547 0.750806 0.372103 +v 0.199813 0.786140 0.340206 +v 0.090752 0.801206 0.326081 +v -0.000000 0.813615 0.263228 +v -0.049184 0.826023 0.176722 +v -0.056896 0.841089 0.096873 +v -0.045307 0.861474 0.045307 +v -0.279185 0.786140 -0.279184 +v -0.239960 0.801206 -0.239960 +v -0.186892 0.813615 -0.186892 +v -0.130049 0.826023 -0.130048 +v -0.079497 0.841089 -0.079497 +v -0.045307 0.861474 -0.045307 +v -0.372103 0.750806 -0.218547 +v -0.358865 0.765755 -0.210772 +v -0.031195 0.978466 -0.111754 +v -0.045285 0.997741 -0.076986 +v -0.111754 0.978466 0.031195 +v -0.085811 0.997741 -0.023955 +v 0.111377 0.765755 0.400190 +v 0.115486 0.750806 0.414952 +v -0.047296 0.888729 0.027792 +v -0.065466 0.919969 0.038494 +v -0.089770 0.951211 0.052799 +v -0.038821 0.888729 -0.038821 +v -0.038494 0.919969 -0.065466 +v -0.027927 0.951211 -0.100064 +v -0.414952 0.750806 -0.115486 +v -0.400190 0.765755 -0.111377 +v -0.058974 0.978466 -0.100259 +v -0.063220 0.997741 -0.063219 +v -0.115809 0.978466 0.000000 +v -0.076986 0.997741 -0.045285 +v 0.105586 0.786140 0.379381 +v -0.000000 0.765755 0.414784 +v -0.000000 0.750806 0.430085 +v -0.000000 0.801206 0.337972 +v -0.070682 0.813615 0.253966 +v -0.093076 0.826023 0.158473 +v -0.079497 0.841089 0.079497 +v -0.055210 0.861474 0.032427 +v -0.340206 0.786140 -0.199813 +v -0.292408 0.801206 -0.171740 +v -0.227741 0.813615 -0.133759 +v -0.158473 0.826023 -0.093076 +v -0.096873 0.841089 -0.056896 +v -0.055210 0.861474 -0.032427 +v -0.430085 0.750806 0.000000 +v -0.414784 0.765755 0.000000 +v -0.052799 0.951211 -0.089769 +v -0.082331 0.978466 -0.082330 +v -0.100064 0.951211 0.027927 +v -0.111754 0.978466 -0.031195 +v -0.000000 0.786140 0.393218 +v -0.115486 0.750806 0.414952 +v -0.111377 0.765755 0.400190 +v -0.052735 0.888729 0.014691 +v -0.072979 0.919969 0.020357 +v -0.047296 0.888729 -0.027792 +v -0.053751 0.919969 -0.053751 +v -0.414952 0.750806 0.115486 +v -0.400190 0.765755 0.111377 +v -0.379381 0.786140 -0.105586 +v -0.073714 0.951211 -0.073714 +v -0.100259 0.978466 -0.058974 +v -0.103696 0.951211 0.000000 +v -0.105586 0.786140 0.379381 +v -0.218547 0.750806 0.372103 +v -0.210772 0.765755 0.358865 +v -0.090752 0.801206 0.326081 +v -0.133759 0.813615 0.227741 +v -0.130049 0.826023 0.130048 +v -0.096873 0.841089 0.056896 +v -0.061568 0.861474 0.017135 +v -0.326081 0.801206 -0.090752 +v -0.253966 0.813615 -0.070682 +v -0.176722 0.826023 -0.049184 +v -0.108029 0.841089 -0.030065 +v -0.061568 0.861474 -0.017135 +v -0.372103 0.750806 0.218547 +v -0.358865 0.765755 0.210772 +v -0.393219 0.786140 0.000000 +v -0.089770 0.951211 -0.052799 +v -0.100064 0.951211 -0.027927 +v -0.199813 0.786140 0.340206 +v -0.305360 0.750806 0.305360 +v -0.294497 0.765755 0.294497 +v -0.054655 0.888729 0.000000 +v -0.075630 0.919969 0.000000 +v -0.052735 0.888729 -0.014691 +v -0.065466 0.919969 -0.038494 +v -0.379381 0.786140 0.105586 +v -0.171740 0.801206 0.292408 +v -0.279185 0.786140 0.279184 +v -0.186892 0.813615 0.186892 +v -0.158473 0.826023 0.093076 +v -0.108029 0.841089 0.030065 +v -0.063813 0.861474 0.000000 +v -0.337972 0.801206 0.000000 +v -0.263228 0.813615 0.000000 +v -0.183167 0.826023 0.000000 +v -0.111968 0.841089 0.000000 +v -0.340206 0.786140 0.199813 +v -0.072979 0.919969 -0.020357 +v -0.239960 0.801206 0.239960 +v -0.326081 0.801206 0.090752 +v -0.292408 0.801206 0.171740 +v -0.227741 0.813615 0.133759 +v -0.176722 0.826023 0.049184 +v -0.253966 0.813615 0.070682 +v -0.526706 0.651362 -0.039883 +v -0.534329 0.646030 0.000000 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.638129 0.287158 0.000000 +v -0.631184 0.277569 0.039883 +v -0.501666 0.699221 -0.063813 +v -0.508714 0.682112 -0.071712 +v -0.611709 0.194244 0.000000 +v -0.608883 0.198681 0.039883 +v -0.517593 0.664661 0.063813 +v -0.508714 0.682112 0.071712 +v -0.631184 0.277569 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.615480 0.216617 0.063578 +v -0.615553 0.216807 -0.063813 +v -0.517593 0.664661 -0.063813 +v -0.498530 0.712498 -0.039883 +v -0.619922 0.238069 0.071790 +v -0.526706 0.651362 0.039883 +v -0.608884 0.198682 -0.039883 +v 0.605100 0.399712 0.137265 +v 0.613258 0.341675 0.154354 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.613258 0.341675 -0.154354 +v 0.605101 0.399712 -0.137265 +v 0.600960 0.444810 0.085753 +v 0.121642 0.750009 -0.437072 +v -0.000000 0.750009 -0.453012 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 -0.121642 +v -0.453012 0.750009 0.000000 +v -0.437073 0.750009 -0.121642 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.391940 0.750009 0.230197 +v -0.437073 0.750009 0.121642 +v 0.121642 0.750009 0.437072 +v -0.000000 0.750009 0.453012 +v -0.121642 0.750009 0.437072 +v 0.437073 0.750009 0.121642 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 -0.321639 +v 0.230197 0.750009 -0.391940 +v -0.121642 0.750009 -0.437072 +v 0.391939 0.750009 -0.230197 +v 0.321638 0.750009 0.321639 +v 0.230197 0.750009 0.391940 +v -0.230198 0.750009 -0.391939 +v -0.501255 0.717792 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v -0.321639 0.750009 -0.321639 +v -0.391940 0.750009 -0.230197 +v -0.498530 0.712498 0.039883 +v -0.501667 0.699221 0.063813 +v 0.617684 0.235930 -0.085941 +v 0.619427 0.283145 -0.137236 +v 0.619427 0.283145 0.137236 +vn -0.901883 0.415418 0.118168 +vn -0.905637 0.407056 0.118656 +vn -0.877041 0.418744 0.235298 +vn 0.058443 -0.998260 0.000732 +vn 0.015107 -0.999878 0.000183 +vn 0.014557 -0.949278 0.314035 +vn 0.056703 -0.947539 0.314524 +vn 0.162053 -0.986755 0.002014 +vn 0.157933 -0.933592 0.321604 +vn 0.392376 -0.919767 0.004334 +vn 0.378307 -0.856655 0.350688 +vn 0.783776 -0.620991 0.005249 +vn 0.726829 -0.553880 0.406079 +vn 0.994812 -0.101627 0.001984 +vn 0.908139 -0.082766 0.410321 +vn 0.003082 -0.939787 0.341685 +vn 0.002167 -0.619495 0.784967 +vn 0.011536 -0.679403 0.733634 +vn 0.044679 -0.675588 0.735923 +vn 0.123325 -0.652272 0.747856 +vn 0.275399 -0.556871 0.783593 +vn 0.460067 -0.316263 0.829615 +vn 0.563036 -0.041200 0.825373 +vn -0.000427 0.122166 0.992492 +vn 0.000397 0.003632 0.999969 +vn 0.002869 0.011841 0.999908 +vn 0.004852 0.029298 0.999542 +vn -0.008179 0.053499 0.998505 +vn -0.046510 0.041536 0.998047 +vn -0.039155 0.003113 0.999207 +vn -0.850551 0.473769 -0.228217 +vn -0.897885 0.424177 -0.117649 +vn -0.880886 0.473281 0.000000 +vn -0.013611 0.682394 0.730827 +vn -0.053896 0.680441 0.730796 +vn -0.147557 0.656789 0.739464 +vn -0.325968 0.560564 0.761223 +vn -0.537645 0.315806 0.781762 +vn -0.611530 0.029939 0.790613 +vn -0.904172 0.427137 0.000000 +vn -0.897885 0.424146 0.117618 +vn -0.020112 0.949461 0.313150 +vn -0.081820 0.945433 0.315287 +vn -0.227699 0.916379 0.329173 +vn -0.504196 0.785302 0.359203 +vn -0.810633 0.443220 0.382611 +vn -0.921232 0.039705 0.386944 +vn -0.020569 0.949400 -0.313334 +vn -0.021729 0.999756 -0.000092 +vn -0.004242 0.950468 -0.310770 +vn -0.088260 0.996094 -0.000488 +vn -0.246895 0.969024 -0.001343 +vn -0.549730 0.835322 -0.002350 +vn -0.880673 0.473647 -0.001984 +vn -0.999084 0.042146 -0.000610 +vn -0.877041 0.418744 -0.235298 +vn -0.920286 0.391156 0.000000 +vn -0.905637 0.407056 -0.118656 +vn -0.083132 0.945006 -0.316202 +vn -0.230201 0.914823 -0.331797 +vn -0.505570 0.782800 -0.362743 +vn -0.808710 0.444960 -0.384625 +vn -0.920835 0.042055 -0.387646 +vn -0.897885 0.424146 -0.117618 +vn -0.901883 0.415448 -0.118168 +vn -0.014161 0.682394 -0.730796 +vn -0.055361 0.680074 -0.731010 +vn -0.150029 0.655660 -0.739982 +vn -0.327616 0.560594 -0.760491 +vn -0.537431 0.320933 -0.779809 +vn -0.611988 0.033387 -0.790155 +vn 0.015168 -0.949339 -0.313852 +vn 0.011902 -0.679403 -0.733634 +vn 0.003265 -0.939817 -0.341594 +vn 0.000183 0.004212 -0.999969 +vn 0.003510 0.014008 -0.999878 +vn 0.005921 0.035951 -0.999329 +vn -0.010132 0.064333 -0.997864 +vn -0.051576 0.048463 -0.997467 +vn -0.041597 0.003998 -0.999115 +vn 0.003082 -0.620106 -0.784478 +vn -0.000031 0.122440 -0.992462 +vn -0.897885 0.424177 0.117649 +vn 0.046449 -0.674398 -0.736869 +vn 0.125980 -0.648946 -0.750298 +vn 0.275430 -0.552477 -0.786676 +vn 0.455519 -0.320536 -0.830500 +vn 0.561693 -0.046480 -0.826014 +vn -0.888668 0.391644 0.238441 +vn 0.058046 -0.947630 -0.314005 +vn 0.159948 -0.933836 -0.319865 +vn 0.380169 -0.857753 -0.345927 +vn 0.725547 -0.560930 -0.398602 +vn 0.908597 -0.089236 -0.407971 +vn 0.003235 -0.999969 0.000031 +vn 0.973144 0.230110 0.000824 +vn 0.890896 0.211737 0.401776 +vn 0.912900 0.408094 0.002533 +vn 0.836970 0.380932 0.392834 +vn 0.829035 0.559160 0.003784 +vn 0.764519 0.528550 0.368969 +vn 0.718650 0.695334 0.003937 +vn 0.668294 0.663717 0.335917 +vn 0.579577 0.814905 0.002838 +vn 0.542650 0.779687 0.312357 +vn 0.495163 0.868770 0.002258 +vn 0.458052 0.820643 0.341624 +vn 0.561205 0.137028 0.816218 +vn 0.532029 0.253456 0.807886 +vn 0.497543 0.363445 0.787591 +vn 0.449538 0.472060 0.758293 +vn 0.373669 0.563555 0.736686 +vn 0.289041 0.531114 0.796442 +vn -0.023225 -0.005249 0.999695 +vn -0.016785 -0.010254 0.999786 +vn -0.011444 -0.012940 0.999847 +vn -0.009796 -0.013276 0.999847 +vn -0.014801 -0.013916 0.999786 +vn -0.089755 -0.176122 0.980255 +vn -0.585772 -0.152379 0.795984 +vn -0.538896 -0.288766 0.791314 +vn -0.484146 -0.407910 0.774071 +vn -0.424635 -0.509781 0.748161 +vn -0.355907 -0.584765 0.728935 +vn -0.889828 -0.237159 0.389782 +vn -0.808740 -0.446852 0.382366 +vn -0.702475 -0.613269 0.361095 +vn -0.590625 -0.734855 0.333293 +vn -0.483291 -0.816767 0.315104 +vn -0.912076 0.409955 0.000000 +vn -0.965606 -0.259987 -0.000458 +vn -0.872433 -0.488693 -0.001465 +vn -0.748436 -0.663167 -0.002197 +vn -0.621601 -0.783288 -0.002136 +vn -0.507065 -0.861873 -0.001251 +vn -0.438215 -0.854366 0.279183 +vn -0.456130 -0.889889 -0.000732 +vn -0.889126 -0.238868 -0.390332 +vn -0.807001 -0.448531 -0.384075 +vn -0.700980 -0.613392 -0.363750 +vn -0.590442 -0.733757 -0.336039 +vn -0.484787 -0.815332 -0.316477 +vn -0.440962 -0.852931 -0.279305 +vn -0.359691 -0.584185 -0.727531 +vn -0.358074 -0.682241 -0.637410 +vn -0.585467 -0.154668 -0.795770 +vn -0.538499 -0.291696 -0.790490 +vn -0.484512 -0.409772 -0.772851 +vn -0.426496 -0.510056 -0.746910 +vn -0.909543 -0.399274 -0.115207 +vn -0.971191 -0.204688 -0.121891 +vn -0.912931 -0.326609 -0.244606 +vn -0.020478 -0.017853 -0.999603 +vn -0.024537 -0.005737 -0.999664 +vn -0.020844 -0.012207 -0.999695 +vn -0.017548 -0.016846 -0.999695 +vn -0.016724 -0.018097 -0.999695 +vn -0.909116 -0.400311 0.115055 +vn -0.873775 -0.472610 0.114475 +vn -0.795892 -0.566485 0.213538 +vn -0.353069 -0.684103 0.638203 +vn 0.559679 0.139714 -0.816828 +vn 0.528581 0.255501 -0.809473 +vn 0.494217 0.362987 -0.789911 +vn 0.449049 0.469283 -0.760308 +vn 0.378246 0.560869 -0.736412 +vn -0.091983 -0.174383 -0.980346 +vn 0.295267 0.530625 -0.794488 +vn 0.890500 0.214759 -0.401044 +vn 0.836634 0.384075 -0.390515 +vn 0.765191 0.530198 -0.365123 +vn 0.671041 0.663228 -0.331339 +vn 0.547929 0.777642 -0.308206 +vn 0.464522 0.818842 -0.337199 +vn 0.931486 0.265572 -0.248543 +vn 0.939543 0.342357 0.000000 +vn 0.947539 0.295114 -0.122684 +vn -0.351421 0.936186 0.001953 +vn -0.144444 0.989502 0.003174 +vn -0.126743 0.878811 0.459975 +vn -0.716758 0.697287 -0.000946 +vn -0.299997 0.838313 0.455214 +vn -0.621876 0.660207 0.421155 +vn -0.901822 0.432081 -0.004517 +vn -0.807031 0.443434 0.389904 +vn -0.930204 0.366863 -0.008484 +vn -0.824549 0.383312 0.416059 +vn -0.850673 0.525529 -0.011628 +vn -0.722465 0.508988 0.467910 +vn -0.668447 0.743645 -0.011139 +vn -0.531449 0.686514 0.496170 +vn -0.116459 0.505448 0.854946 +vn -0.258400 0.470656 0.843593 +vn -0.407605 0.396985 0.822321 +vn -0.450270 0.352367 0.820399 +vn -0.385876 0.395734 0.833338 +vn -0.270669 0.487838 0.829890 +vn 0.141606 -0.001190 0.989898 +vn -0.067690 0.525346 0.848170 +vn 0.989593 0.100253 0.103122 +vn 0.970244 0.213324 0.114475 +vn 0.960418 0.152654 0.232917 +vn 0.241829 0.092502 0.965880 +vn 0.209296 0.170660 0.962828 +vn 0.096194 0.178625 0.979186 +vn 0.009552 0.154332 0.987945 +vn -0.000122 0.151952 0.988372 +vn 0.361248 -0.477279 0.801019 +vn 0.607929 -0.282540 0.741997 +vn 0.679220 -0.106754 0.726096 +vn 0.583911 -0.078524 0.807978 +vn 0.402722 -0.205237 0.891995 +vn 0.279519 -0.338694 0.898404 +vn 0.488601 -0.768700 0.412671 +vn 0.784570 -0.501511 0.364544 +vn 0.893918 -0.279611 0.350291 +vn 0.861415 -0.285287 0.420179 +vn 0.679373 -0.540452 0.496323 +vn 0.458327 -0.754540 0.469588 +vn 0.524155 -0.851588 -0.000153 +vn 0.827143 -0.561968 0.001679 +vn 0.943205 -0.332133 0.003479 +vn 0.933256 -0.359081 0.005737 +vn 0.756859 -0.653493 0.006470 +vn 0.492843 -0.870083 0.004120 +vn 0.322489 -0.946562 -0.001129 +vn 0.912839 -0.326609 0.244942 +vn 0.824396 -0.565996 0.000000 +vn 0.894162 -0.447676 0.000000 +vn 0.486557 -0.770501 -0.411756 +vn 0.783990 -0.504074 -0.362285 +vn 0.895199 -0.281899 -0.345134 +vn 0.863735 -0.289010 -0.412824 +vn 0.682119 -0.544267 -0.488296 +vn 0.461928 -0.758202 -0.460128 +vn 0.357463 -0.479141 -0.801599 +vn 0.605884 -0.285867 -0.742393 +vn 0.679739 -0.108646 -0.725333 +vn 0.583636 -0.077883 -0.808222 +vn 0.401440 -0.199225 -0.893918 +vn 0.281961 -0.330638 -0.900632 +vn 0.135228 -0.002380 -0.990783 +vn 0.235755 0.091128 -0.967498 +vn 0.200720 0.170629 -0.964660 +vn 0.086123 0.184576 -0.979003 +vn 0.000671 0.174322 -0.984680 +vn -0.007141 0.169012 -0.985565 +vn 0.966613 -0.042848 -0.252602 +vn 0.960418 0.152654 -0.232917 +vn 0.989593 0.100223 -0.103092 +vn -0.119297 0.503342 -0.855770 +vn -0.261269 0.472793 -0.841517 +vn -0.414075 0.399792 -0.817713 +vn -0.459700 0.357036 -0.813105 +vn -0.394024 0.408490 -0.823298 +vn -0.277871 0.487381 -0.827754 +vn -0.072207 0.520127 -0.851009 +vn -0.298654 0.840297 -0.452376 +vn -0.617512 0.663961 -0.421613 +vn -0.801324 0.450209 -0.393872 +vn -0.819422 0.389691 -0.420270 +vn -0.721274 0.506912 -0.471969 +vn -0.538347 0.670644 -0.510239 +vn -0.482009 0.876125 -0.005127 +vn -0.394635 0.815363 0.423536 +vn -0.321909 0.946745 -0.002594 +vn -0.255287 0.921995 0.291086 +vn 0.004242 0.999969 0.000397 +vn -0.002960 0.999939 -0.010102 +vn 0.853450 0.521073 -0.007050 +vn 0.392041 0.688986 -0.609546 +vn 0.805170 -0.592517 -0.023621 +vn 0.588763 -0.206122 -0.781579 +vn 0.681478 -0.731040 -0.033296 +vn 0.485031 -0.441237 -0.754967 +vn -0.206824 0.638203 0.741539 +vn -0.129490 0.862056 0.489944 +vn -0.033418 0.999176 0.022340 +vn 0.047700 0.864040 -0.501114 +vn 0.099307 0.538743 -0.836573 +vn 0.053560 0.251839 -0.966277 +vn 0.020112 0.322611 0.946287 +vn 0.021943 0.748894 0.662282 +vn -0.025941 0.995605 0.089908 +vn -0.059175 0.930876 -0.360424 +vn -0.080172 0.784448 -0.614948 +vn -0.142582 0.557604 -0.817743 +vn 0.281747 -0.174993 0.943388 +vn 0.303903 0.444136 0.842830 +vn 0.034333 0.983764 0.175970 +vn -0.113865 0.956420 -0.268777 +vn -0.155339 0.858852 -0.488021 +vn -0.207404 0.641865 -0.738182 +vn 0.467238 -0.683187 0.561144 +vn 0.699515 0.004364 0.714560 +vn 0.355296 0.891934 0.279641 +vn -0.170354 0.971465 -0.164861 +vn -0.245552 0.901181 -0.357097 +vn -0.248726 0.651082 -0.717063 +vn 0.494430 -0.869167 0.006317 +vn 0.933134 -0.358898 0.019868 +vn 0.703146 0.710685 0.021790 +vn -0.203650 0.978942 -0.012574 +vn -0.326456 0.942869 -0.066073 +vn -0.397595 0.857082 -0.327525 +vn 0.460616 -0.712546 -0.529221 +vn 0.695486 -0.098544 -0.711722 +vn 0.397534 0.853816 -0.336070 +vn -0.198248 0.963439 0.180151 +vn -0.306833 0.888516 0.341075 +vn -0.393689 0.807672 0.438887 +vn 0.276559 -0.211951 -0.937315 +vn 0.294626 0.366161 -0.882656 +vn 0.046632 0.973235 -0.224982 +vn -0.146733 0.912168 0.382611 +vn -0.202643 0.700797 0.683950 +vn -0.232673 0.506485 0.830226 +vn 0.011689 0.309397 -0.950835 +vn 0.013245 0.708640 -0.705435 +vn -0.027589 0.995758 -0.087680 +vn -0.047395 0.829371 0.556658 +vn -0.015259 0.386608 0.922086 +vn 0.004639 0.119510 0.992798 +vn -0.211035 0.631001 -0.746513 +vn -0.138768 0.848781 -0.510147 +vn -0.024995 0.999664 -0.001190 +vn 0.120426 0.724570 0.678579 +vn 0.260750 0.006531 0.965361 +vn 0.272500 -0.255898 0.927488 +vn -0.395581 0.809961 -0.432905 +vn -0.258827 0.918851 -0.297800 +vn 0.004730 0.999878 0.013031 +vn 0.466628 0.599780 0.649983 +vn 0.621937 -0.400861 0.672628 +vn 0.551042 -0.592181 0.587878 +vn 0.649068 0.384991 -0.656087 +vn 0.055971 0.691214 0.720450 +vn -0.115940 0.804590 0.582354 +vn -0.262185 0.897946 0.353435 +vn -0.341655 0.885006 -0.316263 +vn -0.081423 0.793085 -0.603626 +vn -0.155675 0.857753 -0.489883 +vn 0.728690 0.365978 0.578784 +vn 0.318674 0.539384 0.779382 +vn 0.953551 0.300150 -0.024415 +vn -0.133976 0.836818 -0.530808 +vn 0.095401 0.667959 -0.738029 +vn 0.000000 0.999969 0.000000 +vn -0.992523 -0.122013 0.000000 +vn -0.937346 -0.348338 0.000000 +vn -0.905148 -0.348827 -0.242836 +vn -0.958617 -0.122227 -0.257057 +vn -0.832057 0.554674 0.000000 +vn -0.803217 0.555376 -0.215339 +vn -0.048616 0.998810 0.000000 +vn -0.046236 0.998840 -0.012726 +vn 0.544267 0.838893 0.000000 +vn 0.525376 0.839106 0.140843 +vn 0.783471 0.621387 0.000000 +vn 0.756371 0.621845 0.202918 +vn 0.880886 0.473281 0.000000 +vn 0.850551 0.473769 0.228217 +vn -0.810907 -0.349376 -0.469375 +vn -0.859004 -0.122410 -0.497085 +vn -0.719657 0.555559 -0.416425 +vn -0.041749 0.998810 -0.024415 +vn 0.470077 0.839625 0.272011 +vn 0.677236 0.622608 0.391980 +vn 0.761803 0.474471 0.440962 +vn -0.662465 -0.349620 -0.662465 +vn -0.701773 -0.122440 -0.701773 +vn -0.587878 0.555650 -0.587878 +vn -0.034272 0.998810 -0.034272 +vn 0.383831 0.839808 0.383831 +vn 0.553148 0.622913 0.553148 +vn 0.622303 0.474776 0.622303 +vn -0.469375 -0.349376 -0.810907 +vn -0.497085 -0.122379 -0.859004 +vn -0.416425 0.555559 -0.719657 +vn -0.024415 0.998810 -0.041749 +vn 0.272011 0.839625 0.470077 +vn 0.391980 0.622608 0.677236 +vn 0.440962 0.474471 0.761834 +vn -0.242836 -0.348827 -0.905148 +vn -0.257057 -0.122227 -0.958617 +vn -0.215339 0.555376 -0.803217 +vn -0.012726 0.998840 -0.046205 +vn 0.140843 0.839106 0.525376 +vn 0.202918 0.621845 0.756371 +vn 0.228217 0.473769 0.850551 +vn 0.000000 -0.348338 -0.937346 +vn 0.000000 -0.122013 -0.992523 +vn 0.000000 0.554674 -0.832057 +vn 0.000000 0.998810 -0.048616 +vn 0.000000 0.838893 0.544267 +vn 0.000000 0.621387 0.783471 +vn 0.000000 0.473281 0.880886 +vn 0.242836 -0.348827 -0.905148 +vn 0.257057 -0.122227 -0.958617 +vn 0.215308 0.555376 -0.803217 +vn 0.012726 0.998840 -0.046205 +vn -0.140843 0.839106 0.525376 +vn -0.202918 0.621845 0.756340 +vn -0.228217 0.473769 0.850551 +vn 0.469375 -0.349376 -0.810907 +vn 0.497085 -0.122379 -0.859004 +vn 0.416425 0.555559 -0.719657 +vn 0.024415 0.998810 -0.041749 +vn -0.272011 0.839625 0.470077 +vn -0.391980 0.622608 0.677236 +vn -0.440962 0.474502 0.761803 +vn 0.662465 -0.349620 -0.662465 +vn 0.701773 -0.122471 -0.701773 +vn 0.587878 0.555650 -0.587878 +vn 0.034272 0.998810 -0.034272 +vn -0.383831 0.839808 0.383831 +vn -0.553148 0.622913 0.553148 +vn -0.622303 0.474776 0.622303 +vn 0.810907 -0.349406 -0.469375 +vn 0.859004 -0.122379 -0.497085 +vn 0.719657 0.555559 -0.416425 +vn 0.041749 0.998810 -0.024415 +vn -0.470077 0.839625 0.272011 +vn -0.677236 0.622608 0.391980 +vn -0.761803 0.474471 0.440962 +vn 0.905148 -0.348827 -0.242836 +vn 0.958617 -0.122227 -0.257057 +vn 0.803217 0.555376 -0.215339 +vn 0.046205 0.998840 -0.012726 +vn -0.525376 0.839106 0.140843 +vn -0.756340 0.621876 0.202918 +vn -0.850551 0.473769 0.228217 +vn 0.937346 -0.348338 0.000000 +vn 0.992523 -0.122013 0.000000 +vn 0.832026 0.554674 0.000000 +vn 0.048616 0.998810 0.000000 +vn -0.544267 0.838893 0.000000 +vn -0.783471 0.621387 0.000000 +vn 0.905148 -0.348827 0.242836 +vn 0.958617 -0.122227 0.257057 +vn 0.803217 0.555376 0.215308 +vn 0.046205 0.998840 0.012726 +vn -0.525376 0.839106 -0.140843 +vn -0.756340 0.621876 -0.202918 +vn 0.810907 -0.349406 0.469375 +vn 0.859004 -0.122379 0.497085 +vn 0.719657 0.555559 0.416425 +vn 0.041749 0.998810 0.024415 +vn -0.470077 0.839625 -0.272011 +vn -0.677236 0.622608 -0.391980 +vn -0.761803 0.474471 -0.440962 +vn 0.662465 -0.349620 0.662465 +vn 0.701773 -0.122471 0.701773 +vn 0.587878 0.555650 0.587878 +vn 0.034272 0.998810 0.034272 +vn -0.383831 0.839808 -0.383831 +vn -0.553148 0.622913 -0.553148 +vn -0.622303 0.474776 -0.622303 +vn 0.469375 -0.349376 0.810907 +vn 0.497085 -0.122379 0.859004 +vn 0.416425 0.555559 0.719657 +vn 0.024415 0.998810 0.041749 +vn -0.272011 0.839625 -0.470077 +vn -0.391980 0.622608 -0.677236 +vn -0.440962 0.474471 -0.761803 +vn 0.242836 -0.348827 0.905148 +vn 0.257057 -0.122227 0.958617 +vn 0.215339 0.555376 0.803217 +vn 0.012726 0.998840 0.046205 +vn -0.140843 0.839106 -0.525376 +vn -0.202918 0.621845 -0.756371 +vn -0.228217 0.473769 -0.850551 +vn 0.000000 -0.348338 0.937346 +vn 0.000000 -0.122013 0.992523 +vn 0.000000 0.554674 0.832057 +vn 0.000000 0.998810 0.048616 +vn 0.000000 0.838893 -0.544267 +vn 0.000000 0.621387 -0.783471 +vn 0.000000 0.473281 -0.880886 +vn -0.242836 -0.348827 0.905148 +vn -0.257057 -0.122227 0.958617 +vn -0.215308 0.555376 0.803217 +vn -0.012726 0.998840 0.046205 +vn 0.140843 0.839106 -0.525376 +vn 0.202918 0.621845 -0.756371 +vn 0.228217 0.473769 -0.850551 +vn -0.469375 -0.349376 0.810907 +vn -0.497085 -0.122379 0.859004 +vn -0.416425 0.555559 0.719657 +vn -0.024415 0.998810 0.041749 +vn 0.272011 0.839625 -0.470077 +vn 0.391980 0.622608 -0.677236 +vn 0.440962 0.474471 -0.761803 +vn -0.662465 -0.349620 0.662465 +vn -0.701773 -0.122440 0.701773 +vn -0.587878 0.555650 0.587878 +vn -0.034272 0.998810 0.034272 +vn 0.383831 0.839808 -0.383831 +vn 0.553148 0.622913 -0.553148 +vn 0.622303 0.474776 -0.622303 +vn -0.810907 -0.349376 0.469375 +vn -0.859004 -0.122410 0.497085 +vn -0.719657 0.555528 0.416425 +vn -0.041749 0.998810 0.024415 +vn 0.470077 0.839625 -0.272011 +vn 0.677236 0.622639 -0.391980 +vn 0.761803 0.474471 -0.440962 +vn -0.905148 -0.348827 0.242836 +vn -0.958617 -0.122227 0.257057 +vn -0.803217 0.555376 0.215339 +vn -0.046236 0.998840 0.012726 +vn 0.525376 0.839106 -0.140843 +vn 0.756371 0.621845 -0.202918 +vn 0.850551 0.473769 -0.228217 +vn 0.908292 0.418256 0.000000 +vn 0.877041 0.418744 0.235298 +vn 0.920286 0.391156 0.000000 +vn 0.888668 0.391644 0.238441 +vn 0.907315 0.342753 0.243446 +vn 0.785638 0.419416 0.454756 +vn 0.796075 0.392285 0.460799 +vn 0.812830 0.343333 0.470504 +vn 0.931486 0.265542 0.248543 +vn 0.834162 0.266366 0.482864 +vn 0.855312 0.152379 0.495132 +vn 0.966613 -0.042848 0.252602 +vn 0.864498 -0.045808 0.500504 +vn 0.641804 0.419691 0.641804 +vn 0.650349 0.392499 0.650349 +vn 0.664052 0.343577 0.664052 +vn 0.681509 0.266579 0.681509 +vn 0.698813 0.152501 0.698813 +vn 0.706351 -0.045869 0.706351 +vn 0.454756 0.419416 0.785638 +vn 0.460799 0.392285 0.796075 +vn 0.470504 0.343333 0.812830 +vn 0.482864 0.266366 0.834162 +vn 0.495132 0.152409 0.855312 +vn 0.500504 -0.045808 0.864498 +vn 0.235298 0.418744 0.877041 +vn 0.238441 0.391644 0.888668 +vn 0.243446 0.342753 0.907315 +vn 0.249855 0.265908 0.931028 +vn 0.256172 0.152104 0.954558 +vn 0.258980 -0.045717 0.964782 +vn 0.000000 0.418256 0.908292 +vn 0.000000 0.391156 0.920286 +vn 0.000000 0.342357 0.939543 +vn 0.000000 0.265542 0.964080 +vn 0.000000 0.151891 0.988372 +vn 0.000000 -0.045656 0.998932 +vn -0.235298 0.418744 0.877041 +vn -0.238441 0.391644 0.888668 +vn -0.243446 0.342753 0.907315 +vn -0.249855 0.265877 0.931028 +vn -0.256172 0.152104 0.954558 +vn -0.258980 -0.045717 0.964782 +vn -0.454756 0.419416 0.785638 +vn -0.460799 0.392285 0.796075 +vn -0.470504 0.343333 0.812830 +vn -0.482864 0.266366 0.834162 +vn -0.495132 0.152379 0.855312 +vn -0.500504 -0.045808 0.864498 +vn -0.641804 0.419691 0.641804 +vn -0.650349 0.392499 0.650349 +vn -0.664052 0.343577 0.664052 +vn -0.681509 0.266579 0.681509 +vn -0.698813 0.152501 0.698813 +vn -0.706351 -0.045869 0.706351 +vn -0.785638 0.419416 0.454756 +vn -0.796075 0.392285 0.460799 +vn -0.812830 0.343364 0.470504 +vn -0.834162 0.266366 0.482864 +vn -0.855312 0.152379 0.495132 +vn -0.864498 -0.045808 0.500504 +vn -0.907315 0.342753 0.243446 +vn -0.931028 0.265908 0.249855 +vn -0.954558 0.152104 0.256172 +vn -0.964782 -0.045717 0.258980 +vn -0.939543 0.342357 0.000000 +vn -0.964080 0.265542 0.000000 +vn -0.988372 0.151891 0.000000 +vn -0.888668 0.391644 -0.238441 +vn -0.907315 0.342753 -0.243446 +vn -0.931028 0.265877 -0.249855 +vn -0.954558 0.152104 -0.256172 +vn -0.785638 0.419416 -0.454756 +vn -0.796075 0.392285 -0.460799 +vn -0.812830 0.343333 -0.470504 +vn -0.834162 0.266366 -0.482864 +vn -0.855312 0.152379 -0.495132 +vn -0.964782 -0.045717 -0.258980 +vn -0.864498 -0.045808 -0.500504 +vn -0.641804 0.419691 -0.641804 +vn -0.650349 0.392499 -0.650349 +vn -0.664052 0.343577 -0.664052 +vn -0.681509 0.266579 -0.681509 +vn -0.698813 0.152501 -0.698813 +vn -0.706351 -0.045869 -0.706351 +vn -0.454756 0.419416 -0.785638 +vn -0.460799 0.392285 -0.796075 +vn -0.470504 0.343333 -0.812830 +vn -0.482864 0.266366 -0.834162 +vn -0.495132 0.152379 -0.855312 +vn -0.500504 -0.045808 -0.864498 +vn -0.235298 0.418744 -0.877041 +vn -0.238441 0.391644 -0.888668 +vn -0.243446 0.342753 -0.907315 +vn -0.249855 0.265908 -0.931028 +vn -0.256172 0.152104 -0.954558 +vn -0.258980 -0.045717 -0.964782 +vn 0.000000 0.418256 -0.908292 +vn 0.000000 0.391156 -0.920286 +vn 0.000000 0.342357 -0.939543 +vn 0.000000 0.265542 -0.964080 +vn 0.000000 0.151891 -0.988372 +vn 0.000000 -0.045656 -0.998932 +vn 0.235298 0.418744 -0.877041 +vn 0.238441 0.391644 -0.888668 +vn 0.243446 0.342753 -0.907315 +vn 0.249855 0.265877 -0.931028 +vn 0.256172 0.152104 -0.954558 +vn 0.258980 -0.045717 -0.964782 +vn 0.454756 0.419416 -0.785638 +vn 0.460799 0.392285 -0.796075 +vn 0.470504 0.343333 -0.812830 +vn 0.482864 0.266366 -0.834162 +vn 0.495132 0.152379 -0.855312 +vn 0.500504 -0.045808 -0.864498 +vn 0.641804 0.419691 -0.641804 +vn 0.650349 0.392499 -0.650349 +vn 0.664052 0.343577 -0.664052 +vn 0.681509 0.266579 -0.681509 +vn 0.698813 0.152501 -0.698813 +vn 0.706351 -0.045869 -0.706351 +vn 0.785638 0.419416 -0.454756 +vn 0.796075 0.392285 -0.460799 +vn 0.812830 0.343364 -0.470504 +vn 0.834162 0.266366 -0.482864 +vn 0.855312 0.152379 -0.495132 +vn 0.864498 -0.045808 -0.500504 +vn 0.877041 0.418744 -0.235298 +vn 0.888668 0.391644 -0.238441 +vn 0.907315 0.342753 -0.243446 +vn 0.795892 -0.566485 0.213538 +vn 0.712180 -0.701987 0.000000 +vn 0.687399 -0.702445 0.184393 +vn 0.652974 -0.757347 0.000000 +vn 0.630146 -0.757805 0.169012 +vn 0.724021 -0.689749 0.000000 +vn 0.698752 -0.690329 0.187414 +vn 0.886410 -0.462874 0.000000 +vn 0.855861 -0.463454 0.229530 +vn 0.817774 -0.327158 0.473434 +vn 0.712729 -0.567248 0.412549 +vn 0.615345 -0.703146 0.356151 +vn 0.564043 -0.758446 0.326456 +vn 0.625660 -0.690939 0.362102 +vn 0.766625 -0.464125 0.443678 +vn 0.668111 -0.327403 0.668111 +vn 0.582171 -0.567522 0.582171 +vn 0.502579 -0.703421 0.502579 +vn 0.460646 -0.758660 0.460646 +vn 0.510971 -0.691183 0.510971 +vn 0.626209 -0.464370 0.626240 +vn 0.473434 -0.327158 0.817774 +vn 0.412549 -0.567248 0.712729 +vn 0.356151 -0.703146 0.615375 +vn 0.326456 -0.758446 0.564043 +vn 0.362102 -0.690939 0.625660 +vn 0.443678 -0.464125 0.766625 +vn 0.245003 -0.326609 0.912839 +vn 0.213538 -0.566485 0.795892 +vn 0.184393 -0.702445 0.687399 +vn 0.169012 -0.757805 0.630146 +vn 0.187414 -0.690329 0.698752 +vn 0.229530 -0.463454 0.855831 +vn 0.000000 -0.326243 0.945250 +vn 0.000000 -0.565996 0.824396 +vn 0.000000 -0.701987 0.712180 +vn 0.000000 -0.757347 0.652974 +vn 0.000000 -0.689749 0.724021 +vn 0.000000 -0.462905 0.886380 +vn -0.245003 -0.326609 0.912839 +vn -0.213538 -0.566485 0.795892 +vn -0.184393 -0.702445 0.687399 +vn -0.169012 -0.757805 0.630146 +vn -0.187414 -0.690329 0.698752 +vn -0.229530 -0.463454 0.855861 +vn -0.473434 -0.327158 0.817774 +vn -0.412549 -0.567248 0.712729 +vn -0.356151 -0.703146 0.615375 +vn -0.326456 -0.758446 0.564043 +vn -0.362102 -0.690939 0.625660 +vn -0.443678 -0.464125 0.766625 +vn -0.668111 -0.327403 0.668111 +vn -0.582171 -0.567522 0.582171 +vn -0.502579 -0.703421 0.502579 +vn -0.460646 -0.758660 0.460646 +vn -0.510971 -0.691183 0.510971 +vn -0.626209 -0.464370 0.626209 +vn -0.817774 -0.327158 0.473434 +vn -0.712729 -0.567248 0.412549 +vn -0.615375 -0.703146 0.356151 +vn -0.564043 -0.758446 0.326456 +vn -0.625660 -0.690939 0.362102 +vn -0.766625 -0.464125 0.443678 +vn -0.912931 -0.326609 0.244575 +vn -0.687399 -0.702445 0.184393 +vn -0.630146 -0.757805 0.169012 +vn -0.698752 -0.690329 0.187414 +vn -0.855831 -0.463485 0.229530 +vn -0.824396 -0.565996 0.000000 +vn -0.712180 -0.701987 0.000000 +vn -0.652974 -0.757347 0.000000 +vn -0.724021 -0.689749 0.000000 +vn -0.886410 -0.462874 0.000000 +vn -0.795892 -0.566485 -0.213538 +vn -0.687399 -0.702445 -0.184393 +vn -0.630146 -0.757805 -0.169012 +vn -0.698752 -0.690329 -0.187414 +vn -0.855831 -0.463454 -0.229530 +vn -0.817774 -0.327158 -0.473434 +vn -0.712729 -0.567217 -0.412549 +vn -0.615375 -0.703146 -0.356151 +vn -0.564043 -0.758446 -0.326456 +vn -0.625660 -0.690939 -0.362102 +vn -0.766625 -0.464125 -0.443678 +vn -0.668111 -0.327403 -0.668111 +vn -0.582171 -0.567522 -0.582171 +vn -0.502579 -0.703421 -0.502579 +vn -0.460646 -0.758660 -0.460646 +vn -0.510971 -0.691183 -0.510971 +vn -0.626209 -0.464370 -0.626209 +vn -0.473434 -0.327158 -0.817774 +vn -0.412549 -0.567248 -0.712729 +vn -0.356151 -0.703146 -0.615375 +vn -0.326456 -0.758446 -0.564043 +vn -0.362102 -0.690939 -0.625660 +vn -0.443678 -0.464125 -0.766625 +vn -0.245003 -0.326609 -0.912839 +vn -0.213538 -0.566485 -0.795892 +vn -0.184393 -0.702445 -0.687399 +vn -0.169012 -0.757805 -0.630146 +vn -0.187414 -0.690329 -0.698752 +vn -0.229530 -0.463454 -0.855831 +vn 0.000000 -0.326243 -0.945250 +vn 0.000000 -0.565996 -0.824396 +vn 0.000000 -0.701987 -0.712180 +vn 0.000000 -0.757347 -0.652974 +vn 0.000000 -0.689749 -0.724021 +vn 0.000000 -0.462905 -0.886380 +vn 0.245003 -0.326609 -0.912839 +vn 0.213538 -0.566485 -0.795892 +vn 0.184393 -0.702445 -0.687399 +vn 0.169012 -0.757805 -0.630146 +vn 0.187445 -0.690329 -0.698752 +vn 0.229530 -0.463454 -0.855861 +vn 0.473434 -0.327158 -0.817774 +vn 0.412549 -0.567248 -0.712729 +vn 0.356151 -0.703146 -0.615375 +vn 0.326456 -0.758446 -0.564043 +vn 0.362102 -0.690939 -0.625660 +vn 0.443678 -0.464125 -0.766625 +vn 0.668111 -0.327403 -0.668111 +vn 0.582171 -0.567522 -0.582171 +vn 0.502579 -0.703421 -0.502579 +vn 0.460646 -0.758660 -0.460646 +vn 0.510971 -0.691183 -0.510971 +vn 0.626209 -0.464370 -0.626209 +vn 0.817774 -0.327158 -0.473434 +vn 0.712729 -0.567248 -0.412549 +vn 0.615375 -0.703146 -0.356151 +vn 0.564043 -0.758446 -0.326456 +vn 0.625660 -0.690939 -0.362102 +vn 0.766625 -0.464125 -0.443678 +vn 0.912839 -0.326609 -0.244942 +vn 0.795892 -0.566485 -0.213538 +vn 0.687399 -0.702445 -0.184393 +vn 0.630146 -0.757805 -0.169012 +vn 0.698752 -0.690329 -0.187414 +vn 0.855861 -0.463454 -0.229530 +vn 0.025666 -0.999664 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.024781 -0.999664 -0.006623 +vn 0.068667 -0.997620 0.000000 +vn 0.066256 -0.997620 -0.017731 +vn 0.157170 -0.987548 0.000000 +vn 0.151677 -0.987579 -0.040620 +vn 0.373150 -0.927763 0.000000 +vn 0.360118 -0.927885 -0.096469 +vn 0.789148 -0.614154 0.000000 +vn 0.762017 -0.614399 -0.204505 +vn 0.022156 -0.999664 -0.012787 +vn 0.059236 -0.997650 -0.034272 +vn 0.135624 -0.987640 -0.078463 +vn 0.322153 -0.928129 -0.186377 +vn 0.682333 -0.615131 -0.394971 +vn 0.018067 -0.999664 -0.018067 +vn 0.048341 -0.997650 -0.048341 +vn 0.110691 -0.987640 -0.110691 +vn 0.262947 -0.928251 -0.262947 +vn 0.557329 -0.615375 -0.557329 +vn 0.012787 -0.999664 -0.022156 +vn 0.034272 -0.997650 -0.059236 +vn 0.078463 -0.987640 -0.135624 +vn 0.186377 -0.928129 -0.322153 +vn 0.394971 -0.615131 -0.682302 +vn 0.006623 -0.999664 -0.024781 +vn 0.017731 -0.997620 -0.066256 +vn 0.040620 -0.987579 -0.151677 +vn 0.096469 -0.927885 -0.360118 +vn 0.204474 -0.614399 -0.762017 +vn 0.000000 -0.999664 -0.025666 +vn 0.000000 -0.997620 -0.068667 +vn 0.000000 -0.987548 -0.157170 +vn 0.000000 -0.927763 -0.373150 +vn 0.000000 -0.614154 -0.789148 +vn -0.006623 -0.999664 -0.024781 +vn -0.017731 -0.997620 -0.066256 +vn -0.040620 -0.987579 -0.151677 +vn -0.096469 -0.927885 -0.360118 +vn -0.204474 -0.614399 -0.762017 +vn -0.012787 -0.999664 -0.022156 +vn -0.034272 -0.997650 -0.059236 +vn -0.078463 -0.987640 -0.135624 +vn -0.186377 -0.928129 -0.322153 +vn -0.394971 -0.615131 -0.682333 +vn -0.018067 -0.999664 -0.018067 +vn -0.048341 -0.997650 -0.048341 +vn -0.110691 -0.987640 -0.110691 +vn -0.262947 -0.928251 -0.262947 +vn -0.557329 -0.615375 -0.557329 +vn -0.022156 -0.999664 -0.012787 +vn -0.059236 -0.997650 -0.034272 +vn -0.135624 -0.987640 -0.078463 +vn -0.322153 -0.928129 -0.186377 +vn -0.682302 -0.615131 -0.394971 +vn -0.024781 -0.999664 -0.006623 +vn -0.066256 -0.997620 -0.017731 +vn -0.151677 -0.987579 -0.040620 +vn -0.360118 -0.927885 -0.096469 +vn -0.762017 -0.614399 -0.204474 +vn -0.025666 -0.999664 0.000000 +vn -0.068667 -0.997620 0.000000 +vn -0.157170 -0.987548 0.000000 +vn -0.373150 -0.927763 0.000000 +vn -0.789148 -0.614154 0.000000 +vn -0.024781 -0.999664 0.006623 +vn -0.066256 -0.997620 0.017731 +vn -0.151677 -0.987579 0.040620 +vn -0.360149 -0.927885 0.096469 +vn -0.762017 -0.614399 0.204474 +vn -0.022156 -0.999664 0.012787 +vn -0.059236 -0.997650 0.034272 +vn -0.135624 -0.987640 0.078463 +vn -0.322153 -0.928129 0.186377 +vn -0.682333 -0.615131 0.394971 +vn -0.018067 -0.999664 0.018067 +vn -0.048341 -0.997650 0.048341 +vn -0.110691 -0.987640 0.110691 +vn -0.262947 -0.928251 0.262947 +vn -0.557329 -0.615375 0.557329 +vn -0.012787 -0.999664 0.022156 +vn -0.034272 -0.997650 0.059236 +vn -0.078463 -0.987640 0.135624 +vn -0.186377 -0.928129 0.322153 +vn -0.394971 -0.615131 0.682302 +vn -0.006623 -0.999664 0.024781 +vn -0.017731 -0.997620 0.066256 +vn -0.040620 -0.987579 0.151677 +vn -0.096469 -0.927885 0.360118 +vn -0.204474 -0.614399 0.762017 +vn 0.000000 -0.999664 0.025666 +vn 0.000000 -0.997620 0.068667 +vn 0.000000 -0.987548 0.157170 +vn 0.000000 -0.927763 0.373150 +vn 0.000000 -0.614154 0.789148 +vn 0.006623 -0.999664 0.024781 +vn 0.017731 -0.997620 0.066256 +vn 0.040620 -0.987579 0.151677 +vn 0.096469 -0.927885 0.360149 +vn 0.204474 -0.614399 0.762017 +vn 0.012787 -0.999664 0.022156 +vn 0.034272 -0.997650 0.059236 +vn 0.078463 -0.987640 0.135624 +vn 0.186377 -0.928129 0.322153 +vn 0.394971 -0.615131 0.682333 +vn 0.018067 -0.999664 0.018067 +vn 0.048341 -0.997650 0.048341 +vn 0.110691 -0.987640 0.110691 +vn 0.262947 -0.928251 0.262947 +vn 0.557329 -0.615375 0.557329 +vn 0.022156 -0.999664 0.012787 +vn 0.059236 -0.997650 0.034272 +vn 0.135624 -0.987640 0.078463 +vn 0.322153 -0.928129 0.186346 +vn 0.682302 -0.615131 0.394971 +vn 0.024781 -0.999664 0.006623 +vn 0.066256 -0.997620 0.017731 +vn 0.151677 -0.987579 0.040620 +vn 0.360118 -0.927885 0.096469 +vn 0.762017 -0.614399 0.204474 +vn 0.464827 -0.373638 -0.802667 +vn 0.655812 -0.373882 -0.655812 +vn 0.000000 -0.372539 0.927976 +vn -0.240699 -0.373028 0.896023 +vn -0.802667 -0.373608 0.464827 +vn 0.896023 -0.372997 -0.240699 +vn -0.927976 -0.372539 0.000000 +vn 0.927976 -0.372539 0.000000 +vn 0.717063 0.696982 0.000000 +vn 0.990387 -0.138310 -0.000061 +vn 0.956694 -0.138737 0.255806 +vn 0.692129 0.697470 0.185583 +vn 0.857326 -0.139317 0.495529 +vn 0.620045 0.697653 0.358837 +vn 0.700125 -0.139531 0.700217 +vn 0.506516 0.697714 0.506546 +vn 0.495468 -0.139286 0.857356 +vn 0.358776 0.697714 0.620014 +vn 0.255867 -0.138737 0.956694 +vn 0.185583 0.697531 0.692068 +vn 0.000061 -0.138310 0.990387 +vn 0.000000 0.696982 0.717063 +vn -0.255806 -0.138737 0.956694 +vn -0.185583 0.697470 0.692129 +vn -0.495529 -0.139317 0.857326 +vn -0.358837 0.697653 0.620045 +vn -0.700217 -0.139531 0.700156 +vn -0.506546 0.697714 0.506516 +vn -0.857356 -0.139286 0.495468 +vn -0.620014 0.697714 0.358776 +vn -0.956694 -0.138737 0.255867 +vn -0.692068 0.697531 0.185583 +vn -0.990387 -0.138310 0.000061 +vn -0.717063 0.696982 0.000000 +vn -0.956694 -0.138737 -0.255806 +vn -0.692129 0.697470 -0.185583 +vn -0.857326 -0.139317 -0.495529 +vn -0.620045 0.697653 -0.358837 +vn -0.700125 -0.139531 -0.700217 +vn -0.506516 0.697714 -0.506546 +vn -0.495468 -0.139286 -0.857356 +vn -0.358776 0.697714 -0.620014 +vn -0.255867 -0.138737 -0.956694 +vn -0.185583 0.697531 -0.692068 +vn -0.000061 -0.138310 -0.990387 +vn 0.000000 0.696982 -0.717063 +vn 0.255806 -0.138737 -0.956694 +vn 0.185583 0.697470 -0.692129 +vn 0.495529 -0.139317 -0.857326 +vn 0.358837 0.697653 -0.620045 +vn 0.700217 -0.139531 -0.700156 +vn 0.506546 0.697714 -0.506516 +vn 0.857356 -0.139286 -0.495468 +vn 0.620014 0.697714 -0.358776 +vn 0.956694 -0.138737 -0.255867 +vn 0.692068 0.697531 -0.185583 +vn 0.292520 0.956236 0.000000 +vn 0.282083 0.956389 0.075686 +vn 0.177953 0.984008 0.000000 +vn 0.171606 0.984069 0.046022 +vn 0.158879 0.987274 0.000000 +vn 0.153264 0.987304 0.041078 +vn 0.217719 0.975982 0.000000 +vn 0.210059 0.976043 0.056276 +vn 0.504715 0.863277 0.000000 +vn 0.487197 0.863460 0.130558 +vn 0.693258 0.720664 0.000000 +vn 0.669057 0.721183 0.179449 +vn 0.252388 0.956511 0.146092 +vn 0.153508 0.984130 0.088839 +vn 0.137059 0.987365 0.079318 +vn 0.187872 0.976135 0.108676 +vn 0.435926 0.863887 0.252205 +vn 0.598956 0.721824 0.346660 +vn 0.206091 0.956572 0.206091 +vn 0.125340 0.984161 0.125340 +vn 0.111911 0.987396 0.111911 +vn 0.153356 0.976196 0.153356 +vn 0.355907 0.864071 0.355907 +vn 0.489151 0.722098 0.489151 +vn 0.146092 0.956511 0.252388 +vn 0.088839 0.984130 0.153508 +vn 0.079318 0.987365 0.137059 +vn 0.108676 0.976135 0.187872 +vn 0.252205 0.863887 0.435926 +vn 0.346660 0.721824 0.598956 +vn 0.075686 0.956389 0.282083 +vn 0.046022 0.984069 0.171606 +vn 0.041078 0.987304 0.153264 +vn 0.056276 0.976043 0.210059 +vn 0.130558 0.863460 0.487197 +vn 0.179449 0.721183 0.669057 +vn 0.000000 0.956236 0.292520 +vn 0.000000 0.984008 0.177953 +vn 0.000000 0.987274 0.158879 +vn 0.000000 0.975982 0.217719 +vn 0.000000 0.863277 0.504715 +vn 0.000000 0.720664 0.693258 +vn -0.075686 0.956389 0.282083 +vn -0.046022 0.984069 0.171606 +vn -0.041078 0.987304 0.153264 +vn -0.056276 0.976043 0.210059 +vn -0.130558 0.863460 0.487197 +vn -0.179449 0.721183 0.669057 +vn -0.146092 0.956511 0.252388 +vn -0.088839 0.984130 0.153508 +vn -0.079318 0.987365 0.137059 +vn -0.108676 0.976135 0.187872 +vn -0.252205 0.863887 0.435926 +vn -0.346660 0.721824 0.598956 +vn -0.206091 0.956572 0.206091 +vn -0.125340 0.984161 0.125340 +vn -0.111911 0.987396 0.111911 +vn -0.153356 0.976196 0.153356 +vn -0.355907 0.864071 0.355907 +vn -0.489151 0.722098 0.489151 +vn -0.252388 0.956511 0.146092 +vn -0.153508 0.984130 0.088839 +vn -0.137059 0.987365 0.079318 +vn -0.187872 0.976135 0.108676 +vn -0.435926 0.863887 0.252205 +vn -0.598956 0.721824 0.346660 +vn -0.282083 0.956389 0.075686 +vn -0.171606 0.984069 0.046022 +vn -0.153264 0.987304 0.041078 +vn -0.210059 0.976043 0.056276 +vn -0.487197 0.863460 0.130558 +vn -0.669057 0.721183 0.179449 +vn -0.292520 0.956236 0.000000 +vn -0.177953 0.984008 0.000000 +vn -0.158879 0.987274 0.000000 +vn -0.217719 0.975982 0.000000 +vn -0.504715 0.863277 0.000000 +vn -0.693258 0.720664 0.000000 +vn -0.282083 0.956389 -0.075686 +vn -0.171606 0.984069 -0.046022 +vn -0.153264 0.987304 -0.041078 +vn -0.210059 0.976043 -0.056276 +vn -0.487197 0.863460 -0.130558 +vn -0.669057 0.721183 -0.179449 +vn -0.252388 0.956511 -0.146092 +vn -0.153508 0.984130 -0.088839 +vn -0.137059 0.987365 -0.079318 +vn -0.187872 0.976135 -0.108676 +vn -0.435926 0.863887 -0.252205 +vn -0.598956 0.721824 -0.346660 +vn -0.206091 0.956572 -0.206091 +vn -0.125340 0.984161 -0.125340 +vn -0.111911 0.987396 -0.111911 +vn -0.153356 0.976196 -0.153356 +vn -0.355907 0.864071 -0.355907 +vn -0.489151 0.722098 -0.489151 +vn -0.146092 0.956511 -0.252388 +vn -0.088839 0.984130 -0.153508 +vn -0.079318 0.987365 -0.137059 +vn -0.108676 0.976135 -0.187872 +vn -0.252205 0.863887 -0.435926 +vn -0.346660 0.721824 -0.598956 +vn -0.075686 0.956389 -0.282083 +vn -0.046022 0.984069 -0.171606 +vn -0.041078 0.987304 -0.153264 +vn -0.056276 0.976043 -0.210059 +vn -0.130558 0.863460 -0.487197 +vn -0.179449 0.721183 -0.669057 +vn 0.000000 0.956236 -0.292520 +vn 0.000000 0.984008 -0.177953 +vn 0.000000 0.987274 -0.158879 +vn 0.000000 0.975982 -0.217719 +vn 0.000000 0.863277 -0.504715 +vn 0.000000 0.720664 -0.693258 +vn 0.075686 0.956389 -0.282083 +vn 0.046022 0.984069 -0.171606 +vn 0.041078 0.987304 -0.153264 +vn 0.056276 0.976043 -0.210059 +vn 0.130558 0.863460 -0.487197 +vn 0.179449 0.721183 -0.669057 +vn 0.146092 0.956511 -0.252388 +vn 0.088839 0.984130 -0.153508 +vn 0.079318 0.987365 -0.137059 +vn 0.108676 0.976135 -0.187872 +vn 0.252205 0.863887 -0.435926 +vn 0.346660 0.721824 -0.598956 +vn 0.206091 0.956572 -0.206091 +vn 0.125340 0.984161 -0.125340 +vn 0.111911 0.987396 -0.111911 +vn 0.153356 0.976196 -0.153356 +vn 0.355907 0.864071 -0.355907 +vn 0.489151 0.722098 -0.489151 +vn 0.252388 0.956511 -0.146092 +vn 0.153508 0.984130 -0.088839 +vn 0.137059 0.987365 -0.079318 +vn 0.187872 0.976135 -0.108676 +vn 0.435926 0.863887 -0.252205 +vn 0.598956 0.721824 -0.346660 +vn 0.282083 0.956389 -0.075686 +vn 0.171606 0.984069 -0.046022 +vn 0.153264 0.987304 -0.041078 +vn 0.210059 0.976043 -0.056276 +vn 0.487197 0.863460 -0.130558 +vn 0.669057 0.721183 -0.179449 +vn 0.363842 0.931455 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.351451 0.931516 0.093509 +vn 0.968261 0.249916 0.000000 +vn 0.935423 0.249763 0.250130 +vn 0.842860 -0.538102 0.000000 +vn 0.813959 -0.538713 0.217292 +vn 0.786767 -0.617206 -0.000031 +vn 0.759514 -0.618000 0.202857 +vn 0.314432 0.931791 0.181280 +vn 0.838404 0.249855 0.484359 +vn 0.729026 -0.539720 0.420911 +vn 0.680013 -0.619068 0.392743 +vn 0.256386 0.931913 0.256417 +vn 0.684652 0.249886 0.684652 +vn 0.595050 -0.540147 0.595050 +vn 0.555010 -0.619526 0.555040 +vn 0.181280 0.931791 0.314432 +vn 0.484359 0.249825 0.838404 +vn 0.420881 -0.539720 0.729026 +vn 0.392712 -0.619098 0.680013 +vn 0.093509 0.931516 0.351451 +vn 0.250160 0.249763 0.935423 +vn 0.217322 -0.538713 0.813959 +vn 0.202887 -0.618030 0.759484 +vn 0.000000 0.931455 0.363842 +vn 0.000000 0.249916 0.968261 +vn 0.000000 -0.538102 0.842860 +vn 0.000031 -0.617206 0.786767 +vn -0.093509 0.931516 0.351451 +vn -0.250130 0.249763 0.935423 +vn -0.217292 -0.538682 0.813959 +vn -0.202857 -0.618000 0.759514 +vn -0.181280 0.931791 0.314432 +vn -0.484359 0.249855 0.838404 +vn -0.420911 -0.539720 0.729026 +vn -0.392743 -0.619068 0.680013 +vn -0.256417 0.931913 0.256386 +vn -0.684652 0.249886 0.684652 +vn -0.595050 -0.540147 0.595050 +vn -0.555040 -0.619526 0.555010 +vn -0.314432 0.931791 0.181280 +vn -0.838404 0.249825 0.484359 +vn -0.729026 -0.539720 0.420881 +vn -0.680013 -0.619098 0.392712 +vn -0.351451 0.931516 0.093509 +vn -0.935423 0.249763 0.250160 +vn -0.813959 -0.538713 0.217292 +vn -0.759484 -0.618030 0.202887 +vn -0.363842 0.931455 0.000000 +vn -0.968261 0.249916 0.000000 +vn -0.842860 -0.538102 0.000000 +vn -0.786767 -0.617206 0.000031 +vn -0.351451 0.931516 -0.093509 +vn -0.935423 0.249763 -0.250130 +vn -0.813959 -0.538713 -0.217292 +vn -0.759514 -0.618000 -0.202857 +vn -0.314432 0.931791 -0.181280 +vn -0.838404 0.249855 -0.484359 +vn -0.729026 -0.539720 -0.420911 +vn -0.680013 -0.619068 -0.392743 +vn -0.256386 0.931913 -0.256417 +vn -0.684652 0.249886 -0.684652 +vn -0.595050 -0.540147 -0.595050 +vn -0.555010 -0.619526 -0.555040 +vn -0.181280 0.931791 -0.314432 +vn -0.484359 0.249825 -0.838404 +vn -0.420881 -0.539720 -0.729026 +vn -0.392712 -0.619098 -0.680013 +vn -0.093509 0.931516 -0.351451 +vn -0.250160 0.249763 -0.935423 +vn -0.217322 -0.538713 -0.813959 +vn -0.202887 -0.618030 -0.759484 +vn 0.000000 0.931455 -0.363842 +vn 0.000000 0.249916 -0.968261 +vn 0.000000 -0.538102 -0.842860 +vn -0.000031 -0.617206 -0.786767 +vn 0.093509 0.931516 -0.351451 +vn 0.250130 0.249763 -0.935423 +vn 0.217292 -0.538682 -0.813959 +vn 0.202857 -0.618000 -0.759514 +vn 0.181280 0.931791 -0.314432 +vn 0.484359 0.249855 -0.838404 +vn 0.420911 -0.539720 -0.729026 +vn 0.392743 -0.619068 -0.680013 +vn 0.256417 0.931913 -0.256386 +vn 0.684652 0.249886 -0.684652 +vn 0.595050 -0.540147 -0.595050 +vn 0.555040 -0.619526 -0.555010 +vn 0.314432 0.931791 -0.181280 +vn 0.838404 0.249825 -0.484359 +vn 0.729026 -0.539720 -0.420881 +vn 0.680013 -0.619098 -0.392712 +vn 0.351451 0.931516 -0.093509 +vn 0.935423 0.249763 -0.250160 +vn 0.813959 -0.538713 -0.217292 +vn 0.759484 -0.618030 -0.202887 +vn -0.354198 0.930296 -0.095187 +vn 0.095187 0.930296 0.354198 +vn 0.354198 0.930296 0.095187 +vn 0.183721 0.930387 0.317179 +vn -0.183721 0.930387 -0.317179 +vn -0.367443 0.930021 0.000000 +vn -0.183721 0.930387 0.317179 +vn 0.367412 0.930021 0.000000 +vn -0.317179 0.930387 0.183721 +vn -0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 -0.367443 +vn -0.354198 0.930296 0.095187 +vn 0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 0.367443 +vn -0.317179 0.930387 -0.183721 +vn 0.317179 0.930387 -0.183721 +vn -0.095187 0.930296 0.354198 +vn 0.317179 0.930387 0.183721 +vn 0.354198 0.930296 -0.095187 +vn 0.183721 0.930387 -0.317179 +vn -0.034730 0.999390 0.000000 +vn 0.033479 0.999390 -0.009003 +vn 0.034730 0.999390 0.000000 +vn 0.009003 0.999390 -0.033479 +vn 0.000000 0.999390 -0.034730 +vn -0.259163 0.930387 0.259163 +vn -0.017335 0.999390 0.029939 +vn 0.947539 0.295083 0.122654 +vn -0.004486 0.999969 0.000000 +vn -0.004151 0.950468 0.310739 +vn -0.003021 0.719291 0.694662 +vn -0.998688 0.050722 0.000000 +vn -0.003143 0.719321 -0.694632 +vn 0.970214 0.213324 -0.114505 +vn -0.136235 0.879482 -0.455947 +vn 0.949858 0.312662 0.000000 +vn 0.055757 -0.017579 -0.998260 +vn 0.201300 -0.540880 -0.816645 +vn 0.974456 -0.186071 -0.125645 +vn 0.988098 -0.096286 0.119938 +vn 0.974456 -0.186041 0.125614 +vn -0.879574 -0.475723 0.000000 +vn -0.873775 -0.472610 -0.114475 +vn 0.988067 -0.096286 -0.119938 +vn 0.295480 -0.855464 -0.425214 +vn -0.976196 -0.174993 -0.127903 +vn -0.971007 -0.205725 0.121677 +vn -0.976196 -0.174963 0.127903 +vn -0.976196 -0.174993 0.127903 +vn 0.896054 -0.372997 0.240699 +vn -0.802667 -0.373638 -0.464827 +vn -0.655812 -0.373852 -0.655812 +vn -0.240699 -0.373028 -0.896023 +vn -0.464827 -0.373638 -0.802667 +vn -0.896023 -0.373028 0.240699 +vn 0.000000 -0.372539 -0.927976 +vn -0.655812 -0.373852 0.655812 +vn 0.240699 -0.373028 0.896023 +vn -0.896023 -0.373028 -0.240699 +vn 0.802667 -0.373638 -0.464827 +vn 0.655812 -0.373882 0.655812 +vn 0.464827 -0.373638 0.802667 +vn -0.464827 -0.373638 0.802667 +vn 0.240699 -0.373028 -0.896023 +vn 0.802667 -0.373638 0.464827 +vn -0.033479 0.999390 0.009003 +vn -0.259163 0.930387 -0.259163 +vn -0.024445 0.999390 -0.024445 +vn -0.029939 0.999390 -0.017335 +vn 0.259163 0.930387 -0.259163 +vn 0.024445 0.999390 -0.024445 +vn 0.017335 0.999390 -0.029939 +vn 0.029939 0.999390 -0.017335 +vn 0.033479 0.999390 0.009003 +vn -0.009003 0.999390 0.033479 +vn 0.000000 0.999390 0.034730 +vn -0.017335 0.999390 -0.029939 +vn 0.259163 0.930387 0.259163 +vn 0.029939 0.999390 0.017335 +vn -0.009003 0.999390 -0.033479 +vn 0.024445 0.999390 0.024445 +vn 0.017335 0.999390 0.029939 +vn 0.009003 0.999390 0.033479 +vn -0.033479 0.999390 -0.009003 +vn -0.024445 0.999390 0.024445 +vn -0.029939 0.999390 0.017335 +vn 0.055757 -0.017579 0.998260 +vn 0.294198 -0.855403 0.426252 +vn 0.201300 -0.540880 0.816614 +s 1 +f 34//1 1243//2 593//3 +f 52//4 27//5 40//6 +f 52//4 40//6 65//7 +f 77//8 52//4 65//7 +f 77//8 65//7 84//9 +f 107//10 77//8 84//9 +f 107//10 84//9 85//11 +f 115//12 107//10 85//11 +f 115//12 85//11 99//13 +f 129//14 115//12 99//13 +f 129//14 99//13 128//15 +f 1252//16 36//17 40//6 +f 65//7 40//6 64//18 +f 65//7 64//18 58//19 +f 84//9 65//7 58//19 +f 84//9 58//19 59//20 +f 85//11 84//9 59//20 +f 85//11 59//20 70//21 +f 99//13 85//11 70//21 +f 99//13 70//21 98//22 +f 128//15 99//13 98//22 +f 128//15 98//22 114//23 +f 1244//24 33//25 64//18 +f 58//19 64//18 33//25 +f 58//19 33//25 35//26 +f 59//20 58//19 35//26 +f 59//20 35//26 45//27 +f 70//21 59//20 45//27 +f 70//21 45//27 69//28 +f 98//22 70//21 69//28 +f 98//22 69//28 83//29 +f 114//23 98//22 83//29 +f 114//23 83//29 113//30 +f 553//31 1//32 566//33 +f 35//26 33//25 20//34 +f 35//26 20//34 24//35 +f 45//27 35//26 24//35 +f 45//27 24//35 44//36 +f 69//28 45//27 44//36 +f 69//28 44//36 57//37 +f 83//29 69//28 57//37 +f 83//29 57//37 82//38 +f 113//30 83//29 82//38 +f 113//30 82//38 112//39 +f 566//33 1283//40 9//41 +f 24//35 20//34 18//42 +f 24//35 18//42 23//43 +f 44//36 24//35 23//43 +f 44//36 23//43 32//44 +f 57//37 44//36 32//44 +f 57//37 32//44 56//45 +f 82//38 57//37 56//45 +f 82//38 56//45 81//46 +f 112//39 82//38 81//46 +f 112//39 81//46 111//47 +f 4//48 8//49 1250//50 +f 23//43 18//42 8//49 +f 23//43 8//49 17//51 +f 32//44 23//43 17//51 +f 32//44 17//51 31//52 +f 56//45 32//44 31//52 +f 56//45 31//52 55//53 +f 81//46 56//45 55//53 +f 81//46 55//53 80//54 +f 111//47 81//46 80//54 +f 111//47 80//54 110//55 +f 565//56 592//57 1233//58 +f 17//51 8//49 4//48 +f 17//51 4//48 16//59 +f 31//52 17//51 16//59 +f 31//52 16//59 30//60 +f 55//53 31//52 30//60 +f 55//53 30//60 54//61 +f 80//54 55//53 54//61 +f 80//54 54//61 79//62 +f 110//55 80//54 79//62 +f 110//55 79//62 109//63 +f 1//32 565//56 2//64 +f 6//65 2//64 565//56 +f 16//59 4//48 7//66 +f 16//59 7//66 22//67 +f 30//60 16//59 22//67 +f 30//60 22//67 43//68 +f 54//61 30//60 43//68 +f 54//61 43//68 68//69 +f 79//62 54//61 68//69 +f 79//62 68//69 97//70 +f 109//63 79//62 97//70 +f 109//63 97//70 127//71 +f 565//56 1233//58 1249//58 +f 13//72 14//73 5//74 +f 22//67 7//66 15//75 +f 22//67 15//75 29//76 +f 43//68 22//67 29//76 +f 43//68 29//76 42//77 +f 68//69 43//68 42//77 +f 68//69 42//77 67//78 +f 97//70 68//69 67//78 +f 97//70 67//78 96//79 +f 127//71 97//70 96//79 +f 127//71 96//79 126//80 +f 11//81 15//75 1240//82 +f 1289//83 34//1 593//3 +f 29//76 15//75 14//73 +f 29//76 14//73 21//84 +f 42//77 29//76 21//84 +f 42//77 21//84 41//85 +f 67//78 42//77 41//85 +f 67//78 41//85 66//86 +f 96//79 67//78 66//86 +f 96//79 66//86 95//87 +f 126//80 96//79 95//87 +f 126//80 95//87 125//88 +f 636//89 1243//2 26//2 +f 636//89 26//2 592//57 +f 21//84 14//73 13//72 +f 21//84 13//72 28//90 +f 41//85 21//84 28//90 +f 41//85 28//90 53//91 +f 66//86 41//85 53//91 +f 66//86 53//91 78//92 +f 95//87 66//86 78//92 +f 95//87 78//92 108//93 +f 125//88 95//87 108//93 +f 125//88 108//93 136//94 +f 12//95 13//72 5//74 +f 28//90 13//72 27//5 +f 28//90 27//5 52//4 +f 53//91 28//90 52//4 +f 53//91 52//4 77//8 +f 78//92 53//91 77//8 +f 78//92 77//8 107//10 +f 108//93 78//92 107//10 +f 108//93 107//10 115//12 +f 136//94 108//93 115//12 +f 136//94 115//12 129//14 +f 148//96 129//14 128//15 +f 148//96 128//15 143//97 +f 121//98 148//96 143//97 +f 121//98 143//97 122//99 +f 92//100 121//98 122//99 +f 92//100 122//99 93//101 +f 62//102 92//100 93//101 +f 62//102 93//101 63//103 +f 39//104 62//102 63//103 +f 39//104 63//103 51//105 +f 10//106 39//104 51//105 +f 10//106 51//105 49//107 +f 143//97 128//15 114//23 +f 143//97 114//23 142//108 +f 122//99 143//97 142//108 +f 122//99 142//108 123//109 +f 93//101 122//99 123//109 +f 93//101 123//109 94//110 +f 63//103 93//101 94//110 +f 63//103 94//110 76//111 +f 51//105 63//103 76//111 +f 51//105 76//111 75//112 +f 49//107 51//105 75//112 +f 49//107 75//112 61//113 +f 142//108 114//23 113//30 +f 142//108 113//30 141//114 +f 123//109 142//108 141//114 +f 123//109 141//114 124//115 +f 94//110 123//109 124//115 +f 94//110 124//115 106//116 +f 76//111 94//110 106//116 +f 76//111 106//116 105//117 +f 75//112 76//111 105//117 +f 75//112 105//117 91//118 +f 61//113 75//112 91//118 +f 61//113 91//118 90//119 +f 141//114 113//30 112//39 +f 141//114 112//39 140//120 +f 124//115 141//114 140//120 +f 124//115 140//120 135//121 +f 106//116 124//115 135//121 +f 106//116 135//121 134//122 +f 105//117 106//116 134//122 +f 105//117 134//122 120//123 +f 91//118 105//117 120//123 +f 91//118 120//123 119//124 +f 90//119 91//118 119//124 +f 140//120 112//39 111//47 +f 140//120 111//47 139//125 +f 135//121 140//120 139//125 +f 135//121 139//125 155//126 +f 134//122 135//121 155//126 +f 134//122 155//126 147//127 +f 120//123 134//122 147//127 +f 120//123 147//127 144//128 +f 119//124 120//123 144//128 +f 119//124 144//128 116//129 +f 26//2 1234//130 592//57 +f 139//125 111//47 110//55 +f 139//125 110//55 138//131 +f 155//126 139//125 138//131 +f 155//126 138//131 156//132 +f 147//127 155//126 156//132 +f 147//127 156//132 145//133 +f 144//128 147//127 145//133 +f 144//128 145//133 117//134 +f 116//129 144//128 117//134 +f 116//129 117//134 88//135 +f 27//5 13//72 12//95 +f 1242//136 88//135 71//137 +f 138//131 110//55 109//63 +f 138//131 109//63 137//138 +f 156//132 138//131 137//138 +f 156//132 137//138 154//139 +f 145//133 156//132 154//139 +f 145//133 154//139 131//140 +f 117//134 145//133 131//140 +f 117//134 131//140 101//141 +f 88//135 117//134 101//141 +f 88//135 101//141 86//142 +f 60//143 74//144 1248//145 +f 137//138 109//63 127//71 +f 137//138 127//71 151//146 +f 154//139 137//138 151//146 +f 154//139 151//146 153//147 +f 131//140 154//139 153//147 +f 131//140 153//147 130//148 +f 101//141 131//140 130//148 +f 101//141 130//148 100//149 +f 86//142 101//141 100//149 +f 86//142 100//149 74//144 +f 47//150 1235//151 631//152 +f 74//144 48//153 1248//145 +f 151//146 127//71 126//80 +f 151//146 126//80 150//154 +f 153//147 151//146 150//154 +f 153//147 150//154 146//155 +f 130//148 153//147 146//155 +f 130//148 146//155 118//156 +f 100//149 130//148 118//156 +f 100//149 118//156 89//157 +f 74//144 100//149 89//157 +f 74//144 89//157 48//153 +f 1247//158 87//159 715//160 +f 104//161 116//129 1242//136 +f 150//154 126//80 125//88 +f 150//154 125//88 149//162 +f 146//155 150//154 149//162 +f 146//155 149//162 132//163 +f 118//156 146//155 132//163 +f 118//156 132//163 102//164 +f 89//157 118//156 102//164 +f 89//157 102//164 72//165 +f 48//153 89//157 72//165 +f 48//153 72//165 46//166 +f 37//167 48//153 46//166 +f 37//167 46//166 38//168 +f 149//162 125//88 136//94 +f 149//162 136//94 152//169 +f 132//163 149//162 152//169 +f 132//163 152//169 133//170 +f 102//164 132//163 133//170 +f 102//164 133//170 103//171 +f 72//165 102//164 103//171 +f 72//165 103//171 73//172 +f 46//166 72//165 73//172 +f 46//166 73//172 50//173 +f 38//168 46//166 50//173 +f 38//168 50//173 25//174 +f 152//169 136//94 129//14 +f 152//169 129//14 148//96 +f 133//170 152//169 148//96 +f 133//170 148//96 121//98 +f 103//171 133//170 121//98 +f 103//171 121//98 92//100 +f 73//172 103//171 92//100 +f 73//172 92//100 62//102 +f 50//173 73//172 62//102 +f 50//173 62//102 39//104 +f 25//174 50//173 39//104 +f 39//104 10//106 25//174 +f 539//175 509//176 159//177 +f 160//178 158//179 157//180 +f 166//181 160//178 163//182 +f 166//181 163//182 173//183 +f 177//184 166//181 173//183 +f 177//184 173//183 183//185 +f 189//186 177//184 183//185 +f 189//186 183//185 197//187 +f 205//188 189//186 197//187 +f 205//188 197//187 216//189 +f 225//190 205//188 216//189 +f 225//190 216//189 235//191 +f 173//183 163//182 172//192 +f 173//183 172//192 184//193 +f 183//185 173//183 184//193 +f 183//185 184//193 198//194 +f 197//187 183//185 198//194 +f 197//187 198//194 217//195 +f 216//189 197//187 217//195 +f 216//189 217//195 236//196 +f 235//191 216//189 236//196 +f 235//191 236//196 253//197 +f 182//198 172//192 1254//199 +f 1255//200 167//201 595//202 +f 184//193 172//192 182//198 +f 184//193 182//198 196//203 +f 198//194 184//193 196//203 +f 198//194 196//203 214//204 +f 217//195 198//194 214//204 +f 217//195 214//204 232//205 +f 236//196 217//195 232//205 +f 236//196 232//205 250//206 +f 253//197 236//196 250//206 +f 253//197 250//206 267//207 +f 196//203 182//198 199//208 +f 196//203 199//208 215//209 +f 214//204 196//203 215//209 +f 214//204 215//209 233//210 +f 232//205 214//204 233//210 +f 232//205 233//210 251//211 +f 250//206 232//205 251//211 +f 250//206 251//211 257//212 +f 267//207 250//206 257//212 +f 267//207 257//212 256//213 +f 215//209 199//208 218//214 +f 215//209 218//214 234//215 +f 233//210 215//209 234//215 +f 233//210 234//215 241//216 +f 251//211 233//210 241//216 +f 251//211 241//216 240//217 +f 257//212 251//211 240//217 +f 257//212 240//217 239//218 +f 256//213 257//212 239//218 +f 256//213 239//218 238//219 +f 234//215 218//214 219//220 +f 234//215 219//220 224//221 +f 241//216 234//215 224//221 +f 241//216 224//221 223//222 +f 240//217 241//216 223//222 +f 240//217 223//222 222//223 +f 239//218 240//217 222//223 +f 239//218 222//223 221//224 +f 238//219 239//218 221//224 +f 238//219 221//224 220//225 +f 219//220 218//214 1285//226 +f 648//227 691//228 207//229 +f 224//221 219//220 208//230 +f 224//221 208//230 204//231 +f 223//222 224//221 204//231 +f 223//222 204//231 203//232 +f 222//223 223//222 203//232 +f 222//223 203//232 202//233 +f 221//224 222//223 202//233 +f 221//224 202//233 201//234 +f 220//225 221//224 201//234 +f 220//225 201//234 212//235 +f 204//231 208//230 191//236 +f 204//231 191//236 188//237 +f 203//232 204//231 188//237 +f 203//232 188//237 187//238 +f 202//233 203//232 187//238 +f 202//233 187//238 186//239 +f 201//234 202//233 186//239 +f 201//234 186//239 194//240 +f 212//235 201//234 194//240 +f 212//235 194//240 211//241 +f 188//237 191//236 174//242 +f 188//237 174//242 176//243 +f 187//238 188//237 176//243 +f 187//238 176//243 175//244 +f 186//239 187//238 175//244 +f 186//239 175//244 180//245 +f 194//240 186//239 180//245 +f 194//240 180//245 193//246 +f 211//241 194//240 193//246 +f 211//241 193//246 210//247 +f 613//248 585//249 1258//250 +f 176//243 174//242 168//251 +f 176//243 168//251 165//252 +f 175//244 176//243 165//252 +f 175//244 165//252 170//253 +f 180//245 175//244 170//253 +f 180//245 170//253 179//254 +f 193//246 180//245 179//254 +f 193//246 179//254 192//255 +f 210//247 193//246 192//255 +f 210//247 192//255 209//256 +f 168//251 174//242 164//257 +f 165//252 168//251 161//258 +f 165//252 161//258 162//259 +f 170//253 165//252 162//259 +f 170//253 162//259 171//260 +f 179//254 170//253 171//260 +f 179//254 171//260 181//261 +f 192//255 179//254 181//261 +f 192//255 181//261 195//262 +f 209//256 192//255 195//262 +f 209//256 195//262 213//263 +f 160//178 161//258 158//179 +f 161//258 160//178 162//259 +f 162//259 160//178 166//181 +f 171//260 162//259 166//181 +f 171//260 166//181 177//184 +f 181//261 171//260 177//184 +f 181//261 177//184 189//186 +f 195//262 181//261 189//186 +f 195//262 189//186 205//188 +f 213//263 195//262 205//188 +f 213//263 205//188 225//190 +f 242//264 225//190 235//191 +f 242//264 235//191 252//265 +f 258//266 242//264 252//265 +f 258//266 252//265 268//267 +f 273//268 258//266 268//267 +f 273//268 268//267 283//269 +f 287//270 273//268 283//269 +f 287//270 283//269 298//271 +f 300//272 287//270 298//271 +f 300//272 298//271 299//273 +f 312//274 300//272 299//273 +f 312//274 299//273 310//275 +f 252//265 235//191 253//197 +f 252//265 253//197 269//276 +f 268//267 252//265 269//276 +f 268//267 269//276 284//277 +f 283//269 268//267 284//277 +f 283//269 284//277 286//278 +f 298//271 283//269 286//278 +f 298//271 286//278 285//279 +f 299//273 298//271 285//279 +f 299//273 285//279 296//280 +f 310//275 299//273 296//280 +f 310//275 296//280 309//281 +f 269//276 253//197 267//207 +f 269//276 267//207 272//282 +f 284//277 269//276 272//282 +f 284//277 272//282 271//283 +f 286//278 284//277 271//283 +f 286//278 271//283 270//284 +f 285//279 286//278 270//284 +f 285//279 270//284 281//285 +f 296//280 285//279 281//285 +f 296//280 281//285 295//286 +f 309//281 296//280 295//286 +f 309//281 295//286 308//287 +f 272//282 267//207 256//213 +f 272//282 256//213 255//288 +f 271//283 272//282 255//288 +f 271//283 255//288 254//289 +f 270//284 271//283 254//289 +f 270//284 254//289 265//290 +f 281//285 270//284 265//290 +f 281//285 265//290 280//291 +f 295//286 281//285 280//291 +f 295//286 280//291 294//292 +f 308//287 295//286 294//292 +f 308//287 294//292 307//293 +f 255//288 256//213 238//219 +f 255//288 238//219 237//294 +f 254//289 255//288 237//294 +f 254//289 237//294 248//295 +f 265//290 254//289 248//295 +f 265//290 248//295 264//296 +f 280//291 265//290 264//296 +f 280//291 264//296 279//297 +f 294//292 280//291 279//297 +f 294//292 279//297 293//298 +f 307//293 294//292 293//298 +f 307//293 293//298 306//299 +f 237//294 238//219 220//225 +f 237//294 220//225 230//300 +f 248//295 237//294 230//300 +f 248//295 230//300 247//301 +f 264//296 248//295 247//301 +f 264//296 247//301 263//302 +f 279//297 264//296 263//302 +f 279//297 263//302 278//303 +f 293//298 279//297 278//303 +f 293//298 278//303 292//304 +f 306//299 293//298 292//304 +f 306//299 292//304 305//305 +f 230//300 220//225 212//235 +f 230//300 212//235 229//306 +f 247//301 230//300 229//306 +f 247//301 229//306 246//307 +f 263//302 247//301 246//307 +f 263//302 246//307 262//308 +f 278//303 263//302 262//308 +f 278//303 262//308 277//309 +f 292//304 278//303 277//309 +f 292//304 277//309 291//310 +f 305//305 292//304 291//310 +f 305//305 291//310 304//311 +f 229//306 212//235 211//241 +f 229//306 211//241 228//312 +f 246//307 229//306 228//312 +f 246//307 228//312 245//313 +f 262//308 246//307 245//313 +f 262//308 245//313 261//314 +f 277//309 262//308 261//314 +f 277//309 261//314 276//315 +f 291//310 277//309 276//315 +f 291//310 276//315 290//316 +f 304//311 291//310 290//316 +f 304//311 290//316 303//317 +f 228//312 211//241 210//247 +f 228//312 210//247 227//318 +f 245//313 228//312 227//318 +f 245//313 227//318 244//319 +f 261//314 245//313 244//319 +f 261//314 244//319 260//320 +f 276//315 261//314 260//320 +f 276//315 260//320 275//321 +f 290//316 276//315 275//321 +f 290//316 275//321 289//322 +f 303//317 290//316 289//322 +f 303//317 289//322 302//323 +f 227//318 210//247 209//256 +f 227//318 209//256 226//324 +f 244//319 227//318 226//324 +f 244//319 226//324 243//325 +f 260//320 244//319 243//325 +f 260//320 243//325 259//326 +f 275//321 260//320 259//326 +f 275//321 259//326 274//327 +f 289//322 275//321 274//327 +f 289//322 274//327 288//328 +f 302//323 289//322 288//328 +f 302//323 288//328 301//329 +f 226//324 209//256 213//263 +f 226//324 213//263 231//330 +f 243//325 226//324 231//330 +f 243//325 231//330 249//331 +f 259//326 243//325 249//331 +f 259//326 249//331 266//332 +f 274//327 259//326 266//332 +f 274//327 266//332 282//333 +f 288//328 274//327 282//333 +f 288//328 282//333 297//334 +f 301//329 288//328 297//334 +f 301//329 297//334 311//335 +f 231//330 213//263 225//190 +f 231//330 225//190 242//264 +f 249//331 231//330 242//264 +f 249//331 242//264 258//266 +f 266//332 249//331 258//266 +f 266//332 258//266 273//268 +f 282//333 266//332 273//268 +f 282//333 273//268 287//270 +f 297//334 282//333 287//270 +f 297//334 287//270 300//272 +f 311//335 297//334 300//272 +f 311//335 300//272 312//274 +f 312//274 310//275 323//336 +f 302//323 315//337 316//338 +f 304//311 317//339 318//340 +f 303//317 316//338 317//339 +f 309//281 308//287 321//341 +f 307//293 306//299 319//342 +f 311//335 313//343 314//344 +f 301//329 314//344 315//337 +f 312//274 324//345 313//343 +f 306//299 305//305 318//340 +f 308//287 307//293 320//346 +f 310//275 309//281 322//347 +f 322//347 321//341 325//348 +f 314//344 313//343 325//348 +f 323//336 322//347 325//348 +f 319//342 318//340 325//348 +f 315//337 314//344 325//348 +f 321//341 320//346 325//348 +f 324//345 323//336 325//348 +f 320//346 319//342 325//348 +f 317//339 316//338 325//348 +f 316//338 315//337 325//348 +f 313//343 324//345 325//348 +f 318//340 317//339 325//348 +f 326//349 327//350 328//351 +f 326//349 328//351 329//352 +f 333//353 326//349 329//352 +f 333//353 329//352 338//354 +f 347//355 333//353 338//354 +f 347//355 338//354 354//356 +f 364//357 347//355 354//356 +f 364//357 354//356 374//358 +f 386//359 364//357 374//358 +f 386//359 374//358 398//360 +f 412//361 386//359 398//360 +f 412//361 398//360 429//362 +f 329//352 328//351 334//363 +f 329//352 334//363 339//364 +f 338//354 329//352 339//364 +f 338//354 339//364 355//365 +f 354//356 338//354 355//365 +f 354//356 355//365 375//366 +f 374//358 354//356 375//366 +f 374//358 375//366 399//367 +f 398//360 374//358 399//367 +f 398//360 399//367 430//368 +f 429//362 398//360 430//368 +f 429//362 430//368 464//369 +f 339//364 334//363 342//370 +f 339//364 342//370 356//371 +f 355//365 339//364 356//371 +f 355//365 356//371 376//372 +f 375//366 355//365 376//372 +f 375//366 376//372 400//373 +f 399//367 375//366 400//373 +f 399//367 400//373 431//374 +f 430//368 399//367 431//374 +f 430//368 431//374 465//375 +f 464//369 430//368 465//375 +f 464//369 465//375 497//376 +f 356//371 342//370 351//377 +f 356//371 351//377 370//378 +f 376//372 356//371 370//378 +f 376//372 370//378 393//379 +f 400//373 376//372 393//379 +f 400//373 393//379 422//380 +f 431//374 400//373 422//380 +f 431//374 422//380 457//381 +f 465//375 431//374 457//381 +f 465//375 457//381 490//382 +f 497//376 465//375 490//382 +f 497//376 490//382 521//383 +f 370//378 351//377 361//384 +f 370//378 361//384 382//385 +f 393//379 370//378 382//385 +f 393//379 382//385 408//386 +f 422//380 393//379 408//386 +f 422//380 408//386 439//387 +f 457//381 422//380 439//387 +f 457//381 439//387 473//388 +f 490//382 457//381 473//388 +f 490//382 473//388 504//389 +f 521//383 490//382 504//389 +f 521//383 504//389 535//390 +f 382//385 361//384 369//391 +f 382//385 369//391 392//392 +f 408//386 382//385 392//392 +f 408//386 392//392 421//393 +f 439//387 408//386 421//393 +f 439//387 421//393 456//394 +f 473//388 439//387 456//394 +f 473//388 456//394 489//395 +f 504//389 473//388 489//395 +f 504//389 489//395 520//396 +f 535//390 504//389 520//396 +f 535//390 520//396 550//397 +f 392//392 369//391 380//398 +f 392//392 380//398 407//399 +f 421//393 392//392 407//399 +f 421//393 407//399 438//400 +f 456//394 421//393 438//400 +f 456//394 438//400 472//401 +f 489//395 456//394 472//401 +f 489//395 472//401 503//402 +f 520//396 489//395 503//402 +f 520//396 503//402 534//403 +f 550//397 520//396 534//403 +f 550//397 534//403 563//404 +f 407//399 380//398 391//405 +f 407//399 391//405 420//406 +f 438//400 407//399 420//406 +f 438//400 420//406 455//407 +f 472//401 438//400 455//407 +f 472//401 455//407 488//408 +f 503//402 472//401 488//408 +f 503//402 488//408 519//409 +f 534//403 503//402 519//409 +f 534//403 519//409 549//410 +f 563//404 534//403 549//410 +f 563//404 549//410 578//411 +f 420//406 391//405 404//412 +f 420//406 404//412 437//413 +f 455//407 420//406 437//413 +f 455//407 437//413 471//414 +f 488//408 455//407 471//414 +f 488//408 471//414 502//415 +f 519//409 488//408 502//415 +f 519//409 502//415 533//416 +f 549//410 519//409 533//416 +f 549//410 533//416 562//417 +f 578//411 549//410 562//417 +f 578//411 562//417 589//418 +f 437//413 404//412 419//419 +f 437//413 419//419 454//420 +f 471//414 437//413 454//420 +f 471//414 454//420 487//421 +f 502//415 471//414 487//421 +f 502//415 487//421 518//422 +f 533//416 502//415 518//422 +f 533//416 518//422 548//423 +f 562//417 533//416 548//423 +f 562//417 548//423 577//424 +f 589//418 562//417 577//424 +f 589//418 577//424 594//425 +f 454//420 419//419 436//426 +f 454//420 436//426 470//427 +f 487//421 454//420 470//427 +f 487//421 470//427 501//428 +f 518//422 487//421 501//428 +f 518//422 501//428 532//429 +f 548//423 518//422 532//429 +f 548//423 532//429 555//430 +f 577//424 548//423 555//430 +f 577//424 555//430 567//431 +f 594//425 577//424 567//431 +f 594//425 567//431 582//432 +f 470//427 436//426 453//433 +f 470//427 453//433 486//434 +f 501//428 470//427 486//434 +f 501//428 486//434 508//435 +f 532//429 501//428 508//435 +f 532//429 508//435 525//436 +f 555//430 532//429 525//436 +f 555//430 525//436 538//437 +f 567//431 555//430 538//437 +f 567//431 538//437 554//438 +f 582//432 567//431 554//438 +f 582//432 554//438 566//33 +f 486//434 453//433 462//439 +f 486//434 462//439 477//440 +f 508//435 486//434 477//440 +f 508//435 477//440 494//441 +f 525//436 508//435 494//441 +f 525//436 494//441 507//442 +f 538//437 525//436 507//442 +f 538//437 507//442 524//443 +f 554//438 538//437 524//443 +f 554//438 524//443 537//444 +f 566//33 554//438 537//444 +f 566//33 537//444 553//31 +f 477//440 462//439 443//445 +f 477//440 443//445 461//446 +f 494//441 477//440 461//446 +f 494//441 461//446 476//447 +f 507//442 494//441 476//447 +f 507//442 476//447 493//448 +f 524//443 507//442 493//448 +f 524//443 493//448 506//449 +f 537//444 524//443 506//449 +f 537//444 506//449 523//450 +f 553//31 537//444 523//450 +f 553//31 523//450 536//451 +f 461//446 443//445 426//452 +f 461//446 426//452 442//453 +f 476//447 461//446 442//453 +f 476//447 442//453 460//454 +f 493//448 476//447 460//454 +f 493//448 460//454 475//455 +f 506//449 493//448 475//455 +f 506//449 475//455 492//456 +f 523//450 506//449 492//456 +f 523//450 492//456 505//457 +f 536//451 523//450 505//457 +f 536//451 505//457 522//458 +f 442//453 426//452 411//459 +f 442//453 411//459 425//460 +f 460//454 442//453 425//460 +f 460//454 425//460 441//461 +f 475//455 460//454 441//461 +f 475//455 441//461 459//462 +f 492//456 475//455 459//462 +f 492//456 459//462 474//463 +f 505//457 492//456 474//463 +f 505//457 474//463 491//464 +f 522//458 505//457 491//464 +f 522//458 491//464 499//465 +f 425//460 411//459 396//466 +f 425//460 396//466 410//467 +f 441//461 425//460 410//467 +f 441//461 410//467 424//468 +f 459//462 441//461 424//468 +f 459//462 424//468 440//469 +f 474//463 459//462 440//469 +f 474//463 440//469 458//470 +f 491//464 474//463 458//470 +f 491//464 458//470 467//471 +f 499//465 491//464 467//471 +f 499//465 467//471 466//472 +f 410//467 396//466 385//473 +f 410//467 385//473 395//474 +f 424//468 410//467 395//474 +f 424//468 395//474 409//475 +f 440//469 424//468 409//475 +f 440//469 409//475 423//476 +f 458//470 440//469 423//476 +f 458//470 423//476 433//477 +f 467//471 458//470 433//477 +f 467//471 433//477 432//478 +f 466//472 467//471 432//478 +f 466//472 432//478 434//479 +f 395//474 385//473 372//480 +f 395//474 372//480 383//481 +f 409//475 395//474 383//481 +f 409//475 383//481 394//482 +f 423//476 409//475 394//482 +f 423//476 394//482 402//483 +f 433//477 423//476 402//483 +f 433//477 402//483 401//484 +f 432//478 433//477 401//484 +f 432//478 401//484 403//485 +f 434//479 432//478 403//485 +f 434//479 403//485 417//486 +f 383//481 372//480 362//487 +f 383//481 362//487 371//488 +f 394//482 383//481 371//488 +f 394//482 371//488 378//489 +f 402//483 394//482 378//489 +f 402//483 378//489 377//490 +f 401//484 402//483 377//490 +f 401//484 377//490 379//491 +f 403//485 401//484 379//491 +f 403//485 379//491 390//492 +f 417//486 403//485 390//492 +f 417//486 390//492 416//493 +f 371//488 362//487 352//494 +f 371//488 352//494 358//495 +f 378//489 371//488 358//495 +f 378//489 358//495 357//496 +f 377//490 378//489 357//496 +f 377//490 357//496 359//497 +f 379//491 377//490 359//497 +f 379//491 359//497 367//498 +f 390//492 379//491 367//498 +f 390//492 367//498 389//499 +f 416//493 390//492 389//499 +f 416//493 389//499 415//500 +f 358//495 352//494 345//501 +f 358//495 345//501 340//502 +f 357//496 358//495 340//502 +f 357//496 340//502 341//503 +f 359//497 357//496 341//503 +f 359//497 341//503 349//504 +f 367//498 359//497 349//504 +f 367//498 349//504 366//505 +f 389//499 367//498 366//505 +f 389//499 366//505 388//506 +f 415//500 389//499 388//506 +f 415//500 388//506 414//507 +f 340//502 345//501 335//508 +f 340//502 335//508 330//509 +f 341//503 340//502 330//509 +f 341//503 330//509 336//510 +f 349//504 341//503 336//510 +f 349//504 336//510 348//511 +f 366//505 349//504 348//511 +f 366//505 348//511 365//512 +f 388//506 366//505 365//512 +f 388//506 365//512 387//513 +f 414//507 388//506 387//513 +f 414//507 387//513 413//514 +f 330//509 335//508 327//350 +f 327//350 326//349 330//509 +f 330//509 326//349 336//510 +f 336//510 326//349 333//353 +f 348//511 336//510 333//353 +f 348//511 333//353 347//355 +f 365//512 348//511 347//355 +f 365//512 347//355 364//357 +f 387//513 365//512 364//357 +f 387//513 364//357 386//359 +f 413//514 387//513 386//359 +f 413//514 386//359 412//361 +f 445//515 412//361 429//362 +f 445//515 429//362 463//516 +f 478//517 445//515 463//516 +f 478//517 463//516 495//518 +f 509//176 478//517 495//518 +f 509//176 495//518 526//519 +f 463//516 429//362 464//369 +f 463//516 464//369 496//520 +f 495//518 463//516 496//520 +f 495//518 496//520 527//521 +f 526//519 495//518 527//521 +f 526//519 527//521 557//522 +f 556//523 526//519 557//522 +f 556//523 557//522 583//524 +f 595//202 556//523 583//524 +f 595//202 583//524 611//525 +f 621//526 595//202 611//525 +f 621//526 611//525 638//527 +f 496//520 464//369 497//376 +f 496//520 497//376 528//528 +f 527//521 496//520 528//528 +f 527//521 528//528 558//529 +f 557//522 527//521 558//529 +f 557//522 558//529 584//530 +f 583//524 557//522 584//530 +f 583//524 584//530 612//531 +f 611//525 583//524 612//531 +f 611//525 612//531 639//532 +f 638//527 611//525 639//532 +f 638//527 639//532 664//533 +f 528//528 497//376 521//383 +f 528//528 521//383 551//534 +f 558//529 528//528 551//534 +f 558//529 551//534 580//535 +f 584//530 558//529 580//535 +f 584//530 580//535 608//536 +f 612//531 584//530 608//536 +f 612//531 608//536 634//537 +f 639//532 612//531 634//537 +f 639//532 634//537 661//538 +f 664//533 639//532 661//538 +f 664//533 661//538 688//539 +f 551//534 521//383 535//390 +f 551//534 535//390 564//540 +f 580//535 551//534 564//540 +f 580//535 564//540 591//541 +f 608//536 580//535 591//541 +f 608//536 591//541 618//542 +f 634//537 608//536 618//542 +f 634//537 618//542 644//543 +f 661//538 634//537 644//543 +f 661//538 644//543 670//544 +f 688//539 661//538 670//544 +f 688//539 670//544 698//545 +f 564//540 535//390 550//397 +f 564//540 550//397 579//546 +f 591//541 564//540 579//546 +f 591//541 579//546 607//547 +f 618//542 591//541 607//547 +f 618//542 607//547 633//548 +f 644//543 618//542 633//548 +f 644//543 633//548 660//549 +f 670//544 644//543 660//549 +f 670//544 660//549 687//550 +f 698//545 670//544 687//550 +f 698//545 687//550 717//551 +f 579//546 550//397 563//404 +f 579//546 563//404 590//552 +f 607//547 579//546 590//552 +f 607//547 590//552 617//553 +f 633//548 607//547 617//553 +f 633//548 617//553 643//554 +f 660//549 633//548 643//554 +f 660//549 643//554 669//555 +f 687//550 660//549 669//555 +f 687//550 669//555 697//556 +f 717//551 687//550 697//556 +f 717//551 697//556 727//557 +f 590//552 563//404 578//411 +f 590//552 578//411 606//558 +f 617//553 590//552 606//558 +f 617//553 606//558 632//559 +f 643//554 617//553 632//559 +f 643//554 632//559 659//560 +f 669//555 643//554 659//560 +f 669//555 659//560 673//561 +f 697//556 669//555 673//561 +f 697//556 673//561 700//562 +f 727//557 697//556 700//562 +f 727//557 700//562 699//563 +f 606//558 578//411 589//418 +f 606//558 589//418 616//564 +f 632//559 606//558 616//564 +f 632//559 616//564 637//565 +f 659//560 632//559 637//565 +f 659//560 637//565 647//566 +f 673//561 659//560 647//566 +f 673//561 647//566 672//567 +f 700//562 673//561 672//567 +f 700//562 672//567 671//568 +f 699//563 700//562 671//568 +f 699//563 671//568 689//569 +f 616//564 589//418 594//425 +f 616//564 594//425 610//570 +f 637//565 616//564 610//570 +f 637//565 610//570 620//571 +f 647//566 637//565 620//571 +f 647//566 620//571 646//572 +f 672//567 647//566 646//572 +f 672//567 646//572 645//573 +f 671//568 672//567 645//573 +f 671//568 645//573 662//574 +f 689//569 671//568 662//574 +f 689//569 662//574 668//575 +f 610//570 594//425 582//432 +f 610//570 582//432 593//3 +f 620//571 610//570 593//3 +f 620//571 593//3 636//89 +f 646//572 620//571 636//89 +f 646//572 636//89 619//576 +f 645//573 646//572 619//576 +f 645//573 619//576 635//577 +f 662//574 645//573 635//577 +f 662//574 635//577 642//578 +f 668//575 662//574 642//578 +f 668//575 642//578 641//579 +f 593//3 582//432 566//33 +f 619//576 636//89 592//57 +f 619//576 592//57 609//580 +f 635//577 619//576 609//580 +f 635//577 609//580 615//581 +f 642//578 635//577 615//581 +f 642//578 615//581 614//582 +f 641//579 642//578 614//582 +f 592//57 565//56 581//583 +f 609//580 592//57 581//583 +f 609//580 581//583 587//584 +f 615//581 609//580 587//584 +f 615//581 587//584 586//585 +f 614//582 615//581 586//585 +f 614//582 586//585 588//586 +f 565//56 553//31 536//451 +f 565//56 536//451 552//587 +f 581//583 565//56 552//587 +f 581//583 552//587 560//588 +f 587//584 581//583 560//588 +f 587//584 560//588 559//589 +f 586//585 587//584 559//589 +f 586//585 559//589 561//590 +f 588//586 586//585 561//590 +f 588//586 561//590 576//591 +f 605//592 588//586 576//591 +f 605//592 576//591 604//593 +f 552//587 536//451 522//458 +f 552//587 522//458 530//594 +f 560//588 552//587 530//594 +f 560//588 530//594 529//595 +f 559//589 560//588 529//595 +f 559//589 529//595 531//596 +f 561//590 559//589 531//596 +f 561//590 531//596 547//597 +f 576//591 561//590 547//597 +f 576//591 547//597 575//598 +f 604//593 576//591 575//598 +f 604//593 575//598 603//599 +f 530//594 522//458 499//465 +f 530//594 499//465 498//600 +f 529//595 530//594 498//600 +f 529//595 498//600 500//601 +f 531//596 529//595 500//601 +f 531//596 500//601 517//602 +f 547//597 531//596 517//602 +f 547//597 517//602 546//603 +f 575//598 547//597 546//603 +f 575//598 546//603 574//604 +f 603//599 575//598 574//604 +f 603//599 574//604 602//605 +f 498//600 499//465 466//472 +f 498//600 466//472 468//606 +f 500//601 498//600 468//606 +f 500//601 468//606 485//607 +f 517//602 500//601 485//607 +f 517//602 485//607 516//608 +f 546//603 517//602 516//608 +f 546//603 516//608 545//609 +f 574//604 546//603 545//609 +f 574//604 545//609 573//610 +f 602//605 574//604 573//610 +f 602//605 573//610 601//611 +f 468//606 466//472 434//479 +f 468//606 434//479 451//612 +f 485//607 468//606 451//612 +f 485//607 451//612 484//613 +f 516//608 485//607 484//613 +f 516//608 484//613 515//614 +f 545//609 516//608 515//614 +f 545//609 515//614 544//615 +f 573//610 545//609 544//615 +f 573//610 544//615 572//616 +f 601//611 573//610 572//616 +f 601//611 572//616 600//617 +f 451//612 434//479 417//486 +f 451//612 417//486 450//618 +f 484//613 451//612 450//618 +f 484//613 450//618 483//619 +f 515//614 484//613 483//619 +f 515//614 483//619 514//620 +f 544//615 515//614 514//620 +f 544//615 514//620 543//621 +f 572//616 544//615 543//621 +f 572//616 543//621 571//622 +f 600//617 572//616 571//622 +f 600//617 571//622 599//623 +f 450//618 417//486 416//493 +f 450//618 416//493 449//624 +f 483//619 450//618 449//624 +f 483//619 449//624 482//625 +f 514//620 483//619 482//625 +f 514//620 482//625 513//626 +f 543//621 514//620 513//626 +f 543//621 513//626 542//627 +f 571//622 543//621 542//627 +f 571//622 542//627 570//628 +f 599//623 571//622 570//628 +f 599//623 570//628 598//629 +f 449//624 416//493 415//500 +f 449//624 415//500 448//630 +f 482//625 449//624 448//630 +f 482//625 448//630 481//631 +f 513//626 482//625 481//631 +f 513//626 481//631 512//632 +f 542//627 513//626 512//632 +f 542//627 512//632 541//633 +f 570//628 542//627 541//633 +f 570//628 541//633 569//634 +f 598//629 570//628 569//634 +f 598//629 569//634 597//635 +f 448//630 415//500 414//507 +f 448//630 414//507 447//636 +f 481//631 448//630 447//636 +f 481//631 447//636 480//637 +f 512//632 481//631 480//637 +f 512//632 480//637 511//638 +f 541//633 512//632 511//638 +f 541//633 511//638 540//639 +f 569//634 541//633 540//639 +f 569//634 540//639 568//640 +f 597//635 569//634 568//640 +f 597//635 568//640 596//641 +f 447//636 414//507 413//514 +f 447//636 413//514 446//642 +f 480//637 447//636 446//642 +f 480//637 446//642 479//643 +f 511//638 480//637 479//643 +f 511//638 479//643 510//644 +f 540//639 511//638 510//644 +f 540//639 510//644 539//175 +f 568//640 540//639 539//175 +f 568//640 539//175 585//249 +f 596//641 568//640 585//249 +f 596//641 585//249 613//248 +f 446//642 413//514 412//361 +f 446//642 412//361 445//515 +f 479//643 446//642 445//515 +f 479//643 445//515 478//517 +f 510//644 479//643 478//517 +f 510//644 478//517 509//176 +f 539//175 510//644 509//176 +f 691//228 648//227 674//645 +f 702//646 691//228 674//645 +f 702//646 674//645 701//647 +f 731//648 702//646 701//647 +f 731//648 701//647 730//649 +f 759//650 731//648 730//649 +f 759//650 730//649 758//651 +f 786//652 759//650 758//651 +f 786//652 758//651 785//653 +f 648//227 621//526 638//527 +f 648//227 638//527 663//654 +f 674//645 648//227 663//654 +f 674//645 663//654 690//655 +f 701//647 674//645 690//655 +f 701//647 690//655 720//656 +f 730//649 701//647 720//656 +f 730//649 720//656 749//657 +f 758//651 730//649 749//657 +f 758//651 749//657 777//658 +f 785//653 758//651 777//658 +f 785//653 777//658 805//659 +f 663//654 638//527 664//533 +f 663//654 664//533 692//660 +f 690//655 663//654 692//660 +f 690//655 692//660 721//661 +f 720//656 690//655 721//661 +f 720//656 721//661 750//662 +f 749//657 720//656 750//662 +f 749//657 750//662 778//663 +f 777//658 749//657 778//663 +f 777//658 778//663 806//664 +f 805//659 777//658 806//664 +f 805//659 806//664 833//665 +f 692//660 664//533 688//539 +f 692//660 688//539 718//666 +f 721//661 692//660 718//666 +f 721//661 718//666 747//667 +f 750//662 721//661 747//667 +f 750//662 747//667 775//668 +f 778//663 750//662 775//668 +f 778//663 775//668 803//669 +f 806//664 778//663 803//669 +f 806//664 803//669 831//670 +f 833//665 806//664 831//670 +f 833//665 831//670 838//671 +f 718//666 688//539 698//545 +f 718//666 698//545 728//672 +f 747//667 718//666 728//672 +f 747//667 728//672 756//673 +f 775//668 747//667 756//673 +f 775//668 756//673 784//674 +f 803//669 775//668 784//674 +f 803//669 784//674 804//675 +f 831//670 803//669 804//675 +f 831//670 804//675 811//676 +f 838//671 831//670 811//676 +f 838//671 811//676 830//677 +f 728//672 698//545 717//551 +f 728//672 717//551 746//678 +f 756//673 728//672 746//678 +f 756//673 746//678 757//679 +f 784//674 756//673 757//679 +f 784//674 757//679 776//680 +f 804//675 784//674 776//680 +f 804//675 776//680 783//681 +f 811//676 804//675 783//681 +f 811//676 783//681 802//682 +f 830//677 811//676 802//682 +f 830//677 802//682 810//683 +f 746//678 717//551 727//557 +f 746//678 727//557 729//684 +f 757//679 746//678 729//684 +f 757//679 729//684 748//685 +f 776//680 757//679 748//685 +f 776//680 748//685 755//686 +f 783//681 776//680 755//686 +f 783//681 755//686 774//687 +f 802//682 783//681 774//687 +f 802//682 774//687 782//688 +f 810//683 802//682 782//688 +f 810//683 782//688 809//689 +f 729//684 727//557 699//563 +f 729//684 699//563 719//690 +f 748//685 729//684 719//690 +f 748//685 719//690 726//691 +f 755//686 748//685 726//691 +f 755//686 726//691 745//692 +f 774//687 755//686 745//692 +f 774//687 745//692 754//693 +f 782//688 774//687 754//693 +f 782//688 754//693 781//694 +f 809//689 782//688 781//694 +f 809//689 781//694 780//695 +f 719//690 699//563 689//569 +f 719//690 689//569 696//696 +f 726//691 719//690 696//696 +f 726//691 696//696 716//697 +f 745//692 726//691 716//697 +f 745//692 716//697 725//698 +f 754//693 745//692 725//698 +f 754//693 725//698 753//699 +f 781//694 754//693 753//699 +f 781//694 753//699 752//700 +f 780//695 781//694 752//700 +f 780//695 752//700 773//701 +f 696//696 689//569 668//575 +f 696//696 668//575 686//702 +f 716//697 696//696 686//702 +f 716//697 686//702 695//703 +f 725//698 716//697 695//703 +f 725//698 695//703 724//704 +f 753//699 725//698 724//704 +f 753//699 724//704 723//705 +f 752//700 753//699 723//705 +f 752//700 723//705 744//706 +f 773//701 752//700 744//706 +f 773//701 744//706 772//707 +f 686//702 668//575 641//579 +f 686//702 641//579 667//708 +f 695//703 686//702 667//708 +f 695//703 667//708 715//160 +f 724//704 695//703 715//160 +f 724//704 715//160 694//709 +f 723//705 724//704 694//709 +f 723//705 694//709 714//710 +f 744//706 723//705 714//710 +f 744//706 714//710 743//711 +f 772//707 744//706 743//711 +f 772//707 743//711 771//712 +f 694//709 715//160 666//713 +f 694//709 666//713 685//714 +f 714//710 694//709 685//714 +f 714//710 685//714 713//715 +f 743//711 714//710 713//715 +f 743//711 713//715 742//716 +f 771//712 743//711 742//716 +f 771//712 742//716 770//717 +f 666//713 631//152 658//718 +f 685//714 666//713 658//718 +f 685//714 658//718 684//719 +f 713//715 685//714 684//719 +f 713//715 684//719 712//720 +f 742//716 713//715 712//720 +f 742//716 712//720 741//721 +f 770//717 742//716 741//721 +f 770//717 741//721 769//722 +f 631//152 605//592 604//593 +f 631//152 604//593 630//723 +f 658//718 631//152 630//723 +f 658//718 630//723 657//724 +f 684//719 658//718 657//724 +f 684//719 657//724 683//725 +f 712//720 684//719 683//725 +f 712//720 683//725 711//726 +f 741//721 712//720 711//726 +f 741//721 711//726 740//727 +f 769//722 741//721 740//727 +f 769//722 740//727 768//728 +f 630//723 604//593 603//599 +f 630//723 603//599 629//729 +f 657//724 630//723 629//729 +f 657//724 629//729 656//730 +f 683//725 657//724 656//730 +f 683//725 656//730 682//731 +f 711//726 683//725 682//731 +f 711//726 682//731 710//732 +f 740//727 711//726 710//732 +f 740//727 710//732 739//733 +f 768//728 740//727 739//733 +f 768//728 739//733 767//734 +f 629//729 603//599 602//605 +f 629//729 602//605 628//735 +f 656//730 629//729 628//735 +f 656//730 628//735 655//736 +f 682//731 656//730 655//736 +f 682//731 655//736 681//737 +f 710//732 682//731 681//737 +f 710//732 681//737 709//738 +f 739//733 710//732 709//738 +f 739//733 709//738 738//739 +f 767//734 739//733 738//739 +f 767//734 738//739 766//740 +f 628//735 602//605 601//611 +f 628//735 601//611 627//741 +f 655//736 628//735 627//741 +f 655//736 627//741 654//742 +f 681//737 655//736 654//742 +f 681//737 654//742 680//743 +f 709//738 681//737 680//743 +f 709//738 680//743 708//744 +f 738//739 709//738 708//744 +f 738//739 708//744 737//745 +f 766//740 738//739 737//745 +f 766//740 737//745 765//746 +f 627//741 601//611 600//617 +f 627//741 600//617 626//747 +f 654//742 627//741 626//747 +f 654//742 626//747 653//748 +f 680//743 654//742 653//748 +f 680//743 653//748 679//749 +f 708//744 680//743 679//749 +f 708//744 679//749 707//750 +f 737//745 708//744 707//750 +f 737//745 707//750 736//751 +f 765//746 737//745 736//751 +f 765//746 736//751 764//752 +f 626//747 600//617 599//623 +f 626//747 599//623 625//753 +f 653//748 626//747 625//753 +f 653//748 625//753 652//754 +f 679//749 653//748 652//754 +f 679//749 652//754 678//755 +f 707//750 679//749 678//755 +f 707//750 678//755 706//756 +f 736//751 707//750 706//756 +f 736//751 706//756 735//757 +f 764//752 736//751 735//757 +f 764//752 735//757 763//758 +f 625//753 599//623 598//629 +f 625//753 598//629 624//759 +f 652//754 625//753 624//759 +f 652//754 624//759 651//760 +f 678//755 652//754 651//760 +f 678//755 651//760 677//761 +f 706//756 678//755 677//761 +f 706//756 677//761 705//762 +f 735//757 706//756 705//762 +f 735//757 705//762 734//763 +f 763//758 735//757 734//763 +f 763//758 734//763 762//764 +f 624//759 598//629 597//635 +f 624//759 597//635 623//765 +f 651//760 624//759 623//765 +f 651//760 623//765 650//766 +f 677//761 651//760 650//766 +f 677//761 650//766 676//767 +f 705//762 677//761 676//767 +f 705//762 676//767 704//768 +f 734//763 705//762 704//768 +f 734//763 704//768 733//769 +f 762//764 734//763 733//769 +f 762//764 733//769 761//770 +f 623//765 597//635 596//641 +f 623//765 596//641 622//771 +f 650//766 623//765 622//771 +f 650//766 622//771 649//772 +f 676//767 650//766 649//772 +f 676//767 649//772 675//773 +f 704//768 676//767 675//773 +f 704//768 675//773 703//774 +f 733//769 704//768 703//774 +f 733//769 703//774 732//775 +f 761//770 733//769 732//775 +f 761//770 732//775 760//776 +f 622//771 596//641 613//248 +f 622//771 613//248 640//777 +f 649//772 622//771 640//777 +f 649//772 640//777 665//778 +f 675//773 649//772 665//778 +f 675//773 665//778 693//779 +f 703//774 675//773 693//779 +f 703//774 693//779 722//780 +f 732//775 703//774 722//780 +f 732//775 722//780 751//781 +f 760//776 732//775 751//781 +f 760//776 751//781 779//782 +f 693//779 665//778 691//228 +f 693//779 691//228 702//646 +f 722//780 693//779 702//646 +f 722//780 702//646 731//648 +f 751//781 722//780 731//648 +f 751//781 731//648 759//650 +f 779//782 751//781 759//650 +f 779//782 759//650 786//652 +f 917//783 918//784 913//785 +f 892//786 917//783 913//785 +f 892//786 913//785 887//787 +f 866//788 892//786 887//787 +f 866//788 887//787 861//789 +f 840//790 866//788 861//789 +f 840//790 861//789 834//791 +f 813//792 840//790 834//791 +f 813//792 834//791 807//793 +f 786//652 813//792 807//793 +f 786//652 807//793 779//782 +f 913//785 918//784 893//794 +f 887//787 913//785 893//794 +f 887//787 893//794 867//795 +f 861//789 887//787 867//795 +f 861//789 867//795 841//796 +f 834//791 861//789 841//796 +f 834//791 841//796 814//797 +f 807//793 834//791 814//797 +f 807//793 814//797 787//798 +f 779//782 807//793 787//798 +f 779//782 787//798 760//776 +f 893//794 918//784 894//799 +f 867//795 893//794 894//799 +f 867//795 894//799 868//800 +f 841//796 867//795 868//800 +f 841//796 868//800 842//801 +f 814//797 841//796 842//801 +f 814//797 842//801 815//802 +f 787//798 814//797 815//802 +f 787//798 815//802 788//803 +f 760//776 787//798 788//803 +f 760//776 788//803 761//770 +f 894//799 918//784 895//804 +f 868//800 894//799 895//804 +f 868//800 895//804 869//805 +f 842//801 868//800 869//805 +f 842//801 869//805 843//806 +f 815//802 842//801 843//806 +f 815//802 843//806 816//807 +f 788//803 815//802 816//807 +f 788//803 816//807 789//808 +f 761//770 788//803 789//808 +f 761//770 789//808 762//764 +f 895//804 918//784 896//809 +f 869//805 895//804 896//809 +f 869//805 896//809 870//810 +f 843//806 869//805 870//810 +f 843//806 870//810 844//811 +f 816//807 843//806 844//811 +f 816//807 844//811 817//812 +f 789//808 816//807 817//812 +f 789//808 817//812 790//813 +f 762//764 789//808 790//813 +f 762//764 790//813 763//758 +f 896//809 918//784 897//814 +f 870//810 896//809 897//814 +f 870//810 897//814 871//815 +f 844//811 870//810 871//815 +f 844//811 871//815 845//816 +f 817//812 844//811 845//816 +f 817//812 845//816 818//817 +f 790//813 817//812 818//817 +f 790//813 818//817 791//818 +f 763//758 790//813 791//818 +f 763//758 791//818 764//752 +f 897//814 918//784 898//819 +f 871//815 897//814 898//819 +f 871//815 898//819 872//820 +f 845//816 871//815 872//820 +f 845//816 872//820 846//821 +f 818//817 845//816 846//821 +f 818//817 846//821 819//822 +f 791//818 818//817 819//822 +f 791//818 819//822 792//823 +f 764//752 791//818 792//823 +f 764//752 792//823 765//746 +f 898//819 918//784 899//824 +f 872//820 898//819 899//824 +f 872//820 899//824 873//825 +f 846//821 872//820 873//825 +f 846//821 873//825 847//826 +f 819//822 846//821 847//826 +f 819//822 847//826 820//827 +f 792//823 819//822 820//827 +f 792//823 820//827 793//828 +f 765//746 792//823 793//828 +f 765//746 793//828 766//740 +f 899//824 918//784 900//829 +f 873//825 899//824 900//829 +f 873//825 900//829 874//830 +f 847//826 873//825 874//830 +f 847//826 874//830 848//831 +f 820//827 847//826 848//831 +f 820//827 848//831 821//832 +f 793//828 820//827 821//832 +f 793//828 821//832 794//833 +f 766//740 793//828 794//833 +f 766//740 794//833 767//734 +f 900//829 918//784 901//834 +f 874//830 900//829 901//834 +f 874//830 901//834 875//835 +f 848//831 874//830 875//835 +f 848//831 875//835 849//836 +f 821//832 848//831 849//836 +f 821//832 849//836 822//837 +f 794//833 821//832 822//837 +f 794//833 822//837 795//838 +f 767//734 794//833 795//838 +f 767//734 795//838 768//728 +f 901//834 918//784 902//839 +f 875//835 901//834 902//839 +f 875//835 902//839 876//840 +f 849//836 875//835 876//840 +f 849//836 876//840 850//841 +f 822//837 849//836 850//841 +f 822//837 850//841 823//842 +f 795//838 822//837 823//842 +f 795//838 823//842 796//843 +f 768//728 795//838 796//843 +f 768//728 796//843 769//722 +f 902//839 918//784 903//844 +f 876//840 902//839 903//844 +f 876//840 903//844 877//845 +f 850//841 876//840 877//845 +f 850//841 877//845 851//846 +f 823//842 850//841 851//846 +f 823//842 851//846 824//847 +f 796//843 823//842 824//847 +f 796//843 824//847 797//848 +f 769//722 796//843 797//848 +f 769//722 797//848 770//717 +f 903//844 918//784 904//849 +f 877//845 903//844 904//849 +f 877//845 904//849 878//850 +f 851//846 877//845 878//850 +f 851//846 878//850 852//851 +f 824//847 851//846 852//851 +f 824//847 852//851 825//852 +f 797//848 824//847 825//852 +f 797//848 825//852 798//853 +f 770//717 797//848 798//853 +f 770//717 798//853 771//712 +f 904//849 918//784 905//854 +f 878//850 904//849 905//854 +f 878//850 905//854 879//855 +f 852//851 878//850 879//855 +f 852//851 879//855 853//856 +f 825//852 852//851 853//856 +f 825//852 853//856 826//857 +f 798//853 825//852 826//857 +f 798//853 826//857 799//858 +f 771//712 798//853 799//858 +f 771//712 799//858 772//707 +f 905//854 918//784 906//859 +f 879//855 905//854 906//859 +f 879//855 906//859 880//860 +f 853//856 879//855 880//860 +f 853//856 880//860 854//861 +f 826//857 853//856 854//861 +f 826//857 854//861 827//862 +f 799//858 826//857 827//862 +f 799//858 827//862 800//863 +f 772//707 799//858 800//863 +f 772//707 800//863 773//701 +f 906//859 918//784 907//864 +f 880//860 906//859 907//864 +f 880//860 907//864 881//865 +f 854//861 880//860 881//865 +f 854//861 881//865 855//866 +f 827//862 854//861 855//866 +f 827//862 855//866 828//867 +f 800//863 827//862 828//867 +f 800//863 828//867 801//868 +f 773//701 800//863 801//868 +f 773//701 801//868 780//695 +f 907//864 918//784 908//869 +f 881//865 907//864 908//869 +f 881//865 908//869 882//870 +f 855//866 881//865 882//870 +f 855//866 882//870 856//871 +f 828//867 855//866 856//871 +f 828//867 856//871 829//872 +f 801//868 828//867 829//872 +f 801//868 829//872 808//873 +f 780//695 801//868 808//873 +f 780//695 808//873 809//689 +f 908//869 918//784 909//874 +f 882//870 908//869 909//874 +f 882//870 909//874 883//875 +f 856//871 882//870 883//875 +f 856//871 883//875 857//876 +f 829//872 856//871 857//876 +f 829//872 857//876 836//877 +f 808//873 829//872 836//877 +f 808//873 836//877 835//878 +f 809//689 808//873 835//878 +f 809//689 835//878 810//683 +f 909//874 918//784 910//879 +f 883//875 909//874 910//879 +f 883//875 910//879 884//880 +f 857//876 883//875 884//880 +f 857//876 884//880 863//881 +f 836//877 857//876 863//881 +f 836//877 863//881 862//882 +f 835//878 836//877 862//882 +f 835//878 862//882 837//883 +f 810//683 835//878 837//883 +f 810//683 837//883 830//677 +f 910//879 918//784 911//884 +f 884//880 910//879 911//884 +f 884//880 911//884 889//885 +f 863//881 884//880 889//885 +f 863//881 889//885 888//886 +f 862//882 863//881 888//886 +f 862//882 888//886 864//887 +f 837//883 862//882 864//887 +f 837//883 864//887 858//888 +f 830//677 837//883 858//888 +f 830//677 858//888 838//671 +f 911//884 918//784 915//889 +f 889//885 911//884 915//889 +f 889//885 915//889 914//890 +f 888//886 889//885 914//890 +f 888//886 914//890 890//891 +f 864//887 888//886 890//891 +f 864//887 890//891 885//892 +f 858//888 864//887 885//892 +f 858//888 885//892 859//893 +f 838//671 858//888 859//893 +f 838//671 859//893 833//665 +f 915//889 918//784 919//894 +f 914//890 915//889 919//894 +f 914//890 919//894 912//895 +f 890//891 914//890 912//895 +f 890//891 912//895 886//896 +f 885//892 890//891 886//896 +f 885//892 886//896 860//897 +f 859//893 885//892 860//897 +f 859//893 860//897 832//898 +f 833//665 859//893 832//898 +f 833//665 832//898 805//659 +f 919//894 918//784 916//899 +f 912//895 919//894 916//899 +f 912//895 916//899 891//900 +f 886//896 912//895 891//900 +f 886//896 891//900 865//901 +f 860//897 886//896 865//901 +f 860//897 865//901 839//902 +f 832//898 860//897 839//902 +f 832//898 839//902 812//903 +f 805//659 832//898 812//903 +f 805//659 812//903 785//653 +f 916//899 918//784 917//783 +f 891//900 916//899 917//783 +f 891//900 917//783 892//786 +f 865//901 891//900 892//786 +f 865//901 892//786 866//788 +f 839//902 865//901 866//788 +f 839//902 866//788 840//790 +f 812//903 839//902 840//790 +f 812//903 840//790 813//792 +f 785//653 812//903 813//792 +f 785//653 813//792 786//652 +f 404//412 1267//904 1268//905 +f 384//906 373//907 372//480 +f 346//908 345//501 352//494 +f 435//909 436//426 419//419 +f 331//910 327//350 335//508 +f 462//439 453//433 1265//911 +f 920//912 921//913 922//914 +f 920//912 922//914 923//915 +f 923//915 922//914 927//916 +f 923//915 927//916 933//917 +f 933//917 927//916 940//918 +f 933//917 940//918 949//919 +f 949//919 940//918 959//920 +f 949//919 959//920 971//921 +f 971//921 959//920 984//922 +f 971//921 984//922 999//923 +f 999//923 984//922 1011//924 +f 999//923 1011//924 1027//925 +f 1027//925 1011//924 1042//926 +f 1027//925 1042//926 1059//927 +f 1059//927 1042//926 1077//928 +f 1059//927 1077//928 1095//929 +f 1095//929 1077//928 1110//930 +f 1095//929 1110//930 1129//931 +f 1129//931 1110//930 1144//932 +f 1129//931 1144//932 1163//933 +f 1163//933 1144//932 1179//934 +f 1163//933 1179//934 1196//935 +f 1196//935 1179//934 1210//936 +f 1196//935 1210//936 1220//937 +f 1220//937 1210//936 1212//938 +f 1220//937 1212//938 1201//939 +f 1201//939 1212//938 1181//940 +f 1201//939 1181//940 1169//941 +f 1169//941 1181//940 1147//942 +f 1169//941 1147//942 1135//943 +f 1135//943 1147//942 1113//944 +f 1135//943 1113//944 1102//945 +f 1102//945 1113//944 1081//946 +f 1102//945 1081//946 1065//947 +f 1065//947 1081//946 1046//948 +f 1065//947 1046//948 1032//949 +f 1032//949 1046//948 1016//950 +f 1032//949 1016//950 1003//951 +f 1003//951 1016//950 988//952 +f 1003//951 988//952 974//953 +f 974//953 988//952 962//954 +f 974//953 962//954 951//955 +f 951//955 962//954 942//956 +f 951//955 942//956 934//957 +f 934//957 942//956 928//958 +f 934//957 928//958 924//959 +f 924//959 928//958 921//913 +f 921//913 920//912 924//959 +f 926//960 920//912 923//915 +f 926//960 923//915 932//961 +f 938//962 926//960 932//961 +f 938//962 932//961 947//963 +f 956//964 938//962 947//963 +f 956//964 947//963 968//965 +f 980//966 956//964 968//965 +f 980//966 968//965 995//967 +f 1006//968 980//966 995//967 +f 1006//968 995//967 1022//969 +f 1036//970 1006//968 1022//969 +f 1036//970 1022//969 1053//971 +f 932//961 923//915 933//917 +f 932//961 933//917 948//972 +f 947//963 932//961 948//972 +f 947//963 948//972 969//973 +f 968//965 947//963 969//973 +f 968//965 969//973 996//974 +f 995//967 968//965 996//974 +f 995//967 996//974 1023//975 +f 1022//969 995//967 1023//975 +f 1022//969 1023//975 1054//976 +f 1053//971 1022//969 1054//976 +f 1053//971 1054//976 1089//977 +f 948//972 933//917 949//919 +f 948//972 949//919 970//978 +f 969//973 948//972 970//978 +f 969//973 970//978 997//979 +f 996//974 969//973 997//979 +f 996//974 997//979 1024//980 +f 1023//975 996//974 1024//980 +f 1023//975 1024//980 1055//981 +f 1054//976 1023//975 1055//981 +f 1054//976 1055//981 1090//982 +f 1089//977 1054//976 1090//982 +f 1089//977 1090//982 1109//983 +f 970//978 949//919 971//921 +f 970//978 971//921 998//984 +f 997//979 970//978 998//984 +f 997//979 998//984 1025//985 +f 1024//980 997//979 1025//985 +f 1024//980 1025//985 1056//986 +f 1055//981 1024//980 1056//986 +f 1055//981 1056//986 1091//987 +f 1090//982 1055//981 1091//987 +f 1090//982 1091//987 1124//988 +f 1109//983 1090//982 1124//988 +f 1109//983 1124//988 1122//989 +f 998//984 971//921 999//923 +f 998//984 999//923 1026//990 +f 1025//985 998//984 1026//990 +f 1025//985 1026//990 1057//991 +f 1056//986 1025//985 1057//991 +f 1056//986 1057//991 1092//992 +f 1091//987 1056//986 1092//992 +f 1091//987 1092//992 1125//993 +f 1124//988 1091//987 1125//993 +f 1124//988 1125//993 1156//994 +f 1122//989 1124//988 1156//994 +f 1122//989 1156//994 1142//995 +f 1026//990 999//923 1027//925 +f 1026//990 1027//925 1058//996 +f 1057//991 1026//990 1058//996 +f 1057//991 1058//996 1093//997 +f 1092//992 1057//991 1093//997 +f 1092//992 1093//997 1126//998 +f 1125//993 1092//992 1126//998 +f 1125//993 1126//998 1159//999 +f 1156//994 1125//993 1159//999 +f 1156//994 1159//999 1176//1000 +f 1142//995 1156//994 1176//1000 +f 1142//995 1176//1000 1157//1001 +f 1058//996 1027//925 1059//927 +f 1058//996 1059//927 1094//1002 +f 1093//997 1058//996 1094//1002 +f 1093//997 1094//1002 1127//1003 +f 1126//998 1093//997 1127//1003 +f 1126//998 1127//1003 1160//1004 +f 1159//999 1126//998 1160//1004 +f 1159//999 1160//1004 1192//1005 +f 1176//1000 1159//999 1192//1005 +f 1176//1000 1192//1005 1189//1006 +f 1157//1001 1176//1000 1189//1006 +f 1157//1001 1189//1006 1178//1007 +f 1094//1002 1059//927 1095//929 +f 1094//1002 1095//929 1128//1008 +f 1127//1003 1094//1002 1128//1008 +f 1127//1003 1128//1008 1161//1009 +f 1160//1004 1127//1003 1161//1009 +f 1160//1004 1161//1009 1193//1010 +f 1192//1005 1160//1004 1193//1010 +f 1192//1005 1193//1010 1215//1011 +f 1189//1006 1192//1005 1215//1011 +f 1189//1006 1215//1011 1207//1012 +f 1178//1007 1189//1006 1207//1012 +f 1178//1007 1207//1012 1191//1013 +f 1128//1008 1095//929 1129//931 +f 1128//1008 1129//931 1162//1014 +f 1161//1009 1128//1008 1162//1014 +f 1161//1009 1162//1014 1194//1015 +f 1193//1010 1161//1009 1194//1015 +f 1193//1010 1194//1015 1217//1016 +f 1215//1011 1193//1010 1217//1016 +f 1215//1011 1217//1016 1227//1017 +f 1207//1012 1215//1011 1227//1017 +f 1207//1012 1227//1017 1216//1018 +f 1191//1013 1207//1012 1216//1018 +f 1191//1013 1216//1018 1209//1019 +f 1162//1014 1129//931 1163//933 +f 1162//1014 1163//933 1195//1020 +f 1194//1015 1162//1014 1195//1020 +f 1194//1015 1195//1020 1218//1021 +f 1217//1016 1194//1015 1218//1021 +f 1217//1016 1218//1021 1230//1022 +f 1227//1017 1217//1016 1230//1022 +f 1227//1017 1230//1022 1229//1023 +f 1216//1018 1227//1017 1229//1023 +f 1216//1018 1229//1023 1225//1024 +f 1209//1019 1216//1018 1225//1024 +f 1209//1019 1225//1024 1203//1025 +f 1195//1020 1163//933 1196//935 +f 1195//1020 1196//935 1219//1026 +f 1218//1021 1195//1020 1219//1026 +f 1218//1021 1219//1026 1231//1027 +f 1230//1022 1218//1021 1231//1027 +f 1230//1022 1231//1027 1232//1028 +f 1229//1023 1230//1022 1232//1028 +f 1229//1023 1232//1028 1228//1029 +f 1225//1024 1229//1023 1228//1029 +f 1225//1024 1228//1029 1214//1030 +f 1203//1025 1225//1024 1214//1030 +f 1203//1025 1214//1030 1184//1031 +f 1219//1026 1196//935 1220//937 +f 1219//1026 1220//937 1224//1032 +f 1231//1027 1219//1026 1224//1032 +f 1231//1027 1224//1032 1223//1033 +f 1232//1028 1231//1027 1223//1033 +f 1232//1028 1223//1033 1222//1034 +f 1228//1029 1232//1028 1222//1034 +f 1228//1029 1222//1034 1221//1035 +f 1214//1030 1228//1029 1221//1035 +f 1214//1030 1221//1035 1204//1036 +f 1184//1031 1214//1030 1204//1036 +f 1184//1031 1204//1036 1171//1037 +f 1224//1032 1220//937 1201//939 +f 1224//1032 1201//939 1200//1038 +f 1223//1033 1224//1032 1200//1038 +f 1223//1033 1200//1038 1199//1039 +f 1222//1034 1223//1033 1199//1039 +f 1222//1034 1199//1039 1198//1040 +f 1221//1035 1222//1034 1198//1040 +f 1221//1035 1198//1040 1197//1041 +f 1204//1036 1221//1035 1197//1041 +f 1204//1036 1197//1041 1185//1042 +f 1171//1037 1204//1036 1185//1042 +f 1171//1037 1185//1042 1151//1043 +f 1200//1038 1201//939 1169//941 +f 1200//1038 1169//941 1168//1044 +f 1199//1039 1200//1038 1168//1044 +f 1199//1039 1168//1044 1167//1045 +f 1198//1040 1199//1039 1167//1045 +f 1198//1040 1167//1045 1166//1046 +f 1197//1041 1198//1040 1166//1046 +f 1197//1041 1166//1046 1165//1047 +f 1185//1042 1197//1041 1165//1047 +f 1185//1042 1165//1047 1164//1048 +f 1151//1043 1185//1042 1164//1048 +f 1151//1043 1164//1048 1137//1049 +f 1168//1044 1169//941 1135//943 +f 1168//1044 1135//943 1134//1050 +f 1167//1045 1168//1044 1134//1050 +f 1167//1045 1134//1050 1133//1051 +f 1166//1046 1167//1045 1133//1051 +f 1166//1046 1133//1051 1132//1052 +f 1165//1047 1166//1046 1132//1052 +f 1165//1047 1132//1052 1131//1053 +f 1164//1048 1165//1047 1131//1053 +f 1164//1048 1131//1053 1130//1054 +f 1137//1049 1164//1048 1130//1054 +f 1137//1049 1130//1054 1117//1055 +f 1134//1050 1135//943 1102//945 +f 1134//1050 1102//945 1101//1056 +f 1133//1051 1134//1050 1101//1056 +f 1133//1051 1101//1056 1100//1057 +f 1132//1052 1133//1051 1100//1057 +f 1132//1052 1100//1057 1099//1058 +f 1131//1053 1132//1052 1099//1058 +f 1131//1053 1099//1058 1098//1059 +f 1130//1054 1131//1053 1098//1059 +f 1130//1054 1098//1059 1097//1060 +f 1117//1055 1130//1054 1097//1060 +f 1117//1055 1097//1060 1096//1061 +f 1101//1056 1102//945 1065//947 +f 1101//1056 1065//947 1064//1062 +f 1100//1057 1101//1056 1064//1062 +f 1100//1057 1064//1062 1063//1063 +f 1099//1058 1100//1057 1063//1063 +f 1099//1058 1063//1063 1062//1064 +f 1098//1059 1099//1058 1062//1064 +f 1098//1059 1062//1064 1061//1065 +f 1097//1060 1098//1059 1061//1065 +f 1097//1060 1061//1065 1060//1066 +f 1096//1061 1097//1060 1060//1066 +f 1096//1061 1060//1066 1066//1067 +f 1064//1062 1065//947 1032//949 +f 1064//1062 1032//949 1031//1068 +f 1063//1063 1064//1062 1031//1068 +f 1063//1063 1031//1068 1030//1069 +f 1062//1064 1063//1063 1030//1069 +f 1062//1064 1030//1069 1029//1070 +f 1061//1065 1062//1064 1029//1070 +f 1061//1065 1029//1070 1028//1071 +f 1060//1066 1061//1065 1028//1071 +f 1060//1066 1028//1071 1033//1072 +f 1066//1067 1060//1066 1033//1072 +f 1066//1067 1033//1072 1050//1073 +f 1031//1068 1032//949 1003//951 +f 1031//1068 1003//951 1002//1074 +f 1030//1069 1031//1068 1002//1074 +f 1030//1069 1002//1074 1001//1075 +f 1029//1070 1030//1069 1001//1075 +f 1029//1070 1001//1075 1000//1076 +f 1028//1071 1029//1070 1000//1076 +f 1028//1071 1000//1076 1004//1077 +f 1033//1072 1028//1071 1004//1077 +f 1033//1072 1004//1077 1021//1078 +f 1050//1073 1033//1072 1021//1078 +f 1050//1073 1021//1078 1041//1079 +f 1002//1074 1003//951 974//953 +f 1002//1074 974//953 973//1080 +f 1001//1075 1002//1074 973//1080 +f 1001//1075 973//1080 972//1081 +f 1000//1076 1001//1075 972//1081 +f 1000//1076 972//1081 975//1082 +f 1004//1077 1000//1076 975//1082 +f 1004//1077 975//1082 992//1083 +f 1021//1078 1004//1077 992//1083 +f 1021//1078 992//1083 1010//1084 +f 1041//1079 1021//1078 1010//1084 +f 1041//1079 1010//1084 1040//1085 +f 973//1080 974//953 951//955 +f 973//1080 951//955 950//1086 +f 972//1081 973//1080 950//1086 +f 972//1081 950//1086 952//1087 +f 975//1082 972//1081 952//1087 +f 975//1082 952//1087 965//1088 +f 992//1083 975//1082 965//1088 +f 992//1083 965//1088 983//1089 +f 1010//1084 992//1083 983//1089 +f 1010//1084 983//1089 1009//1090 +f 1040//1085 1010//1084 1009//1090 +f 1040//1085 1009//1090 1039//1091 +f 950//1086 951//955 934//957 +f 950//1086 934//957 935//1092 +f 952//1087 950//1086 935//1092 +f 952//1087 935//1092 944//1093 +f 965//1088 952//1087 944//1093 +f 965//1088 944//1093 958//1094 +f 983//1089 965//1088 958//1094 +f 983//1089 958//1094 982//1095 +f 1009//1090 983//1089 982//1095 +f 1009//1090 982//1095 1008//1096 +f 1039//1091 1009//1090 1008//1096 +f 1039//1091 1008//1096 1038//1097 +f 935//1092 934//957 924//959 +f 935//1092 924//959 929//1098 +f 944//1093 935//1092 929//1098 +f 944//1093 929//1098 939//1099 +f 958//1094 944//1093 939//1099 +f 958//1094 939//1099 957//1100 +f 982//1095 958//1094 957//1100 +f 982//1095 957//1100 981//1101 +f 1008//1096 982//1095 981//1101 +f 1008//1096 981//1101 1007//1102 +f 1038//1097 1008//1096 1007//1102 +f 1038//1097 1007//1102 1037//1103 +f 924//959 920//912 929//1098 +f 929//1098 920//912 926//960 +f 939//1099 929//1098 926//960 +f 939//1099 926//960 938//962 +f 957//1100 939//1099 938//962 +f 957//1100 938//962 956//964 +f 981//1101 957//1100 956//964 +f 981//1101 956//964 980//966 +f 1007//1102 981//1101 980//966 +f 1007//1102 980//966 1006//968 +f 1037//1103 1007//1102 1006//968 +f 1037//1103 1006//968 1036//970 +f 993//1104 1005//1105 976//1106 +f 966//1107 993//1104 976//1106 +f 966//1107 976//1106 953//1108 +f 945//1109 966//1107 953//1108 +f 945//1109 953//1108 936//1110 +f 930//1111 945//1109 936//1110 +f 930//1111 936//1110 925//1112 +f 921//913 930//1111 925//1112 +f 921//913 925//1112 922//914 +f 976//1106 1005//1105 977//1113 +f 953//1108 976//1106 977//1113 +f 953//1108 977//1113 954//1114 +f 936//1110 953//1108 954//1114 +f 936//1110 954//1114 937//1115 +f 925//1112 936//1110 937//1115 +f 925//1112 937//1115 931//1116 +f 922//914 925//1112 931//1116 +f 922//914 931//1116 927//916 +f 977//1113 1005//1105 978//1117 +f 954//1114 977//1113 978//1117 +f 954//1114 978//1117 955//1118 +f 937//1115 954//1114 955//1118 +f 937//1115 955//1118 946//1119 +f 931//1116 937//1115 946//1119 +f 931//1116 946//1119 941//1120 +f 927//916 931//1116 941//1120 +f 927//916 941//1120 940//918 +f 978//1117 1005//1105 979//1121 +f 955//1118 978//1117 979//1121 +f 955//1118 979//1121 967//1122 +f 946//1119 955//1118 967//1122 +f 946//1119 967//1122 961//1123 +f 941//1120 946//1119 961//1123 +f 941//1120 961//1123 960//1124 +f 940//918 941//1120 960//1124 +f 940//918 960//1124 959//920 +f 979//1121 1005//1105 994//1125 +f 967//1122 979//1121 994//1125 +f 967//1122 994//1125 987//1126 +f 961//1123 967//1122 987//1126 +f 961//1123 987//1126 986//1127 +f 960//1124 961//1123 986//1127 +f 960//1124 986//1127 985//1128 +f 959//920 960//1124 985//1128 +f 959//920 985//1128 984//922 +f 994//1125 1005//1105 1015//1129 +f 987//1126 994//1125 1015//1129 +f 987//1126 1015//1129 1014//1130 +f 986//1127 987//1126 1014//1130 +f 986//1127 1014//1130 1013//1131 +f 985//1128 986//1127 1013//1131 +f 985//1128 1013//1131 1012//1132 +f 984//922 985//1128 1012//1132 +f 984//922 1012//1132 1011//924 +f 1015//1129 1005//1105 1035//1133 +f 1014//1130 1015//1129 1035//1133 +f 1014//1130 1035//1133 1045//1134 +f 1013//1131 1014//1130 1045//1134 +f 1013//1131 1045//1134 1044//1135 +f 1012//1132 1013//1131 1044//1135 +f 1012//1132 1044//1135 1043//1136 +f 1011//924 1012//1132 1043//1136 +f 1011//924 1043//1136 1042//926 +f 1035//1133 1005//1105 1052//1137 +f 1045//1134 1035//1133 1052//1137 +f 1045//1134 1052//1137 1080//1138 +f 1044//1135 1045//1134 1080//1138 +f 1044//1135 1080//1138 1079//1139 +f 1043//1136 1044//1135 1079//1139 +f 1043//1136 1079//1139 1078//1140 +f 1042//926 1043//1136 1078//1140 +f 1042//926 1078//1140 1077//928 +f 1052//1137 1005//1105 1068//1141 +f 1080//1138 1052//1137 1068//1141 +f 1080//1138 1068//1141 1106//1142 +f 1079//1139 1080//1138 1106//1142 +f 1079//1139 1106//1142 1112//1143 +f 1078//1140 1079//1139 1112//1143 +f 1078//1140 1112//1143 1111//1144 +f 1077//928 1078//1140 1111//1144 +f 1077//928 1111//1144 1110//930 +f 1068//1141 1005//1105 1087//1145 +f 1106//1142 1068//1141 1087//1145 +f 1106//1142 1087//1145 1120//1146 +f 1112//1143 1106//1142 1120//1146 +f 1112//1143 1120//1146 1146//1147 +f 1111//1144 1112//1143 1146//1147 +f 1111//1144 1146//1147 1145//1148 +f 1110//930 1111//1144 1145//1148 +f 1110//930 1145//1148 1144//932 +f 1087//1145 1005//1105 1107//1149 +f 1120//1146 1087//1145 1107//1149 +f 1120//1146 1107//1149 1140//1150 +f 1146//1147 1120//1146 1140//1150 +f 1146//1147 1140//1150 1174//1151 +f 1145//1148 1146//1147 1174//1151 +f 1145//1148 1174//1151 1180//1152 +f 1144//932 1145//1148 1180//1152 +f 1144//932 1180//1152 1179//934 +f 1107//1149 1005//1105 1121//1153 +f 1140//1150 1107//1149 1121//1153 +f 1140//1150 1121//1153 1154//1154 +f 1174//1151 1140//1150 1154//1154 +f 1174//1151 1154//1154 1188//1155 +f 1180//1152 1174//1151 1188//1155 +f 1180//1152 1188//1155 1211//1156 +f 1179//934 1180//1152 1211//1156 +f 1179//934 1211//1156 1210//936 +f 1121//1153 1005//1105 1141//1157 +f 1154//1154 1121//1153 1141//1157 +f 1154//1154 1141//1157 1175//1158 +f 1188//1155 1154//1154 1175//1158 +f 1188//1155 1175//1158 1206//1159 +f 1211//1156 1188//1155 1206//1159 +f 1211//1156 1206//1159 1226//1160 +f 1210//936 1211//1156 1226//1160 +f 1210//936 1226//1160 1212//938 +f 1141//1157 1005//1105 1155//1161 +f 1175//1158 1141//1157 1155//1161 +f 1175//1158 1155//1161 1187//1162 +f 1206//1159 1175//1158 1187//1162 +f 1206//1159 1187//1162 1205//1163 +f 1226//1160 1206//1159 1205//1163 +f 1226//1160 1205//1163 1213//1164 +f 1212//938 1226//1160 1213//1164 +f 1212//938 1213//1164 1181//940 +f 1155//1161 1005//1105 1153//1165 +f 1187//1162 1155//1161 1153//1165 +f 1187//1162 1153//1165 1173//1166 +f 1205//1163 1187//1162 1173//1166 +f 1205//1163 1173//1166 1186//1167 +f 1213//1164 1205//1163 1186//1167 +f 1213//1164 1186//1167 1182//1168 +f 1181//940 1213//1164 1182//1168 +f 1181//940 1182//1168 1147//942 +f 1153//1165 1005//1105 1139//1169 +f 1173//1166 1153//1165 1139//1169 +f 1173//1166 1139//1169 1152//1170 +f 1186//1167 1173//1166 1152//1170 +f 1186//1167 1152//1170 1172//1171 +f 1182//1168 1186//1167 1172//1171 +f 1182//1168 1172//1171 1148//1172 +f 1147//942 1182//1168 1148//1172 +f 1147//942 1148//1172 1113//944 +f 1139//1169 1005//1105 1119//1173 +f 1152//1170 1139//1169 1119//1173 +f 1152//1170 1119//1173 1138//1174 +f 1172//1171 1152//1170 1138//1174 +f 1172//1171 1138//1174 1149//1175 +f 1148//1172 1172//1171 1149//1175 +f 1148//1172 1149//1175 1114//1176 +f 1113//944 1148//1172 1114//1176 +f 1113//944 1114//1176 1081//946 +f 1119//1173 1005//1105 1105//1177 +f 1138//1174 1119//1173 1105//1177 +f 1138//1174 1105//1177 1118//1178 +f 1149//1175 1138//1174 1118//1178 +f 1149//1175 1118//1178 1115//1179 +f 1114//1176 1149//1175 1115//1179 +f 1114//1176 1115//1179 1082//1180 +f 1081//946 1114//1176 1082//1180 +f 1081//946 1082//1180 1046//948 +f 1105//1177 1005//1105 1086//1181 +f 1118//1178 1105//1177 1086//1181 +f 1118//1178 1086//1181 1104//1182 +f 1115//1179 1118//1178 1104//1182 +f 1115//1179 1104//1182 1083//1183 +f 1082//1180 1115//1179 1083//1183 +f 1082//1180 1083//1183 1047//1184 +f 1046//948 1082//1180 1047//1184 +f 1046//948 1047//1184 1016//950 +f 1086//1181 1005//1105 1067//1185 +f 1104//1182 1086//1181 1067//1185 +f 1104//1182 1067//1185 1084//1186 +f 1083//1183 1104//1182 1084//1186 +f 1083//1183 1084//1186 1048//1187 +f 1047//1184 1083//1183 1048//1187 +f 1047//1184 1048//1187 1017//1188 +f 1016//950 1047//1184 1017//1188 +f 1016//950 1017//1188 988//952 +f 1067//1185 1005//1105 1051//1189 +f 1084//1186 1067//1185 1051//1189 +f 1084//1186 1051//1189 1049//1190 +f 1048//1187 1084//1186 1049//1190 +f 1048//1187 1049//1190 1018//1191 +f 1017//1188 1048//1187 1018//1191 +f 1017//1188 1018//1191 989//1192 +f 988//952 1017//1188 989//1192 +f 988//952 989//1192 962//954 +f 1051//1189 1005//1105 1034//1193 +f 1049//1190 1051//1189 1034//1193 +f 1049//1190 1034//1193 1019//1194 +f 1018//1191 1049//1190 1019//1194 +f 1018//1191 1019//1194 990//1195 +f 989//1192 1018//1191 990//1195 +f 989//1192 990//1195 963//1196 +f 962//954 989//1192 963//1196 +f 962//954 963//1196 942//956 +f 1034//1193 1005//1105 1020//1197 +f 1019//1194 1034//1193 1020//1197 +f 1019//1194 1020//1197 991//1198 +f 990//1195 1019//1194 991//1198 +f 990//1195 991//1198 964//1199 +f 963//1196 990//1195 964//1199 +f 963//1196 964//1199 943//1200 +f 942//956 963//1196 943//1200 +f 942//956 943//1200 928//958 +f 1020//1197 1005//1105 993//1104 +f 991//1198 1020//1197 993//1104 +f 991//1198 993//1104 966//1107 +f 964//1199 991//1198 966//1107 +f 964//1199 966//1107 945//1109 +f 943//1200 964//1199 945//1109 +f 943//1200 945//1109 930//1111 +f 928//958 943//1200 930//1111 +f 928//958 930//1111 921//913 +f 1151//1043 1137//1049 1150//1201 +f 1142//995 1143//1202 1122//989 +f 1053//971 1089//977 1069//1203 +f 1122//989 1123//1204 1109//983 +f 1096//1061 1103//1205 1117//1055 +f 1171//1037 1170//1206 1184//1031 +f 1191//1013 1209//1019 1190//1207 +f 1036//970 1053//971 1070//1208 +f 1036//970 1070//1208 1037//1103 +f 1203//1025 1202//1209 1209//1019 +f 1066//1067 1085//1210 1096//1061 +f 1050//1073 1076//1211 1066//1067 +f 1184//1031 1183//1212 1203//1025 +f 1041//1079 1040//1085 1075//1213 +f 1171//1037 1151//1043 1170//1206 +f 1157//1001 1158//1214 1142//995 +f 1137//1049 1117//1055 1136//1215 +f 1038//1097 1072//1216 1039//1091 +f 1178//1007 1191//1013 1177//1217 +f 1089//977 1109//983 1088//1218 +f 1037//1103 1071//1219 1038//1097 +f 1050//1073 1041//1079 1076//1211 +f 1157//1001 1178//1007 1158//1214 +f 1040//1085 1039//1091 1074//1220 +f 1170//1206 1150//1201 452//1221 +f 1264//1222 1071//1219 1263//1223 +f 1261//1224 1262//1225 1076//1211 +f 1085//1210 1076//1211 1262//1225 +f 1190//1207 1208//1226 405//1227 +f 509//176 526//519 1260//1228 +f 1260//1228 526//519 556//523 +f 167//201 556//523 595//202 +f 595//202 621//526 1255//200 +f 172//192 163//182 1254//199 +f 8//49 18//42 3//1229 +f 3//1229 18//42 1288//1230 +f 15//75 7//66 1240//82 +f 1250//50 8//49 3//1229 +f 1//32 1283//40 566//33 +f 593//3 566//33 9//41 +f 19//1231 20//34 33//25 +f 1243//2 636//89 593//3 +f 64//18 40//6 36//17 +f 1244//24 64//18 36//17 +f 641//579 614//582 1237//1232 +f 1250//50 1239//1233 4//48 +f 7//66 4//48 1239//1233 +f 5//74 14//73 11//81 +f 1240//82 7//66 1239//1233 +f 1//32 553//31 565//56 +f 593//3 9//41 1289//83 +f 18//42 20//34 1288//1230 +f 40//6 27//5 1252//16 +f 1249//58 6//65 565//56 +f 14//73 15//75 11//81 +f 592//57 1234//130 1233//58 +f 1237//1232 614//582 588//586 +f 1237//1232 588//586 605//592 +f 539//175 159//177 1259//1234 +f 164//257 1257//1235 168//251 +f 509//176 1256//1236 159//177 +f 1258//250 585//249 1259//1234 +f 169//1237 164//257 174//242 +f 191//236 208//230 185//1238 +f 1290//1239 207//229 640//777 +f 621//526 1292//1240 1255//200 +f 163//182 160//178 157//180 +f 1284//1241 1292//1240 648//227 +f 1252//16 27//5 12//95 +f 119//124 116//129 104//161 +f 116//129 88//135 1242//136 +f 87//159 666//713 715//160 +f 87//159 1241//1242 666//713 +f 1253//1243 47//150 631//152 +f 631//152 666//713 1253//1243 +f 86//142 74//144 60//143 +f 640//777 1291//1244 1290//1239 +f 1291//1244 640//777 613//248 +f 208//230 219//220 200//1245 +f 665//778 640//777 207//229 +f 1285//226 200//1245 219//220 +f 648//227 207//229 1284//1241 +f 691//228 665//778 207//229 +f 605//592 1236//1246 1245//1246 +f 1235//151 605//592 631//152 +f 1248//145 48//153 37//167 +f 667//708 1251//1247 1247//158 +f 605//592 1235//151 1236//1246 +f 641//579 1238//1248 1246//1249 +f 641//579 1237//1232 1238//1248 +f 404//412 391//405 1267//904 +f 1265//911 453//433 436//426 +f 328//351 327//350 331//910 +f 443//445 462//439 469//1250 +f 342//370 1275//1251 344//1252 +f 342//370 334//363 1275//1251 +f 372//480 385//473 384//906 +f 351//377 1271//1253 361//384 +f 351//377 350//1254 1271//1253 +f 337//1255 335//508 345//501 +f 384//906 385//473 396//466 +f 361//384 368//1256 369//391 +f 361//384 1271//1253 368//1256 +f 352//494 1276//1257 346//908 +f 397//1258 396//466 411//459 +f 342//370 350//1254 351//377 +f 342//370 344//1252 350//1254 +f 380//398 369//391 368//1256 +f 334//363 328//351 332//1259 +f 404//412 418//1260 419//419 +f 404//412 1268//905 418//1260 +f 426//452 1286//1261 1282//1262 +f 1282//1262 411//459 426//452 +f 352//494 362//487 1277//1263 +f 1277//1263 1276//1257 352//494 +f 391//405 380//398 381//1264 +f 426//452 443//445 444//1265 +f 444//1265 1286//1261 426//452 +f 362//487 372//480 373//907 +f 373//907 1277//1263 362//487 +f 1202//1209 1183//1212 1270//1266 +f 1116//1267 428//1268 1136//1215 +f 428//1268 1287//1269 1136//1215 +f 1073//1270 353//1271 1074//1220 +f 353//1271 363//1272 1074//1220 +f 353//1271 1073//1270 1279//1273 +f 1070//1208 1069//1203 1263//1223 +f 1274//1274 1069//1203 1088//1218 +f 1177//1217 1273//1275 1272//1276 +f 1272//1276 1158//1214 1177//1217 +f 428//1268 1116//1267 427//1277 +f 1088//1218 1108//1278 343//1279 +f 1103//1205 1085//1210 1278//1280 +f 1108//1278 1123//1204 1280//1281 +f 1123//1204 1281//1282 1280//1281 +f 1143//1202 1158//1214 360//1283 +f 1158//1214 1272//1276 360//1283 +f 1075//1213 1261//1224 1076//1211 +f 1085//1210 1262//1225 1278//1280 +f 1123//1204 1143//1202 1281//1282 +f 1143//1202 360//1283 1281//1282 +f 1074//1220 363//1272 1075//1213 +f 363//1272 1261//1224 1075//1213 +f 1270//1266 1183//1212 452//1221 +f 1266//1284 1150//1201 1136//1215 +f 1273//1275 1177//1217 1190//1207 +f 1208//1226 1202//1209 406//1285 +f 1202//1209 1269//1286 406//1285 +f 1072//1216 1071//1219 1264//1222 +f 1241//1242 1253//1243 666//713 +f 71//137 86//142 60//143 +f 88//135 86//142 71//137 +f 1245//1246 1237//1232 605//592 +f 119//124 104//161 90//119 +f 667//708 1246//1249 1251//1247 +f 621//526 648//227 1292//1240 +f 208//230 200//1245 185//1238 +f 174//242 191//236 169//1237 +f 1258//250 1291//1244 613//248 +f 1244//24 19//1231 33//25 +f 1288//1230 20//34 19//1231 +f 199//208 182//198 178//1287 +f 206//1288 218//214 190//1289 +f 1260//1228 556//523 167//201 +f 157//180 1254//199 163//182 +f 178//1287 182//198 1254//199 +f 218//214 206//1288 1285//226 +f 161//258 1257//1235 158//179 +f 324//345 312//274 323//336 +f 303//317 302//323 316//338 +f 305//305 304//311 318//340 +f 304//311 303//317 317//339 +f 322//347 309//281 321//341 +f 320//346 307//293 319//342 +f 301//329 311//335 314//344 +f 302//323 301//329 315//337 +f 311//335 312//274 313//343 +f 319//342 306//299 318//340 +f 321//341 308//287 320//346 +f 323//336 310//275 322//347 +f 418//1260 435//909 419//419 +f 337//1255 331//910 335//508 +f 469//1250 462//439 1265//911 +f 1137//1049 1136//1215 1150//1201 +f 1143//1202 1123//1204 1122//989 +f 1089//977 1088//1218 1069//1203 +f 1123//1204 1108//1278 1109//983 +f 1103//1205 1116//1267 1117//1055 +f 1170//1206 1183//1212 1184//1031 +f 1209//1019 1208//1226 1190//1207 +f 1053//971 1069//1203 1070//1208 +f 1070//1208 1071//1219 1037//1103 +f 1202//1209 1208//1226 1209//1019 +f 1085//1210 1103//1205 1096//1061 +f 1076//1211 1085//1210 1066//1067 +f 1183//1212 1202//1209 1203//1025 +f 1040//1085 1074//1220 1075//1213 +f 1151//1043 1150//1201 1170//1206 +f 1158//1214 1143//1202 1142//995 +f 1117//1055 1116//1267 1136//1215 +f 1072//1216 1073//1270 1039//1091 +f 1191//1013 1190//1207 1177//1217 +f 1109//983 1108//1278 1088//1218 +f 1071//1219 1072//1216 1038//1097 +f 1041//1079 1075//1213 1076//1211 +f 1178//1007 1177//1217 1158//1214 +f 1039//1091 1073//1270 1074//1220 +f 1150//1201 1266//1284 452//1221 +f 1071//1219 1070//1208 1263//1223 +f 1208//1226 406//1285 405//1227 +f 1256//1236 509//176 1260//1228 +f 1257//1235 161//258 168//251 +f 585//249 539//175 1259//1234 +f 715//160 667//708 1247//158 +f 667//708 641//579 1246//1249 +f 435//909 1265//911 436//426 +f 332//1259 328//351 331//910 +f 444//1265 443//445 469//1250 +f 346//908 337//1255 345//501 +f 397//1258 384//906 396//466 +f 1282//1262 397//1258 411//459 +f 381//1264 380//398 368//1256 +f 1275//1251 334//363 332//1259 +f 1267//904 391//405 381//1264 +f 1269//1286 1202//1209 1270//1266 +f 1073//1270 1072//1216 1279//1273 +f 1069//1203 1274//1274 1263//1223 +f 343//1279 1274//1274 1088//1218 +f 1116//1267 1103//1205 427//1277 +f 1108//1278 1280//1281 343//1279 +f 427//1277 1103//1205 1278//1280 +f 1183//1212 1170//1206 452//1221 +f 1287//1269 1266//1284 1136//1215 +f 405//1227 1273//1275 1190//1207 +f 1279//1273 1072//1216 1264//1222 +f 191//236 185//1238 169//1237 +f 190//1289 199//208 178//1287 +f 218//214 199//208 190//1289 diff --git a/L00(old)/src/GLSL.cpp b/L00(old)/src/GLSL.cpp new file mode 100644 index 0000000..2969872 --- /dev/null +++ b/L00(old)/src/GLSL.cpp @@ -0,0 +1,152 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#include "GLSL.h" +#include +#include +#include +#include + +using namespace std; + +namespace GLSL { + +const char * errorString(GLenum err) +{ + switch(err) { + case GL_NO_ERROR: + return "No error"; + case GL_INVALID_ENUM: + return "Invalid enum"; + case GL_INVALID_VALUE: + return "Invalid value"; + case GL_INVALID_OPERATION: + return "Invalid operation"; + case GL_STACK_OVERFLOW: + return "Stack overflow"; + case GL_STACK_UNDERFLOW: + return "Stack underflow"; + case GL_OUT_OF_MEMORY: + return "Out of memory"; + default: + return "No error"; + } +} + +void checkVersion() +{ + int major, minor; + major = minor = 0; + const char *verstr = (const char *)glGetString(GL_VERSION); + + if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) { + printf("Invalid GL_VERSION format %d.%d\n", major, minor); + } + if(major < 2) { + printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor); + exit(0); + } +} + +void checkError(const char *str) +{ + GLenum glErr = glGetError(); + if(glErr != GL_NO_ERROR) { + if(str) { + printf("%s: ", str); + } + printf("GL_ERROR = %s.\n", errorString(glErr)); + assert(false); + } +} + +void printShaderInfoLog(GLuint shader) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Shader InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +void printProgramInfoLog(GLuint program) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Program InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +char *textFileRead(const char *fn) +{ + FILE *fp; + char *content = NULL; + int count = 0; + if(fn != NULL) { + fp = fopen(fn,"rt"); + if(fp != NULL) { + fseek(fp, 0, SEEK_END); + count = (int)ftell(fp); + rewind(fp); + if(count > 0) { + content = (char *)malloc(sizeof(char) * (count+1)); + count = (int)fread(content,sizeof(char),count,fp); + content[count] = '\0'; + } + fclose(fp); + } else { + printf("error loading %s\n", fn); + } + } + return content; +} + +int textFileWrite(const char *fn, const char *s) +{ + FILE *fp; + int status = 0; + if(fn != NULL) { + fp = fopen(fn,"w"); + if(fp != NULL) { + if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) { + status = 1; + } + fclose(fp); + } + } + return(status); +} + +} diff --git a/L00(old)/src/GLSL.h b/L00(old)/src/GLSL.h new file mode 100644 index 0000000..f945fdd --- /dev/null +++ b/L00(old)/src/GLSL.h @@ -0,0 +1,40 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#pragma once +#ifndef __GLSL__ +#define __GLSL__ + +#define GLEW_STATIC +#include + +/////////////////////////////////////////////////////////////////////////////// +// For printing out the current file and line number // +/////////////////////////////////////////////////////////////////////////////// +#include + +template +std::string NumberToString(T x) +{ + std::ostringstream ss; + ss << x; + return ss.str(); +} + +#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str() +/////////////////////////////////////////////////////////////////////////////// + +namespace GLSL { + + void checkVersion(); + void checkError(const char *str = 0); + void printProgramInfoLog(GLuint program); + void printShaderInfoLog(GLuint shader); + int textFileWrite(const char *filename, const char *s); + char *textFileRead(const char *filename); +} + +#endif diff --git a/L00(old)/src/MatrixStack.cpp b/L00(old)/src/MatrixStack.cpp new file mode 100644 index 0000000..eaa6e6c --- /dev/null +++ b/L00(old)/src/MatrixStack.cpp @@ -0,0 +1,114 @@ +#include "MatrixStack.h" + +#include +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +using namespace std; + +MatrixStack::MatrixStack() +{ + mstack = make_shared< stack >(); + mstack->push(glm::mat4(1.0)); +} + +MatrixStack::~MatrixStack() +{ +} + +void MatrixStack::pushMatrix() +{ + const glm::mat4 &top = mstack->top(); + mstack->push(top); + assert(mstack->size() < 100); +} + +void MatrixStack::popMatrix() +{ + assert(!mstack->empty()); + mstack->pop(); + // There should always be one matrix left. + assert(!mstack->empty()); +} + +void MatrixStack::loadIdentity() +{ + glm::mat4 &top = mstack->top(); + top = glm::mat4(1.0); +} + +void MatrixStack::translate(const glm::vec3 &t) +{ + glm::mat4 &top = mstack->top(); + top *= glm::translate(t); +} + +void MatrixStack::translate(float x, float y, float z) +{ + translate(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(const glm::vec3 &s) +{ + glm::mat4 &top = mstack->top(); + top *= glm::scale(s); +} + +void MatrixStack::scale(float x, float y, float z) +{ + scale(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(float s) +{ + scale(glm::vec3(s, s, s)); +} + +void MatrixStack::rotate(float angle, const glm::vec3 &axis) +{ + glm::mat4 &top = mstack->top(); + top *= glm::rotate(angle, axis); +} + +void MatrixStack::rotate(float angle, float x, float y, float z) +{ + rotate(angle, glm::vec3(x, y, z)); +} + +void MatrixStack::multMatrix(const glm::mat4 &matrix) +{ + glm::mat4 &top = mstack->top(); + top *= matrix; +} + +const glm::mat4 &MatrixStack::topMatrix() const +{ + return mstack->top(); +} + +void MatrixStack::print(const glm::mat4 &mat, const char *name) +{ + if(name) { + printf("%s = [\n", name); + } + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + // mat[j] returns the jth column + printf("%- 5.2f ", mat[j][i]); + } + printf("\n"); + } + if(name) { + printf("];"); + } + printf("\n"); +} + +void MatrixStack::print(const char *name) const +{ + print(mstack->top(), name); +} diff --git a/L00(old)/src/MatrixStack.h b/L00(old)/src/MatrixStack.h new file mode 100644 index 0000000..66278ce --- /dev/null +++ b/L00(old)/src/MatrixStack.h @@ -0,0 +1,50 @@ +#pragma once +#ifndef _MatrixStack_H_ +#define _MatrixStack_H_ + +#include +#include +#include + +class MatrixStack +{ +public: + MatrixStack(); + virtual ~MatrixStack(); + + // glPushMatrix(): Copies the current matrix and adds it to the top of the stack + void pushMatrix(); + // glPopMatrix(): Removes the top of the stack and sets the current matrix to be the matrix that is now on top + void popMatrix(); + + // glLoadIdentity(): Sets the top matrix to be the identity + void loadIdentity(); + // glMultMatrix(): Right multiplies the top matrix + void multMatrix(const glm::mat4 &matrix); + + // glTranslate(): Right multiplies the top matrix by a translation matrix + void translate(const glm::vec3 &trans); + void translate(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(const glm::vec3 &scale); + void scale(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(float size); + // glRotate(): Right multiplies the top matrix by a rotation matrix (angle in radians) + void rotate(float angle, const glm::vec3 &axis); + void rotate(float angle, float x, float y, float z); + + // glGet(GL_MODELVIEW_MATRIX): Gets the top matrix + const glm::mat4 &topMatrix() const; + + // Prints out the specified matrix + static void print(const glm::mat4 &mat, const char *name = 0); + // Prints out the top matrix + void print(const char *name = 0) const; + +private: + std::shared_ptr< std::stack > mstack; + +}; + +#endif diff --git a/L00(old)/src/Program.cpp b/L00(old)/src/Program.cpp new file mode 100644 index 0000000..1e85538 --- /dev/null +++ b/L00(old)/src/Program.cpp @@ -0,0 +1,126 @@ +#include "Program.h" + +#include +#include + +#include "GLSL.h" + +using namespace std; + +Program::Program() : + vShaderName(""), + fShaderName(""), + pid(0), + verbose(true) +{ + +} + +Program::~Program() +{ + +} + +void Program::setShaderNames(const string &v, const string &f) +{ + vShaderName = v; + fShaderName = f; +} + +bool Program::init() +{ + GLint rc; + + // Create shader handles + GLuint VS = glCreateShader(GL_VERTEX_SHADER); + GLuint FS = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + const char *vshader = GLSL::textFileRead(vShaderName.c_str()); + const char *fshader = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(VS, 1, &vshader, NULL); + glShaderSource(FS, 1, &fshader, NULL); + + // Compile vertex shader + glCompileShader(VS); + glGetShaderiv(VS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(VS); + cout << "Error compiling vertex shader " << vShaderName << endl; + } + return false; + } + + // Compile fragment shader + glCompileShader(FS); + glGetShaderiv(FS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(FS); + cout << "Error compiling fragment shader " << fShaderName << endl; + } + return false; + } + + // Create the program and link + pid = glCreateProgram(); + glAttachShader(pid, VS); + glAttachShader(pid, FS); + glLinkProgram(pid); + glGetProgramiv(pid, GL_LINK_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printProgramInfoLog(pid); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + } + return false; + } + + GLSL::checkError(GET_FILE_LINE); + return true; +} + +void Program::bind() +{ + glUseProgram(pid); +} + +void Program::unbind() +{ + glUseProgram(0); +} + +void Program::addAttribute(const string &name) +{ + attributes[name] = glGetAttribLocation(pid, name.c_str()); +} + +void Program::addUniform(const string &name) +{ + uniforms[name] = glGetUniformLocation(pid, name.c_str()); +} + +GLint Program::getAttribute(const string &name) const +{ + map::const_iterator attribute = attributes.find(name.c_str()); + if(attribute == attributes.end()) { + if(isVerbose()) { + cout << name << " is not an attribute variable" << endl; + } + return -1; + } + return attribute->second; +} + +GLint Program::getUniform(const string &name) const +{ + map::const_iterator uniform = uniforms.find(name.c_str()); + if(uniform == uniforms.end()) { + if(isVerbose()) { + cout << name << " is not a uniform variable" << endl; + } + return -1; + } + return uniform->second; +} diff --git a/L00(old)/src/Program.h b/L00(old)/src/Program.h new file mode 100644 index 0000000..51e58bb --- /dev/null +++ b/L00(old)/src/Program.h @@ -0,0 +1,44 @@ +#pragma once +#ifndef __Program__ +#define __Program__ + +#include +#include + +#define GLEW_STATIC +#include + +/** + * An OpenGL Program (vertex and fragment shaders) + */ +class Program +{ +public: + Program(); + virtual ~Program(); + + void setVerbose(bool v) { verbose = v; } + bool isVerbose() const { return verbose; } + + void setShaderNames(const std::string &v, const std::string &f); + virtual bool init(); + virtual void bind(); + virtual void unbind(); + + void addAttribute(const std::string &name); + void addUniform(const std::string &name); + GLint getAttribute(const std::string &name) const; + GLint getUniform(const std::string &name) const; + +protected: + std::string vShaderName; + std::string fShaderName; + +private: + GLuint pid; + std::map attributes; + std::map uniforms; + bool verbose; +}; + +#endif diff --git a/L00(old)/src/Shape.cpp b/L00(old)/src/Shape.cpp new file mode 100644 index 0000000..a559ba5 --- /dev/null +++ b/L00(old)/src/Shape.cpp @@ -0,0 +1,135 @@ +#include "Shape.h" +#include + +#include "GLSL.h" +#include "Program.h" + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +using namespace std; + +Shape::Shape() : + posBufID(0), + norBufID(0), + texBufID(0) +{ +} + +Shape::~Shape() +{ +} + +void Shape::loadMesh(const string &meshName) +{ + // Load geometry + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + if(!attrib.texcoords.empty()) { + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+0]); + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+1]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } +} + +void Shape::init() +{ + // Send the position array to the GPU + glGenBuffers(1, &posBufID); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + // Send the normal array to the GPU + if(!norBuf.empty()) { + glGenBuffers(1, &norBufID); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + } + + // Send the texture array to the GPU + if(!texBuf.empty()) { + glGenBuffers(1, &texBufID); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glBufferData(GL_ARRAY_BUFFER, texBuf.size()*sizeof(float), &texBuf[0], GL_STATIC_DRAW); + } + + // Unbind the arrays + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} + +void Shape::draw(const shared_ptr prog) const +{ + // Bind position buffer + int h_pos = prog->getAttribute("vertPos"); + glEnableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glVertexAttribPointer(h_pos, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + + // Bind normal buffer + int h_nor = prog->getAttribute("vertNor"); + if(h_nor != -1 && norBufID != 0) { + glEnableVertexAttribArray(h_nor); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glVertexAttribPointer(h_nor, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Bind texcoords buffer + int h_tex = prog->getAttribute("vertTex"); + if(h_tex != -1 && texBufID != 0) { + glEnableVertexAttribArray(h_tex); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glVertexAttribPointer(h_tex, 2, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Draw + int count = posBuf.size()/3; // number of indices to be rendered + glDrawArrays(GL_TRIANGLES, 0, count); + + // Disable and unbind + if(h_tex != -1) { + glDisableVertexAttribArray(h_tex); + } + if(h_nor != -1) { + glDisableVertexAttribArray(h_nor); + } + glDisableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} diff --git a/L00(old)/src/Shape.h b/L00(old)/src/Shape.h new file mode 100644 index 0000000..df2aea3 --- /dev/null +++ b/L00(old)/src/Shape.h @@ -0,0 +1,36 @@ +#pragma once +#ifndef _SHAPE_H_ +#define _SHAPE_H_ + +#include +#include +#include + +class Program; + +/** + * A shape defined by a list of triangles + * - posBuf should be of length 3*ntris + * - norBuf should be of length 3*ntris (if normals are available) + * - texBuf should be of length 2*ntris (if texture coords are available) + * posBufID, norBufID, and texBufID are OpenGL buffer identifiers. + */ +class Shape +{ +public: + Shape(); + virtual ~Shape(); + void loadMesh(const std::string &meshName); + void init(); + void draw(const std::shared_ptr prog) const; + +private: + std::vector posBuf; + std::vector norBuf; + std::vector texBuf; + unsigned posBufID; + unsigned norBufID; + unsigned texBufID; +}; + +#endif diff --git a/L00(old)/src/main.cpp b/L00(old)/src/main.cpp new file mode 100644 index 0000000..17dd855 --- /dev/null +++ b/L00(old)/src/main.cpp @@ -0,0 +1,152 @@ +#define _USE_MATH_DEFINES +#include +#include + +#define GLEW_STATIC +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +#include "GLSL.h" +#include "MatrixStack.h" +#include "Program.h" +#include "Shape.h" + +using namespace std; + +GLFWwindow *window; // Main application window +string RES_DIR = ""; // Where data files live +shared_ptr prog; +shared_ptr shape; + +static void error_callback(int error, const char *description) +{ + cerr << description << endl; +} + +static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GL_TRUE); + } +} + +static void init() +{ + GLSL::checkVersion(); + + // Set background color. + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + // Enable z-buffer test. + glEnable(GL_DEPTH_TEST); + + // Initialize mesh. + shape = make_shared(); + shape->loadMesh(RES_DIR + "teapot.obj"); + shape->init(); + + // Initialize the GLSL program. + prog = make_shared(); + prog->setVerbose(false); // Set this to true when debugging. + prog->setShaderNames(RES_DIR + "simple_vert.glsl", RES_DIR + "simple_frag.glsl"); + prog->init(); + prog->addUniform("P"); + prog->addUniform("MV"); + prog->addAttribute("vertPos"); + prog->addAttribute("vertNor"); + + // If there were any OpenGL errors, this will print something. + // You can intersperse this line in your code to find the exact location + // of your OpenGL error. + GLSL::checkError(GET_FILE_LINE); +} + +static void render() +{ + // Get current frame buffer size. + int width, height; + glfwGetFramebufferSize(window, &width, &height); + float aspect = width/(float)height; + glViewport(0, 0, width, height); + + // Clear framebuffer. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Create matrix stacks. + auto P = make_shared(); + auto MV = make_shared(); + // Apply projection. + P->pushMatrix(); + P->multMatrix(glm::perspective((float)(45.0*M_PI/180.0), aspect, 0.01f, 100.0f)); + // Apply camera transform. + MV->pushMatrix(); + MV->translate(glm::vec3(0, -0.5, -3)); + + // Draw mesh using GLSL. + prog->bind(); + glUniformMatrix4fv(prog->getUniform("P"), 1, GL_FALSE, &P->topMatrix()[0][0]); + glUniformMatrix4fv(prog->getUniform("MV"), 1, GL_FALSE, &MV->topMatrix()[0][0]); + shape->draw(prog); + prog->unbind(); + + // Pop matrix stacks. + MV->popMatrix(); + P->popMatrix(); + + GLSL::checkError(GET_FILE_LINE); +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + cout << "Please specify the resource directory." << endl; + return 0; + } + RES_DIR = argv[1] + string("/"); + + // Set error callback. + glfwSetErrorCallback(error_callback); + // Initialize the library. + if(!glfwInit()) { + return -1; + } + // Create a windowed mode window and its OpenGL context. + window = glfwCreateWindow(640, 480, "YOUR NAME", NULL, NULL); + if(!window) { + glfwTerminate(); + return -1; + } + // Make the window's context current. + glfwMakeContextCurrent(window); + // Initialize GLEW. + glewExperimental = true; + if(glewInit() != GLEW_OK) { + cerr << "Failed to initialize GLEW" << endl; + return -1; + } + glGetError(); // A bug in glewInit() causes an error that we can safely ignore. + cout << "OpenGL version: " << glGetString(GL_VERSION) << endl; + cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; + // Set vsync. + glfwSwapInterval(1); + // Set keyboard callback. + glfwSetKeyCallback(window, key_callback); + // Initialize scene. + init(); + // Loop until the user closes the window. + while(!glfwWindowShouldClose(window)) { + // Render scene. + render(); + // Swap front and back buffers. + glfwSwapBuffers(window); + // Poll for and process events. + glfwPollEvents(); + } + // Quit program. + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/L00(old)/src/tiny_obj_loader.h b/L00(old)/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/L00(old)/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/L00.zip b/L00.zip new file mode 100644 index 0000000..5d88ccc Binary files /dev/null and b/L00.zip differ diff --git a/L00/.gitignore b/L00/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L00/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L00/CMakeLists.txt b/L00/CMakeLists.txt new file mode 100644 index 0000000..f6a10e7 --- /dev/null +++ b/L00/CMakeLists.txt @@ -0,0 +1,118 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L00) + +# FOR LAB MACHINES ONLY! +# DO NOT EDIT +SET(DEF_DIR_GLM "C:\\c++\\glm") +SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1") +SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0") + +# Use glob to get the list of all source files. +FILE(GLOB_RECURSE SOURCES "src/*.cpp") + +# We don't really need to include header and resource files to build, but it's +# nice to have them show up in IDEs. +FILE(GLOB_RECURSE HEADERS "src/*.h") +FILE(GLOB_RECURSE GLSL "resources/*.glsl") + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL}) + +# Get the GLM environment variable. Since GLM is a header-only library, we +# just need to add it to the include directory. +SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}") +IF(NOT GLM_INCLUDE_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}") + IF(IS_DIRECTORY ${DEF_DIR_GLM}) + MESSAGE(STATUS "Found!") + SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR}) + +# Get the GLFW environment variable. There should be a CMakeLists.txt in the +# specified directory. +SET(GLFW_DIR "$ENV{GLFW_DIR}") +IF(NOT GLFW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}") + IF(IS_DIRECTORY ${DEF_DIR_GLFW}) + MESSAGE(STATUS "Found!") + SET(GLFW_DIR ${DEF_DIR_GLFW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF) +OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF) +OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF) +IF(CMAKE_BUILD_TYPE MATCHES Release) + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release) +ELSE() + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug) +ENDIF() +INCLUDE_DIRECTORIES(${GLFW_DIR}/include) +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES}) + +# Get the GLEW environment variable. +SET(GLEW_DIR "$ENV{GLEW_DIR}") +IF(NOT GLEW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}") + IF(IS_DIRECTORY ${DEF_DIR_GLEW}) + MESSAGE(STATUS "Found!") + SET(GLEW_DIR ${DEF_DIR_GLEW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLEW_DIR}/include) +IF(WIN32) + # With prebuilt binaries + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib) +ELSE() + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a) +ENDIF() + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib) +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") + IF(APPLE) + # Add required frameworks for GLFW. + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo") + ELSE() + #Link the Linux OpenGL library + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL") + ENDIF() +ENDIF() diff --git a/L00/resources/simple_frag.glsl b/L00/resources/simple_frag.glsl new file mode 100644 index 0000000..fc76efb --- /dev/null +++ b/L00/resources/simple_frag.glsl @@ -0,0 +1,11 @@ +#version 120 + +varying vec3 vNor; + +void main() +{ + vec3 normal = normalize(vNor); + // Map normal in the range [-1, 1] to color in range [0, 1]; + vec3 color = 0.5*normal + 0.5; + gl_FragColor = vec4(color, 1.0); +} diff --git a/L00/resources/simple_vert.glsl b/L00/resources/simple_vert.glsl new file mode 100644 index 0000000..5ace583 --- /dev/null +++ b/L00/resources/simple_vert.glsl @@ -0,0 +1,12 @@ +#version 120 +attribute vec4 aPos; +attribute vec3 aNor; +uniform mat4 P; +uniform mat4 MV; +varying vec3 vNor; + +void main() +{ + gl_Position = P * MV * aPos; + vNor = (MV * vec4(aNor, 0.0)).xyz; +} diff --git a/L00/resources/teapot.obj b/L00/resources/teapot.obj new file mode 100644 index 0000000..6fed453 --- /dev/null +++ b/L00/resources/teapot.obj @@ -0,0 +1,5049 @@ +# Blender v2.65 (sub 0) OBJ File +# www.blender.org +o teapot.005 +v -0.498530 0.712498 -0.039883 +v -0.501666 0.699221 -0.063813 +v -0.501255 0.717792 0.000000 +v -0.624036 0.711938 -0.039883 +v -0.526706 0.651362 -0.039883 +v -0.508714 0.682112 -0.071712 +v -0.622039 0.698704 -0.063813 +v -0.624834 0.717232 0.000000 +v -0.498530 0.712498 0.039883 +v -0.638129 0.287158 0.000000 +v -0.517593 0.664661 -0.063813 +v -0.534329 0.646030 0.000000 +v -0.614850 0.651067 -0.039883 +v -0.616848 0.664299 -0.063813 +v -0.619445 0.681503 -0.071790 +v -0.741245 0.707456 -0.039883 +v -0.744483 0.712577 0.000000 +v -0.624036 0.711938 0.039883 +v -0.501667 0.699221 0.063813 +v -0.622039 0.698704 0.063813 +v -0.712095 0.661370 -0.063813 +v -0.733150 0.694655 -0.063813 +v -0.741245 0.707456 0.039883 +v -0.733150 0.694655 0.063813 +v -0.631184 0.277569 -0.039883 +v -0.526706 0.651362 0.039883 +v -0.614053 0.645774 0.000000 +v -0.704000 0.648569 -0.039883 +v -0.722621 0.678012 -0.071790 +v -0.832523 0.695296 -0.039883 +v -0.837545 0.699948 0.000000 +v -0.832523 0.695296 0.039883 +v -0.619445 0.681503 0.071790 +v -0.508714 0.682112 0.071712 +v -0.722621 0.678012 0.071790 +v -0.517593 0.664661 0.063813 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.710066 0.328372 0.000000 +v -0.614850 0.651067 0.039883 +v -0.787321 0.653419 -0.063813 +v -0.803644 0.668539 -0.071790 +v -0.819967 0.683663 -0.063813 +v -0.819967 0.683663 0.063813 +v -0.803644 0.668539 0.071790 +v -0.711425 0.307332 -0.063813 +v -0.615553 0.216807 -0.063813 +v -0.712688 0.287795 -0.071790 +v -0.631184 0.277569 0.039883 +v -0.710455 0.322361 -0.039883 +v -0.710455 0.322361 0.039883 +v -0.700762 0.643448 0.000000 +v -0.774766 0.641786 -0.039883 +v -0.897800 0.671612 -0.039883 +v -0.904015 0.675354 0.000000 +v -0.897800 0.671612 0.039883 +v -0.882265 0.662257 0.063813 +v -0.712095 0.661370 0.063813 +v -0.787321 0.653419 0.063813 +v -0.608884 0.198682 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.766936 0.377559 0.000000 +v -0.769651 0.372307 0.039883 +v -0.616848 0.664299 0.063813 +v -0.704000 0.648569 0.039883 +v -0.841868 0.637931 -0.063813 +v -0.862065 0.650094 -0.071790 +v -0.882265 0.662257 -0.063813 +v -0.862065 0.650094 0.071790 +v -0.841868 0.637931 0.063813 +v -0.611709 0.194244 0.000000 +v -0.776434 0.359177 -0.063813 +v -0.769651 0.372307 -0.039883 +v -0.713952 0.268259 -0.063813 +v -0.711425 0.307332 0.063813 +v -0.776434 0.359177 0.063813 +v -0.769743 0.637131 0.000000 +v -0.826329 0.628576 -0.039883 +v -0.937016 0.632565 -0.039883 +v -0.943899 0.634805 0.000000 +v -0.937016 0.632565 0.039883 +v -0.919812 0.626965 0.063813 +v -0.897443 0.619684 0.071790 +v -0.774766 0.641786 0.039883 +v -0.826329 0.628576 0.039883 +v -0.714922 0.253231 -0.039883 +v -0.608883 0.198681 0.039883 +v -0.715311 0.247220 0.000000 +v -0.785253 0.342107 -0.071790 +v -0.619922 0.238069 0.071790 +v -0.712688 0.287795 0.071790 +v -0.809626 0.430737 0.000000 +v -0.814205 0.426194 0.039883 +v -0.825653 0.414838 0.063813 +v -0.875076 0.612403 -0.063813 +v -0.897443 0.619684 -0.071790 +v -0.919812 0.626965 -0.063813 +v -0.875076 0.612403 0.063813 +v -0.857869 0.606800 0.039883 +v -0.794072 0.325038 -0.063813 +v -0.800855 0.311909 -0.039883 +v -0.825653 0.414838 -0.063813 +v -0.814205 0.426194 -0.039883 +v -0.615480 0.216617 0.063578 +v -0.785253 0.342107 0.071790 +v -0.840534 0.400078 0.071790 +v -0.820114 0.624834 0.000000 +v -0.857869 0.606800 -0.039883 +v -0.950104 0.574316 -0.039883 +v -0.957194 0.574316 0.000000 +v -0.950104 0.574316 0.039883 +v -0.932377 0.574316 0.063813 +v -0.909334 0.574316 0.071790 +v -0.886292 0.574316 0.063813 +v -0.850987 0.604560 0.000000 +v -0.714922 0.253231 0.039883 +v -0.803571 0.306656 0.000000 +v -0.840534 0.400078 -0.071790 +v -0.713952 0.268259 0.063813 +v -0.794072 0.325038 0.063813 +v -0.839022 0.483916 0.000000 +v -0.844976 0.480304 0.039883 +v -0.859854 0.471278 0.063813 +v -0.879202 0.459542 0.071790 +v -0.886292 0.574316 -0.063813 +v -0.909334 0.574316 -0.071790 +v -0.932377 0.574316 -0.063813 +v -0.868564 0.574316 0.039883 +v -0.861474 0.574316 0.000000 +v -0.855419 0.385315 -0.063813 +v -0.866867 0.373960 -0.039883 +v -0.859854 0.471278 -0.063813 +v -0.844976 0.480304 -0.039883 +v -0.855419 0.385315 0.063813 +v -0.898547 0.447807 0.063813 +v -0.868564 0.574316 -0.039883 +v -0.941014 0.505765 -0.039883 +v -0.947813 0.503580 0.000000 +v -0.941014 0.505765 0.039883 +v -0.924011 0.511234 0.063813 +v -0.901913 0.518343 0.071790 +v -0.879811 0.525448 0.063813 +v -0.862808 0.530917 0.039883 +v -0.800855 0.311909 0.039883 +v -0.871445 0.369416 0.000000 +v -0.879202 0.459542 -0.071790 +v -0.866867 0.373960 0.039883 +v -0.856009 0.533103 0.000000 +v -0.879811 0.525448 -0.063813 +v -0.901913 0.518343 -0.071790 +v -0.924011 0.511234 -0.063813 +v -0.862808 0.530917 -0.039883 +v -0.898547 0.447807 -0.063813 +v -0.913428 0.438781 -0.039883 +v -0.913428 0.438781 0.039883 +v -0.919378 0.435169 0.000000 +v 0.600960 0.444810 0.085753 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.656890 0.471064 0.000000 +v 0.661223 0.454734 -0.083705 +v 0.730696 0.501576 -0.073611 +v 0.661223 0.454734 0.083705 +v 0.605101 0.399712 -0.137265 +v 0.746455 0.470391 -0.117778 +v 0.724395 0.514048 0.000000 +v 0.605100 0.399712 0.137265 +v 0.672055 0.413907 -0.133928 +v 0.613258 0.341675 -0.154354 +v 0.786583 0.544847 -0.096783 +v 0.768856 0.565896 -0.060489 +v 0.672055 0.413907 0.133928 +v 0.730696 0.501576 0.073611 +v 0.686135 0.360830 -0.150669 +v 0.809626 0.517481 -0.108881 +v 0.766935 0.429850 -0.132501 +v 0.761767 0.574316 0.000000 +v 0.613258 0.341675 0.154354 +v 0.813417 0.626247 -0.075788 +v 0.839021 0.611098 -0.085261 +v 0.793721 0.637899 -0.047367 +v 0.686135 0.360830 0.150669 +v 0.768856 0.565896 0.060489 +v 0.746455 0.470391 0.117778 +v 0.619427 0.283145 -0.137236 +v 0.864627 0.595949 -0.075788 +v 0.832669 0.490118 -0.096783 +v 0.787419 0.389310 -0.117778 +v 0.785843 0.642561 0.000000 +v 0.619427 0.283145 0.137236 +v 0.700219 0.307756 -0.133928 +v 0.847933 0.703560 -0.059638 +v 0.879938 0.698065 -0.067092 +v 0.911944 0.692571 -0.059638 +v 0.823314 0.707784 -0.037273 +v 0.766935 0.429850 0.132501 +v 0.793721 0.637899 0.047367 +v 0.786583 0.544847 0.096783 +v 0.700219 0.307756 0.133928 +v 0.617684 0.235930 -0.085941 +v 0.936563 0.688344 -0.037273 +v 0.884319 0.584297 -0.047367 +v 0.850396 0.469070 -0.060489 +v 0.803175 0.358128 -0.073611 +v 0.813468 0.709475 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v 0.711051 0.266929 -0.083705 +v 0.911107 0.765755 -0.053178 +v 0.957193 0.765755 -0.059825 +v 1.003279 0.765755 -0.053178 +v 1.038733 0.765755 -0.033236 +v 0.875654 0.765755 -0.033236 +v 0.809626 0.517481 0.108881 +v 0.787419 0.389310 0.117778 +v 0.823314 0.707784 0.037273 +v 0.813417 0.626247 0.075788 +v 0.711051 0.266929 0.083705 +v 0.715384 0.250599 0.000000 +v 1.052913 0.765755 0.000000 +v 0.946409 0.686653 0.000000 +v 0.892200 0.579635 0.000000 +v 0.857486 0.460650 0.000000 +v 0.809479 0.345652 0.000000 +v 0.861474 0.765755 0.000000 +v 0.929990 0.776479 -0.051602 +v 0.979075 0.777181 -0.058052 +v 1.028157 0.777879 -0.051602 +v 1.065915 0.778419 -0.032251 +v 1.081016 0.778632 0.000000 +v 0.892235 0.775943 -0.032251 +v 0.839021 0.611098 0.085261 +v 0.832669 0.490118 0.096783 +v 0.803175 0.358128 0.073611 +v 0.875654 0.765755 0.033236 +v 0.847933 0.703560 0.059638 +v 1.065915 0.778419 0.032174 +v 1.038733 0.765755 0.033236 +v 0.936563 0.688344 0.037273 +v 0.884319 0.584297 0.047367 +v 0.850396 0.469070 0.060489 +v 0.877131 0.775726 0.000000 +v 0.943713 0.783087 -0.047663 +v 0.992645 0.784366 -0.053621 +v 1.041577 0.785649 -0.047663 +v 1.079216 0.786631 -0.029789 +v 1.094273 0.787027 0.000000 +v 1.079216 0.786631 0.029174 +v 0.906073 0.782101 -0.029789 +v 0.879938 0.698065 0.067092 +v 0.864627 0.595949 0.075788 +v 0.892235 0.775943 0.032236 +v 0.911107 0.765755 0.053178 +v 1.041577 0.785649 0.046875 +v 1.028157 0.777879 0.051503 +v 1.003279 0.765755 0.053178 +v 0.911944 0.692571 0.059638 +v 0.891016 0.781708 0.000000 +v 0.951249 0.785448 -0.042542 +v 0.997575 0.787068 -0.047860 +v 1.043903 0.788686 -0.042542 +v 1.079539 0.789934 -0.026589 +v 1.093795 0.790431 0.000000 +v 1.079539 0.789934 0.024511 +v 1.043903 0.788686 0.039883 +v 0.915613 0.784200 -0.026589 +v 0.957193 0.765755 0.059825 +v 0.906073 0.782101 0.029666 +v 0.929990 0.776479 0.051553 +v 0.997575 0.787068 0.045616 +v 0.992645 0.784366 0.052956 +v 0.979075 0.777181 0.057969 +v 0.901357 0.783702 0.000000 +v 0.951569 0.783431 -0.037421 +v 0.993532 0.785033 -0.042099 +v 1.035492 0.786631 -0.037421 +v 1.067772 0.787863 -0.023388 +v 1.080684 0.788354 0.000000 +v 1.067772 0.787863 0.018464 +v 1.035492 0.786631 0.031119 +v 0.993532 0.785033 0.036781 +v 0.919292 0.782200 -0.023388 +v 0.915613 0.784200 0.026173 +v 0.943713 0.783087 0.047269 +v 0.951569 0.783431 0.034270 +v 0.951249 0.785448 0.041213 +v 0.906379 0.781708 0.000000 +v 0.943653 0.776909 -0.033482 +v 0.980182 0.778010 -0.037667 +v 1.016712 0.779111 -0.033482 +v 1.044812 0.779957 -0.020926 +v 1.056052 0.780295 0.000000 +v 1.044812 0.779957 0.011310 +v 1.016712 0.779111 0.021172 +v 0.980182 0.778010 0.027281 +v 0.943653 0.776909 0.027327 +v 0.915553 0.776064 -0.020926 +v 0.919292 0.782200 0.022403 +v 0.915553 0.776064 0.019003 +v 0.904312 0.775726 0.000000 +v 0.926468 0.765755 -0.031906 +v 0.957193 0.765755 -0.035895 +v 0.987920 0.765755 -0.031906 +v 1.011552 0.765755 -0.019942 +v 1.021006 0.765755 0.000000 +v 1.011552 0.765755 0.003324 +v 0.987920 0.765755 0.010635 +v 0.957193 0.765755 0.017947 +v 0.926468 0.765755 0.021271 +v 0.902834 0.765755 0.016618 +v 0.902834 0.765755 -0.019942 +v 0.893380 0.765755 0.000000 +v 0.886428 0.750924 -0.019014 +v 0.908324 0.750924 -0.030099 +v 0.936793 0.750924 -0.033795 +v 0.965261 0.750924 -0.030099 +v 0.987158 0.750924 -0.019014 +v 0.995918 0.750924 -0.000537 +v 0.987158 0.750924 0.002542 +v 0.965261 0.750924 0.009317 +v 0.936793 0.750924 0.016092 +v 0.908324 0.750924 0.019171 +v 0.886428 0.750924 0.014860 +v 0.877668 0.750924 -0.000537 +v 0.936793 0.750924 -0.007312 +v 0.440746 0.783205 0.000000 +v 0.446690 0.765755 0.000000 +v 0.430973 0.765755 0.119945 +v 0.425236 0.783205 0.118348 +v 0.425236 0.783205 -0.118348 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 0.121642 +v 0.441668 0.793673 0.000000 +v 0.386470 0.765755 0.226985 +v 0.430973 0.765755 -0.119945 +v 0.426127 0.793673 -0.118596 +v 0.437073 0.750009 -0.121642 +v 0.426127 0.793673 0.118596 +v 0.381327 0.783205 0.223964 +v 0.381327 0.783205 -0.223964 +v 0.382124 0.793673 -0.224433 +v 0.317150 0.765755 0.317150 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 0.321639 +v 0.386470 0.765755 -0.226985 +v 0.391939 0.750009 -0.230197 +v 0.447686 0.797164 0.000000 +v 0.431936 0.797164 -0.120212 +v 0.387332 0.797164 -0.227491 +v 0.230197 0.750009 0.391940 +v 0.226984 0.765755 0.386470 +v 0.317150 0.765755 -0.317150 +v 0.321638 0.750009 -0.321639 +v 0.431936 0.797164 0.120212 +v 0.382124 0.793673 0.224433 +v 0.312929 0.783205 0.312929 +v 0.313584 0.793673 -0.313584 +v 0.312929 0.783205 -0.312929 +v 0.317858 0.797164 -0.317858 +v 0.121642 0.750009 0.437072 +v 0.119944 0.765755 0.430973 +v 0.226984 0.765755 -0.386470 +v 0.230197 0.750009 -0.391940 +v 0.457031 0.793673 0.000000 +v 0.440950 0.793673 -0.122721 +v 0.395416 0.793673 -0.232239 +v 0.324491 0.793673 -0.324492 +v -0.000000 0.750009 0.453012 +v -0.000000 0.765755 0.446690 +v 0.223963 0.783205 0.381327 +v 0.223963 0.783205 -0.381327 +v 0.119944 0.765755 -0.430973 +v 0.121642 0.750009 -0.437072 +v 0.440950 0.793673 0.122721 +v 0.387332 0.797164 0.227491 +v 0.313584 0.793673 0.313584 +v 0.227491 0.797164 -0.387332 +v 0.224433 0.793673 -0.382125 +v 0.232239 0.793673 -0.395417 +v -0.119945 0.765755 0.430973 +v -0.121642 0.750009 0.437072 +v 0.118348 0.783205 0.425237 +v 0.118348 0.783205 -0.425237 +v -0.000000 0.750009 -0.453012 +v -0.000000 0.765755 -0.446690 +v 0.467924 0.783205 0.000000 +v 0.451460 0.783205 -0.125646 +v 0.404842 0.783205 -0.237775 +v 0.332226 0.783205 -0.332226 +v 0.237775 0.783205 -0.404842 +v -0.226985 0.765755 0.386470 +v -0.000000 0.783205 0.440746 +v 0.224433 0.793673 0.382125 +v 0.118596 0.793673 -0.426127 +v -0.000000 0.783205 -0.440746 +v -0.119945 0.765755 -0.430973 +v -0.121642 0.750009 -0.437072 +v 0.451460 0.783205 0.125646 +v 0.395416 0.793673 0.232239 +v 0.317858 0.797164 0.317858 +v 0.122721 0.793673 -0.440950 +v 0.120212 0.797164 -0.431937 +v 0.125646 0.783205 -0.451460 +v -0.317150 0.765755 0.317150 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.118348 0.783205 0.425237 +v 0.118596 0.793673 0.426127 +v -0.000000 0.793673 -0.441668 +v -0.118348 0.783205 -0.425237 +v -0.226985 0.765755 -0.386470 +v 0.478596 0.765755 0.000000 +v 0.461756 0.765755 -0.128512 +v 0.414076 0.765755 -0.243198 +v 0.339803 0.765755 -0.339804 +v 0.243198 0.765755 -0.414076 +v 0.128512 0.765755 -0.461757 +v -0.391940 0.750009 0.230197 +v -0.386470 0.765755 0.226985 +v -0.223964 0.783205 0.381327 +v -0.000000 0.793673 0.441668 +v 0.227491 0.797164 0.387332 +v -0.000000 0.797164 -0.447686 +v -0.118596 0.793673 -0.426127 +v -0.223964 0.783205 -0.381327 +v -0.317150 0.765755 -0.317150 +v -0.230198 0.750009 -0.391939 +v -0.321639 0.750009 -0.321639 +v 0.461756 0.765755 0.128512 +v 0.404842 0.783205 0.237775 +v 0.324491 0.793673 0.324492 +v -0.000000 0.783205 -0.467924 +v -0.000000 0.793673 -0.457031 +v -0.000000 0.765755 -0.478597 +v -0.437073 0.750009 0.121642 +v -0.430974 0.765755 0.119945 +v -0.312929 0.783205 0.312929 +v -0.118596 0.793673 0.426127 +v 0.120212 0.797164 0.431937 +v -0.120212 0.797164 -0.431937 +v -0.224433 0.793673 -0.382125 +v -0.312929 0.783205 -0.312929 +v -0.386470 0.765755 -0.226985 +v -0.391940 0.750009 -0.230197 +v 0.518110 0.682112 0.000000 +v 0.499881 0.682112 -0.139122 +v 0.448260 0.682112 -0.263277 +v 0.367859 0.682112 -0.367859 +v 0.263277 0.682112 -0.448260 +v 0.139122 0.682112 -0.499882 +v -0.000000 0.682112 -0.518110 +v -0.453012 0.750009 0.000000 +v -0.446690 0.765755 0.000000 +v -0.381327 0.783205 0.223964 +v -0.224433 0.793673 0.382125 +v -0.000000 0.797164 0.447686 +v 0.232239 0.793673 0.395417 +v -0.122721 0.793673 -0.440950 +v -0.227491 0.797164 -0.387332 +v -0.313584 0.793673 -0.313584 +v -0.381327 0.783205 -0.223964 +v -0.430974 0.765755 -0.119945 +v 0.499881 0.682112 0.139122 +v 0.414076 0.765755 0.243198 +v 0.332226 0.783205 0.332226 +v -0.128513 0.765755 -0.461757 +v -0.125646 0.783205 -0.451460 +v -0.139123 0.682112 -0.499882 +v -0.437073 0.750009 -0.121642 +v -0.425237 0.783205 0.118348 +v -0.313584 0.793673 0.313584 +v -0.120212 0.797164 0.431937 +v 0.122721 0.793673 0.440950 +v -0.232240 0.793673 -0.395417 +v -0.317859 0.797164 -0.317858 +v -0.382125 0.793673 -0.224433 +v -0.425237 0.783205 -0.118348 +v 0.555408 0.599133 0.000000 +v 0.535865 0.599133 -0.149137 +v 0.480530 0.599133 -0.282230 +v 0.394341 0.599133 -0.394341 +v 0.282230 0.599133 -0.480530 +v 0.149137 0.599133 -0.535866 +v -0.000000 0.599133 -0.555408 +v -0.149138 0.599133 -0.535866 +v -0.440746 0.783205 0.000000 +v -0.382125 0.793673 0.224433 +v -0.227491 0.797164 0.387332 +v -0.000000 0.793673 0.457031 +v 0.237775 0.783205 0.404842 +v -0.237775 0.783205 -0.404842 +v -0.324492 0.793673 -0.324492 +v -0.387332 0.797164 -0.227491 +v -0.426127 0.793673 -0.118596 +v 0.535865 0.599133 0.149137 +v 0.448260 0.682112 0.263277 +v 0.339803 0.765755 0.339804 +v -0.263278 0.682112 -0.448260 +v -0.243198 0.765755 -0.414076 +v -0.282230 0.599133 -0.480530 +v -0.426127 0.793673 0.118596 +v -0.317859 0.797164 0.317858 +v -0.122721 0.793673 0.440950 +v 0.125646 0.783205 0.451460 +v -0.332226 0.783205 -0.332226 +v -0.395417 0.793673 -0.232239 +v -0.431937 0.797164 -0.120212 +v -0.441668 0.793673 0.000000 +v 0.588275 0.517481 0.000000 +v 0.567578 0.517481 -0.157963 +v 0.508969 0.517485 -0.298931 +v 0.417675 0.517481 -0.417675 +v 0.298931 0.517485 -0.508969 +v 0.157963 0.517485 -0.567578 +v -0.000000 0.517481 -0.588275 +v -0.157963 0.517481 -0.567578 +v -0.298931 0.517485 -0.508969 +v -0.387332 0.797164 0.227491 +v -0.232240 0.793673 0.395417 +v -0.000000 0.783205 0.467924 +v 0.243198 0.765755 0.414076 +v -0.339804 0.765755 -0.339804 +v -0.404842 0.783205 -0.237775 +v -0.440950 0.793673 -0.122721 +v -0.447686 0.797164 0.000000 +v 0.567578 0.517485 0.157963 +v 0.480530 0.599133 0.282230 +v 0.367859 0.682112 0.367859 +v -0.394341 0.599133 -0.394341 +v -0.367859 0.682112 -0.367859 +v -0.417675 0.517481 -0.417675 +v -0.431937 0.797164 0.120212 +v -0.324492 0.793673 0.324492 +v -0.125646 0.783205 0.451460 +v 0.128512 0.765755 0.461757 +v -0.414076 0.765755 -0.243198 +v -0.451461 0.783205 -0.125646 +v -0.457031 0.793673 0.000000 +v 0.592873 0.437827 -0.165003 +v 0.531651 0.437827 -0.312254 +v 0.436292 0.437827 -0.436292 +v 0.312254 0.437827 -0.531651 +v 0.165003 0.437827 -0.592873 +v -0.000000 0.437827 -0.614496 +v -0.165004 0.437827 -0.592873 +v -0.312255 0.437827 -0.531651 +v -0.436292 0.437827 -0.436292 +v -0.395417 0.793673 0.232239 +v -0.237775 0.783205 0.404842 +v -0.000000 0.765755 0.478597 +v 0.263277 0.682112 0.448260 +v -0.448260 0.682112 -0.263277 +v -0.461757 0.765755 -0.128512 +v -0.467924 0.783205 0.000000 +v -0.440950 0.793673 0.122721 +v 0.592873 0.437827 0.165003 +v 0.508969 0.517485 0.298931 +v 0.394341 0.599133 0.394341 +v -0.508969 0.517485 -0.298931 +v -0.480530 0.599133 -0.282230 +v -0.531651 0.437827 -0.312254 +v -0.332226 0.783205 0.332226 +v -0.128513 0.765755 0.461757 +v 0.139122 0.682112 0.499882 +v -0.499882 0.682112 -0.139122 +v -0.478597 0.765755 0.000000 +v -0.451461 0.783205 0.125646 +v 0.546669 0.360830 -0.321075 +v 0.448614 0.360830 -0.448614 +v 0.321074 0.360830 -0.546669 +v 0.169664 0.360830 -0.609621 +v -0.000000 0.360830 -0.631850 +v -0.169664 0.360830 -0.609621 +v -0.321075 0.360830 -0.546669 +v -0.448615 0.360830 -0.448614 +v -0.546669 0.360830 -0.321075 +v -0.404842 0.783205 0.237775 +v -0.243198 0.765755 0.414076 +v -0.000000 0.682112 0.518110 +v 0.282230 0.599133 0.480530 +v -0.535866 0.599133 -0.149137 +v -0.461757 0.765755 0.128512 +v 0.531651 0.437827 0.312254 +v 0.417675 0.517481 0.417675 +v 0.609621 0.360830 -0.169664 +v -0.592873 0.437827 -0.165003 +v -0.567578 0.517485 -0.157963 +v -0.609621 0.360830 -0.169664 +v -0.339804 0.765755 0.339804 +v -0.139123 0.682112 0.499882 +v 0.149137 0.599133 0.535866 +v -0.555408 0.599133 0.000000 +v -0.499882 0.682112 0.139122 +v -0.414076 0.765755 0.243198 +v 0.609621 0.360830 0.169664 +v 0.552100 0.287158 -0.324265 +v 0.453072 0.287158 -0.453072 +v 0.324265 0.287158 -0.552100 +v 0.171349 0.287158 -0.615677 +v -0.000000 0.287158 -0.638129 +v -0.171350 0.287158 -0.615677 +v -0.324265 0.287158 -0.552100 +v -0.453072 0.287158 -0.453072 +v -0.552100 0.287158 -0.324265 +v -0.615677 0.287158 -0.171349 +v -0.263278 0.682112 0.448260 +v -0.000000 0.599133 0.555408 +v 0.298931 0.517485 0.508969 +v -0.588275 0.517481 0.000000 +v -0.448260 0.682112 0.263277 +v 0.546669 0.360830 0.321075 +v 0.436292 0.437827 0.436292 +v 0.615677 0.287158 -0.171349 +v -0.631850 0.360830 0.000000 +v -0.614496 0.437827 0.000000 +v -0.367859 0.682112 0.367859 +v -0.149138 0.599133 0.535866 +v 0.157963 0.517481 0.567578 +v -0.567578 0.517481 0.157963 +v -0.480530 0.599133 0.282230 +v 0.615677 0.287158 0.171349 +v 0.541877 0.221240 -0.318259 +v 0.444680 0.221240 -0.444680 +v 0.318259 0.221240 -0.541877 +v 0.168176 0.221240 -0.604276 +v -0.000000 0.221240 -0.626311 +v -0.168177 0.221240 -0.604276 +v -0.318259 0.221240 -0.541877 +v -0.444680 0.221240 -0.444680 +v -0.541877 0.221240 -0.318259 +v -0.604277 0.221240 -0.168176 +v -0.282230 0.599133 0.480530 +v -0.000000 0.517481 0.588275 +v 0.312254 0.437827 0.531651 +v -0.592873 0.437827 0.165003 +v -0.535866 0.599133 0.149137 +v -0.394341 0.599133 0.394341 +v 0.552100 0.287158 0.324265 +v 0.448614 0.360830 0.448614 +v 0.604276 0.221240 -0.168176 +v -0.615677 0.287158 0.171349 +v -0.609621 0.360830 0.169664 +v -0.157963 0.517485 0.567578 +v 0.165003 0.437827 0.592873 +v -0.531651 0.437827 0.312254 +v -0.508969 0.517485 0.298931 +v -0.417675 0.517481 0.417675 +v 0.604276 0.221240 0.168176 +v 0.516317 0.166623 -0.303247 +v 0.423705 0.166623 -0.423705 +v 0.303247 0.166623 -0.516317 +v 0.160243 0.166623 -0.575771 +v -0.000000 0.166623 -0.596769 +v -0.160244 0.166623 -0.575771 +v -0.303247 0.166623 -0.516317 +v -0.423705 0.166623 -0.423705 +v -0.516317 0.166623 -0.303247 +v -0.575771 0.166623 -0.160243 +v -0.298931 0.517485 0.508969 +v -0.000000 0.437827 0.614496 +v 0.321074 0.360830 0.546669 +v -0.546669 0.360830 0.321075 +v 0.541877 0.221240 0.318259 +v 0.453072 0.287158 0.453072 +v 0.575771 0.166623 -0.160243 +v -0.596769 0.166623 0.000000 +v -0.604277 0.221240 0.168176 +v -0.552100 0.287158 0.324265 +v -0.165004 0.437827 0.592873 +v 0.169664 0.360830 0.609621 +v -0.448615 0.360830 0.448614 +v -0.436292 0.437827 0.436292 +v -0.312255 0.437827 0.531651 +v 0.575771 0.166623 0.160243 +v 0.483086 0.122640 -0.283731 +v 0.396438 0.122640 -0.396438 +v 0.283731 0.122640 -0.483086 +v 0.149931 0.122640 -0.538718 +v -0.000000 0.122640 -0.558363 +v -0.149931 0.122640 -0.538718 +v -0.283731 0.122640 -0.483086 +v -0.396438 0.122640 -0.396438 +v -0.483087 0.122640 -0.283731 +v -0.538718 0.122640 -0.149931 +v -0.558363 0.122640 0.000000 +v -0.541877 0.221240 0.318259 +v -0.000000 0.360830 0.631850 +v 0.324265 0.287158 0.552100 +v -0.453072 0.287158 0.453072 +v 0.516317 0.166623 0.303247 +v 0.596768 0.166623 0.000000 +v 0.444680 0.221240 0.444680 +v 0.538718 0.122640 -0.149931 +v -0.538718 0.122640 0.149931 +v -0.516317 0.166623 0.303247 +v -0.444680 0.221240 0.444680 +v -0.169664 0.360830 0.609621 +v 0.171349 0.287158 0.615677 +v -0.324265 0.287158 0.552100 +v -0.321075 0.360830 0.546669 +v 0.538718 0.122640 0.149931 +v 0.558363 0.122640 0.000000 +v 0.449858 0.088629 -0.264215 +v 0.369171 0.088629 -0.369171 +v 0.264215 0.088629 -0.449859 +v 0.139618 0.088629 -0.501662 +v -0.000000 0.088629 -0.519957 +v -0.139618 0.088629 -0.501662 +v -0.264215 0.088629 -0.449859 +v -0.369171 0.088629 -0.369171 +v -0.449859 0.088629 -0.264215 +v -0.501662 0.088629 -0.139618 +v -0.519957 0.088629 0.000000 +v -0.501662 0.088629 0.139618 +v -0.575771 0.166623 0.160243 +v -0.423705 0.166623 0.423705 +v -0.000000 0.287158 0.638129 +v 0.318259 0.221240 0.541877 +v -0.318259 0.221240 0.541877 +v 0.483086 0.122640 0.283731 +v 0.423705 0.166623 0.423705 +v 0.501662 0.088629 -0.139618 +v -0.449859 0.088629 0.264215 +v -0.483087 0.122640 0.283731 +v -0.396438 0.122640 0.396438 +v -0.303247 0.166623 0.516317 +v -0.171350 0.287158 0.615677 +v 0.168176 0.221240 0.604276 +v -0.168177 0.221240 0.604276 +v 0.501662 0.088629 0.139618 +v 0.519957 0.088629 0.000000 +v 0.424299 0.063924 -0.249203 +v 0.348195 0.063924 -0.348195 +v 0.249203 0.063924 -0.424298 +v 0.131685 0.063924 -0.473160 +v -0.000000 0.063924 -0.490415 +v -0.131686 0.063924 -0.473160 +v -0.249203 0.063924 -0.424298 +v -0.348196 0.063924 -0.348195 +v -0.424299 0.063924 -0.249203 +v -0.473160 0.063924 -0.131685 +v -0.490415 0.063924 0.000000 +v -0.473160 0.063924 0.131685 +v -0.424299 0.063924 0.249203 +v -0.283731 0.122640 0.483086 +v -0.000000 0.221240 0.626311 +v 0.303247 0.166623 0.516317 +v -0.160244 0.166623 0.575771 +v 0.449858 0.088629 0.264215 +v 0.396438 0.122640 0.396438 +v 0.473160 0.063924 -0.131685 +v -0.348196 0.063924 0.348195 +v -0.369171 0.088629 0.369171 +v -0.264215 0.088629 0.449859 +v -0.149931 0.122640 0.538718 +v 0.160243 0.166623 0.575771 +v -0.000000 0.166623 0.596769 +v 0.473160 0.063924 0.131685 +v 0.490415 0.063924 0.000000 +v 0.414076 0.047860 -0.243198 +v 0.339803 0.047860 -0.339804 +v 0.243198 0.047860 -0.414076 +v 0.128512 0.047860 -0.461757 +v -0.000000 0.047860 -0.478597 +v -0.128513 0.047860 -0.461757 +v -0.243198 0.047860 -0.414076 +v -0.339804 0.047860 -0.339804 +v -0.414076 0.047860 -0.243198 +v -0.461757 0.047860 -0.128512 +v -0.478597 0.047860 0.000000 +v -0.461757 0.047860 0.128512 +v -0.414076 0.047860 0.243198 +v -0.339804 0.047860 0.339804 +v -0.139618 0.088629 0.501662 +v 0.283731 0.122640 0.483086 +v -0.000000 0.122640 0.558363 +v 0.424299 0.063924 0.249203 +v 0.369171 0.088629 0.369171 +v 0.461756 0.047860 -0.128512 +v -0.243198 0.047860 0.414076 +v -0.249203 0.063924 0.424298 +v -0.131686 0.063924 0.473160 +v -0.000000 0.088629 0.519957 +v 0.149931 0.122640 0.538718 +v 0.461756 0.047860 0.128512 +v 0.478596 0.047860 0.000000 +v 0.410719 0.036005 -0.241228 +v 0.337050 0.036005 -0.337050 +v 0.241227 0.036005 -0.410719 +v 0.127471 0.036005 -0.458017 +v -0.000000 0.036005 -0.474720 +v -0.127471 0.036005 -0.458017 +v -0.241228 0.036005 -0.410719 +v -0.337051 0.036005 -0.337050 +v -0.410719 0.036005 -0.241228 +v -0.458017 0.036005 -0.127471 +v -0.474721 0.036005 0.000000 +v -0.458017 0.036005 0.127471 +v -0.410719 0.036005 0.241228 +v -0.337051 0.036005 0.337050 +v -0.241228 0.036005 0.410719 +v -0.000000 0.063924 0.490415 +v 0.264215 0.088629 0.449859 +v 0.139618 0.088629 0.501662 +v 0.414076 0.047860 0.243198 +v 0.348195 0.063924 0.348195 +v 0.458017 0.036005 -0.127471 +v -0.127471 0.036005 0.458017 +v -0.128513 0.047860 0.461757 +v -0.000000 0.047860 0.478597 +v 0.131685 0.063924 0.473160 +v 0.458017 0.036005 0.127471 +v 0.474720 0.036005 0.000000 +v 0.394137 0.024816 -0.231489 +v 0.323442 0.024816 -0.323442 +v 0.231489 0.024816 -0.394137 +v 0.122324 0.024816 -0.439524 +v -0.000000 0.024816 -0.455554 +v -0.122325 0.024816 -0.439524 +v -0.231489 0.024816 -0.394137 +v -0.323442 0.024816 -0.323442 +v -0.394137 0.024816 -0.231489 +v -0.439524 0.024816 -0.122325 +v -0.455554 0.024816 0.000000 +v -0.439524 0.024816 0.122325 +v -0.394137 0.024816 0.231489 +v -0.323442 0.024816 0.323442 +v -0.231489 0.024816 0.394137 +v -0.122325 0.024816 0.439524 +v 0.128512 0.047860 0.461757 +v 0.249203 0.063924 0.424298 +v 0.410719 0.036005 0.241228 +v 0.339803 0.047860 0.339804 +v 0.439524 0.024816 -0.122325 +v -0.000000 0.036005 0.474720 +v -0.000000 0.024816 0.455554 +v 0.127471 0.036005 0.458017 +v 0.243198 0.047860 0.414076 +v 0.439524 0.024816 0.122325 +v 0.455554 0.024816 0.000000 +v 0.354551 0.014956 -0.208238 +v 0.290957 0.014956 -0.290957 +v 0.208238 0.014956 -0.354551 +v 0.110038 0.014956 -0.395378 +v -0.000000 0.014956 -0.409797 +v -0.110038 0.014956 -0.395378 +v -0.208239 0.014956 -0.354551 +v -0.290957 0.014956 -0.290957 +v -0.354551 0.014956 -0.208238 +v -0.395378 0.014956 -0.110038 +v -0.409797 0.014956 0.000000 +v -0.395378 0.014956 0.110038 +v -0.354551 0.014956 0.208238 +v -0.290957 0.014956 0.290957 +v -0.208239 0.014956 0.354551 +v -0.110038 0.014956 0.395378 +v -0.000000 0.014956 0.409797 +v 0.241227 0.036005 0.410719 +v 0.337050 0.036005 0.337050 +v 0.394137 0.024816 0.231489 +v 0.395378 0.014956 -0.110038 +v 0.122324 0.024816 0.439524 +v 0.110038 0.014956 0.395378 +v 0.231489 0.024816 0.394137 +v 0.395378 0.014956 0.110038 +v 0.409797 0.014956 0.000000 +v 0.282184 0.007090 -0.165735 +v 0.231570 0.007090 -0.231570 +v 0.165735 0.007090 -0.282185 +v 0.087579 0.007090 -0.314679 +v -0.000000 0.007090 -0.326154 +v -0.087579 0.007090 -0.314679 +v -0.165735 0.007090 -0.282185 +v -0.231570 0.007090 -0.231570 +v -0.282184 0.007090 -0.165735 +v -0.314679 0.007090 -0.087579 +v -0.326155 0.007090 0.000000 +v -0.314679 0.007090 0.087579 +v -0.282184 0.007090 0.165735 +v -0.231570 0.007090 0.231570 +v -0.165735 0.007090 0.282185 +v -0.087579 0.007090 0.314679 +v -0.000000 0.007090 0.326154 +v 0.087579 0.007090 0.314679 +v 0.323442 0.024816 0.323442 +v 0.354551 0.014956 0.208238 +v 0.314679 0.007090 -0.087579 +v 0.208238 0.014956 0.354551 +v 0.165735 0.007090 0.282185 +v 0.290957 0.014956 0.290957 +v 0.314679 0.007090 0.087579 +v 0.326154 0.007090 0.000000 +v 0.167259 0.001883 -0.098236 +v 0.137258 0.001883 -0.137259 +v 0.098236 0.001883 -0.167259 +v 0.051910 0.001883 -0.186520 +v -0.000000 0.001883 -0.193322 +v -0.051911 0.001883 -0.186520 +v -0.098237 0.001883 -0.167259 +v -0.137259 0.001883 -0.137259 +v -0.167259 0.001883 -0.098236 +v -0.186520 0.001883 -0.051911 +v -0.193323 0.001883 0.000000 +v -0.186520 0.001883 0.051911 +v -0.167259 0.001883 0.098236 +v -0.137259 0.001883 0.137259 +v -0.098237 0.001883 0.167259 +v -0.051911 0.001883 0.186520 +v -0.000000 0.001883 0.193322 +v 0.051910 0.001883 0.186520 +v 0.098236 0.001883 0.167259 +v 0.282184 0.007090 0.165735 +v 0.186520 0.001883 -0.051911 +v 0.231570 0.007090 0.231570 +v 0.137258 0.001883 0.137259 +v 0.186520 0.001883 0.051911 +v 0.193322 0.001883 0.000000 +v -0.000000 0.000000 0.000000 +v 0.167259 0.001883 0.098236 +v 0.063813 0.861474 0.000000 +v 0.054654 0.888729 0.000000 +v 0.052734 0.888729 0.014691 +v 0.061568 0.861474 0.017135 +v 0.061568 0.861474 -0.017135 +v 0.072979 0.919969 0.020357 +v 0.111968 0.841089 0.000000 +v 0.047296 0.888729 0.027792 +v 0.052734 0.888729 -0.014691 +v 0.108028 0.841089 -0.030065 +v 0.075630 0.919969 0.000000 +v 0.065466 0.919969 0.038494 +v 0.108028 0.841089 0.030065 +v 0.055210 0.861474 0.032427 +v 0.055210 0.861474 -0.032427 +v 0.096873 0.841089 -0.056896 +v 0.100064 0.951211 0.027927 +v 0.089769 0.951211 0.052799 +v 0.183167 0.826023 0.000000 +v 0.176722 0.826023 -0.049184 +v 0.038821 0.888729 0.038821 +v 0.053751 0.919969 0.053751 +v 0.047296 0.888729 -0.027792 +v 0.072979 0.919969 -0.020357 +v 0.158473 0.826023 -0.093076 +v 0.103696 0.951211 0.000000 +v 0.073714 0.951211 0.073714 +v 0.176722 0.826023 0.049184 +v 0.096873 0.841089 0.056896 +v 0.045307 0.861474 0.045307 +v 0.079497 0.841089 -0.079497 +v 0.045307 0.861474 -0.045307 +v 0.130048 0.826023 -0.130048 +v 0.111754 0.978466 0.031195 +v 0.100259 0.978466 0.058974 +v 0.082330 0.978466 0.082330 +v 0.263228 0.813615 0.000000 +v 0.253966 0.813615 -0.070682 +v 0.227741 0.813615 -0.133759 +v 0.027792 0.888729 0.047296 +v 0.038494 0.919969 0.065466 +v 0.052799 0.951211 0.089769 +v 0.038821 0.888729 -0.038821 +v 0.065466 0.919969 -0.038494 +v 0.100064 0.951211 -0.027927 +v 0.186892 0.813615 -0.186892 +v 0.115809 0.978466 0.000000 +v 0.058974 0.978466 0.100259 +v 0.253966 0.813615 0.070682 +v 0.158473 0.826023 0.093076 +v 0.079497 0.841089 0.079497 +v 0.032426 0.861474 0.055210 +v 0.093076 0.826023 -0.158473 +v 0.056896 0.841089 -0.096873 +v 0.032426 0.861474 -0.055210 +v 0.133759 0.813615 -0.227741 +v 0.085811 0.997741 0.023955 +v 0.076985 0.997741 0.045285 +v 0.063219 0.997741 0.063219 +v 0.045285 0.997741 0.076986 +v 0.337972 0.801206 0.000000 +v 0.326081 0.801206 -0.090752 +v 0.292408 0.801206 -0.171740 +v 0.239960 0.801206 -0.239960 +v 0.014691 0.888729 0.052735 +v 0.020357 0.919969 0.072979 +v 0.027927 0.951211 0.100064 +v 0.031195 0.978466 0.111754 +v 0.027792 0.888729 -0.047296 +v 0.053751 0.919969 -0.053751 +v 0.089769 0.951211 -0.052799 +v 0.111754 0.978466 -0.031195 +v 0.171740 0.801206 -0.292408 +v 0.088924 0.997741 0.000000 +v 0.023955 0.997741 0.085811 +v 0.326081 0.801206 0.090752 +v 0.227741 0.813615 0.133759 +v 0.130048 0.826023 0.130048 +v 0.056896 0.841089 0.096873 +v 0.017135 0.861474 0.061568 +v 0.070682 0.813615 -0.253966 +v 0.049184 0.826023 -0.176722 +v 0.030065 0.841089 -0.108029 +v 0.017135 0.861474 -0.061568 +v 0.090752 0.801206 -0.326081 +v -0.000000 1.005054 0.000000 +v 0.393218 0.786140 0.000000 +v 0.379380 0.786140 -0.105586 +v 0.340206 0.786140 -0.199813 +v 0.279184 0.786140 -0.279184 +v 0.199813 0.786140 -0.340206 +v -0.000000 0.888729 0.054654 +v -0.000000 0.919969 0.075630 +v -0.000000 0.951211 0.103696 +v -0.000000 0.978466 0.115809 +v -0.000000 0.997741 0.088925 +v 0.014691 0.888729 -0.052735 +v 0.038494 0.919969 -0.065466 +v 0.073714 0.951211 -0.073714 +v 0.100259 0.978466 -0.058974 +v 0.085811 0.997741 -0.023955 +v 0.105586 0.786140 -0.379381 +v 0.379380 0.786140 0.105586 +v 0.292408 0.801206 0.171740 +v 0.186892 0.813615 0.186892 +v 0.093076 0.826023 0.158473 +v 0.030065 0.841089 0.108029 +v -0.000000 0.861474 0.063813 +v -0.000000 0.801206 -0.337972 +v -0.000000 0.813615 -0.263228 +v -0.000000 0.826023 -0.183167 +v -0.000000 0.841089 -0.111968 +v -0.000000 0.861474 -0.063813 +v -0.000000 0.786140 -0.393218 +v 0.076985 0.997741 -0.045285 +v -0.023955 0.997741 0.085811 +v 0.414784 0.765755 0.000000 +v 0.400190 0.765755 -0.111377 +v 0.358865 0.765755 -0.210772 +v 0.294497 0.765755 -0.294497 +v 0.210772 0.765755 -0.358865 +v 0.111377 0.765755 -0.400190 +v -0.014691 0.888729 0.052735 +v -0.020357 0.919969 0.072979 +v -0.027927 0.951211 0.100064 +v -0.031195 0.978466 0.111754 +v -0.000000 0.888729 -0.054654 +v 0.020357 0.919969 -0.072979 +v 0.052799 0.951211 -0.089769 +v 0.082330 0.978466 -0.082330 +v -0.000000 0.765755 -0.414784 +v 0.063219 0.997741 -0.063219 +v -0.045285 0.997741 0.076986 +v 0.400190 0.765755 0.111377 +v 0.340206 0.786140 0.199813 +v 0.239960 0.801206 0.239960 +v 0.133759 0.813615 0.227741 +v 0.049184 0.826023 0.176722 +v -0.000000 0.841089 0.111968 +v -0.017135 0.861474 0.061568 +v -0.105586 0.786140 -0.379381 +v -0.090752 0.801206 -0.326081 +v -0.070682 0.813615 -0.253966 +v -0.049184 0.826023 -0.176722 +v -0.030066 0.841089 -0.108029 +v -0.017135 0.861474 -0.061568 +v -0.111377 0.765755 -0.400190 +v 0.045285 0.997741 -0.076986 +v -0.063220 0.997741 0.063219 +v 0.414952 0.750806 0.115486 +v 0.430085 0.750806 0.000000 +v 0.414952 0.750806 -0.115486 +v 0.372103 0.750806 -0.218547 +v 0.305360 0.750806 -0.305360 +v 0.218547 0.750806 -0.372103 +v 0.115486 0.750806 -0.414952 +v -0.000000 0.750806 -0.430085 +v -0.027793 0.888729 0.047296 +v -0.038494 0.919969 0.065466 +v -0.052799 0.951211 0.089769 +v -0.058974 0.978466 0.100259 +v -0.014691 0.888729 -0.052735 +v -0.000000 0.919969 -0.075630 +v 0.027927 0.951211 -0.100064 +v 0.058974 0.978466 -0.100259 +v -0.115486 0.750806 -0.414952 +v 0.023955 0.997741 -0.085811 +v -0.076986 0.997741 0.045285 +v 0.372103 0.750806 0.218547 +v 0.358865 0.765755 0.210772 +v 0.279184 0.786140 0.279184 +v 0.171740 0.801206 0.292408 +v 0.070682 0.813615 0.253966 +v -0.000000 0.826023 0.183167 +v -0.030066 0.841089 0.108029 +v -0.032427 0.861474 0.055210 +v -0.210772 0.765755 -0.358865 +v -0.199813 0.786140 -0.340206 +v -0.171740 0.801206 -0.292408 +v -0.133759 0.813615 -0.227741 +v -0.093076 0.826023 -0.158473 +v -0.056896 0.841089 -0.096873 +v -0.032427 0.861474 -0.055210 +v -0.218547 0.750806 -0.372103 +v 0.031195 0.978466 -0.111754 +v -0.000000 0.997741 -0.088925 +v -0.082331 0.978466 0.082330 +v -0.085811 0.997741 0.023955 +v 0.305360 0.750806 0.305360 +v 0.294497 0.765755 0.294497 +v -0.038821 0.888729 0.038821 +v -0.053751 0.919969 0.053751 +v -0.073714 0.951211 0.073714 +v -0.027793 0.888729 -0.047296 +v -0.020357 0.919969 -0.072979 +v -0.000000 0.951211 -0.103696 +v -0.305360 0.750806 -0.305360 +v -0.294497 0.765755 -0.294497 +v -0.000000 0.978466 -0.115809 +v -0.023955 0.997741 -0.085811 +v -0.100259 0.978466 0.058974 +v -0.088925 0.997741 0.000000 +v 0.210772 0.765755 0.358865 +v 0.218547 0.750806 0.372103 +v 0.199813 0.786140 0.340206 +v 0.090752 0.801206 0.326081 +v -0.000000 0.813615 0.263228 +v -0.049184 0.826023 0.176722 +v -0.056896 0.841089 0.096873 +v -0.045307 0.861474 0.045307 +v -0.279185 0.786140 -0.279184 +v -0.239960 0.801206 -0.239960 +v -0.186892 0.813615 -0.186892 +v -0.130049 0.826023 -0.130048 +v -0.079497 0.841089 -0.079497 +v -0.045307 0.861474 -0.045307 +v -0.372103 0.750806 -0.218547 +v -0.358865 0.765755 -0.210772 +v -0.031195 0.978466 -0.111754 +v -0.045285 0.997741 -0.076986 +v -0.111754 0.978466 0.031195 +v -0.085811 0.997741 -0.023955 +v 0.111377 0.765755 0.400190 +v 0.115486 0.750806 0.414952 +v -0.047296 0.888729 0.027792 +v -0.065466 0.919969 0.038494 +v -0.089770 0.951211 0.052799 +v -0.038821 0.888729 -0.038821 +v -0.038494 0.919969 -0.065466 +v -0.027927 0.951211 -0.100064 +v -0.414952 0.750806 -0.115486 +v -0.400190 0.765755 -0.111377 +v -0.058974 0.978466 -0.100259 +v -0.063220 0.997741 -0.063219 +v -0.115809 0.978466 0.000000 +v -0.076986 0.997741 -0.045285 +v 0.105586 0.786140 0.379381 +v -0.000000 0.765755 0.414784 +v -0.000000 0.750806 0.430085 +v -0.000000 0.801206 0.337972 +v -0.070682 0.813615 0.253966 +v -0.093076 0.826023 0.158473 +v -0.079497 0.841089 0.079497 +v -0.055210 0.861474 0.032427 +v -0.340206 0.786140 -0.199813 +v -0.292408 0.801206 -0.171740 +v -0.227741 0.813615 -0.133759 +v -0.158473 0.826023 -0.093076 +v -0.096873 0.841089 -0.056896 +v -0.055210 0.861474 -0.032427 +v -0.430085 0.750806 0.000000 +v -0.414784 0.765755 0.000000 +v -0.052799 0.951211 -0.089769 +v -0.082331 0.978466 -0.082330 +v -0.100064 0.951211 0.027927 +v -0.111754 0.978466 -0.031195 +v -0.000000 0.786140 0.393218 +v -0.115486 0.750806 0.414952 +v -0.111377 0.765755 0.400190 +v -0.052735 0.888729 0.014691 +v -0.072979 0.919969 0.020357 +v -0.047296 0.888729 -0.027792 +v -0.053751 0.919969 -0.053751 +v -0.414952 0.750806 0.115486 +v -0.400190 0.765755 0.111377 +v -0.379381 0.786140 -0.105586 +v -0.073714 0.951211 -0.073714 +v -0.100259 0.978466 -0.058974 +v -0.103696 0.951211 0.000000 +v -0.105586 0.786140 0.379381 +v -0.218547 0.750806 0.372103 +v -0.210772 0.765755 0.358865 +v -0.090752 0.801206 0.326081 +v -0.133759 0.813615 0.227741 +v -0.130049 0.826023 0.130048 +v -0.096873 0.841089 0.056896 +v -0.061568 0.861474 0.017135 +v -0.326081 0.801206 -0.090752 +v -0.253966 0.813615 -0.070682 +v -0.176722 0.826023 -0.049184 +v -0.108029 0.841089 -0.030065 +v -0.061568 0.861474 -0.017135 +v -0.372103 0.750806 0.218547 +v -0.358865 0.765755 0.210772 +v -0.393219 0.786140 0.000000 +v -0.089770 0.951211 -0.052799 +v -0.100064 0.951211 -0.027927 +v -0.199813 0.786140 0.340206 +v -0.305360 0.750806 0.305360 +v -0.294497 0.765755 0.294497 +v -0.054655 0.888729 0.000000 +v -0.075630 0.919969 0.000000 +v -0.052735 0.888729 -0.014691 +v -0.065466 0.919969 -0.038494 +v -0.379381 0.786140 0.105586 +v -0.171740 0.801206 0.292408 +v -0.279185 0.786140 0.279184 +v -0.186892 0.813615 0.186892 +v -0.158473 0.826023 0.093076 +v -0.108029 0.841089 0.030065 +v -0.063813 0.861474 0.000000 +v -0.337972 0.801206 0.000000 +v -0.263228 0.813615 0.000000 +v -0.183167 0.826023 0.000000 +v -0.111968 0.841089 0.000000 +v -0.340206 0.786140 0.199813 +v -0.072979 0.919969 -0.020357 +v -0.239960 0.801206 0.239960 +v -0.326081 0.801206 0.090752 +v -0.292408 0.801206 0.171740 +v -0.227741 0.813615 0.133759 +v -0.176722 0.826023 0.049184 +v -0.253966 0.813615 0.070682 +v -0.526706 0.651362 -0.039883 +v -0.534329 0.646030 0.000000 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.638129 0.287158 0.000000 +v -0.631184 0.277569 0.039883 +v -0.501666 0.699221 -0.063813 +v -0.508714 0.682112 -0.071712 +v -0.611709 0.194244 0.000000 +v -0.608883 0.198681 0.039883 +v -0.517593 0.664661 0.063813 +v -0.508714 0.682112 0.071712 +v -0.631184 0.277569 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.615480 0.216617 0.063578 +v -0.615553 0.216807 -0.063813 +v -0.517593 0.664661 -0.063813 +v -0.498530 0.712498 -0.039883 +v -0.619922 0.238069 0.071790 +v -0.526706 0.651362 0.039883 +v -0.608884 0.198682 -0.039883 +v 0.605100 0.399712 0.137265 +v 0.613258 0.341675 0.154354 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.613258 0.341675 -0.154354 +v 0.605101 0.399712 -0.137265 +v 0.600960 0.444810 0.085753 +v 0.121642 0.750009 -0.437072 +v -0.000000 0.750009 -0.453012 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 -0.121642 +v -0.453012 0.750009 0.000000 +v -0.437073 0.750009 -0.121642 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.391940 0.750009 0.230197 +v -0.437073 0.750009 0.121642 +v 0.121642 0.750009 0.437072 +v -0.000000 0.750009 0.453012 +v -0.121642 0.750009 0.437072 +v 0.437073 0.750009 0.121642 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 -0.321639 +v 0.230197 0.750009 -0.391940 +v -0.121642 0.750009 -0.437072 +v 0.391939 0.750009 -0.230197 +v 0.321638 0.750009 0.321639 +v 0.230197 0.750009 0.391940 +v -0.230198 0.750009 -0.391939 +v -0.501255 0.717792 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v -0.321639 0.750009 -0.321639 +v -0.391940 0.750009 -0.230197 +v -0.498530 0.712498 0.039883 +v -0.501667 0.699221 0.063813 +v 0.617684 0.235930 -0.085941 +v 0.619427 0.283145 -0.137236 +v 0.619427 0.283145 0.137236 +vn -0.901883 0.415418 0.118168 +vn -0.905637 0.407056 0.118656 +vn -0.877041 0.418744 0.235298 +vn 0.058443 -0.998260 0.000732 +vn 0.015107 -0.999878 0.000183 +vn 0.014557 -0.949278 0.314035 +vn 0.056703 -0.947539 0.314524 +vn 0.162053 -0.986755 0.002014 +vn 0.157933 -0.933592 0.321604 +vn 0.392376 -0.919767 0.004334 +vn 0.378307 -0.856655 0.350688 +vn 0.783776 -0.620991 0.005249 +vn 0.726829 -0.553880 0.406079 +vn 0.994812 -0.101627 0.001984 +vn 0.908139 -0.082766 0.410321 +vn 0.003082 -0.939787 0.341685 +vn 0.002167 -0.619495 0.784967 +vn 0.011536 -0.679403 0.733634 +vn 0.044679 -0.675588 0.735923 +vn 0.123325 -0.652272 0.747856 +vn 0.275399 -0.556871 0.783593 +vn 0.460067 -0.316263 0.829615 +vn 0.563036 -0.041200 0.825373 +vn -0.000427 0.122166 0.992492 +vn 0.000397 0.003632 0.999969 +vn 0.002869 0.011841 0.999908 +vn 0.004852 0.029298 0.999542 +vn -0.008179 0.053499 0.998505 +vn -0.046510 0.041536 0.998047 +vn -0.039155 0.003113 0.999207 +vn -0.850551 0.473769 -0.228217 +vn -0.897885 0.424177 -0.117649 +vn -0.880886 0.473281 0.000000 +vn -0.013611 0.682394 0.730827 +vn -0.053896 0.680441 0.730796 +vn -0.147557 0.656789 0.739464 +vn -0.325968 0.560564 0.761223 +vn -0.537645 0.315806 0.781762 +vn -0.611530 0.029939 0.790613 +vn -0.904172 0.427137 0.000000 +vn -0.897885 0.424146 0.117618 +vn -0.020112 0.949461 0.313150 +vn -0.081820 0.945433 0.315287 +vn -0.227699 0.916379 0.329173 +vn -0.504196 0.785302 0.359203 +vn -0.810633 0.443220 0.382611 +vn -0.921232 0.039705 0.386944 +vn -0.020569 0.949400 -0.313334 +vn -0.021729 0.999756 -0.000092 +vn -0.004242 0.950468 -0.310770 +vn -0.088260 0.996094 -0.000488 +vn -0.246895 0.969024 -0.001343 +vn -0.549730 0.835322 -0.002350 +vn -0.880673 0.473647 -0.001984 +vn -0.999084 0.042146 -0.000610 +vn -0.877041 0.418744 -0.235298 +vn -0.920286 0.391156 0.000000 +vn -0.905637 0.407056 -0.118656 +vn -0.083132 0.945006 -0.316202 +vn -0.230201 0.914823 -0.331797 +vn -0.505570 0.782800 -0.362743 +vn -0.808710 0.444960 -0.384625 +vn -0.920835 0.042055 -0.387646 +vn -0.897885 0.424146 -0.117618 +vn -0.901883 0.415448 -0.118168 +vn -0.014161 0.682394 -0.730796 +vn -0.055361 0.680074 -0.731010 +vn -0.150029 0.655660 -0.739982 +vn -0.327616 0.560594 -0.760491 +vn -0.537431 0.320933 -0.779809 +vn -0.611988 0.033387 -0.790155 +vn 0.015168 -0.949339 -0.313852 +vn 0.011902 -0.679403 -0.733634 +vn 0.003265 -0.939817 -0.341594 +vn 0.000183 0.004212 -0.999969 +vn 0.003510 0.014008 -0.999878 +vn 0.005921 0.035951 -0.999329 +vn -0.010132 0.064333 -0.997864 +vn -0.051576 0.048463 -0.997467 +vn -0.041597 0.003998 -0.999115 +vn 0.003082 -0.620106 -0.784478 +vn -0.000031 0.122440 -0.992462 +vn -0.897885 0.424177 0.117649 +vn 0.046449 -0.674398 -0.736869 +vn 0.125980 -0.648946 -0.750298 +vn 0.275430 -0.552477 -0.786676 +vn 0.455519 -0.320536 -0.830500 +vn 0.561693 -0.046480 -0.826014 +vn -0.888668 0.391644 0.238441 +vn 0.058046 -0.947630 -0.314005 +vn 0.159948 -0.933836 -0.319865 +vn 0.380169 -0.857753 -0.345927 +vn 0.725547 -0.560930 -0.398602 +vn 0.908597 -0.089236 -0.407971 +vn 0.003235 -0.999969 0.000031 +vn 0.973144 0.230110 0.000824 +vn 0.890896 0.211737 0.401776 +vn 0.912900 0.408094 0.002533 +vn 0.836970 0.380932 0.392834 +vn 0.829035 0.559160 0.003784 +vn 0.764519 0.528550 0.368969 +vn 0.718650 0.695334 0.003937 +vn 0.668294 0.663717 0.335917 +vn 0.579577 0.814905 0.002838 +vn 0.542650 0.779687 0.312357 +vn 0.495163 0.868770 0.002258 +vn 0.458052 0.820643 0.341624 +vn 0.561205 0.137028 0.816218 +vn 0.532029 0.253456 0.807886 +vn 0.497543 0.363445 0.787591 +vn 0.449538 0.472060 0.758293 +vn 0.373669 0.563555 0.736686 +vn 0.289041 0.531114 0.796442 +vn -0.023225 -0.005249 0.999695 +vn -0.016785 -0.010254 0.999786 +vn -0.011444 -0.012940 0.999847 +vn -0.009796 -0.013276 0.999847 +vn -0.014801 -0.013916 0.999786 +vn -0.089755 -0.176122 0.980255 +vn -0.585772 -0.152379 0.795984 +vn -0.538896 -0.288766 0.791314 +vn -0.484146 -0.407910 0.774071 +vn -0.424635 -0.509781 0.748161 +vn -0.355907 -0.584765 0.728935 +vn -0.889828 -0.237159 0.389782 +vn -0.808740 -0.446852 0.382366 +vn -0.702475 -0.613269 0.361095 +vn -0.590625 -0.734855 0.333293 +vn -0.483291 -0.816767 0.315104 +vn -0.912076 0.409955 0.000000 +vn -0.965606 -0.259987 -0.000458 +vn -0.872433 -0.488693 -0.001465 +vn -0.748436 -0.663167 -0.002197 +vn -0.621601 -0.783288 -0.002136 +vn -0.507065 -0.861873 -0.001251 +vn -0.438215 -0.854366 0.279183 +vn -0.456130 -0.889889 -0.000732 +vn -0.889126 -0.238868 -0.390332 +vn -0.807001 -0.448531 -0.384075 +vn -0.700980 -0.613392 -0.363750 +vn -0.590442 -0.733757 -0.336039 +vn -0.484787 -0.815332 -0.316477 +vn -0.440962 -0.852931 -0.279305 +vn -0.359691 -0.584185 -0.727531 +vn -0.358074 -0.682241 -0.637410 +vn -0.585467 -0.154668 -0.795770 +vn -0.538499 -0.291696 -0.790490 +vn -0.484512 -0.409772 -0.772851 +vn -0.426496 -0.510056 -0.746910 +vn -0.909543 -0.399274 -0.115207 +vn -0.971191 -0.204688 -0.121891 +vn -0.912931 -0.326609 -0.244606 +vn -0.020478 -0.017853 -0.999603 +vn -0.024537 -0.005737 -0.999664 +vn -0.020844 -0.012207 -0.999695 +vn -0.017548 -0.016846 -0.999695 +vn -0.016724 -0.018097 -0.999695 +vn -0.909116 -0.400311 0.115055 +vn -0.873775 -0.472610 0.114475 +vn -0.795892 -0.566485 0.213538 +vn -0.353069 -0.684103 0.638203 +vn 0.559679 0.139714 -0.816828 +vn 0.528581 0.255501 -0.809473 +vn 0.494217 0.362987 -0.789911 +vn 0.449049 0.469283 -0.760308 +vn 0.378246 0.560869 -0.736412 +vn -0.091983 -0.174383 -0.980346 +vn 0.295267 0.530625 -0.794488 +vn 0.890500 0.214759 -0.401044 +vn 0.836634 0.384075 -0.390515 +vn 0.765191 0.530198 -0.365123 +vn 0.671041 0.663228 -0.331339 +vn 0.547929 0.777642 -0.308206 +vn 0.464522 0.818842 -0.337199 +vn 0.931486 0.265572 -0.248543 +vn 0.939543 0.342357 0.000000 +vn 0.947539 0.295114 -0.122684 +vn -0.351421 0.936186 0.001953 +vn -0.144444 0.989502 0.003174 +vn -0.126743 0.878811 0.459975 +vn -0.716758 0.697287 -0.000946 +vn -0.299997 0.838313 0.455214 +vn -0.621876 0.660207 0.421155 +vn -0.901822 0.432081 -0.004517 +vn -0.807031 0.443434 0.389904 +vn -0.930204 0.366863 -0.008484 +vn -0.824549 0.383312 0.416059 +vn -0.850673 0.525529 -0.011628 +vn -0.722465 0.508988 0.467910 +vn -0.668447 0.743645 -0.011139 +vn -0.531449 0.686514 0.496170 +vn -0.116459 0.505448 0.854946 +vn -0.258400 0.470656 0.843593 +vn -0.407605 0.396985 0.822321 +vn -0.450270 0.352367 0.820399 +vn -0.385876 0.395734 0.833338 +vn -0.270669 0.487838 0.829890 +vn 0.141606 -0.001190 0.989898 +vn -0.067690 0.525346 0.848170 +vn 0.989593 0.100253 0.103122 +vn 0.970244 0.213324 0.114475 +vn 0.960418 0.152654 0.232917 +vn 0.241829 0.092502 0.965880 +vn 0.209296 0.170660 0.962828 +vn 0.096194 0.178625 0.979186 +vn 0.009552 0.154332 0.987945 +vn -0.000122 0.151952 0.988372 +vn 0.361248 -0.477279 0.801019 +vn 0.607929 -0.282540 0.741997 +vn 0.679220 -0.106754 0.726096 +vn 0.583911 -0.078524 0.807978 +vn 0.402722 -0.205237 0.891995 +vn 0.279519 -0.338694 0.898404 +vn 0.488601 -0.768700 0.412671 +vn 0.784570 -0.501511 0.364544 +vn 0.893918 -0.279611 0.350291 +vn 0.861415 -0.285287 0.420179 +vn 0.679373 -0.540452 0.496323 +vn 0.458327 -0.754540 0.469588 +vn 0.524155 -0.851588 -0.000153 +vn 0.827143 -0.561968 0.001679 +vn 0.943205 -0.332133 0.003479 +vn 0.933256 -0.359081 0.005737 +vn 0.756859 -0.653493 0.006470 +vn 0.492843 -0.870083 0.004120 +vn 0.322489 -0.946562 -0.001129 +vn 0.912839 -0.326609 0.244942 +vn 0.824396 -0.565996 0.000000 +vn 0.894162 -0.447676 0.000000 +vn 0.486557 -0.770501 -0.411756 +vn 0.783990 -0.504074 -0.362285 +vn 0.895199 -0.281899 -0.345134 +vn 0.863735 -0.289010 -0.412824 +vn 0.682119 -0.544267 -0.488296 +vn 0.461928 -0.758202 -0.460128 +vn 0.357463 -0.479141 -0.801599 +vn 0.605884 -0.285867 -0.742393 +vn 0.679739 -0.108646 -0.725333 +vn 0.583636 -0.077883 -0.808222 +vn 0.401440 -0.199225 -0.893918 +vn 0.281961 -0.330638 -0.900632 +vn 0.135228 -0.002380 -0.990783 +vn 0.235755 0.091128 -0.967498 +vn 0.200720 0.170629 -0.964660 +vn 0.086123 0.184576 -0.979003 +vn 0.000671 0.174322 -0.984680 +vn -0.007141 0.169012 -0.985565 +vn 0.966613 -0.042848 -0.252602 +vn 0.960418 0.152654 -0.232917 +vn 0.989593 0.100223 -0.103092 +vn -0.119297 0.503342 -0.855770 +vn -0.261269 0.472793 -0.841517 +vn -0.414075 0.399792 -0.817713 +vn -0.459700 0.357036 -0.813105 +vn -0.394024 0.408490 -0.823298 +vn -0.277871 0.487381 -0.827754 +vn -0.072207 0.520127 -0.851009 +vn -0.298654 0.840297 -0.452376 +vn -0.617512 0.663961 -0.421613 +vn -0.801324 0.450209 -0.393872 +vn -0.819422 0.389691 -0.420270 +vn -0.721274 0.506912 -0.471969 +vn -0.538347 0.670644 -0.510239 +vn -0.482009 0.876125 -0.005127 +vn -0.394635 0.815363 0.423536 +vn -0.321909 0.946745 -0.002594 +vn -0.255287 0.921995 0.291086 +vn 0.004242 0.999969 0.000397 +vn -0.002960 0.999939 -0.010102 +vn 0.853450 0.521073 -0.007050 +vn 0.392041 0.688986 -0.609546 +vn 0.805170 -0.592517 -0.023621 +vn 0.588763 -0.206122 -0.781579 +vn 0.681478 -0.731040 -0.033296 +vn 0.485031 -0.441237 -0.754967 +vn -0.206824 0.638203 0.741539 +vn -0.129490 0.862056 0.489944 +vn -0.033418 0.999176 0.022340 +vn 0.047700 0.864040 -0.501114 +vn 0.099307 0.538743 -0.836573 +vn 0.053560 0.251839 -0.966277 +vn 0.020112 0.322611 0.946287 +vn 0.021943 0.748894 0.662282 +vn -0.025941 0.995605 0.089908 +vn -0.059175 0.930876 -0.360424 +vn -0.080172 0.784448 -0.614948 +vn -0.142582 0.557604 -0.817743 +vn 0.281747 -0.174993 0.943388 +vn 0.303903 0.444136 0.842830 +vn 0.034333 0.983764 0.175970 +vn -0.113865 0.956420 -0.268777 +vn -0.155339 0.858852 -0.488021 +vn -0.207404 0.641865 -0.738182 +vn 0.467238 -0.683187 0.561144 +vn 0.699515 0.004364 0.714560 +vn 0.355296 0.891934 0.279641 +vn -0.170354 0.971465 -0.164861 +vn -0.245552 0.901181 -0.357097 +vn -0.248726 0.651082 -0.717063 +vn 0.494430 -0.869167 0.006317 +vn 0.933134 -0.358898 0.019868 +vn 0.703146 0.710685 0.021790 +vn -0.203650 0.978942 -0.012574 +vn -0.326456 0.942869 -0.066073 +vn -0.397595 0.857082 -0.327525 +vn 0.460616 -0.712546 -0.529221 +vn 0.695486 -0.098544 -0.711722 +vn 0.397534 0.853816 -0.336070 +vn -0.198248 0.963439 0.180151 +vn -0.306833 0.888516 0.341075 +vn -0.393689 0.807672 0.438887 +vn 0.276559 -0.211951 -0.937315 +vn 0.294626 0.366161 -0.882656 +vn 0.046632 0.973235 -0.224982 +vn -0.146733 0.912168 0.382611 +vn -0.202643 0.700797 0.683950 +vn -0.232673 0.506485 0.830226 +vn 0.011689 0.309397 -0.950835 +vn 0.013245 0.708640 -0.705435 +vn -0.027589 0.995758 -0.087680 +vn -0.047395 0.829371 0.556658 +vn -0.015259 0.386608 0.922086 +vn 0.004639 0.119510 0.992798 +vn -0.211035 0.631001 -0.746513 +vn -0.138768 0.848781 -0.510147 +vn -0.024995 0.999664 -0.001190 +vn 0.120426 0.724570 0.678579 +vn 0.260750 0.006531 0.965361 +vn 0.272500 -0.255898 0.927488 +vn -0.395581 0.809961 -0.432905 +vn -0.258827 0.918851 -0.297800 +vn 0.004730 0.999878 0.013031 +vn 0.466628 0.599780 0.649983 +vn 0.621937 -0.400861 0.672628 +vn 0.551042 -0.592181 0.587878 +vn 0.649068 0.384991 -0.656087 +vn 0.055971 0.691214 0.720450 +vn -0.115940 0.804590 0.582354 +vn -0.262185 0.897946 0.353435 +vn -0.341655 0.885006 -0.316263 +vn -0.081423 0.793085 -0.603626 +vn -0.155675 0.857753 -0.489883 +vn 0.728690 0.365978 0.578784 +vn 0.318674 0.539384 0.779382 +vn 0.953551 0.300150 -0.024415 +vn -0.133976 0.836818 -0.530808 +vn 0.095401 0.667959 -0.738029 +vn 0.000000 0.999969 0.000000 +vn -0.992523 -0.122013 0.000000 +vn -0.937346 -0.348338 0.000000 +vn -0.905148 -0.348827 -0.242836 +vn -0.958617 -0.122227 -0.257057 +vn -0.832057 0.554674 0.000000 +vn -0.803217 0.555376 -0.215339 +vn -0.048616 0.998810 0.000000 +vn -0.046236 0.998840 -0.012726 +vn 0.544267 0.838893 0.000000 +vn 0.525376 0.839106 0.140843 +vn 0.783471 0.621387 0.000000 +vn 0.756371 0.621845 0.202918 +vn 0.880886 0.473281 0.000000 +vn 0.850551 0.473769 0.228217 +vn -0.810907 -0.349376 -0.469375 +vn -0.859004 -0.122410 -0.497085 +vn -0.719657 0.555559 -0.416425 +vn -0.041749 0.998810 -0.024415 +vn 0.470077 0.839625 0.272011 +vn 0.677236 0.622608 0.391980 +vn 0.761803 0.474471 0.440962 +vn -0.662465 -0.349620 -0.662465 +vn -0.701773 -0.122440 -0.701773 +vn -0.587878 0.555650 -0.587878 +vn -0.034272 0.998810 -0.034272 +vn 0.383831 0.839808 0.383831 +vn 0.553148 0.622913 0.553148 +vn 0.622303 0.474776 0.622303 +vn -0.469375 -0.349376 -0.810907 +vn -0.497085 -0.122379 -0.859004 +vn -0.416425 0.555559 -0.719657 +vn -0.024415 0.998810 -0.041749 +vn 0.272011 0.839625 0.470077 +vn 0.391980 0.622608 0.677236 +vn 0.440962 0.474471 0.761834 +vn -0.242836 -0.348827 -0.905148 +vn -0.257057 -0.122227 -0.958617 +vn -0.215339 0.555376 -0.803217 +vn -0.012726 0.998840 -0.046205 +vn 0.140843 0.839106 0.525376 +vn 0.202918 0.621845 0.756371 +vn 0.228217 0.473769 0.850551 +vn 0.000000 -0.348338 -0.937346 +vn 0.000000 -0.122013 -0.992523 +vn 0.000000 0.554674 -0.832057 +vn 0.000000 0.998810 -0.048616 +vn 0.000000 0.838893 0.544267 +vn 0.000000 0.621387 0.783471 +vn 0.000000 0.473281 0.880886 +vn 0.242836 -0.348827 -0.905148 +vn 0.257057 -0.122227 -0.958617 +vn 0.215308 0.555376 -0.803217 +vn 0.012726 0.998840 -0.046205 +vn -0.140843 0.839106 0.525376 +vn -0.202918 0.621845 0.756340 +vn -0.228217 0.473769 0.850551 +vn 0.469375 -0.349376 -0.810907 +vn 0.497085 -0.122379 -0.859004 +vn 0.416425 0.555559 -0.719657 +vn 0.024415 0.998810 -0.041749 +vn -0.272011 0.839625 0.470077 +vn -0.391980 0.622608 0.677236 +vn -0.440962 0.474502 0.761803 +vn 0.662465 -0.349620 -0.662465 +vn 0.701773 -0.122471 -0.701773 +vn 0.587878 0.555650 -0.587878 +vn 0.034272 0.998810 -0.034272 +vn -0.383831 0.839808 0.383831 +vn -0.553148 0.622913 0.553148 +vn -0.622303 0.474776 0.622303 +vn 0.810907 -0.349406 -0.469375 +vn 0.859004 -0.122379 -0.497085 +vn 0.719657 0.555559 -0.416425 +vn 0.041749 0.998810 -0.024415 +vn -0.470077 0.839625 0.272011 +vn -0.677236 0.622608 0.391980 +vn -0.761803 0.474471 0.440962 +vn 0.905148 -0.348827 -0.242836 +vn 0.958617 -0.122227 -0.257057 +vn 0.803217 0.555376 -0.215339 +vn 0.046205 0.998840 -0.012726 +vn -0.525376 0.839106 0.140843 +vn -0.756340 0.621876 0.202918 +vn -0.850551 0.473769 0.228217 +vn 0.937346 -0.348338 0.000000 +vn 0.992523 -0.122013 0.000000 +vn 0.832026 0.554674 0.000000 +vn 0.048616 0.998810 0.000000 +vn -0.544267 0.838893 0.000000 +vn -0.783471 0.621387 0.000000 +vn 0.905148 -0.348827 0.242836 +vn 0.958617 -0.122227 0.257057 +vn 0.803217 0.555376 0.215308 +vn 0.046205 0.998840 0.012726 +vn -0.525376 0.839106 -0.140843 +vn -0.756340 0.621876 -0.202918 +vn 0.810907 -0.349406 0.469375 +vn 0.859004 -0.122379 0.497085 +vn 0.719657 0.555559 0.416425 +vn 0.041749 0.998810 0.024415 +vn -0.470077 0.839625 -0.272011 +vn -0.677236 0.622608 -0.391980 +vn -0.761803 0.474471 -0.440962 +vn 0.662465 -0.349620 0.662465 +vn 0.701773 -0.122471 0.701773 +vn 0.587878 0.555650 0.587878 +vn 0.034272 0.998810 0.034272 +vn -0.383831 0.839808 -0.383831 +vn -0.553148 0.622913 -0.553148 +vn -0.622303 0.474776 -0.622303 +vn 0.469375 -0.349376 0.810907 +vn 0.497085 -0.122379 0.859004 +vn 0.416425 0.555559 0.719657 +vn 0.024415 0.998810 0.041749 +vn -0.272011 0.839625 -0.470077 +vn -0.391980 0.622608 -0.677236 +vn -0.440962 0.474471 -0.761803 +vn 0.242836 -0.348827 0.905148 +vn 0.257057 -0.122227 0.958617 +vn 0.215339 0.555376 0.803217 +vn 0.012726 0.998840 0.046205 +vn -0.140843 0.839106 -0.525376 +vn -0.202918 0.621845 -0.756371 +vn -0.228217 0.473769 -0.850551 +vn 0.000000 -0.348338 0.937346 +vn 0.000000 -0.122013 0.992523 +vn 0.000000 0.554674 0.832057 +vn 0.000000 0.998810 0.048616 +vn 0.000000 0.838893 -0.544267 +vn 0.000000 0.621387 -0.783471 +vn 0.000000 0.473281 -0.880886 +vn -0.242836 -0.348827 0.905148 +vn -0.257057 -0.122227 0.958617 +vn -0.215308 0.555376 0.803217 +vn -0.012726 0.998840 0.046205 +vn 0.140843 0.839106 -0.525376 +vn 0.202918 0.621845 -0.756371 +vn 0.228217 0.473769 -0.850551 +vn -0.469375 -0.349376 0.810907 +vn -0.497085 -0.122379 0.859004 +vn -0.416425 0.555559 0.719657 +vn -0.024415 0.998810 0.041749 +vn 0.272011 0.839625 -0.470077 +vn 0.391980 0.622608 -0.677236 +vn 0.440962 0.474471 -0.761803 +vn -0.662465 -0.349620 0.662465 +vn -0.701773 -0.122440 0.701773 +vn -0.587878 0.555650 0.587878 +vn -0.034272 0.998810 0.034272 +vn 0.383831 0.839808 -0.383831 +vn 0.553148 0.622913 -0.553148 +vn 0.622303 0.474776 -0.622303 +vn -0.810907 -0.349376 0.469375 +vn -0.859004 -0.122410 0.497085 +vn -0.719657 0.555528 0.416425 +vn -0.041749 0.998810 0.024415 +vn 0.470077 0.839625 -0.272011 +vn 0.677236 0.622639 -0.391980 +vn 0.761803 0.474471 -0.440962 +vn -0.905148 -0.348827 0.242836 +vn -0.958617 -0.122227 0.257057 +vn -0.803217 0.555376 0.215339 +vn -0.046236 0.998840 0.012726 +vn 0.525376 0.839106 -0.140843 +vn 0.756371 0.621845 -0.202918 +vn 0.850551 0.473769 -0.228217 +vn 0.908292 0.418256 0.000000 +vn 0.877041 0.418744 0.235298 +vn 0.920286 0.391156 0.000000 +vn 0.888668 0.391644 0.238441 +vn 0.907315 0.342753 0.243446 +vn 0.785638 0.419416 0.454756 +vn 0.796075 0.392285 0.460799 +vn 0.812830 0.343333 0.470504 +vn 0.931486 0.265542 0.248543 +vn 0.834162 0.266366 0.482864 +vn 0.855312 0.152379 0.495132 +vn 0.966613 -0.042848 0.252602 +vn 0.864498 -0.045808 0.500504 +vn 0.641804 0.419691 0.641804 +vn 0.650349 0.392499 0.650349 +vn 0.664052 0.343577 0.664052 +vn 0.681509 0.266579 0.681509 +vn 0.698813 0.152501 0.698813 +vn 0.706351 -0.045869 0.706351 +vn 0.454756 0.419416 0.785638 +vn 0.460799 0.392285 0.796075 +vn 0.470504 0.343333 0.812830 +vn 0.482864 0.266366 0.834162 +vn 0.495132 0.152409 0.855312 +vn 0.500504 -0.045808 0.864498 +vn 0.235298 0.418744 0.877041 +vn 0.238441 0.391644 0.888668 +vn 0.243446 0.342753 0.907315 +vn 0.249855 0.265908 0.931028 +vn 0.256172 0.152104 0.954558 +vn 0.258980 -0.045717 0.964782 +vn 0.000000 0.418256 0.908292 +vn 0.000000 0.391156 0.920286 +vn 0.000000 0.342357 0.939543 +vn 0.000000 0.265542 0.964080 +vn 0.000000 0.151891 0.988372 +vn 0.000000 -0.045656 0.998932 +vn -0.235298 0.418744 0.877041 +vn -0.238441 0.391644 0.888668 +vn -0.243446 0.342753 0.907315 +vn -0.249855 0.265877 0.931028 +vn -0.256172 0.152104 0.954558 +vn -0.258980 -0.045717 0.964782 +vn -0.454756 0.419416 0.785638 +vn -0.460799 0.392285 0.796075 +vn -0.470504 0.343333 0.812830 +vn -0.482864 0.266366 0.834162 +vn -0.495132 0.152379 0.855312 +vn -0.500504 -0.045808 0.864498 +vn -0.641804 0.419691 0.641804 +vn -0.650349 0.392499 0.650349 +vn -0.664052 0.343577 0.664052 +vn -0.681509 0.266579 0.681509 +vn -0.698813 0.152501 0.698813 +vn -0.706351 -0.045869 0.706351 +vn -0.785638 0.419416 0.454756 +vn -0.796075 0.392285 0.460799 +vn -0.812830 0.343364 0.470504 +vn -0.834162 0.266366 0.482864 +vn -0.855312 0.152379 0.495132 +vn -0.864498 -0.045808 0.500504 +vn -0.907315 0.342753 0.243446 +vn -0.931028 0.265908 0.249855 +vn -0.954558 0.152104 0.256172 +vn -0.964782 -0.045717 0.258980 +vn -0.939543 0.342357 0.000000 +vn -0.964080 0.265542 0.000000 +vn -0.988372 0.151891 0.000000 +vn -0.888668 0.391644 -0.238441 +vn -0.907315 0.342753 -0.243446 +vn -0.931028 0.265877 -0.249855 +vn -0.954558 0.152104 -0.256172 +vn -0.785638 0.419416 -0.454756 +vn -0.796075 0.392285 -0.460799 +vn -0.812830 0.343333 -0.470504 +vn -0.834162 0.266366 -0.482864 +vn -0.855312 0.152379 -0.495132 +vn -0.964782 -0.045717 -0.258980 +vn -0.864498 -0.045808 -0.500504 +vn -0.641804 0.419691 -0.641804 +vn -0.650349 0.392499 -0.650349 +vn -0.664052 0.343577 -0.664052 +vn -0.681509 0.266579 -0.681509 +vn -0.698813 0.152501 -0.698813 +vn -0.706351 -0.045869 -0.706351 +vn -0.454756 0.419416 -0.785638 +vn -0.460799 0.392285 -0.796075 +vn -0.470504 0.343333 -0.812830 +vn -0.482864 0.266366 -0.834162 +vn -0.495132 0.152379 -0.855312 +vn -0.500504 -0.045808 -0.864498 +vn -0.235298 0.418744 -0.877041 +vn -0.238441 0.391644 -0.888668 +vn -0.243446 0.342753 -0.907315 +vn -0.249855 0.265908 -0.931028 +vn -0.256172 0.152104 -0.954558 +vn -0.258980 -0.045717 -0.964782 +vn 0.000000 0.418256 -0.908292 +vn 0.000000 0.391156 -0.920286 +vn 0.000000 0.342357 -0.939543 +vn 0.000000 0.265542 -0.964080 +vn 0.000000 0.151891 -0.988372 +vn 0.000000 -0.045656 -0.998932 +vn 0.235298 0.418744 -0.877041 +vn 0.238441 0.391644 -0.888668 +vn 0.243446 0.342753 -0.907315 +vn 0.249855 0.265877 -0.931028 +vn 0.256172 0.152104 -0.954558 +vn 0.258980 -0.045717 -0.964782 +vn 0.454756 0.419416 -0.785638 +vn 0.460799 0.392285 -0.796075 +vn 0.470504 0.343333 -0.812830 +vn 0.482864 0.266366 -0.834162 +vn 0.495132 0.152379 -0.855312 +vn 0.500504 -0.045808 -0.864498 +vn 0.641804 0.419691 -0.641804 +vn 0.650349 0.392499 -0.650349 +vn 0.664052 0.343577 -0.664052 +vn 0.681509 0.266579 -0.681509 +vn 0.698813 0.152501 -0.698813 +vn 0.706351 -0.045869 -0.706351 +vn 0.785638 0.419416 -0.454756 +vn 0.796075 0.392285 -0.460799 +vn 0.812830 0.343364 -0.470504 +vn 0.834162 0.266366 -0.482864 +vn 0.855312 0.152379 -0.495132 +vn 0.864498 -0.045808 -0.500504 +vn 0.877041 0.418744 -0.235298 +vn 0.888668 0.391644 -0.238441 +vn 0.907315 0.342753 -0.243446 +vn 0.795892 -0.566485 0.213538 +vn 0.712180 -0.701987 0.000000 +vn 0.687399 -0.702445 0.184393 +vn 0.652974 -0.757347 0.000000 +vn 0.630146 -0.757805 0.169012 +vn 0.724021 -0.689749 0.000000 +vn 0.698752 -0.690329 0.187414 +vn 0.886410 -0.462874 0.000000 +vn 0.855861 -0.463454 0.229530 +vn 0.817774 -0.327158 0.473434 +vn 0.712729 -0.567248 0.412549 +vn 0.615345 -0.703146 0.356151 +vn 0.564043 -0.758446 0.326456 +vn 0.625660 -0.690939 0.362102 +vn 0.766625 -0.464125 0.443678 +vn 0.668111 -0.327403 0.668111 +vn 0.582171 -0.567522 0.582171 +vn 0.502579 -0.703421 0.502579 +vn 0.460646 -0.758660 0.460646 +vn 0.510971 -0.691183 0.510971 +vn 0.626209 -0.464370 0.626240 +vn 0.473434 -0.327158 0.817774 +vn 0.412549 -0.567248 0.712729 +vn 0.356151 -0.703146 0.615375 +vn 0.326456 -0.758446 0.564043 +vn 0.362102 -0.690939 0.625660 +vn 0.443678 -0.464125 0.766625 +vn 0.245003 -0.326609 0.912839 +vn 0.213538 -0.566485 0.795892 +vn 0.184393 -0.702445 0.687399 +vn 0.169012 -0.757805 0.630146 +vn 0.187414 -0.690329 0.698752 +vn 0.229530 -0.463454 0.855831 +vn 0.000000 -0.326243 0.945250 +vn 0.000000 -0.565996 0.824396 +vn 0.000000 -0.701987 0.712180 +vn 0.000000 -0.757347 0.652974 +vn 0.000000 -0.689749 0.724021 +vn 0.000000 -0.462905 0.886380 +vn -0.245003 -0.326609 0.912839 +vn -0.213538 -0.566485 0.795892 +vn -0.184393 -0.702445 0.687399 +vn -0.169012 -0.757805 0.630146 +vn -0.187414 -0.690329 0.698752 +vn -0.229530 -0.463454 0.855861 +vn -0.473434 -0.327158 0.817774 +vn -0.412549 -0.567248 0.712729 +vn -0.356151 -0.703146 0.615375 +vn -0.326456 -0.758446 0.564043 +vn -0.362102 -0.690939 0.625660 +vn -0.443678 -0.464125 0.766625 +vn -0.668111 -0.327403 0.668111 +vn -0.582171 -0.567522 0.582171 +vn -0.502579 -0.703421 0.502579 +vn -0.460646 -0.758660 0.460646 +vn -0.510971 -0.691183 0.510971 +vn -0.626209 -0.464370 0.626209 +vn -0.817774 -0.327158 0.473434 +vn -0.712729 -0.567248 0.412549 +vn -0.615375 -0.703146 0.356151 +vn -0.564043 -0.758446 0.326456 +vn -0.625660 -0.690939 0.362102 +vn -0.766625 -0.464125 0.443678 +vn -0.912931 -0.326609 0.244575 +vn -0.687399 -0.702445 0.184393 +vn -0.630146 -0.757805 0.169012 +vn -0.698752 -0.690329 0.187414 +vn -0.855831 -0.463485 0.229530 +vn -0.824396 -0.565996 0.000000 +vn -0.712180 -0.701987 0.000000 +vn -0.652974 -0.757347 0.000000 +vn -0.724021 -0.689749 0.000000 +vn -0.886410 -0.462874 0.000000 +vn -0.795892 -0.566485 -0.213538 +vn -0.687399 -0.702445 -0.184393 +vn -0.630146 -0.757805 -0.169012 +vn -0.698752 -0.690329 -0.187414 +vn -0.855831 -0.463454 -0.229530 +vn -0.817774 -0.327158 -0.473434 +vn -0.712729 -0.567217 -0.412549 +vn -0.615375 -0.703146 -0.356151 +vn -0.564043 -0.758446 -0.326456 +vn -0.625660 -0.690939 -0.362102 +vn -0.766625 -0.464125 -0.443678 +vn -0.668111 -0.327403 -0.668111 +vn -0.582171 -0.567522 -0.582171 +vn -0.502579 -0.703421 -0.502579 +vn -0.460646 -0.758660 -0.460646 +vn -0.510971 -0.691183 -0.510971 +vn -0.626209 -0.464370 -0.626209 +vn -0.473434 -0.327158 -0.817774 +vn -0.412549 -0.567248 -0.712729 +vn -0.356151 -0.703146 -0.615375 +vn -0.326456 -0.758446 -0.564043 +vn -0.362102 -0.690939 -0.625660 +vn -0.443678 -0.464125 -0.766625 +vn -0.245003 -0.326609 -0.912839 +vn -0.213538 -0.566485 -0.795892 +vn -0.184393 -0.702445 -0.687399 +vn -0.169012 -0.757805 -0.630146 +vn -0.187414 -0.690329 -0.698752 +vn -0.229530 -0.463454 -0.855831 +vn 0.000000 -0.326243 -0.945250 +vn 0.000000 -0.565996 -0.824396 +vn 0.000000 -0.701987 -0.712180 +vn 0.000000 -0.757347 -0.652974 +vn 0.000000 -0.689749 -0.724021 +vn 0.000000 -0.462905 -0.886380 +vn 0.245003 -0.326609 -0.912839 +vn 0.213538 -0.566485 -0.795892 +vn 0.184393 -0.702445 -0.687399 +vn 0.169012 -0.757805 -0.630146 +vn 0.187445 -0.690329 -0.698752 +vn 0.229530 -0.463454 -0.855861 +vn 0.473434 -0.327158 -0.817774 +vn 0.412549 -0.567248 -0.712729 +vn 0.356151 -0.703146 -0.615375 +vn 0.326456 -0.758446 -0.564043 +vn 0.362102 -0.690939 -0.625660 +vn 0.443678 -0.464125 -0.766625 +vn 0.668111 -0.327403 -0.668111 +vn 0.582171 -0.567522 -0.582171 +vn 0.502579 -0.703421 -0.502579 +vn 0.460646 -0.758660 -0.460646 +vn 0.510971 -0.691183 -0.510971 +vn 0.626209 -0.464370 -0.626209 +vn 0.817774 -0.327158 -0.473434 +vn 0.712729 -0.567248 -0.412549 +vn 0.615375 -0.703146 -0.356151 +vn 0.564043 -0.758446 -0.326456 +vn 0.625660 -0.690939 -0.362102 +vn 0.766625 -0.464125 -0.443678 +vn 0.912839 -0.326609 -0.244942 +vn 0.795892 -0.566485 -0.213538 +vn 0.687399 -0.702445 -0.184393 +vn 0.630146 -0.757805 -0.169012 +vn 0.698752 -0.690329 -0.187414 +vn 0.855861 -0.463454 -0.229530 +vn 0.025666 -0.999664 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.024781 -0.999664 -0.006623 +vn 0.068667 -0.997620 0.000000 +vn 0.066256 -0.997620 -0.017731 +vn 0.157170 -0.987548 0.000000 +vn 0.151677 -0.987579 -0.040620 +vn 0.373150 -0.927763 0.000000 +vn 0.360118 -0.927885 -0.096469 +vn 0.789148 -0.614154 0.000000 +vn 0.762017 -0.614399 -0.204505 +vn 0.022156 -0.999664 -0.012787 +vn 0.059236 -0.997650 -0.034272 +vn 0.135624 -0.987640 -0.078463 +vn 0.322153 -0.928129 -0.186377 +vn 0.682333 -0.615131 -0.394971 +vn 0.018067 -0.999664 -0.018067 +vn 0.048341 -0.997650 -0.048341 +vn 0.110691 -0.987640 -0.110691 +vn 0.262947 -0.928251 -0.262947 +vn 0.557329 -0.615375 -0.557329 +vn 0.012787 -0.999664 -0.022156 +vn 0.034272 -0.997650 -0.059236 +vn 0.078463 -0.987640 -0.135624 +vn 0.186377 -0.928129 -0.322153 +vn 0.394971 -0.615131 -0.682302 +vn 0.006623 -0.999664 -0.024781 +vn 0.017731 -0.997620 -0.066256 +vn 0.040620 -0.987579 -0.151677 +vn 0.096469 -0.927885 -0.360118 +vn 0.204474 -0.614399 -0.762017 +vn 0.000000 -0.999664 -0.025666 +vn 0.000000 -0.997620 -0.068667 +vn 0.000000 -0.987548 -0.157170 +vn 0.000000 -0.927763 -0.373150 +vn 0.000000 -0.614154 -0.789148 +vn -0.006623 -0.999664 -0.024781 +vn -0.017731 -0.997620 -0.066256 +vn -0.040620 -0.987579 -0.151677 +vn -0.096469 -0.927885 -0.360118 +vn -0.204474 -0.614399 -0.762017 +vn -0.012787 -0.999664 -0.022156 +vn -0.034272 -0.997650 -0.059236 +vn -0.078463 -0.987640 -0.135624 +vn -0.186377 -0.928129 -0.322153 +vn -0.394971 -0.615131 -0.682333 +vn -0.018067 -0.999664 -0.018067 +vn -0.048341 -0.997650 -0.048341 +vn -0.110691 -0.987640 -0.110691 +vn -0.262947 -0.928251 -0.262947 +vn -0.557329 -0.615375 -0.557329 +vn -0.022156 -0.999664 -0.012787 +vn -0.059236 -0.997650 -0.034272 +vn -0.135624 -0.987640 -0.078463 +vn -0.322153 -0.928129 -0.186377 +vn -0.682302 -0.615131 -0.394971 +vn -0.024781 -0.999664 -0.006623 +vn -0.066256 -0.997620 -0.017731 +vn -0.151677 -0.987579 -0.040620 +vn -0.360118 -0.927885 -0.096469 +vn -0.762017 -0.614399 -0.204474 +vn -0.025666 -0.999664 0.000000 +vn -0.068667 -0.997620 0.000000 +vn -0.157170 -0.987548 0.000000 +vn -0.373150 -0.927763 0.000000 +vn -0.789148 -0.614154 0.000000 +vn -0.024781 -0.999664 0.006623 +vn -0.066256 -0.997620 0.017731 +vn -0.151677 -0.987579 0.040620 +vn -0.360149 -0.927885 0.096469 +vn -0.762017 -0.614399 0.204474 +vn -0.022156 -0.999664 0.012787 +vn -0.059236 -0.997650 0.034272 +vn -0.135624 -0.987640 0.078463 +vn -0.322153 -0.928129 0.186377 +vn -0.682333 -0.615131 0.394971 +vn -0.018067 -0.999664 0.018067 +vn -0.048341 -0.997650 0.048341 +vn -0.110691 -0.987640 0.110691 +vn -0.262947 -0.928251 0.262947 +vn -0.557329 -0.615375 0.557329 +vn -0.012787 -0.999664 0.022156 +vn -0.034272 -0.997650 0.059236 +vn -0.078463 -0.987640 0.135624 +vn -0.186377 -0.928129 0.322153 +vn -0.394971 -0.615131 0.682302 +vn -0.006623 -0.999664 0.024781 +vn -0.017731 -0.997620 0.066256 +vn -0.040620 -0.987579 0.151677 +vn -0.096469 -0.927885 0.360118 +vn -0.204474 -0.614399 0.762017 +vn 0.000000 -0.999664 0.025666 +vn 0.000000 -0.997620 0.068667 +vn 0.000000 -0.987548 0.157170 +vn 0.000000 -0.927763 0.373150 +vn 0.000000 -0.614154 0.789148 +vn 0.006623 -0.999664 0.024781 +vn 0.017731 -0.997620 0.066256 +vn 0.040620 -0.987579 0.151677 +vn 0.096469 -0.927885 0.360149 +vn 0.204474 -0.614399 0.762017 +vn 0.012787 -0.999664 0.022156 +vn 0.034272 -0.997650 0.059236 +vn 0.078463 -0.987640 0.135624 +vn 0.186377 -0.928129 0.322153 +vn 0.394971 -0.615131 0.682333 +vn 0.018067 -0.999664 0.018067 +vn 0.048341 -0.997650 0.048341 +vn 0.110691 -0.987640 0.110691 +vn 0.262947 -0.928251 0.262947 +vn 0.557329 -0.615375 0.557329 +vn 0.022156 -0.999664 0.012787 +vn 0.059236 -0.997650 0.034272 +vn 0.135624 -0.987640 0.078463 +vn 0.322153 -0.928129 0.186346 +vn 0.682302 -0.615131 0.394971 +vn 0.024781 -0.999664 0.006623 +vn 0.066256 -0.997620 0.017731 +vn 0.151677 -0.987579 0.040620 +vn 0.360118 -0.927885 0.096469 +vn 0.762017 -0.614399 0.204474 +vn 0.464827 -0.373638 -0.802667 +vn 0.655812 -0.373882 -0.655812 +vn 0.000000 -0.372539 0.927976 +vn -0.240699 -0.373028 0.896023 +vn -0.802667 -0.373608 0.464827 +vn 0.896023 -0.372997 -0.240699 +vn -0.927976 -0.372539 0.000000 +vn 0.927976 -0.372539 0.000000 +vn 0.717063 0.696982 0.000000 +vn 0.990387 -0.138310 -0.000061 +vn 0.956694 -0.138737 0.255806 +vn 0.692129 0.697470 0.185583 +vn 0.857326 -0.139317 0.495529 +vn 0.620045 0.697653 0.358837 +vn 0.700125 -0.139531 0.700217 +vn 0.506516 0.697714 0.506546 +vn 0.495468 -0.139286 0.857356 +vn 0.358776 0.697714 0.620014 +vn 0.255867 -0.138737 0.956694 +vn 0.185583 0.697531 0.692068 +vn 0.000061 -0.138310 0.990387 +vn 0.000000 0.696982 0.717063 +vn -0.255806 -0.138737 0.956694 +vn -0.185583 0.697470 0.692129 +vn -0.495529 -0.139317 0.857326 +vn -0.358837 0.697653 0.620045 +vn -0.700217 -0.139531 0.700156 +vn -0.506546 0.697714 0.506516 +vn -0.857356 -0.139286 0.495468 +vn -0.620014 0.697714 0.358776 +vn -0.956694 -0.138737 0.255867 +vn -0.692068 0.697531 0.185583 +vn -0.990387 -0.138310 0.000061 +vn -0.717063 0.696982 0.000000 +vn -0.956694 -0.138737 -0.255806 +vn -0.692129 0.697470 -0.185583 +vn -0.857326 -0.139317 -0.495529 +vn -0.620045 0.697653 -0.358837 +vn -0.700125 -0.139531 -0.700217 +vn -0.506516 0.697714 -0.506546 +vn -0.495468 -0.139286 -0.857356 +vn -0.358776 0.697714 -0.620014 +vn -0.255867 -0.138737 -0.956694 +vn -0.185583 0.697531 -0.692068 +vn -0.000061 -0.138310 -0.990387 +vn 0.000000 0.696982 -0.717063 +vn 0.255806 -0.138737 -0.956694 +vn 0.185583 0.697470 -0.692129 +vn 0.495529 -0.139317 -0.857326 +vn 0.358837 0.697653 -0.620045 +vn 0.700217 -0.139531 -0.700156 +vn 0.506546 0.697714 -0.506516 +vn 0.857356 -0.139286 -0.495468 +vn 0.620014 0.697714 -0.358776 +vn 0.956694 -0.138737 -0.255867 +vn 0.692068 0.697531 -0.185583 +vn 0.292520 0.956236 0.000000 +vn 0.282083 0.956389 0.075686 +vn 0.177953 0.984008 0.000000 +vn 0.171606 0.984069 0.046022 +vn 0.158879 0.987274 0.000000 +vn 0.153264 0.987304 0.041078 +vn 0.217719 0.975982 0.000000 +vn 0.210059 0.976043 0.056276 +vn 0.504715 0.863277 0.000000 +vn 0.487197 0.863460 0.130558 +vn 0.693258 0.720664 0.000000 +vn 0.669057 0.721183 0.179449 +vn 0.252388 0.956511 0.146092 +vn 0.153508 0.984130 0.088839 +vn 0.137059 0.987365 0.079318 +vn 0.187872 0.976135 0.108676 +vn 0.435926 0.863887 0.252205 +vn 0.598956 0.721824 0.346660 +vn 0.206091 0.956572 0.206091 +vn 0.125340 0.984161 0.125340 +vn 0.111911 0.987396 0.111911 +vn 0.153356 0.976196 0.153356 +vn 0.355907 0.864071 0.355907 +vn 0.489151 0.722098 0.489151 +vn 0.146092 0.956511 0.252388 +vn 0.088839 0.984130 0.153508 +vn 0.079318 0.987365 0.137059 +vn 0.108676 0.976135 0.187872 +vn 0.252205 0.863887 0.435926 +vn 0.346660 0.721824 0.598956 +vn 0.075686 0.956389 0.282083 +vn 0.046022 0.984069 0.171606 +vn 0.041078 0.987304 0.153264 +vn 0.056276 0.976043 0.210059 +vn 0.130558 0.863460 0.487197 +vn 0.179449 0.721183 0.669057 +vn 0.000000 0.956236 0.292520 +vn 0.000000 0.984008 0.177953 +vn 0.000000 0.987274 0.158879 +vn 0.000000 0.975982 0.217719 +vn 0.000000 0.863277 0.504715 +vn 0.000000 0.720664 0.693258 +vn -0.075686 0.956389 0.282083 +vn -0.046022 0.984069 0.171606 +vn -0.041078 0.987304 0.153264 +vn -0.056276 0.976043 0.210059 +vn -0.130558 0.863460 0.487197 +vn -0.179449 0.721183 0.669057 +vn -0.146092 0.956511 0.252388 +vn -0.088839 0.984130 0.153508 +vn -0.079318 0.987365 0.137059 +vn -0.108676 0.976135 0.187872 +vn -0.252205 0.863887 0.435926 +vn -0.346660 0.721824 0.598956 +vn -0.206091 0.956572 0.206091 +vn -0.125340 0.984161 0.125340 +vn -0.111911 0.987396 0.111911 +vn -0.153356 0.976196 0.153356 +vn -0.355907 0.864071 0.355907 +vn -0.489151 0.722098 0.489151 +vn -0.252388 0.956511 0.146092 +vn -0.153508 0.984130 0.088839 +vn -0.137059 0.987365 0.079318 +vn -0.187872 0.976135 0.108676 +vn -0.435926 0.863887 0.252205 +vn -0.598956 0.721824 0.346660 +vn -0.282083 0.956389 0.075686 +vn -0.171606 0.984069 0.046022 +vn -0.153264 0.987304 0.041078 +vn -0.210059 0.976043 0.056276 +vn -0.487197 0.863460 0.130558 +vn -0.669057 0.721183 0.179449 +vn -0.292520 0.956236 0.000000 +vn -0.177953 0.984008 0.000000 +vn -0.158879 0.987274 0.000000 +vn -0.217719 0.975982 0.000000 +vn -0.504715 0.863277 0.000000 +vn -0.693258 0.720664 0.000000 +vn -0.282083 0.956389 -0.075686 +vn -0.171606 0.984069 -0.046022 +vn -0.153264 0.987304 -0.041078 +vn -0.210059 0.976043 -0.056276 +vn -0.487197 0.863460 -0.130558 +vn -0.669057 0.721183 -0.179449 +vn -0.252388 0.956511 -0.146092 +vn -0.153508 0.984130 -0.088839 +vn -0.137059 0.987365 -0.079318 +vn -0.187872 0.976135 -0.108676 +vn -0.435926 0.863887 -0.252205 +vn -0.598956 0.721824 -0.346660 +vn -0.206091 0.956572 -0.206091 +vn -0.125340 0.984161 -0.125340 +vn -0.111911 0.987396 -0.111911 +vn -0.153356 0.976196 -0.153356 +vn -0.355907 0.864071 -0.355907 +vn -0.489151 0.722098 -0.489151 +vn -0.146092 0.956511 -0.252388 +vn -0.088839 0.984130 -0.153508 +vn -0.079318 0.987365 -0.137059 +vn -0.108676 0.976135 -0.187872 +vn -0.252205 0.863887 -0.435926 +vn -0.346660 0.721824 -0.598956 +vn -0.075686 0.956389 -0.282083 +vn -0.046022 0.984069 -0.171606 +vn -0.041078 0.987304 -0.153264 +vn -0.056276 0.976043 -0.210059 +vn -0.130558 0.863460 -0.487197 +vn -0.179449 0.721183 -0.669057 +vn 0.000000 0.956236 -0.292520 +vn 0.000000 0.984008 -0.177953 +vn 0.000000 0.987274 -0.158879 +vn 0.000000 0.975982 -0.217719 +vn 0.000000 0.863277 -0.504715 +vn 0.000000 0.720664 -0.693258 +vn 0.075686 0.956389 -0.282083 +vn 0.046022 0.984069 -0.171606 +vn 0.041078 0.987304 -0.153264 +vn 0.056276 0.976043 -0.210059 +vn 0.130558 0.863460 -0.487197 +vn 0.179449 0.721183 -0.669057 +vn 0.146092 0.956511 -0.252388 +vn 0.088839 0.984130 -0.153508 +vn 0.079318 0.987365 -0.137059 +vn 0.108676 0.976135 -0.187872 +vn 0.252205 0.863887 -0.435926 +vn 0.346660 0.721824 -0.598956 +vn 0.206091 0.956572 -0.206091 +vn 0.125340 0.984161 -0.125340 +vn 0.111911 0.987396 -0.111911 +vn 0.153356 0.976196 -0.153356 +vn 0.355907 0.864071 -0.355907 +vn 0.489151 0.722098 -0.489151 +vn 0.252388 0.956511 -0.146092 +vn 0.153508 0.984130 -0.088839 +vn 0.137059 0.987365 -0.079318 +vn 0.187872 0.976135 -0.108676 +vn 0.435926 0.863887 -0.252205 +vn 0.598956 0.721824 -0.346660 +vn 0.282083 0.956389 -0.075686 +vn 0.171606 0.984069 -0.046022 +vn 0.153264 0.987304 -0.041078 +vn 0.210059 0.976043 -0.056276 +vn 0.487197 0.863460 -0.130558 +vn 0.669057 0.721183 -0.179449 +vn 0.363842 0.931455 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.351451 0.931516 0.093509 +vn 0.968261 0.249916 0.000000 +vn 0.935423 0.249763 0.250130 +vn 0.842860 -0.538102 0.000000 +vn 0.813959 -0.538713 0.217292 +vn 0.786767 -0.617206 -0.000031 +vn 0.759514 -0.618000 0.202857 +vn 0.314432 0.931791 0.181280 +vn 0.838404 0.249855 0.484359 +vn 0.729026 -0.539720 0.420911 +vn 0.680013 -0.619068 0.392743 +vn 0.256386 0.931913 0.256417 +vn 0.684652 0.249886 0.684652 +vn 0.595050 -0.540147 0.595050 +vn 0.555010 -0.619526 0.555040 +vn 0.181280 0.931791 0.314432 +vn 0.484359 0.249825 0.838404 +vn 0.420881 -0.539720 0.729026 +vn 0.392712 -0.619098 0.680013 +vn 0.093509 0.931516 0.351451 +vn 0.250160 0.249763 0.935423 +vn 0.217322 -0.538713 0.813959 +vn 0.202887 -0.618030 0.759484 +vn 0.000000 0.931455 0.363842 +vn 0.000000 0.249916 0.968261 +vn 0.000000 -0.538102 0.842860 +vn 0.000031 -0.617206 0.786767 +vn -0.093509 0.931516 0.351451 +vn -0.250130 0.249763 0.935423 +vn -0.217292 -0.538682 0.813959 +vn -0.202857 -0.618000 0.759514 +vn -0.181280 0.931791 0.314432 +vn -0.484359 0.249855 0.838404 +vn -0.420911 -0.539720 0.729026 +vn -0.392743 -0.619068 0.680013 +vn -0.256417 0.931913 0.256386 +vn -0.684652 0.249886 0.684652 +vn -0.595050 -0.540147 0.595050 +vn -0.555040 -0.619526 0.555010 +vn -0.314432 0.931791 0.181280 +vn -0.838404 0.249825 0.484359 +vn -0.729026 -0.539720 0.420881 +vn -0.680013 -0.619098 0.392712 +vn -0.351451 0.931516 0.093509 +vn -0.935423 0.249763 0.250160 +vn -0.813959 -0.538713 0.217292 +vn -0.759484 -0.618030 0.202887 +vn -0.363842 0.931455 0.000000 +vn -0.968261 0.249916 0.000000 +vn -0.842860 -0.538102 0.000000 +vn -0.786767 -0.617206 0.000031 +vn -0.351451 0.931516 -0.093509 +vn -0.935423 0.249763 -0.250130 +vn -0.813959 -0.538713 -0.217292 +vn -0.759514 -0.618000 -0.202857 +vn -0.314432 0.931791 -0.181280 +vn -0.838404 0.249855 -0.484359 +vn -0.729026 -0.539720 -0.420911 +vn -0.680013 -0.619068 -0.392743 +vn -0.256386 0.931913 -0.256417 +vn -0.684652 0.249886 -0.684652 +vn -0.595050 -0.540147 -0.595050 +vn -0.555010 -0.619526 -0.555040 +vn -0.181280 0.931791 -0.314432 +vn -0.484359 0.249825 -0.838404 +vn -0.420881 -0.539720 -0.729026 +vn -0.392712 -0.619098 -0.680013 +vn -0.093509 0.931516 -0.351451 +vn -0.250160 0.249763 -0.935423 +vn -0.217322 -0.538713 -0.813959 +vn -0.202887 -0.618030 -0.759484 +vn 0.000000 0.931455 -0.363842 +vn 0.000000 0.249916 -0.968261 +vn 0.000000 -0.538102 -0.842860 +vn -0.000031 -0.617206 -0.786767 +vn 0.093509 0.931516 -0.351451 +vn 0.250130 0.249763 -0.935423 +vn 0.217292 -0.538682 -0.813959 +vn 0.202857 -0.618000 -0.759514 +vn 0.181280 0.931791 -0.314432 +vn 0.484359 0.249855 -0.838404 +vn 0.420911 -0.539720 -0.729026 +vn 0.392743 -0.619068 -0.680013 +vn 0.256417 0.931913 -0.256386 +vn 0.684652 0.249886 -0.684652 +vn 0.595050 -0.540147 -0.595050 +vn 0.555040 -0.619526 -0.555010 +vn 0.314432 0.931791 -0.181280 +vn 0.838404 0.249825 -0.484359 +vn 0.729026 -0.539720 -0.420881 +vn 0.680013 -0.619098 -0.392712 +vn 0.351451 0.931516 -0.093509 +vn 0.935423 0.249763 -0.250160 +vn 0.813959 -0.538713 -0.217292 +vn 0.759484 -0.618030 -0.202887 +vn -0.354198 0.930296 -0.095187 +vn 0.095187 0.930296 0.354198 +vn 0.354198 0.930296 0.095187 +vn 0.183721 0.930387 0.317179 +vn -0.183721 0.930387 -0.317179 +vn -0.367443 0.930021 0.000000 +vn -0.183721 0.930387 0.317179 +vn 0.367412 0.930021 0.000000 +vn -0.317179 0.930387 0.183721 +vn -0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 -0.367443 +vn -0.354198 0.930296 0.095187 +vn 0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 0.367443 +vn -0.317179 0.930387 -0.183721 +vn 0.317179 0.930387 -0.183721 +vn -0.095187 0.930296 0.354198 +vn 0.317179 0.930387 0.183721 +vn 0.354198 0.930296 -0.095187 +vn 0.183721 0.930387 -0.317179 +vn -0.034730 0.999390 0.000000 +vn 0.033479 0.999390 -0.009003 +vn 0.034730 0.999390 0.000000 +vn 0.009003 0.999390 -0.033479 +vn 0.000000 0.999390 -0.034730 +vn -0.259163 0.930387 0.259163 +vn -0.017335 0.999390 0.029939 +vn 0.947539 0.295083 0.122654 +vn -0.004486 0.999969 0.000000 +vn -0.004151 0.950468 0.310739 +vn -0.003021 0.719291 0.694662 +vn -0.998688 0.050722 0.000000 +vn -0.003143 0.719321 -0.694632 +vn 0.970214 0.213324 -0.114505 +vn -0.136235 0.879482 -0.455947 +vn 0.949858 0.312662 0.000000 +vn 0.055757 -0.017579 -0.998260 +vn 0.201300 -0.540880 -0.816645 +vn 0.974456 -0.186071 -0.125645 +vn 0.988098 -0.096286 0.119938 +vn 0.974456 -0.186041 0.125614 +vn -0.879574 -0.475723 0.000000 +vn -0.873775 -0.472610 -0.114475 +vn 0.988067 -0.096286 -0.119938 +vn 0.295480 -0.855464 -0.425214 +vn -0.976196 -0.174993 -0.127903 +vn -0.971007 -0.205725 0.121677 +vn -0.976196 -0.174963 0.127903 +vn -0.976196 -0.174993 0.127903 +vn 0.896054 -0.372997 0.240699 +vn -0.802667 -0.373638 -0.464827 +vn -0.655812 -0.373852 -0.655812 +vn -0.240699 -0.373028 -0.896023 +vn -0.464827 -0.373638 -0.802667 +vn -0.896023 -0.373028 0.240699 +vn 0.000000 -0.372539 -0.927976 +vn -0.655812 -0.373852 0.655812 +vn 0.240699 -0.373028 0.896023 +vn -0.896023 -0.373028 -0.240699 +vn 0.802667 -0.373638 -0.464827 +vn 0.655812 -0.373882 0.655812 +vn 0.464827 -0.373638 0.802667 +vn -0.464827 -0.373638 0.802667 +vn 0.240699 -0.373028 -0.896023 +vn 0.802667 -0.373638 0.464827 +vn -0.033479 0.999390 0.009003 +vn -0.259163 0.930387 -0.259163 +vn -0.024445 0.999390 -0.024445 +vn -0.029939 0.999390 -0.017335 +vn 0.259163 0.930387 -0.259163 +vn 0.024445 0.999390 -0.024445 +vn 0.017335 0.999390 -0.029939 +vn 0.029939 0.999390 -0.017335 +vn 0.033479 0.999390 0.009003 +vn -0.009003 0.999390 0.033479 +vn 0.000000 0.999390 0.034730 +vn -0.017335 0.999390 -0.029939 +vn 0.259163 0.930387 0.259163 +vn 0.029939 0.999390 0.017335 +vn -0.009003 0.999390 -0.033479 +vn 0.024445 0.999390 0.024445 +vn 0.017335 0.999390 0.029939 +vn 0.009003 0.999390 0.033479 +vn -0.033479 0.999390 -0.009003 +vn -0.024445 0.999390 0.024445 +vn -0.029939 0.999390 0.017335 +vn 0.055757 -0.017579 0.998260 +vn 0.294198 -0.855403 0.426252 +vn 0.201300 -0.540880 0.816614 +s 1 +f 34//1 1243//2 593//3 +f 52//4 27//5 40//6 +f 52//4 40//6 65//7 +f 77//8 52//4 65//7 +f 77//8 65//7 84//9 +f 107//10 77//8 84//9 +f 107//10 84//9 85//11 +f 115//12 107//10 85//11 +f 115//12 85//11 99//13 +f 129//14 115//12 99//13 +f 129//14 99//13 128//15 +f 1252//16 36//17 40//6 +f 65//7 40//6 64//18 +f 65//7 64//18 58//19 +f 84//9 65//7 58//19 +f 84//9 58//19 59//20 +f 85//11 84//9 59//20 +f 85//11 59//20 70//21 +f 99//13 85//11 70//21 +f 99//13 70//21 98//22 +f 128//15 99//13 98//22 +f 128//15 98//22 114//23 +f 1244//24 33//25 64//18 +f 58//19 64//18 33//25 +f 58//19 33//25 35//26 +f 59//20 58//19 35//26 +f 59//20 35//26 45//27 +f 70//21 59//20 45//27 +f 70//21 45//27 69//28 +f 98//22 70//21 69//28 +f 98//22 69//28 83//29 +f 114//23 98//22 83//29 +f 114//23 83//29 113//30 +f 553//31 1//32 566//33 +f 35//26 33//25 20//34 +f 35//26 20//34 24//35 +f 45//27 35//26 24//35 +f 45//27 24//35 44//36 +f 69//28 45//27 44//36 +f 69//28 44//36 57//37 +f 83//29 69//28 57//37 +f 83//29 57//37 82//38 +f 113//30 83//29 82//38 +f 113//30 82//38 112//39 +f 566//33 1283//40 9//41 +f 24//35 20//34 18//42 +f 24//35 18//42 23//43 +f 44//36 24//35 23//43 +f 44//36 23//43 32//44 +f 57//37 44//36 32//44 +f 57//37 32//44 56//45 +f 82//38 57//37 56//45 +f 82//38 56//45 81//46 +f 112//39 82//38 81//46 +f 112//39 81//46 111//47 +f 4//48 8//49 1250//50 +f 23//43 18//42 8//49 +f 23//43 8//49 17//51 +f 32//44 23//43 17//51 +f 32//44 17//51 31//52 +f 56//45 32//44 31//52 +f 56//45 31//52 55//53 +f 81//46 56//45 55//53 +f 81//46 55//53 80//54 +f 111//47 81//46 80//54 +f 111//47 80//54 110//55 +f 565//56 592//57 1233//58 +f 17//51 8//49 4//48 +f 17//51 4//48 16//59 +f 31//52 17//51 16//59 +f 31//52 16//59 30//60 +f 55//53 31//52 30//60 +f 55//53 30//60 54//61 +f 80//54 55//53 54//61 +f 80//54 54//61 79//62 +f 110//55 80//54 79//62 +f 110//55 79//62 109//63 +f 1//32 565//56 2//64 +f 6//65 2//64 565//56 +f 16//59 4//48 7//66 +f 16//59 7//66 22//67 +f 30//60 16//59 22//67 +f 30//60 22//67 43//68 +f 54//61 30//60 43//68 +f 54//61 43//68 68//69 +f 79//62 54//61 68//69 +f 79//62 68//69 97//70 +f 109//63 79//62 97//70 +f 109//63 97//70 127//71 +f 565//56 1233//58 1249//58 +f 13//72 14//73 5//74 +f 22//67 7//66 15//75 +f 22//67 15//75 29//76 +f 43//68 22//67 29//76 +f 43//68 29//76 42//77 +f 68//69 43//68 42//77 +f 68//69 42//77 67//78 +f 97//70 68//69 67//78 +f 97//70 67//78 96//79 +f 127//71 97//70 96//79 +f 127//71 96//79 126//80 +f 11//81 15//75 1240//82 +f 1289//83 34//1 593//3 +f 29//76 15//75 14//73 +f 29//76 14//73 21//84 +f 42//77 29//76 21//84 +f 42//77 21//84 41//85 +f 67//78 42//77 41//85 +f 67//78 41//85 66//86 +f 96//79 67//78 66//86 +f 96//79 66//86 95//87 +f 126//80 96//79 95//87 +f 126//80 95//87 125//88 +f 636//89 1243//2 26//2 +f 636//89 26//2 592//57 +f 21//84 14//73 13//72 +f 21//84 13//72 28//90 +f 41//85 21//84 28//90 +f 41//85 28//90 53//91 +f 66//86 41//85 53//91 +f 66//86 53//91 78//92 +f 95//87 66//86 78//92 +f 95//87 78//92 108//93 +f 125//88 95//87 108//93 +f 125//88 108//93 136//94 +f 12//95 13//72 5//74 +f 28//90 13//72 27//5 +f 28//90 27//5 52//4 +f 53//91 28//90 52//4 +f 53//91 52//4 77//8 +f 78//92 53//91 77//8 +f 78//92 77//8 107//10 +f 108//93 78//92 107//10 +f 108//93 107//10 115//12 +f 136//94 108//93 115//12 +f 136//94 115//12 129//14 +f 148//96 129//14 128//15 +f 148//96 128//15 143//97 +f 121//98 148//96 143//97 +f 121//98 143//97 122//99 +f 92//100 121//98 122//99 +f 92//100 122//99 93//101 +f 62//102 92//100 93//101 +f 62//102 93//101 63//103 +f 39//104 62//102 63//103 +f 39//104 63//103 51//105 +f 10//106 39//104 51//105 +f 10//106 51//105 49//107 +f 143//97 128//15 114//23 +f 143//97 114//23 142//108 +f 122//99 143//97 142//108 +f 122//99 142//108 123//109 +f 93//101 122//99 123//109 +f 93//101 123//109 94//110 +f 63//103 93//101 94//110 +f 63//103 94//110 76//111 +f 51//105 63//103 76//111 +f 51//105 76//111 75//112 +f 49//107 51//105 75//112 +f 49//107 75//112 61//113 +f 142//108 114//23 113//30 +f 142//108 113//30 141//114 +f 123//109 142//108 141//114 +f 123//109 141//114 124//115 +f 94//110 123//109 124//115 +f 94//110 124//115 106//116 +f 76//111 94//110 106//116 +f 76//111 106//116 105//117 +f 75//112 76//111 105//117 +f 75//112 105//117 91//118 +f 61//113 75//112 91//118 +f 61//113 91//118 90//119 +f 141//114 113//30 112//39 +f 141//114 112//39 140//120 +f 124//115 141//114 140//120 +f 124//115 140//120 135//121 +f 106//116 124//115 135//121 +f 106//116 135//121 134//122 +f 105//117 106//116 134//122 +f 105//117 134//122 120//123 +f 91//118 105//117 120//123 +f 91//118 120//123 119//124 +f 90//119 91//118 119//124 +f 140//120 112//39 111//47 +f 140//120 111//47 139//125 +f 135//121 140//120 139//125 +f 135//121 139//125 155//126 +f 134//122 135//121 155//126 +f 134//122 155//126 147//127 +f 120//123 134//122 147//127 +f 120//123 147//127 144//128 +f 119//124 120//123 144//128 +f 119//124 144//128 116//129 +f 26//2 1234//130 592//57 +f 139//125 111//47 110//55 +f 139//125 110//55 138//131 +f 155//126 139//125 138//131 +f 155//126 138//131 156//132 +f 147//127 155//126 156//132 +f 147//127 156//132 145//133 +f 144//128 147//127 145//133 +f 144//128 145//133 117//134 +f 116//129 144//128 117//134 +f 116//129 117//134 88//135 +f 27//5 13//72 12//95 +f 1242//136 88//135 71//137 +f 138//131 110//55 109//63 +f 138//131 109//63 137//138 +f 156//132 138//131 137//138 +f 156//132 137//138 154//139 +f 145//133 156//132 154//139 +f 145//133 154//139 131//140 +f 117//134 145//133 131//140 +f 117//134 131//140 101//141 +f 88//135 117//134 101//141 +f 88//135 101//141 86//142 +f 60//143 74//144 1248//145 +f 137//138 109//63 127//71 +f 137//138 127//71 151//146 +f 154//139 137//138 151//146 +f 154//139 151//146 153//147 +f 131//140 154//139 153//147 +f 131//140 153//147 130//148 +f 101//141 131//140 130//148 +f 101//141 130//148 100//149 +f 86//142 101//141 100//149 +f 86//142 100//149 74//144 +f 47//150 1235//151 631//152 +f 74//144 48//153 1248//145 +f 151//146 127//71 126//80 +f 151//146 126//80 150//154 +f 153//147 151//146 150//154 +f 153//147 150//154 146//155 +f 130//148 153//147 146//155 +f 130//148 146//155 118//156 +f 100//149 130//148 118//156 +f 100//149 118//156 89//157 +f 74//144 100//149 89//157 +f 74//144 89//157 48//153 +f 1247//158 87//159 715//160 +f 104//161 116//129 1242//136 +f 150//154 126//80 125//88 +f 150//154 125//88 149//162 +f 146//155 150//154 149//162 +f 146//155 149//162 132//163 +f 118//156 146//155 132//163 +f 118//156 132//163 102//164 +f 89//157 118//156 102//164 +f 89//157 102//164 72//165 +f 48//153 89//157 72//165 +f 48//153 72//165 46//166 +f 37//167 48//153 46//166 +f 37//167 46//166 38//168 +f 149//162 125//88 136//94 +f 149//162 136//94 152//169 +f 132//163 149//162 152//169 +f 132//163 152//169 133//170 +f 102//164 132//163 133//170 +f 102//164 133//170 103//171 +f 72//165 102//164 103//171 +f 72//165 103//171 73//172 +f 46//166 72//165 73//172 +f 46//166 73//172 50//173 +f 38//168 46//166 50//173 +f 38//168 50//173 25//174 +f 152//169 136//94 129//14 +f 152//169 129//14 148//96 +f 133//170 152//169 148//96 +f 133//170 148//96 121//98 +f 103//171 133//170 121//98 +f 103//171 121//98 92//100 +f 73//172 103//171 92//100 +f 73//172 92//100 62//102 +f 50//173 73//172 62//102 +f 50//173 62//102 39//104 +f 25//174 50//173 39//104 +f 39//104 10//106 25//174 +f 539//175 509//176 159//177 +f 160//178 158//179 157//180 +f 166//181 160//178 163//182 +f 166//181 163//182 173//183 +f 177//184 166//181 173//183 +f 177//184 173//183 183//185 +f 189//186 177//184 183//185 +f 189//186 183//185 197//187 +f 205//188 189//186 197//187 +f 205//188 197//187 216//189 +f 225//190 205//188 216//189 +f 225//190 216//189 235//191 +f 173//183 163//182 172//192 +f 173//183 172//192 184//193 +f 183//185 173//183 184//193 +f 183//185 184//193 198//194 +f 197//187 183//185 198//194 +f 197//187 198//194 217//195 +f 216//189 197//187 217//195 +f 216//189 217//195 236//196 +f 235//191 216//189 236//196 +f 235//191 236//196 253//197 +f 182//198 172//192 1254//199 +f 1255//200 167//201 595//202 +f 184//193 172//192 182//198 +f 184//193 182//198 196//203 +f 198//194 184//193 196//203 +f 198//194 196//203 214//204 +f 217//195 198//194 214//204 +f 217//195 214//204 232//205 +f 236//196 217//195 232//205 +f 236//196 232//205 250//206 +f 253//197 236//196 250//206 +f 253//197 250//206 267//207 +f 196//203 182//198 199//208 +f 196//203 199//208 215//209 +f 214//204 196//203 215//209 +f 214//204 215//209 233//210 +f 232//205 214//204 233//210 +f 232//205 233//210 251//211 +f 250//206 232//205 251//211 +f 250//206 251//211 257//212 +f 267//207 250//206 257//212 +f 267//207 257//212 256//213 +f 215//209 199//208 218//214 +f 215//209 218//214 234//215 +f 233//210 215//209 234//215 +f 233//210 234//215 241//216 +f 251//211 233//210 241//216 +f 251//211 241//216 240//217 +f 257//212 251//211 240//217 +f 257//212 240//217 239//218 +f 256//213 257//212 239//218 +f 256//213 239//218 238//219 +f 234//215 218//214 219//220 +f 234//215 219//220 224//221 +f 241//216 234//215 224//221 +f 241//216 224//221 223//222 +f 240//217 241//216 223//222 +f 240//217 223//222 222//223 +f 239//218 240//217 222//223 +f 239//218 222//223 221//224 +f 238//219 239//218 221//224 +f 238//219 221//224 220//225 +f 219//220 218//214 1285//226 +f 648//227 691//228 207//229 +f 224//221 219//220 208//230 +f 224//221 208//230 204//231 +f 223//222 224//221 204//231 +f 223//222 204//231 203//232 +f 222//223 223//222 203//232 +f 222//223 203//232 202//233 +f 221//224 222//223 202//233 +f 221//224 202//233 201//234 +f 220//225 221//224 201//234 +f 220//225 201//234 212//235 +f 204//231 208//230 191//236 +f 204//231 191//236 188//237 +f 203//232 204//231 188//237 +f 203//232 188//237 187//238 +f 202//233 203//232 187//238 +f 202//233 187//238 186//239 +f 201//234 202//233 186//239 +f 201//234 186//239 194//240 +f 212//235 201//234 194//240 +f 212//235 194//240 211//241 +f 188//237 191//236 174//242 +f 188//237 174//242 176//243 +f 187//238 188//237 176//243 +f 187//238 176//243 175//244 +f 186//239 187//238 175//244 +f 186//239 175//244 180//245 +f 194//240 186//239 180//245 +f 194//240 180//245 193//246 +f 211//241 194//240 193//246 +f 211//241 193//246 210//247 +f 613//248 585//249 1258//250 +f 176//243 174//242 168//251 +f 176//243 168//251 165//252 +f 175//244 176//243 165//252 +f 175//244 165//252 170//253 +f 180//245 175//244 170//253 +f 180//245 170//253 179//254 +f 193//246 180//245 179//254 +f 193//246 179//254 192//255 +f 210//247 193//246 192//255 +f 210//247 192//255 209//256 +f 168//251 174//242 164//257 +f 165//252 168//251 161//258 +f 165//252 161//258 162//259 +f 170//253 165//252 162//259 +f 170//253 162//259 171//260 +f 179//254 170//253 171//260 +f 179//254 171//260 181//261 +f 192//255 179//254 181//261 +f 192//255 181//261 195//262 +f 209//256 192//255 195//262 +f 209//256 195//262 213//263 +f 160//178 161//258 158//179 +f 161//258 160//178 162//259 +f 162//259 160//178 166//181 +f 171//260 162//259 166//181 +f 171//260 166//181 177//184 +f 181//261 171//260 177//184 +f 181//261 177//184 189//186 +f 195//262 181//261 189//186 +f 195//262 189//186 205//188 +f 213//263 195//262 205//188 +f 213//263 205//188 225//190 +f 242//264 225//190 235//191 +f 242//264 235//191 252//265 +f 258//266 242//264 252//265 +f 258//266 252//265 268//267 +f 273//268 258//266 268//267 +f 273//268 268//267 283//269 +f 287//270 273//268 283//269 +f 287//270 283//269 298//271 +f 300//272 287//270 298//271 +f 300//272 298//271 299//273 +f 312//274 300//272 299//273 +f 312//274 299//273 310//275 +f 252//265 235//191 253//197 +f 252//265 253//197 269//276 +f 268//267 252//265 269//276 +f 268//267 269//276 284//277 +f 283//269 268//267 284//277 +f 283//269 284//277 286//278 +f 298//271 283//269 286//278 +f 298//271 286//278 285//279 +f 299//273 298//271 285//279 +f 299//273 285//279 296//280 +f 310//275 299//273 296//280 +f 310//275 296//280 309//281 +f 269//276 253//197 267//207 +f 269//276 267//207 272//282 +f 284//277 269//276 272//282 +f 284//277 272//282 271//283 +f 286//278 284//277 271//283 +f 286//278 271//283 270//284 +f 285//279 286//278 270//284 +f 285//279 270//284 281//285 +f 296//280 285//279 281//285 +f 296//280 281//285 295//286 +f 309//281 296//280 295//286 +f 309//281 295//286 308//287 +f 272//282 267//207 256//213 +f 272//282 256//213 255//288 +f 271//283 272//282 255//288 +f 271//283 255//288 254//289 +f 270//284 271//283 254//289 +f 270//284 254//289 265//290 +f 281//285 270//284 265//290 +f 281//285 265//290 280//291 +f 295//286 281//285 280//291 +f 295//286 280//291 294//292 +f 308//287 295//286 294//292 +f 308//287 294//292 307//293 +f 255//288 256//213 238//219 +f 255//288 238//219 237//294 +f 254//289 255//288 237//294 +f 254//289 237//294 248//295 +f 265//290 254//289 248//295 +f 265//290 248//295 264//296 +f 280//291 265//290 264//296 +f 280//291 264//296 279//297 +f 294//292 280//291 279//297 +f 294//292 279//297 293//298 +f 307//293 294//292 293//298 +f 307//293 293//298 306//299 +f 237//294 238//219 220//225 +f 237//294 220//225 230//300 +f 248//295 237//294 230//300 +f 248//295 230//300 247//301 +f 264//296 248//295 247//301 +f 264//296 247//301 263//302 +f 279//297 264//296 263//302 +f 279//297 263//302 278//303 +f 293//298 279//297 278//303 +f 293//298 278//303 292//304 +f 306//299 293//298 292//304 +f 306//299 292//304 305//305 +f 230//300 220//225 212//235 +f 230//300 212//235 229//306 +f 247//301 230//300 229//306 +f 247//301 229//306 246//307 +f 263//302 247//301 246//307 +f 263//302 246//307 262//308 +f 278//303 263//302 262//308 +f 278//303 262//308 277//309 +f 292//304 278//303 277//309 +f 292//304 277//309 291//310 +f 305//305 292//304 291//310 +f 305//305 291//310 304//311 +f 229//306 212//235 211//241 +f 229//306 211//241 228//312 +f 246//307 229//306 228//312 +f 246//307 228//312 245//313 +f 262//308 246//307 245//313 +f 262//308 245//313 261//314 +f 277//309 262//308 261//314 +f 277//309 261//314 276//315 +f 291//310 277//309 276//315 +f 291//310 276//315 290//316 +f 304//311 291//310 290//316 +f 304//311 290//316 303//317 +f 228//312 211//241 210//247 +f 228//312 210//247 227//318 +f 245//313 228//312 227//318 +f 245//313 227//318 244//319 +f 261//314 245//313 244//319 +f 261//314 244//319 260//320 +f 276//315 261//314 260//320 +f 276//315 260//320 275//321 +f 290//316 276//315 275//321 +f 290//316 275//321 289//322 +f 303//317 290//316 289//322 +f 303//317 289//322 302//323 +f 227//318 210//247 209//256 +f 227//318 209//256 226//324 +f 244//319 227//318 226//324 +f 244//319 226//324 243//325 +f 260//320 244//319 243//325 +f 260//320 243//325 259//326 +f 275//321 260//320 259//326 +f 275//321 259//326 274//327 +f 289//322 275//321 274//327 +f 289//322 274//327 288//328 +f 302//323 289//322 288//328 +f 302//323 288//328 301//329 +f 226//324 209//256 213//263 +f 226//324 213//263 231//330 +f 243//325 226//324 231//330 +f 243//325 231//330 249//331 +f 259//326 243//325 249//331 +f 259//326 249//331 266//332 +f 274//327 259//326 266//332 +f 274//327 266//332 282//333 +f 288//328 274//327 282//333 +f 288//328 282//333 297//334 +f 301//329 288//328 297//334 +f 301//329 297//334 311//335 +f 231//330 213//263 225//190 +f 231//330 225//190 242//264 +f 249//331 231//330 242//264 +f 249//331 242//264 258//266 +f 266//332 249//331 258//266 +f 266//332 258//266 273//268 +f 282//333 266//332 273//268 +f 282//333 273//268 287//270 +f 297//334 282//333 287//270 +f 297//334 287//270 300//272 +f 311//335 297//334 300//272 +f 311//335 300//272 312//274 +f 312//274 310//275 323//336 +f 302//323 315//337 316//338 +f 304//311 317//339 318//340 +f 303//317 316//338 317//339 +f 309//281 308//287 321//341 +f 307//293 306//299 319//342 +f 311//335 313//343 314//344 +f 301//329 314//344 315//337 +f 312//274 324//345 313//343 +f 306//299 305//305 318//340 +f 308//287 307//293 320//346 +f 310//275 309//281 322//347 +f 322//347 321//341 325//348 +f 314//344 313//343 325//348 +f 323//336 322//347 325//348 +f 319//342 318//340 325//348 +f 315//337 314//344 325//348 +f 321//341 320//346 325//348 +f 324//345 323//336 325//348 +f 320//346 319//342 325//348 +f 317//339 316//338 325//348 +f 316//338 315//337 325//348 +f 313//343 324//345 325//348 +f 318//340 317//339 325//348 +f 326//349 327//350 328//351 +f 326//349 328//351 329//352 +f 333//353 326//349 329//352 +f 333//353 329//352 338//354 +f 347//355 333//353 338//354 +f 347//355 338//354 354//356 +f 364//357 347//355 354//356 +f 364//357 354//356 374//358 +f 386//359 364//357 374//358 +f 386//359 374//358 398//360 +f 412//361 386//359 398//360 +f 412//361 398//360 429//362 +f 329//352 328//351 334//363 +f 329//352 334//363 339//364 +f 338//354 329//352 339//364 +f 338//354 339//364 355//365 +f 354//356 338//354 355//365 +f 354//356 355//365 375//366 +f 374//358 354//356 375//366 +f 374//358 375//366 399//367 +f 398//360 374//358 399//367 +f 398//360 399//367 430//368 +f 429//362 398//360 430//368 +f 429//362 430//368 464//369 +f 339//364 334//363 342//370 +f 339//364 342//370 356//371 +f 355//365 339//364 356//371 +f 355//365 356//371 376//372 +f 375//366 355//365 376//372 +f 375//366 376//372 400//373 +f 399//367 375//366 400//373 +f 399//367 400//373 431//374 +f 430//368 399//367 431//374 +f 430//368 431//374 465//375 +f 464//369 430//368 465//375 +f 464//369 465//375 497//376 +f 356//371 342//370 351//377 +f 356//371 351//377 370//378 +f 376//372 356//371 370//378 +f 376//372 370//378 393//379 +f 400//373 376//372 393//379 +f 400//373 393//379 422//380 +f 431//374 400//373 422//380 +f 431//374 422//380 457//381 +f 465//375 431//374 457//381 +f 465//375 457//381 490//382 +f 497//376 465//375 490//382 +f 497//376 490//382 521//383 +f 370//378 351//377 361//384 +f 370//378 361//384 382//385 +f 393//379 370//378 382//385 +f 393//379 382//385 408//386 +f 422//380 393//379 408//386 +f 422//380 408//386 439//387 +f 457//381 422//380 439//387 +f 457//381 439//387 473//388 +f 490//382 457//381 473//388 +f 490//382 473//388 504//389 +f 521//383 490//382 504//389 +f 521//383 504//389 535//390 +f 382//385 361//384 369//391 +f 382//385 369//391 392//392 +f 408//386 382//385 392//392 +f 408//386 392//392 421//393 +f 439//387 408//386 421//393 +f 439//387 421//393 456//394 +f 473//388 439//387 456//394 +f 473//388 456//394 489//395 +f 504//389 473//388 489//395 +f 504//389 489//395 520//396 +f 535//390 504//389 520//396 +f 535//390 520//396 550//397 +f 392//392 369//391 380//398 +f 392//392 380//398 407//399 +f 421//393 392//392 407//399 +f 421//393 407//399 438//400 +f 456//394 421//393 438//400 +f 456//394 438//400 472//401 +f 489//395 456//394 472//401 +f 489//395 472//401 503//402 +f 520//396 489//395 503//402 +f 520//396 503//402 534//403 +f 550//397 520//396 534//403 +f 550//397 534//403 563//404 +f 407//399 380//398 391//405 +f 407//399 391//405 420//406 +f 438//400 407//399 420//406 +f 438//400 420//406 455//407 +f 472//401 438//400 455//407 +f 472//401 455//407 488//408 +f 503//402 472//401 488//408 +f 503//402 488//408 519//409 +f 534//403 503//402 519//409 +f 534//403 519//409 549//410 +f 563//404 534//403 549//410 +f 563//404 549//410 578//411 +f 420//406 391//405 404//412 +f 420//406 404//412 437//413 +f 455//407 420//406 437//413 +f 455//407 437//413 471//414 +f 488//408 455//407 471//414 +f 488//408 471//414 502//415 +f 519//409 488//408 502//415 +f 519//409 502//415 533//416 +f 549//410 519//409 533//416 +f 549//410 533//416 562//417 +f 578//411 549//410 562//417 +f 578//411 562//417 589//418 +f 437//413 404//412 419//419 +f 437//413 419//419 454//420 +f 471//414 437//413 454//420 +f 471//414 454//420 487//421 +f 502//415 471//414 487//421 +f 502//415 487//421 518//422 +f 533//416 502//415 518//422 +f 533//416 518//422 548//423 +f 562//417 533//416 548//423 +f 562//417 548//423 577//424 +f 589//418 562//417 577//424 +f 589//418 577//424 594//425 +f 454//420 419//419 436//426 +f 454//420 436//426 470//427 +f 487//421 454//420 470//427 +f 487//421 470//427 501//428 +f 518//422 487//421 501//428 +f 518//422 501//428 532//429 +f 548//423 518//422 532//429 +f 548//423 532//429 555//430 +f 577//424 548//423 555//430 +f 577//424 555//430 567//431 +f 594//425 577//424 567//431 +f 594//425 567//431 582//432 +f 470//427 436//426 453//433 +f 470//427 453//433 486//434 +f 501//428 470//427 486//434 +f 501//428 486//434 508//435 +f 532//429 501//428 508//435 +f 532//429 508//435 525//436 +f 555//430 532//429 525//436 +f 555//430 525//436 538//437 +f 567//431 555//430 538//437 +f 567//431 538//437 554//438 +f 582//432 567//431 554//438 +f 582//432 554//438 566//33 +f 486//434 453//433 462//439 +f 486//434 462//439 477//440 +f 508//435 486//434 477//440 +f 508//435 477//440 494//441 +f 525//436 508//435 494//441 +f 525//436 494//441 507//442 +f 538//437 525//436 507//442 +f 538//437 507//442 524//443 +f 554//438 538//437 524//443 +f 554//438 524//443 537//444 +f 566//33 554//438 537//444 +f 566//33 537//444 553//31 +f 477//440 462//439 443//445 +f 477//440 443//445 461//446 +f 494//441 477//440 461//446 +f 494//441 461//446 476//447 +f 507//442 494//441 476//447 +f 507//442 476//447 493//448 +f 524//443 507//442 493//448 +f 524//443 493//448 506//449 +f 537//444 524//443 506//449 +f 537//444 506//449 523//450 +f 553//31 537//444 523//450 +f 553//31 523//450 536//451 +f 461//446 443//445 426//452 +f 461//446 426//452 442//453 +f 476//447 461//446 442//453 +f 476//447 442//453 460//454 +f 493//448 476//447 460//454 +f 493//448 460//454 475//455 +f 506//449 493//448 475//455 +f 506//449 475//455 492//456 +f 523//450 506//449 492//456 +f 523//450 492//456 505//457 +f 536//451 523//450 505//457 +f 536//451 505//457 522//458 +f 442//453 426//452 411//459 +f 442//453 411//459 425//460 +f 460//454 442//453 425//460 +f 460//454 425//460 441//461 +f 475//455 460//454 441//461 +f 475//455 441//461 459//462 +f 492//456 475//455 459//462 +f 492//456 459//462 474//463 +f 505//457 492//456 474//463 +f 505//457 474//463 491//464 +f 522//458 505//457 491//464 +f 522//458 491//464 499//465 +f 425//460 411//459 396//466 +f 425//460 396//466 410//467 +f 441//461 425//460 410//467 +f 441//461 410//467 424//468 +f 459//462 441//461 424//468 +f 459//462 424//468 440//469 +f 474//463 459//462 440//469 +f 474//463 440//469 458//470 +f 491//464 474//463 458//470 +f 491//464 458//470 467//471 +f 499//465 491//464 467//471 +f 499//465 467//471 466//472 +f 410//467 396//466 385//473 +f 410//467 385//473 395//474 +f 424//468 410//467 395//474 +f 424//468 395//474 409//475 +f 440//469 424//468 409//475 +f 440//469 409//475 423//476 +f 458//470 440//469 423//476 +f 458//470 423//476 433//477 +f 467//471 458//470 433//477 +f 467//471 433//477 432//478 +f 466//472 467//471 432//478 +f 466//472 432//478 434//479 +f 395//474 385//473 372//480 +f 395//474 372//480 383//481 +f 409//475 395//474 383//481 +f 409//475 383//481 394//482 +f 423//476 409//475 394//482 +f 423//476 394//482 402//483 +f 433//477 423//476 402//483 +f 433//477 402//483 401//484 +f 432//478 433//477 401//484 +f 432//478 401//484 403//485 +f 434//479 432//478 403//485 +f 434//479 403//485 417//486 +f 383//481 372//480 362//487 +f 383//481 362//487 371//488 +f 394//482 383//481 371//488 +f 394//482 371//488 378//489 +f 402//483 394//482 378//489 +f 402//483 378//489 377//490 +f 401//484 402//483 377//490 +f 401//484 377//490 379//491 +f 403//485 401//484 379//491 +f 403//485 379//491 390//492 +f 417//486 403//485 390//492 +f 417//486 390//492 416//493 +f 371//488 362//487 352//494 +f 371//488 352//494 358//495 +f 378//489 371//488 358//495 +f 378//489 358//495 357//496 +f 377//490 378//489 357//496 +f 377//490 357//496 359//497 +f 379//491 377//490 359//497 +f 379//491 359//497 367//498 +f 390//492 379//491 367//498 +f 390//492 367//498 389//499 +f 416//493 390//492 389//499 +f 416//493 389//499 415//500 +f 358//495 352//494 345//501 +f 358//495 345//501 340//502 +f 357//496 358//495 340//502 +f 357//496 340//502 341//503 +f 359//497 357//496 341//503 +f 359//497 341//503 349//504 +f 367//498 359//497 349//504 +f 367//498 349//504 366//505 +f 389//499 367//498 366//505 +f 389//499 366//505 388//506 +f 415//500 389//499 388//506 +f 415//500 388//506 414//507 +f 340//502 345//501 335//508 +f 340//502 335//508 330//509 +f 341//503 340//502 330//509 +f 341//503 330//509 336//510 +f 349//504 341//503 336//510 +f 349//504 336//510 348//511 +f 366//505 349//504 348//511 +f 366//505 348//511 365//512 +f 388//506 366//505 365//512 +f 388//506 365//512 387//513 +f 414//507 388//506 387//513 +f 414//507 387//513 413//514 +f 330//509 335//508 327//350 +f 327//350 326//349 330//509 +f 330//509 326//349 336//510 +f 336//510 326//349 333//353 +f 348//511 336//510 333//353 +f 348//511 333//353 347//355 +f 365//512 348//511 347//355 +f 365//512 347//355 364//357 +f 387//513 365//512 364//357 +f 387//513 364//357 386//359 +f 413//514 387//513 386//359 +f 413//514 386//359 412//361 +f 445//515 412//361 429//362 +f 445//515 429//362 463//516 +f 478//517 445//515 463//516 +f 478//517 463//516 495//518 +f 509//176 478//517 495//518 +f 509//176 495//518 526//519 +f 463//516 429//362 464//369 +f 463//516 464//369 496//520 +f 495//518 463//516 496//520 +f 495//518 496//520 527//521 +f 526//519 495//518 527//521 +f 526//519 527//521 557//522 +f 556//523 526//519 557//522 +f 556//523 557//522 583//524 +f 595//202 556//523 583//524 +f 595//202 583//524 611//525 +f 621//526 595//202 611//525 +f 621//526 611//525 638//527 +f 496//520 464//369 497//376 +f 496//520 497//376 528//528 +f 527//521 496//520 528//528 +f 527//521 528//528 558//529 +f 557//522 527//521 558//529 +f 557//522 558//529 584//530 +f 583//524 557//522 584//530 +f 583//524 584//530 612//531 +f 611//525 583//524 612//531 +f 611//525 612//531 639//532 +f 638//527 611//525 639//532 +f 638//527 639//532 664//533 +f 528//528 497//376 521//383 +f 528//528 521//383 551//534 +f 558//529 528//528 551//534 +f 558//529 551//534 580//535 +f 584//530 558//529 580//535 +f 584//530 580//535 608//536 +f 612//531 584//530 608//536 +f 612//531 608//536 634//537 +f 639//532 612//531 634//537 +f 639//532 634//537 661//538 +f 664//533 639//532 661//538 +f 664//533 661//538 688//539 +f 551//534 521//383 535//390 +f 551//534 535//390 564//540 +f 580//535 551//534 564//540 +f 580//535 564//540 591//541 +f 608//536 580//535 591//541 +f 608//536 591//541 618//542 +f 634//537 608//536 618//542 +f 634//537 618//542 644//543 +f 661//538 634//537 644//543 +f 661//538 644//543 670//544 +f 688//539 661//538 670//544 +f 688//539 670//544 698//545 +f 564//540 535//390 550//397 +f 564//540 550//397 579//546 +f 591//541 564//540 579//546 +f 591//541 579//546 607//547 +f 618//542 591//541 607//547 +f 618//542 607//547 633//548 +f 644//543 618//542 633//548 +f 644//543 633//548 660//549 +f 670//544 644//543 660//549 +f 670//544 660//549 687//550 +f 698//545 670//544 687//550 +f 698//545 687//550 717//551 +f 579//546 550//397 563//404 +f 579//546 563//404 590//552 +f 607//547 579//546 590//552 +f 607//547 590//552 617//553 +f 633//548 607//547 617//553 +f 633//548 617//553 643//554 +f 660//549 633//548 643//554 +f 660//549 643//554 669//555 +f 687//550 660//549 669//555 +f 687//550 669//555 697//556 +f 717//551 687//550 697//556 +f 717//551 697//556 727//557 +f 590//552 563//404 578//411 +f 590//552 578//411 606//558 +f 617//553 590//552 606//558 +f 617//553 606//558 632//559 +f 643//554 617//553 632//559 +f 643//554 632//559 659//560 +f 669//555 643//554 659//560 +f 669//555 659//560 673//561 +f 697//556 669//555 673//561 +f 697//556 673//561 700//562 +f 727//557 697//556 700//562 +f 727//557 700//562 699//563 +f 606//558 578//411 589//418 +f 606//558 589//418 616//564 +f 632//559 606//558 616//564 +f 632//559 616//564 637//565 +f 659//560 632//559 637//565 +f 659//560 637//565 647//566 +f 673//561 659//560 647//566 +f 673//561 647//566 672//567 +f 700//562 673//561 672//567 +f 700//562 672//567 671//568 +f 699//563 700//562 671//568 +f 699//563 671//568 689//569 +f 616//564 589//418 594//425 +f 616//564 594//425 610//570 +f 637//565 616//564 610//570 +f 637//565 610//570 620//571 +f 647//566 637//565 620//571 +f 647//566 620//571 646//572 +f 672//567 647//566 646//572 +f 672//567 646//572 645//573 +f 671//568 672//567 645//573 +f 671//568 645//573 662//574 +f 689//569 671//568 662//574 +f 689//569 662//574 668//575 +f 610//570 594//425 582//432 +f 610//570 582//432 593//3 +f 620//571 610//570 593//3 +f 620//571 593//3 636//89 +f 646//572 620//571 636//89 +f 646//572 636//89 619//576 +f 645//573 646//572 619//576 +f 645//573 619//576 635//577 +f 662//574 645//573 635//577 +f 662//574 635//577 642//578 +f 668//575 662//574 642//578 +f 668//575 642//578 641//579 +f 593//3 582//432 566//33 +f 619//576 636//89 592//57 +f 619//576 592//57 609//580 +f 635//577 619//576 609//580 +f 635//577 609//580 615//581 +f 642//578 635//577 615//581 +f 642//578 615//581 614//582 +f 641//579 642//578 614//582 +f 592//57 565//56 581//583 +f 609//580 592//57 581//583 +f 609//580 581//583 587//584 +f 615//581 609//580 587//584 +f 615//581 587//584 586//585 +f 614//582 615//581 586//585 +f 614//582 586//585 588//586 +f 565//56 553//31 536//451 +f 565//56 536//451 552//587 +f 581//583 565//56 552//587 +f 581//583 552//587 560//588 +f 587//584 581//583 560//588 +f 587//584 560//588 559//589 +f 586//585 587//584 559//589 +f 586//585 559//589 561//590 +f 588//586 586//585 561//590 +f 588//586 561//590 576//591 +f 605//592 588//586 576//591 +f 605//592 576//591 604//593 +f 552//587 536//451 522//458 +f 552//587 522//458 530//594 +f 560//588 552//587 530//594 +f 560//588 530//594 529//595 +f 559//589 560//588 529//595 +f 559//589 529//595 531//596 +f 561//590 559//589 531//596 +f 561//590 531//596 547//597 +f 576//591 561//590 547//597 +f 576//591 547//597 575//598 +f 604//593 576//591 575//598 +f 604//593 575//598 603//599 +f 530//594 522//458 499//465 +f 530//594 499//465 498//600 +f 529//595 530//594 498//600 +f 529//595 498//600 500//601 +f 531//596 529//595 500//601 +f 531//596 500//601 517//602 +f 547//597 531//596 517//602 +f 547//597 517//602 546//603 +f 575//598 547//597 546//603 +f 575//598 546//603 574//604 +f 603//599 575//598 574//604 +f 603//599 574//604 602//605 +f 498//600 499//465 466//472 +f 498//600 466//472 468//606 +f 500//601 498//600 468//606 +f 500//601 468//606 485//607 +f 517//602 500//601 485//607 +f 517//602 485//607 516//608 +f 546//603 517//602 516//608 +f 546//603 516//608 545//609 +f 574//604 546//603 545//609 +f 574//604 545//609 573//610 +f 602//605 574//604 573//610 +f 602//605 573//610 601//611 +f 468//606 466//472 434//479 +f 468//606 434//479 451//612 +f 485//607 468//606 451//612 +f 485//607 451//612 484//613 +f 516//608 485//607 484//613 +f 516//608 484//613 515//614 +f 545//609 516//608 515//614 +f 545//609 515//614 544//615 +f 573//610 545//609 544//615 +f 573//610 544//615 572//616 +f 601//611 573//610 572//616 +f 601//611 572//616 600//617 +f 451//612 434//479 417//486 +f 451//612 417//486 450//618 +f 484//613 451//612 450//618 +f 484//613 450//618 483//619 +f 515//614 484//613 483//619 +f 515//614 483//619 514//620 +f 544//615 515//614 514//620 +f 544//615 514//620 543//621 +f 572//616 544//615 543//621 +f 572//616 543//621 571//622 +f 600//617 572//616 571//622 +f 600//617 571//622 599//623 +f 450//618 417//486 416//493 +f 450//618 416//493 449//624 +f 483//619 450//618 449//624 +f 483//619 449//624 482//625 +f 514//620 483//619 482//625 +f 514//620 482//625 513//626 +f 543//621 514//620 513//626 +f 543//621 513//626 542//627 +f 571//622 543//621 542//627 +f 571//622 542//627 570//628 +f 599//623 571//622 570//628 +f 599//623 570//628 598//629 +f 449//624 416//493 415//500 +f 449//624 415//500 448//630 +f 482//625 449//624 448//630 +f 482//625 448//630 481//631 +f 513//626 482//625 481//631 +f 513//626 481//631 512//632 +f 542//627 513//626 512//632 +f 542//627 512//632 541//633 +f 570//628 542//627 541//633 +f 570//628 541//633 569//634 +f 598//629 570//628 569//634 +f 598//629 569//634 597//635 +f 448//630 415//500 414//507 +f 448//630 414//507 447//636 +f 481//631 448//630 447//636 +f 481//631 447//636 480//637 +f 512//632 481//631 480//637 +f 512//632 480//637 511//638 +f 541//633 512//632 511//638 +f 541//633 511//638 540//639 +f 569//634 541//633 540//639 +f 569//634 540//639 568//640 +f 597//635 569//634 568//640 +f 597//635 568//640 596//641 +f 447//636 414//507 413//514 +f 447//636 413//514 446//642 +f 480//637 447//636 446//642 +f 480//637 446//642 479//643 +f 511//638 480//637 479//643 +f 511//638 479//643 510//644 +f 540//639 511//638 510//644 +f 540//639 510//644 539//175 +f 568//640 540//639 539//175 +f 568//640 539//175 585//249 +f 596//641 568//640 585//249 +f 596//641 585//249 613//248 +f 446//642 413//514 412//361 +f 446//642 412//361 445//515 +f 479//643 446//642 445//515 +f 479//643 445//515 478//517 +f 510//644 479//643 478//517 +f 510//644 478//517 509//176 +f 539//175 510//644 509//176 +f 691//228 648//227 674//645 +f 702//646 691//228 674//645 +f 702//646 674//645 701//647 +f 731//648 702//646 701//647 +f 731//648 701//647 730//649 +f 759//650 731//648 730//649 +f 759//650 730//649 758//651 +f 786//652 759//650 758//651 +f 786//652 758//651 785//653 +f 648//227 621//526 638//527 +f 648//227 638//527 663//654 +f 674//645 648//227 663//654 +f 674//645 663//654 690//655 +f 701//647 674//645 690//655 +f 701//647 690//655 720//656 +f 730//649 701//647 720//656 +f 730//649 720//656 749//657 +f 758//651 730//649 749//657 +f 758//651 749//657 777//658 +f 785//653 758//651 777//658 +f 785//653 777//658 805//659 +f 663//654 638//527 664//533 +f 663//654 664//533 692//660 +f 690//655 663//654 692//660 +f 690//655 692//660 721//661 +f 720//656 690//655 721//661 +f 720//656 721//661 750//662 +f 749//657 720//656 750//662 +f 749//657 750//662 778//663 +f 777//658 749//657 778//663 +f 777//658 778//663 806//664 +f 805//659 777//658 806//664 +f 805//659 806//664 833//665 +f 692//660 664//533 688//539 +f 692//660 688//539 718//666 +f 721//661 692//660 718//666 +f 721//661 718//666 747//667 +f 750//662 721//661 747//667 +f 750//662 747//667 775//668 +f 778//663 750//662 775//668 +f 778//663 775//668 803//669 +f 806//664 778//663 803//669 +f 806//664 803//669 831//670 +f 833//665 806//664 831//670 +f 833//665 831//670 838//671 +f 718//666 688//539 698//545 +f 718//666 698//545 728//672 +f 747//667 718//666 728//672 +f 747//667 728//672 756//673 +f 775//668 747//667 756//673 +f 775//668 756//673 784//674 +f 803//669 775//668 784//674 +f 803//669 784//674 804//675 +f 831//670 803//669 804//675 +f 831//670 804//675 811//676 +f 838//671 831//670 811//676 +f 838//671 811//676 830//677 +f 728//672 698//545 717//551 +f 728//672 717//551 746//678 +f 756//673 728//672 746//678 +f 756//673 746//678 757//679 +f 784//674 756//673 757//679 +f 784//674 757//679 776//680 +f 804//675 784//674 776//680 +f 804//675 776//680 783//681 +f 811//676 804//675 783//681 +f 811//676 783//681 802//682 +f 830//677 811//676 802//682 +f 830//677 802//682 810//683 +f 746//678 717//551 727//557 +f 746//678 727//557 729//684 +f 757//679 746//678 729//684 +f 757//679 729//684 748//685 +f 776//680 757//679 748//685 +f 776//680 748//685 755//686 +f 783//681 776//680 755//686 +f 783//681 755//686 774//687 +f 802//682 783//681 774//687 +f 802//682 774//687 782//688 +f 810//683 802//682 782//688 +f 810//683 782//688 809//689 +f 729//684 727//557 699//563 +f 729//684 699//563 719//690 +f 748//685 729//684 719//690 +f 748//685 719//690 726//691 +f 755//686 748//685 726//691 +f 755//686 726//691 745//692 +f 774//687 755//686 745//692 +f 774//687 745//692 754//693 +f 782//688 774//687 754//693 +f 782//688 754//693 781//694 +f 809//689 782//688 781//694 +f 809//689 781//694 780//695 +f 719//690 699//563 689//569 +f 719//690 689//569 696//696 +f 726//691 719//690 696//696 +f 726//691 696//696 716//697 +f 745//692 726//691 716//697 +f 745//692 716//697 725//698 +f 754//693 745//692 725//698 +f 754//693 725//698 753//699 +f 781//694 754//693 753//699 +f 781//694 753//699 752//700 +f 780//695 781//694 752//700 +f 780//695 752//700 773//701 +f 696//696 689//569 668//575 +f 696//696 668//575 686//702 +f 716//697 696//696 686//702 +f 716//697 686//702 695//703 +f 725//698 716//697 695//703 +f 725//698 695//703 724//704 +f 753//699 725//698 724//704 +f 753//699 724//704 723//705 +f 752//700 753//699 723//705 +f 752//700 723//705 744//706 +f 773//701 752//700 744//706 +f 773//701 744//706 772//707 +f 686//702 668//575 641//579 +f 686//702 641//579 667//708 +f 695//703 686//702 667//708 +f 695//703 667//708 715//160 +f 724//704 695//703 715//160 +f 724//704 715//160 694//709 +f 723//705 724//704 694//709 +f 723//705 694//709 714//710 +f 744//706 723//705 714//710 +f 744//706 714//710 743//711 +f 772//707 744//706 743//711 +f 772//707 743//711 771//712 +f 694//709 715//160 666//713 +f 694//709 666//713 685//714 +f 714//710 694//709 685//714 +f 714//710 685//714 713//715 +f 743//711 714//710 713//715 +f 743//711 713//715 742//716 +f 771//712 743//711 742//716 +f 771//712 742//716 770//717 +f 666//713 631//152 658//718 +f 685//714 666//713 658//718 +f 685//714 658//718 684//719 +f 713//715 685//714 684//719 +f 713//715 684//719 712//720 +f 742//716 713//715 712//720 +f 742//716 712//720 741//721 +f 770//717 742//716 741//721 +f 770//717 741//721 769//722 +f 631//152 605//592 604//593 +f 631//152 604//593 630//723 +f 658//718 631//152 630//723 +f 658//718 630//723 657//724 +f 684//719 658//718 657//724 +f 684//719 657//724 683//725 +f 712//720 684//719 683//725 +f 712//720 683//725 711//726 +f 741//721 712//720 711//726 +f 741//721 711//726 740//727 +f 769//722 741//721 740//727 +f 769//722 740//727 768//728 +f 630//723 604//593 603//599 +f 630//723 603//599 629//729 +f 657//724 630//723 629//729 +f 657//724 629//729 656//730 +f 683//725 657//724 656//730 +f 683//725 656//730 682//731 +f 711//726 683//725 682//731 +f 711//726 682//731 710//732 +f 740//727 711//726 710//732 +f 740//727 710//732 739//733 +f 768//728 740//727 739//733 +f 768//728 739//733 767//734 +f 629//729 603//599 602//605 +f 629//729 602//605 628//735 +f 656//730 629//729 628//735 +f 656//730 628//735 655//736 +f 682//731 656//730 655//736 +f 682//731 655//736 681//737 +f 710//732 682//731 681//737 +f 710//732 681//737 709//738 +f 739//733 710//732 709//738 +f 739//733 709//738 738//739 +f 767//734 739//733 738//739 +f 767//734 738//739 766//740 +f 628//735 602//605 601//611 +f 628//735 601//611 627//741 +f 655//736 628//735 627//741 +f 655//736 627//741 654//742 +f 681//737 655//736 654//742 +f 681//737 654//742 680//743 +f 709//738 681//737 680//743 +f 709//738 680//743 708//744 +f 738//739 709//738 708//744 +f 738//739 708//744 737//745 +f 766//740 738//739 737//745 +f 766//740 737//745 765//746 +f 627//741 601//611 600//617 +f 627//741 600//617 626//747 +f 654//742 627//741 626//747 +f 654//742 626//747 653//748 +f 680//743 654//742 653//748 +f 680//743 653//748 679//749 +f 708//744 680//743 679//749 +f 708//744 679//749 707//750 +f 737//745 708//744 707//750 +f 737//745 707//750 736//751 +f 765//746 737//745 736//751 +f 765//746 736//751 764//752 +f 626//747 600//617 599//623 +f 626//747 599//623 625//753 +f 653//748 626//747 625//753 +f 653//748 625//753 652//754 +f 679//749 653//748 652//754 +f 679//749 652//754 678//755 +f 707//750 679//749 678//755 +f 707//750 678//755 706//756 +f 736//751 707//750 706//756 +f 736//751 706//756 735//757 +f 764//752 736//751 735//757 +f 764//752 735//757 763//758 +f 625//753 599//623 598//629 +f 625//753 598//629 624//759 +f 652//754 625//753 624//759 +f 652//754 624//759 651//760 +f 678//755 652//754 651//760 +f 678//755 651//760 677//761 +f 706//756 678//755 677//761 +f 706//756 677//761 705//762 +f 735//757 706//756 705//762 +f 735//757 705//762 734//763 +f 763//758 735//757 734//763 +f 763//758 734//763 762//764 +f 624//759 598//629 597//635 +f 624//759 597//635 623//765 +f 651//760 624//759 623//765 +f 651//760 623//765 650//766 +f 677//761 651//760 650//766 +f 677//761 650//766 676//767 +f 705//762 677//761 676//767 +f 705//762 676//767 704//768 +f 734//763 705//762 704//768 +f 734//763 704//768 733//769 +f 762//764 734//763 733//769 +f 762//764 733//769 761//770 +f 623//765 597//635 596//641 +f 623//765 596//641 622//771 +f 650//766 623//765 622//771 +f 650//766 622//771 649//772 +f 676//767 650//766 649//772 +f 676//767 649//772 675//773 +f 704//768 676//767 675//773 +f 704//768 675//773 703//774 +f 733//769 704//768 703//774 +f 733//769 703//774 732//775 +f 761//770 733//769 732//775 +f 761//770 732//775 760//776 +f 622//771 596//641 613//248 +f 622//771 613//248 640//777 +f 649//772 622//771 640//777 +f 649//772 640//777 665//778 +f 675//773 649//772 665//778 +f 675//773 665//778 693//779 +f 703//774 675//773 693//779 +f 703//774 693//779 722//780 +f 732//775 703//774 722//780 +f 732//775 722//780 751//781 +f 760//776 732//775 751//781 +f 760//776 751//781 779//782 +f 693//779 665//778 691//228 +f 693//779 691//228 702//646 +f 722//780 693//779 702//646 +f 722//780 702//646 731//648 +f 751//781 722//780 731//648 +f 751//781 731//648 759//650 +f 779//782 751//781 759//650 +f 779//782 759//650 786//652 +f 917//783 918//784 913//785 +f 892//786 917//783 913//785 +f 892//786 913//785 887//787 +f 866//788 892//786 887//787 +f 866//788 887//787 861//789 +f 840//790 866//788 861//789 +f 840//790 861//789 834//791 +f 813//792 840//790 834//791 +f 813//792 834//791 807//793 +f 786//652 813//792 807//793 +f 786//652 807//793 779//782 +f 913//785 918//784 893//794 +f 887//787 913//785 893//794 +f 887//787 893//794 867//795 +f 861//789 887//787 867//795 +f 861//789 867//795 841//796 +f 834//791 861//789 841//796 +f 834//791 841//796 814//797 +f 807//793 834//791 814//797 +f 807//793 814//797 787//798 +f 779//782 807//793 787//798 +f 779//782 787//798 760//776 +f 893//794 918//784 894//799 +f 867//795 893//794 894//799 +f 867//795 894//799 868//800 +f 841//796 867//795 868//800 +f 841//796 868//800 842//801 +f 814//797 841//796 842//801 +f 814//797 842//801 815//802 +f 787//798 814//797 815//802 +f 787//798 815//802 788//803 +f 760//776 787//798 788//803 +f 760//776 788//803 761//770 +f 894//799 918//784 895//804 +f 868//800 894//799 895//804 +f 868//800 895//804 869//805 +f 842//801 868//800 869//805 +f 842//801 869//805 843//806 +f 815//802 842//801 843//806 +f 815//802 843//806 816//807 +f 788//803 815//802 816//807 +f 788//803 816//807 789//808 +f 761//770 788//803 789//808 +f 761//770 789//808 762//764 +f 895//804 918//784 896//809 +f 869//805 895//804 896//809 +f 869//805 896//809 870//810 +f 843//806 869//805 870//810 +f 843//806 870//810 844//811 +f 816//807 843//806 844//811 +f 816//807 844//811 817//812 +f 789//808 816//807 817//812 +f 789//808 817//812 790//813 +f 762//764 789//808 790//813 +f 762//764 790//813 763//758 +f 896//809 918//784 897//814 +f 870//810 896//809 897//814 +f 870//810 897//814 871//815 +f 844//811 870//810 871//815 +f 844//811 871//815 845//816 +f 817//812 844//811 845//816 +f 817//812 845//816 818//817 +f 790//813 817//812 818//817 +f 790//813 818//817 791//818 +f 763//758 790//813 791//818 +f 763//758 791//818 764//752 +f 897//814 918//784 898//819 +f 871//815 897//814 898//819 +f 871//815 898//819 872//820 +f 845//816 871//815 872//820 +f 845//816 872//820 846//821 +f 818//817 845//816 846//821 +f 818//817 846//821 819//822 +f 791//818 818//817 819//822 +f 791//818 819//822 792//823 +f 764//752 791//818 792//823 +f 764//752 792//823 765//746 +f 898//819 918//784 899//824 +f 872//820 898//819 899//824 +f 872//820 899//824 873//825 +f 846//821 872//820 873//825 +f 846//821 873//825 847//826 +f 819//822 846//821 847//826 +f 819//822 847//826 820//827 +f 792//823 819//822 820//827 +f 792//823 820//827 793//828 +f 765//746 792//823 793//828 +f 765//746 793//828 766//740 +f 899//824 918//784 900//829 +f 873//825 899//824 900//829 +f 873//825 900//829 874//830 +f 847//826 873//825 874//830 +f 847//826 874//830 848//831 +f 820//827 847//826 848//831 +f 820//827 848//831 821//832 +f 793//828 820//827 821//832 +f 793//828 821//832 794//833 +f 766//740 793//828 794//833 +f 766//740 794//833 767//734 +f 900//829 918//784 901//834 +f 874//830 900//829 901//834 +f 874//830 901//834 875//835 +f 848//831 874//830 875//835 +f 848//831 875//835 849//836 +f 821//832 848//831 849//836 +f 821//832 849//836 822//837 +f 794//833 821//832 822//837 +f 794//833 822//837 795//838 +f 767//734 794//833 795//838 +f 767//734 795//838 768//728 +f 901//834 918//784 902//839 +f 875//835 901//834 902//839 +f 875//835 902//839 876//840 +f 849//836 875//835 876//840 +f 849//836 876//840 850//841 +f 822//837 849//836 850//841 +f 822//837 850//841 823//842 +f 795//838 822//837 823//842 +f 795//838 823//842 796//843 +f 768//728 795//838 796//843 +f 768//728 796//843 769//722 +f 902//839 918//784 903//844 +f 876//840 902//839 903//844 +f 876//840 903//844 877//845 +f 850//841 876//840 877//845 +f 850//841 877//845 851//846 +f 823//842 850//841 851//846 +f 823//842 851//846 824//847 +f 796//843 823//842 824//847 +f 796//843 824//847 797//848 +f 769//722 796//843 797//848 +f 769//722 797//848 770//717 +f 903//844 918//784 904//849 +f 877//845 903//844 904//849 +f 877//845 904//849 878//850 +f 851//846 877//845 878//850 +f 851//846 878//850 852//851 +f 824//847 851//846 852//851 +f 824//847 852//851 825//852 +f 797//848 824//847 825//852 +f 797//848 825//852 798//853 +f 770//717 797//848 798//853 +f 770//717 798//853 771//712 +f 904//849 918//784 905//854 +f 878//850 904//849 905//854 +f 878//850 905//854 879//855 +f 852//851 878//850 879//855 +f 852//851 879//855 853//856 +f 825//852 852//851 853//856 +f 825//852 853//856 826//857 +f 798//853 825//852 826//857 +f 798//853 826//857 799//858 +f 771//712 798//853 799//858 +f 771//712 799//858 772//707 +f 905//854 918//784 906//859 +f 879//855 905//854 906//859 +f 879//855 906//859 880//860 +f 853//856 879//855 880//860 +f 853//856 880//860 854//861 +f 826//857 853//856 854//861 +f 826//857 854//861 827//862 +f 799//858 826//857 827//862 +f 799//858 827//862 800//863 +f 772//707 799//858 800//863 +f 772//707 800//863 773//701 +f 906//859 918//784 907//864 +f 880//860 906//859 907//864 +f 880//860 907//864 881//865 +f 854//861 880//860 881//865 +f 854//861 881//865 855//866 +f 827//862 854//861 855//866 +f 827//862 855//866 828//867 +f 800//863 827//862 828//867 +f 800//863 828//867 801//868 +f 773//701 800//863 801//868 +f 773//701 801//868 780//695 +f 907//864 918//784 908//869 +f 881//865 907//864 908//869 +f 881//865 908//869 882//870 +f 855//866 881//865 882//870 +f 855//866 882//870 856//871 +f 828//867 855//866 856//871 +f 828//867 856//871 829//872 +f 801//868 828//867 829//872 +f 801//868 829//872 808//873 +f 780//695 801//868 808//873 +f 780//695 808//873 809//689 +f 908//869 918//784 909//874 +f 882//870 908//869 909//874 +f 882//870 909//874 883//875 +f 856//871 882//870 883//875 +f 856//871 883//875 857//876 +f 829//872 856//871 857//876 +f 829//872 857//876 836//877 +f 808//873 829//872 836//877 +f 808//873 836//877 835//878 +f 809//689 808//873 835//878 +f 809//689 835//878 810//683 +f 909//874 918//784 910//879 +f 883//875 909//874 910//879 +f 883//875 910//879 884//880 +f 857//876 883//875 884//880 +f 857//876 884//880 863//881 +f 836//877 857//876 863//881 +f 836//877 863//881 862//882 +f 835//878 836//877 862//882 +f 835//878 862//882 837//883 +f 810//683 835//878 837//883 +f 810//683 837//883 830//677 +f 910//879 918//784 911//884 +f 884//880 910//879 911//884 +f 884//880 911//884 889//885 +f 863//881 884//880 889//885 +f 863//881 889//885 888//886 +f 862//882 863//881 888//886 +f 862//882 888//886 864//887 +f 837//883 862//882 864//887 +f 837//883 864//887 858//888 +f 830//677 837//883 858//888 +f 830//677 858//888 838//671 +f 911//884 918//784 915//889 +f 889//885 911//884 915//889 +f 889//885 915//889 914//890 +f 888//886 889//885 914//890 +f 888//886 914//890 890//891 +f 864//887 888//886 890//891 +f 864//887 890//891 885//892 +f 858//888 864//887 885//892 +f 858//888 885//892 859//893 +f 838//671 858//888 859//893 +f 838//671 859//893 833//665 +f 915//889 918//784 919//894 +f 914//890 915//889 919//894 +f 914//890 919//894 912//895 +f 890//891 914//890 912//895 +f 890//891 912//895 886//896 +f 885//892 890//891 886//896 +f 885//892 886//896 860//897 +f 859//893 885//892 860//897 +f 859//893 860//897 832//898 +f 833//665 859//893 832//898 +f 833//665 832//898 805//659 +f 919//894 918//784 916//899 +f 912//895 919//894 916//899 +f 912//895 916//899 891//900 +f 886//896 912//895 891//900 +f 886//896 891//900 865//901 +f 860//897 886//896 865//901 +f 860//897 865//901 839//902 +f 832//898 860//897 839//902 +f 832//898 839//902 812//903 +f 805//659 832//898 812//903 +f 805//659 812//903 785//653 +f 916//899 918//784 917//783 +f 891//900 916//899 917//783 +f 891//900 917//783 892//786 +f 865//901 891//900 892//786 +f 865//901 892//786 866//788 +f 839//902 865//901 866//788 +f 839//902 866//788 840//790 +f 812//903 839//902 840//790 +f 812//903 840//790 813//792 +f 785//653 812//903 813//792 +f 785//653 813//792 786//652 +f 404//412 1267//904 1268//905 +f 384//906 373//907 372//480 +f 346//908 345//501 352//494 +f 435//909 436//426 419//419 +f 331//910 327//350 335//508 +f 462//439 453//433 1265//911 +f 920//912 921//913 922//914 +f 920//912 922//914 923//915 +f 923//915 922//914 927//916 +f 923//915 927//916 933//917 +f 933//917 927//916 940//918 +f 933//917 940//918 949//919 +f 949//919 940//918 959//920 +f 949//919 959//920 971//921 +f 971//921 959//920 984//922 +f 971//921 984//922 999//923 +f 999//923 984//922 1011//924 +f 999//923 1011//924 1027//925 +f 1027//925 1011//924 1042//926 +f 1027//925 1042//926 1059//927 +f 1059//927 1042//926 1077//928 +f 1059//927 1077//928 1095//929 +f 1095//929 1077//928 1110//930 +f 1095//929 1110//930 1129//931 +f 1129//931 1110//930 1144//932 +f 1129//931 1144//932 1163//933 +f 1163//933 1144//932 1179//934 +f 1163//933 1179//934 1196//935 +f 1196//935 1179//934 1210//936 +f 1196//935 1210//936 1220//937 +f 1220//937 1210//936 1212//938 +f 1220//937 1212//938 1201//939 +f 1201//939 1212//938 1181//940 +f 1201//939 1181//940 1169//941 +f 1169//941 1181//940 1147//942 +f 1169//941 1147//942 1135//943 +f 1135//943 1147//942 1113//944 +f 1135//943 1113//944 1102//945 +f 1102//945 1113//944 1081//946 +f 1102//945 1081//946 1065//947 +f 1065//947 1081//946 1046//948 +f 1065//947 1046//948 1032//949 +f 1032//949 1046//948 1016//950 +f 1032//949 1016//950 1003//951 +f 1003//951 1016//950 988//952 +f 1003//951 988//952 974//953 +f 974//953 988//952 962//954 +f 974//953 962//954 951//955 +f 951//955 962//954 942//956 +f 951//955 942//956 934//957 +f 934//957 942//956 928//958 +f 934//957 928//958 924//959 +f 924//959 928//958 921//913 +f 921//913 920//912 924//959 +f 926//960 920//912 923//915 +f 926//960 923//915 932//961 +f 938//962 926//960 932//961 +f 938//962 932//961 947//963 +f 956//964 938//962 947//963 +f 956//964 947//963 968//965 +f 980//966 956//964 968//965 +f 980//966 968//965 995//967 +f 1006//968 980//966 995//967 +f 1006//968 995//967 1022//969 +f 1036//970 1006//968 1022//969 +f 1036//970 1022//969 1053//971 +f 932//961 923//915 933//917 +f 932//961 933//917 948//972 +f 947//963 932//961 948//972 +f 947//963 948//972 969//973 +f 968//965 947//963 969//973 +f 968//965 969//973 996//974 +f 995//967 968//965 996//974 +f 995//967 996//974 1023//975 +f 1022//969 995//967 1023//975 +f 1022//969 1023//975 1054//976 +f 1053//971 1022//969 1054//976 +f 1053//971 1054//976 1089//977 +f 948//972 933//917 949//919 +f 948//972 949//919 970//978 +f 969//973 948//972 970//978 +f 969//973 970//978 997//979 +f 996//974 969//973 997//979 +f 996//974 997//979 1024//980 +f 1023//975 996//974 1024//980 +f 1023//975 1024//980 1055//981 +f 1054//976 1023//975 1055//981 +f 1054//976 1055//981 1090//982 +f 1089//977 1054//976 1090//982 +f 1089//977 1090//982 1109//983 +f 970//978 949//919 971//921 +f 970//978 971//921 998//984 +f 997//979 970//978 998//984 +f 997//979 998//984 1025//985 +f 1024//980 997//979 1025//985 +f 1024//980 1025//985 1056//986 +f 1055//981 1024//980 1056//986 +f 1055//981 1056//986 1091//987 +f 1090//982 1055//981 1091//987 +f 1090//982 1091//987 1124//988 +f 1109//983 1090//982 1124//988 +f 1109//983 1124//988 1122//989 +f 998//984 971//921 999//923 +f 998//984 999//923 1026//990 +f 1025//985 998//984 1026//990 +f 1025//985 1026//990 1057//991 +f 1056//986 1025//985 1057//991 +f 1056//986 1057//991 1092//992 +f 1091//987 1056//986 1092//992 +f 1091//987 1092//992 1125//993 +f 1124//988 1091//987 1125//993 +f 1124//988 1125//993 1156//994 +f 1122//989 1124//988 1156//994 +f 1122//989 1156//994 1142//995 +f 1026//990 999//923 1027//925 +f 1026//990 1027//925 1058//996 +f 1057//991 1026//990 1058//996 +f 1057//991 1058//996 1093//997 +f 1092//992 1057//991 1093//997 +f 1092//992 1093//997 1126//998 +f 1125//993 1092//992 1126//998 +f 1125//993 1126//998 1159//999 +f 1156//994 1125//993 1159//999 +f 1156//994 1159//999 1176//1000 +f 1142//995 1156//994 1176//1000 +f 1142//995 1176//1000 1157//1001 +f 1058//996 1027//925 1059//927 +f 1058//996 1059//927 1094//1002 +f 1093//997 1058//996 1094//1002 +f 1093//997 1094//1002 1127//1003 +f 1126//998 1093//997 1127//1003 +f 1126//998 1127//1003 1160//1004 +f 1159//999 1126//998 1160//1004 +f 1159//999 1160//1004 1192//1005 +f 1176//1000 1159//999 1192//1005 +f 1176//1000 1192//1005 1189//1006 +f 1157//1001 1176//1000 1189//1006 +f 1157//1001 1189//1006 1178//1007 +f 1094//1002 1059//927 1095//929 +f 1094//1002 1095//929 1128//1008 +f 1127//1003 1094//1002 1128//1008 +f 1127//1003 1128//1008 1161//1009 +f 1160//1004 1127//1003 1161//1009 +f 1160//1004 1161//1009 1193//1010 +f 1192//1005 1160//1004 1193//1010 +f 1192//1005 1193//1010 1215//1011 +f 1189//1006 1192//1005 1215//1011 +f 1189//1006 1215//1011 1207//1012 +f 1178//1007 1189//1006 1207//1012 +f 1178//1007 1207//1012 1191//1013 +f 1128//1008 1095//929 1129//931 +f 1128//1008 1129//931 1162//1014 +f 1161//1009 1128//1008 1162//1014 +f 1161//1009 1162//1014 1194//1015 +f 1193//1010 1161//1009 1194//1015 +f 1193//1010 1194//1015 1217//1016 +f 1215//1011 1193//1010 1217//1016 +f 1215//1011 1217//1016 1227//1017 +f 1207//1012 1215//1011 1227//1017 +f 1207//1012 1227//1017 1216//1018 +f 1191//1013 1207//1012 1216//1018 +f 1191//1013 1216//1018 1209//1019 +f 1162//1014 1129//931 1163//933 +f 1162//1014 1163//933 1195//1020 +f 1194//1015 1162//1014 1195//1020 +f 1194//1015 1195//1020 1218//1021 +f 1217//1016 1194//1015 1218//1021 +f 1217//1016 1218//1021 1230//1022 +f 1227//1017 1217//1016 1230//1022 +f 1227//1017 1230//1022 1229//1023 +f 1216//1018 1227//1017 1229//1023 +f 1216//1018 1229//1023 1225//1024 +f 1209//1019 1216//1018 1225//1024 +f 1209//1019 1225//1024 1203//1025 +f 1195//1020 1163//933 1196//935 +f 1195//1020 1196//935 1219//1026 +f 1218//1021 1195//1020 1219//1026 +f 1218//1021 1219//1026 1231//1027 +f 1230//1022 1218//1021 1231//1027 +f 1230//1022 1231//1027 1232//1028 +f 1229//1023 1230//1022 1232//1028 +f 1229//1023 1232//1028 1228//1029 +f 1225//1024 1229//1023 1228//1029 +f 1225//1024 1228//1029 1214//1030 +f 1203//1025 1225//1024 1214//1030 +f 1203//1025 1214//1030 1184//1031 +f 1219//1026 1196//935 1220//937 +f 1219//1026 1220//937 1224//1032 +f 1231//1027 1219//1026 1224//1032 +f 1231//1027 1224//1032 1223//1033 +f 1232//1028 1231//1027 1223//1033 +f 1232//1028 1223//1033 1222//1034 +f 1228//1029 1232//1028 1222//1034 +f 1228//1029 1222//1034 1221//1035 +f 1214//1030 1228//1029 1221//1035 +f 1214//1030 1221//1035 1204//1036 +f 1184//1031 1214//1030 1204//1036 +f 1184//1031 1204//1036 1171//1037 +f 1224//1032 1220//937 1201//939 +f 1224//1032 1201//939 1200//1038 +f 1223//1033 1224//1032 1200//1038 +f 1223//1033 1200//1038 1199//1039 +f 1222//1034 1223//1033 1199//1039 +f 1222//1034 1199//1039 1198//1040 +f 1221//1035 1222//1034 1198//1040 +f 1221//1035 1198//1040 1197//1041 +f 1204//1036 1221//1035 1197//1041 +f 1204//1036 1197//1041 1185//1042 +f 1171//1037 1204//1036 1185//1042 +f 1171//1037 1185//1042 1151//1043 +f 1200//1038 1201//939 1169//941 +f 1200//1038 1169//941 1168//1044 +f 1199//1039 1200//1038 1168//1044 +f 1199//1039 1168//1044 1167//1045 +f 1198//1040 1199//1039 1167//1045 +f 1198//1040 1167//1045 1166//1046 +f 1197//1041 1198//1040 1166//1046 +f 1197//1041 1166//1046 1165//1047 +f 1185//1042 1197//1041 1165//1047 +f 1185//1042 1165//1047 1164//1048 +f 1151//1043 1185//1042 1164//1048 +f 1151//1043 1164//1048 1137//1049 +f 1168//1044 1169//941 1135//943 +f 1168//1044 1135//943 1134//1050 +f 1167//1045 1168//1044 1134//1050 +f 1167//1045 1134//1050 1133//1051 +f 1166//1046 1167//1045 1133//1051 +f 1166//1046 1133//1051 1132//1052 +f 1165//1047 1166//1046 1132//1052 +f 1165//1047 1132//1052 1131//1053 +f 1164//1048 1165//1047 1131//1053 +f 1164//1048 1131//1053 1130//1054 +f 1137//1049 1164//1048 1130//1054 +f 1137//1049 1130//1054 1117//1055 +f 1134//1050 1135//943 1102//945 +f 1134//1050 1102//945 1101//1056 +f 1133//1051 1134//1050 1101//1056 +f 1133//1051 1101//1056 1100//1057 +f 1132//1052 1133//1051 1100//1057 +f 1132//1052 1100//1057 1099//1058 +f 1131//1053 1132//1052 1099//1058 +f 1131//1053 1099//1058 1098//1059 +f 1130//1054 1131//1053 1098//1059 +f 1130//1054 1098//1059 1097//1060 +f 1117//1055 1130//1054 1097//1060 +f 1117//1055 1097//1060 1096//1061 +f 1101//1056 1102//945 1065//947 +f 1101//1056 1065//947 1064//1062 +f 1100//1057 1101//1056 1064//1062 +f 1100//1057 1064//1062 1063//1063 +f 1099//1058 1100//1057 1063//1063 +f 1099//1058 1063//1063 1062//1064 +f 1098//1059 1099//1058 1062//1064 +f 1098//1059 1062//1064 1061//1065 +f 1097//1060 1098//1059 1061//1065 +f 1097//1060 1061//1065 1060//1066 +f 1096//1061 1097//1060 1060//1066 +f 1096//1061 1060//1066 1066//1067 +f 1064//1062 1065//947 1032//949 +f 1064//1062 1032//949 1031//1068 +f 1063//1063 1064//1062 1031//1068 +f 1063//1063 1031//1068 1030//1069 +f 1062//1064 1063//1063 1030//1069 +f 1062//1064 1030//1069 1029//1070 +f 1061//1065 1062//1064 1029//1070 +f 1061//1065 1029//1070 1028//1071 +f 1060//1066 1061//1065 1028//1071 +f 1060//1066 1028//1071 1033//1072 +f 1066//1067 1060//1066 1033//1072 +f 1066//1067 1033//1072 1050//1073 +f 1031//1068 1032//949 1003//951 +f 1031//1068 1003//951 1002//1074 +f 1030//1069 1031//1068 1002//1074 +f 1030//1069 1002//1074 1001//1075 +f 1029//1070 1030//1069 1001//1075 +f 1029//1070 1001//1075 1000//1076 +f 1028//1071 1029//1070 1000//1076 +f 1028//1071 1000//1076 1004//1077 +f 1033//1072 1028//1071 1004//1077 +f 1033//1072 1004//1077 1021//1078 +f 1050//1073 1033//1072 1021//1078 +f 1050//1073 1021//1078 1041//1079 +f 1002//1074 1003//951 974//953 +f 1002//1074 974//953 973//1080 +f 1001//1075 1002//1074 973//1080 +f 1001//1075 973//1080 972//1081 +f 1000//1076 1001//1075 972//1081 +f 1000//1076 972//1081 975//1082 +f 1004//1077 1000//1076 975//1082 +f 1004//1077 975//1082 992//1083 +f 1021//1078 1004//1077 992//1083 +f 1021//1078 992//1083 1010//1084 +f 1041//1079 1021//1078 1010//1084 +f 1041//1079 1010//1084 1040//1085 +f 973//1080 974//953 951//955 +f 973//1080 951//955 950//1086 +f 972//1081 973//1080 950//1086 +f 972//1081 950//1086 952//1087 +f 975//1082 972//1081 952//1087 +f 975//1082 952//1087 965//1088 +f 992//1083 975//1082 965//1088 +f 992//1083 965//1088 983//1089 +f 1010//1084 992//1083 983//1089 +f 1010//1084 983//1089 1009//1090 +f 1040//1085 1010//1084 1009//1090 +f 1040//1085 1009//1090 1039//1091 +f 950//1086 951//955 934//957 +f 950//1086 934//957 935//1092 +f 952//1087 950//1086 935//1092 +f 952//1087 935//1092 944//1093 +f 965//1088 952//1087 944//1093 +f 965//1088 944//1093 958//1094 +f 983//1089 965//1088 958//1094 +f 983//1089 958//1094 982//1095 +f 1009//1090 983//1089 982//1095 +f 1009//1090 982//1095 1008//1096 +f 1039//1091 1009//1090 1008//1096 +f 1039//1091 1008//1096 1038//1097 +f 935//1092 934//957 924//959 +f 935//1092 924//959 929//1098 +f 944//1093 935//1092 929//1098 +f 944//1093 929//1098 939//1099 +f 958//1094 944//1093 939//1099 +f 958//1094 939//1099 957//1100 +f 982//1095 958//1094 957//1100 +f 982//1095 957//1100 981//1101 +f 1008//1096 982//1095 981//1101 +f 1008//1096 981//1101 1007//1102 +f 1038//1097 1008//1096 1007//1102 +f 1038//1097 1007//1102 1037//1103 +f 924//959 920//912 929//1098 +f 929//1098 920//912 926//960 +f 939//1099 929//1098 926//960 +f 939//1099 926//960 938//962 +f 957//1100 939//1099 938//962 +f 957//1100 938//962 956//964 +f 981//1101 957//1100 956//964 +f 981//1101 956//964 980//966 +f 1007//1102 981//1101 980//966 +f 1007//1102 980//966 1006//968 +f 1037//1103 1007//1102 1006//968 +f 1037//1103 1006//968 1036//970 +f 993//1104 1005//1105 976//1106 +f 966//1107 993//1104 976//1106 +f 966//1107 976//1106 953//1108 +f 945//1109 966//1107 953//1108 +f 945//1109 953//1108 936//1110 +f 930//1111 945//1109 936//1110 +f 930//1111 936//1110 925//1112 +f 921//913 930//1111 925//1112 +f 921//913 925//1112 922//914 +f 976//1106 1005//1105 977//1113 +f 953//1108 976//1106 977//1113 +f 953//1108 977//1113 954//1114 +f 936//1110 953//1108 954//1114 +f 936//1110 954//1114 937//1115 +f 925//1112 936//1110 937//1115 +f 925//1112 937//1115 931//1116 +f 922//914 925//1112 931//1116 +f 922//914 931//1116 927//916 +f 977//1113 1005//1105 978//1117 +f 954//1114 977//1113 978//1117 +f 954//1114 978//1117 955//1118 +f 937//1115 954//1114 955//1118 +f 937//1115 955//1118 946//1119 +f 931//1116 937//1115 946//1119 +f 931//1116 946//1119 941//1120 +f 927//916 931//1116 941//1120 +f 927//916 941//1120 940//918 +f 978//1117 1005//1105 979//1121 +f 955//1118 978//1117 979//1121 +f 955//1118 979//1121 967//1122 +f 946//1119 955//1118 967//1122 +f 946//1119 967//1122 961//1123 +f 941//1120 946//1119 961//1123 +f 941//1120 961//1123 960//1124 +f 940//918 941//1120 960//1124 +f 940//918 960//1124 959//920 +f 979//1121 1005//1105 994//1125 +f 967//1122 979//1121 994//1125 +f 967//1122 994//1125 987//1126 +f 961//1123 967//1122 987//1126 +f 961//1123 987//1126 986//1127 +f 960//1124 961//1123 986//1127 +f 960//1124 986//1127 985//1128 +f 959//920 960//1124 985//1128 +f 959//920 985//1128 984//922 +f 994//1125 1005//1105 1015//1129 +f 987//1126 994//1125 1015//1129 +f 987//1126 1015//1129 1014//1130 +f 986//1127 987//1126 1014//1130 +f 986//1127 1014//1130 1013//1131 +f 985//1128 986//1127 1013//1131 +f 985//1128 1013//1131 1012//1132 +f 984//922 985//1128 1012//1132 +f 984//922 1012//1132 1011//924 +f 1015//1129 1005//1105 1035//1133 +f 1014//1130 1015//1129 1035//1133 +f 1014//1130 1035//1133 1045//1134 +f 1013//1131 1014//1130 1045//1134 +f 1013//1131 1045//1134 1044//1135 +f 1012//1132 1013//1131 1044//1135 +f 1012//1132 1044//1135 1043//1136 +f 1011//924 1012//1132 1043//1136 +f 1011//924 1043//1136 1042//926 +f 1035//1133 1005//1105 1052//1137 +f 1045//1134 1035//1133 1052//1137 +f 1045//1134 1052//1137 1080//1138 +f 1044//1135 1045//1134 1080//1138 +f 1044//1135 1080//1138 1079//1139 +f 1043//1136 1044//1135 1079//1139 +f 1043//1136 1079//1139 1078//1140 +f 1042//926 1043//1136 1078//1140 +f 1042//926 1078//1140 1077//928 +f 1052//1137 1005//1105 1068//1141 +f 1080//1138 1052//1137 1068//1141 +f 1080//1138 1068//1141 1106//1142 +f 1079//1139 1080//1138 1106//1142 +f 1079//1139 1106//1142 1112//1143 +f 1078//1140 1079//1139 1112//1143 +f 1078//1140 1112//1143 1111//1144 +f 1077//928 1078//1140 1111//1144 +f 1077//928 1111//1144 1110//930 +f 1068//1141 1005//1105 1087//1145 +f 1106//1142 1068//1141 1087//1145 +f 1106//1142 1087//1145 1120//1146 +f 1112//1143 1106//1142 1120//1146 +f 1112//1143 1120//1146 1146//1147 +f 1111//1144 1112//1143 1146//1147 +f 1111//1144 1146//1147 1145//1148 +f 1110//930 1111//1144 1145//1148 +f 1110//930 1145//1148 1144//932 +f 1087//1145 1005//1105 1107//1149 +f 1120//1146 1087//1145 1107//1149 +f 1120//1146 1107//1149 1140//1150 +f 1146//1147 1120//1146 1140//1150 +f 1146//1147 1140//1150 1174//1151 +f 1145//1148 1146//1147 1174//1151 +f 1145//1148 1174//1151 1180//1152 +f 1144//932 1145//1148 1180//1152 +f 1144//932 1180//1152 1179//934 +f 1107//1149 1005//1105 1121//1153 +f 1140//1150 1107//1149 1121//1153 +f 1140//1150 1121//1153 1154//1154 +f 1174//1151 1140//1150 1154//1154 +f 1174//1151 1154//1154 1188//1155 +f 1180//1152 1174//1151 1188//1155 +f 1180//1152 1188//1155 1211//1156 +f 1179//934 1180//1152 1211//1156 +f 1179//934 1211//1156 1210//936 +f 1121//1153 1005//1105 1141//1157 +f 1154//1154 1121//1153 1141//1157 +f 1154//1154 1141//1157 1175//1158 +f 1188//1155 1154//1154 1175//1158 +f 1188//1155 1175//1158 1206//1159 +f 1211//1156 1188//1155 1206//1159 +f 1211//1156 1206//1159 1226//1160 +f 1210//936 1211//1156 1226//1160 +f 1210//936 1226//1160 1212//938 +f 1141//1157 1005//1105 1155//1161 +f 1175//1158 1141//1157 1155//1161 +f 1175//1158 1155//1161 1187//1162 +f 1206//1159 1175//1158 1187//1162 +f 1206//1159 1187//1162 1205//1163 +f 1226//1160 1206//1159 1205//1163 +f 1226//1160 1205//1163 1213//1164 +f 1212//938 1226//1160 1213//1164 +f 1212//938 1213//1164 1181//940 +f 1155//1161 1005//1105 1153//1165 +f 1187//1162 1155//1161 1153//1165 +f 1187//1162 1153//1165 1173//1166 +f 1205//1163 1187//1162 1173//1166 +f 1205//1163 1173//1166 1186//1167 +f 1213//1164 1205//1163 1186//1167 +f 1213//1164 1186//1167 1182//1168 +f 1181//940 1213//1164 1182//1168 +f 1181//940 1182//1168 1147//942 +f 1153//1165 1005//1105 1139//1169 +f 1173//1166 1153//1165 1139//1169 +f 1173//1166 1139//1169 1152//1170 +f 1186//1167 1173//1166 1152//1170 +f 1186//1167 1152//1170 1172//1171 +f 1182//1168 1186//1167 1172//1171 +f 1182//1168 1172//1171 1148//1172 +f 1147//942 1182//1168 1148//1172 +f 1147//942 1148//1172 1113//944 +f 1139//1169 1005//1105 1119//1173 +f 1152//1170 1139//1169 1119//1173 +f 1152//1170 1119//1173 1138//1174 +f 1172//1171 1152//1170 1138//1174 +f 1172//1171 1138//1174 1149//1175 +f 1148//1172 1172//1171 1149//1175 +f 1148//1172 1149//1175 1114//1176 +f 1113//944 1148//1172 1114//1176 +f 1113//944 1114//1176 1081//946 +f 1119//1173 1005//1105 1105//1177 +f 1138//1174 1119//1173 1105//1177 +f 1138//1174 1105//1177 1118//1178 +f 1149//1175 1138//1174 1118//1178 +f 1149//1175 1118//1178 1115//1179 +f 1114//1176 1149//1175 1115//1179 +f 1114//1176 1115//1179 1082//1180 +f 1081//946 1114//1176 1082//1180 +f 1081//946 1082//1180 1046//948 +f 1105//1177 1005//1105 1086//1181 +f 1118//1178 1105//1177 1086//1181 +f 1118//1178 1086//1181 1104//1182 +f 1115//1179 1118//1178 1104//1182 +f 1115//1179 1104//1182 1083//1183 +f 1082//1180 1115//1179 1083//1183 +f 1082//1180 1083//1183 1047//1184 +f 1046//948 1082//1180 1047//1184 +f 1046//948 1047//1184 1016//950 +f 1086//1181 1005//1105 1067//1185 +f 1104//1182 1086//1181 1067//1185 +f 1104//1182 1067//1185 1084//1186 +f 1083//1183 1104//1182 1084//1186 +f 1083//1183 1084//1186 1048//1187 +f 1047//1184 1083//1183 1048//1187 +f 1047//1184 1048//1187 1017//1188 +f 1016//950 1047//1184 1017//1188 +f 1016//950 1017//1188 988//952 +f 1067//1185 1005//1105 1051//1189 +f 1084//1186 1067//1185 1051//1189 +f 1084//1186 1051//1189 1049//1190 +f 1048//1187 1084//1186 1049//1190 +f 1048//1187 1049//1190 1018//1191 +f 1017//1188 1048//1187 1018//1191 +f 1017//1188 1018//1191 989//1192 +f 988//952 1017//1188 989//1192 +f 988//952 989//1192 962//954 +f 1051//1189 1005//1105 1034//1193 +f 1049//1190 1051//1189 1034//1193 +f 1049//1190 1034//1193 1019//1194 +f 1018//1191 1049//1190 1019//1194 +f 1018//1191 1019//1194 990//1195 +f 989//1192 1018//1191 990//1195 +f 989//1192 990//1195 963//1196 +f 962//954 989//1192 963//1196 +f 962//954 963//1196 942//956 +f 1034//1193 1005//1105 1020//1197 +f 1019//1194 1034//1193 1020//1197 +f 1019//1194 1020//1197 991//1198 +f 990//1195 1019//1194 991//1198 +f 990//1195 991//1198 964//1199 +f 963//1196 990//1195 964//1199 +f 963//1196 964//1199 943//1200 +f 942//956 963//1196 943//1200 +f 942//956 943//1200 928//958 +f 1020//1197 1005//1105 993//1104 +f 991//1198 1020//1197 993//1104 +f 991//1198 993//1104 966//1107 +f 964//1199 991//1198 966//1107 +f 964//1199 966//1107 945//1109 +f 943//1200 964//1199 945//1109 +f 943//1200 945//1109 930//1111 +f 928//958 943//1200 930//1111 +f 928//958 930//1111 921//913 +f 1151//1043 1137//1049 1150//1201 +f 1142//995 1143//1202 1122//989 +f 1053//971 1089//977 1069//1203 +f 1122//989 1123//1204 1109//983 +f 1096//1061 1103//1205 1117//1055 +f 1171//1037 1170//1206 1184//1031 +f 1191//1013 1209//1019 1190//1207 +f 1036//970 1053//971 1070//1208 +f 1036//970 1070//1208 1037//1103 +f 1203//1025 1202//1209 1209//1019 +f 1066//1067 1085//1210 1096//1061 +f 1050//1073 1076//1211 1066//1067 +f 1184//1031 1183//1212 1203//1025 +f 1041//1079 1040//1085 1075//1213 +f 1171//1037 1151//1043 1170//1206 +f 1157//1001 1158//1214 1142//995 +f 1137//1049 1117//1055 1136//1215 +f 1038//1097 1072//1216 1039//1091 +f 1178//1007 1191//1013 1177//1217 +f 1089//977 1109//983 1088//1218 +f 1037//1103 1071//1219 1038//1097 +f 1050//1073 1041//1079 1076//1211 +f 1157//1001 1178//1007 1158//1214 +f 1040//1085 1039//1091 1074//1220 +f 1170//1206 1150//1201 452//1221 +f 1264//1222 1071//1219 1263//1223 +f 1261//1224 1262//1225 1076//1211 +f 1085//1210 1076//1211 1262//1225 +f 1190//1207 1208//1226 405//1227 +f 509//176 526//519 1260//1228 +f 1260//1228 526//519 556//523 +f 167//201 556//523 595//202 +f 595//202 621//526 1255//200 +f 172//192 163//182 1254//199 +f 8//49 18//42 3//1229 +f 3//1229 18//42 1288//1230 +f 15//75 7//66 1240//82 +f 1250//50 8//49 3//1229 +f 1//32 1283//40 566//33 +f 593//3 566//33 9//41 +f 19//1231 20//34 33//25 +f 1243//2 636//89 593//3 +f 64//18 40//6 36//17 +f 1244//24 64//18 36//17 +f 641//579 614//582 1237//1232 +f 1250//50 1239//1233 4//48 +f 7//66 4//48 1239//1233 +f 5//74 14//73 11//81 +f 1240//82 7//66 1239//1233 +f 1//32 553//31 565//56 +f 593//3 9//41 1289//83 +f 18//42 20//34 1288//1230 +f 40//6 27//5 1252//16 +f 1249//58 6//65 565//56 +f 14//73 15//75 11//81 +f 592//57 1234//130 1233//58 +f 1237//1232 614//582 588//586 +f 1237//1232 588//586 605//592 +f 539//175 159//177 1259//1234 +f 164//257 1257//1235 168//251 +f 509//176 1256//1236 159//177 +f 1258//250 585//249 1259//1234 +f 169//1237 164//257 174//242 +f 191//236 208//230 185//1238 +f 1290//1239 207//229 640//777 +f 621//526 1292//1240 1255//200 +f 163//182 160//178 157//180 +f 1284//1241 1292//1240 648//227 +f 1252//16 27//5 12//95 +f 119//124 116//129 104//161 +f 116//129 88//135 1242//136 +f 87//159 666//713 715//160 +f 87//159 1241//1242 666//713 +f 1253//1243 47//150 631//152 +f 631//152 666//713 1253//1243 +f 86//142 74//144 60//143 +f 640//777 1291//1244 1290//1239 +f 1291//1244 640//777 613//248 +f 208//230 219//220 200//1245 +f 665//778 640//777 207//229 +f 1285//226 200//1245 219//220 +f 648//227 207//229 1284//1241 +f 691//228 665//778 207//229 +f 605//592 1236//1246 1245//1246 +f 1235//151 605//592 631//152 +f 1248//145 48//153 37//167 +f 667//708 1251//1247 1247//158 +f 605//592 1235//151 1236//1246 +f 641//579 1238//1248 1246//1249 +f 641//579 1237//1232 1238//1248 +f 404//412 391//405 1267//904 +f 1265//911 453//433 436//426 +f 328//351 327//350 331//910 +f 443//445 462//439 469//1250 +f 342//370 1275//1251 344//1252 +f 342//370 334//363 1275//1251 +f 372//480 385//473 384//906 +f 351//377 1271//1253 361//384 +f 351//377 350//1254 1271//1253 +f 337//1255 335//508 345//501 +f 384//906 385//473 396//466 +f 361//384 368//1256 369//391 +f 361//384 1271//1253 368//1256 +f 352//494 1276//1257 346//908 +f 397//1258 396//466 411//459 +f 342//370 350//1254 351//377 +f 342//370 344//1252 350//1254 +f 380//398 369//391 368//1256 +f 334//363 328//351 332//1259 +f 404//412 418//1260 419//419 +f 404//412 1268//905 418//1260 +f 426//452 1286//1261 1282//1262 +f 1282//1262 411//459 426//452 +f 352//494 362//487 1277//1263 +f 1277//1263 1276//1257 352//494 +f 391//405 380//398 381//1264 +f 426//452 443//445 444//1265 +f 444//1265 1286//1261 426//452 +f 362//487 372//480 373//907 +f 373//907 1277//1263 362//487 +f 1202//1209 1183//1212 1270//1266 +f 1116//1267 428//1268 1136//1215 +f 428//1268 1287//1269 1136//1215 +f 1073//1270 353//1271 1074//1220 +f 353//1271 363//1272 1074//1220 +f 353//1271 1073//1270 1279//1273 +f 1070//1208 1069//1203 1263//1223 +f 1274//1274 1069//1203 1088//1218 +f 1177//1217 1273//1275 1272//1276 +f 1272//1276 1158//1214 1177//1217 +f 428//1268 1116//1267 427//1277 +f 1088//1218 1108//1278 343//1279 +f 1103//1205 1085//1210 1278//1280 +f 1108//1278 1123//1204 1280//1281 +f 1123//1204 1281//1282 1280//1281 +f 1143//1202 1158//1214 360//1283 +f 1158//1214 1272//1276 360//1283 +f 1075//1213 1261//1224 1076//1211 +f 1085//1210 1262//1225 1278//1280 +f 1123//1204 1143//1202 1281//1282 +f 1143//1202 360//1283 1281//1282 +f 1074//1220 363//1272 1075//1213 +f 363//1272 1261//1224 1075//1213 +f 1270//1266 1183//1212 452//1221 +f 1266//1284 1150//1201 1136//1215 +f 1273//1275 1177//1217 1190//1207 +f 1208//1226 1202//1209 406//1285 +f 1202//1209 1269//1286 406//1285 +f 1072//1216 1071//1219 1264//1222 +f 1241//1242 1253//1243 666//713 +f 71//137 86//142 60//143 +f 88//135 86//142 71//137 +f 1245//1246 1237//1232 605//592 +f 119//124 104//161 90//119 +f 667//708 1246//1249 1251//1247 +f 621//526 648//227 1292//1240 +f 208//230 200//1245 185//1238 +f 174//242 191//236 169//1237 +f 1258//250 1291//1244 613//248 +f 1244//24 19//1231 33//25 +f 1288//1230 20//34 19//1231 +f 199//208 182//198 178//1287 +f 206//1288 218//214 190//1289 +f 1260//1228 556//523 167//201 +f 157//180 1254//199 163//182 +f 178//1287 182//198 1254//199 +f 218//214 206//1288 1285//226 +f 161//258 1257//1235 158//179 +f 324//345 312//274 323//336 +f 303//317 302//323 316//338 +f 305//305 304//311 318//340 +f 304//311 303//317 317//339 +f 322//347 309//281 321//341 +f 320//346 307//293 319//342 +f 301//329 311//335 314//344 +f 302//323 301//329 315//337 +f 311//335 312//274 313//343 +f 319//342 306//299 318//340 +f 321//341 308//287 320//346 +f 323//336 310//275 322//347 +f 418//1260 435//909 419//419 +f 337//1255 331//910 335//508 +f 469//1250 462//439 1265//911 +f 1137//1049 1136//1215 1150//1201 +f 1143//1202 1123//1204 1122//989 +f 1089//977 1088//1218 1069//1203 +f 1123//1204 1108//1278 1109//983 +f 1103//1205 1116//1267 1117//1055 +f 1170//1206 1183//1212 1184//1031 +f 1209//1019 1208//1226 1190//1207 +f 1053//971 1069//1203 1070//1208 +f 1070//1208 1071//1219 1037//1103 +f 1202//1209 1208//1226 1209//1019 +f 1085//1210 1103//1205 1096//1061 +f 1076//1211 1085//1210 1066//1067 +f 1183//1212 1202//1209 1203//1025 +f 1040//1085 1074//1220 1075//1213 +f 1151//1043 1150//1201 1170//1206 +f 1158//1214 1143//1202 1142//995 +f 1117//1055 1116//1267 1136//1215 +f 1072//1216 1073//1270 1039//1091 +f 1191//1013 1190//1207 1177//1217 +f 1109//983 1108//1278 1088//1218 +f 1071//1219 1072//1216 1038//1097 +f 1041//1079 1075//1213 1076//1211 +f 1178//1007 1177//1217 1158//1214 +f 1039//1091 1073//1270 1074//1220 +f 1150//1201 1266//1284 452//1221 +f 1071//1219 1070//1208 1263//1223 +f 1208//1226 406//1285 405//1227 +f 1256//1236 509//176 1260//1228 +f 1257//1235 161//258 168//251 +f 585//249 539//175 1259//1234 +f 715//160 667//708 1247//158 +f 667//708 641//579 1246//1249 +f 435//909 1265//911 436//426 +f 332//1259 328//351 331//910 +f 444//1265 443//445 469//1250 +f 346//908 337//1255 345//501 +f 397//1258 384//906 396//466 +f 1282//1262 397//1258 411//459 +f 381//1264 380//398 368//1256 +f 1275//1251 334//363 332//1259 +f 1267//904 391//405 381//1264 +f 1269//1286 1202//1209 1270//1266 +f 1073//1270 1072//1216 1279//1273 +f 1069//1203 1274//1274 1263//1223 +f 343//1279 1274//1274 1088//1218 +f 1116//1267 1103//1205 427//1277 +f 1108//1278 1280//1281 343//1279 +f 427//1277 1103//1205 1278//1280 +f 1183//1212 1170//1206 452//1221 +f 1287//1269 1266//1284 1136//1215 +f 405//1227 1273//1275 1190//1207 +f 1279//1273 1072//1216 1264//1222 +f 191//236 185//1238 169//1237 +f 190//1289 199//208 178//1287 +f 218//214 199//208 190//1289 diff --git a/L00/src/GLSL.cpp b/L00/src/GLSL.cpp new file mode 100644 index 0000000..2969872 --- /dev/null +++ b/L00/src/GLSL.cpp @@ -0,0 +1,152 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#include "GLSL.h" +#include +#include +#include +#include + +using namespace std; + +namespace GLSL { + +const char * errorString(GLenum err) +{ + switch(err) { + case GL_NO_ERROR: + return "No error"; + case GL_INVALID_ENUM: + return "Invalid enum"; + case GL_INVALID_VALUE: + return "Invalid value"; + case GL_INVALID_OPERATION: + return "Invalid operation"; + case GL_STACK_OVERFLOW: + return "Stack overflow"; + case GL_STACK_UNDERFLOW: + return "Stack underflow"; + case GL_OUT_OF_MEMORY: + return "Out of memory"; + default: + return "No error"; + } +} + +void checkVersion() +{ + int major, minor; + major = minor = 0; + const char *verstr = (const char *)glGetString(GL_VERSION); + + if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) { + printf("Invalid GL_VERSION format %d.%d\n", major, minor); + } + if(major < 2) { + printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor); + exit(0); + } +} + +void checkError(const char *str) +{ + GLenum glErr = glGetError(); + if(glErr != GL_NO_ERROR) { + if(str) { + printf("%s: ", str); + } + printf("GL_ERROR = %s.\n", errorString(glErr)); + assert(false); + } +} + +void printShaderInfoLog(GLuint shader) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Shader InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +void printProgramInfoLog(GLuint program) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Program InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +char *textFileRead(const char *fn) +{ + FILE *fp; + char *content = NULL; + int count = 0; + if(fn != NULL) { + fp = fopen(fn,"rt"); + if(fp != NULL) { + fseek(fp, 0, SEEK_END); + count = (int)ftell(fp); + rewind(fp); + if(count > 0) { + content = (char *)malloc(sizeof(char) * (count+1)); + count = (int)fread(content,sizeof(char),count,fp); + content[count] = '\0'; + } + fclose(fp); + } else { + printf("error loading %s\n", fn); + } + } + return content; +} + +int textFileWrite(const char *fn, const char *s) +{ + FILE *fp; + int status = 0; + if(fn != NULL) { + fp = fopen(fn,"w"); + if(fp != NULL) { + if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) { + status = 1; + } + fclose(fp); + } + } + return(status); +} + +} diff --git a/L00/src/GLSL.h b/L00/src/GLSL.h new file mode 100644 index 0000000..f945fdd --- /dev/null +++ b/L00/src/GLSL.h @@ -0,0 +1,40 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#pragma once +#ifndef __GLSL__ +#define __GLSL__ + +#define GLEW_STATIC +#include + +/////////////////////////////////////////////////////////////////////////////// +// For printing out the current file and line number // +/////////////////////////////////////////////////////////////////////////////// +#include + +template +std::string NumberToString(T x) +{ + std::ostringstream ss; + ss << x; + return ss.str(); +} + +#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str() +/////////////////////////////////////////////////////////////////////////////// + +namespace GLSL { + + void checkVersion(); + void checkError(const char *str = 0); + void printProgramInfoLog(GLuint program); + void printShaderInfoLog(GLuint shader); + int textFileWrite(const char *filename, const char *s); + char *textFileRead(const char *filename); +} + +#endif diff --git a/L00/src/MatrixStack.cpp b/L00/src/MatrixStack.cpp new file mode 100644 index 0000000..eaa6e6c --- /dev/null +++ b/L00/src/MatrixStack.cpp @@ -0,0 +1,114 @@ +#include "MatrixStack.h" + +#include +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +using namespace std; + +MatrixStack::MatrixStack() +{ + mstack = make_shared< stack >(); + mstack->push(glm::mat4(1.0)); +} + +MatrixStack::~MatrixStack() +{ +} + +void MatrixStack::pushMatrix() +{ + const glm::mat4 &top = mstack->top(); + mstack->push(top); + assert(mstack->size() < 100); +} + +void MatrixStack::popMatrix() +{ + assert(!mstack->empty()); + mstack->pop(); + // There should always be one matrix left. + assert(!mstack->empty()); +} + +void MatrixStack::loadIdentity() +{ + glm::mat4 &top = mstack->top(); + top = glm::mat4(1.0); +} + +void MatrixStack::translate(const glm::vec3 &t) +{ + glm::mat4 &top = mstack->top(); + top *= glm::translate(t); +} + +void MatrixStack::translate(float x, float y, float z) +{ + translate(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(const glm::vec3 &s) +{ + glm::mat4 &top = mstack->top(); + top *= glm::scale(s); +} + +void MatrixStack::scale(float x, float y, float z) +{ + scale(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(float s) +{ + scale(glm::vec3(s, s, s)); +} + +void MatrixStack::rotate(float angle, const glm::vec3 &axis) +{ + glm::mat4 &top = mstack->top(); + top *= glm::rotate(angle, axis); +} + +void MatrixStack::rotate(float angle, float x, float y, float z) +{ + rotate(angle, glm::vec3(x, y, z)); +} + +void MatrixStack::multMatrix(const glm::mat4 &matrix) +{ + glm::mat4 &top = mstack->top(); + top *= matrix; +} + +const glm::mat4 &MatrixStack::topMatrix() const +{ + return mstack->top(); +} + +void MatrixStack::print(const glm::mat4 &mat, const char *name) +{ + if(name) { + printf("%s = [\n", name); + } + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + // mat[j] returns the jth column + printf("%- 5.2f ", mat[j][i]); + } + printf("\n"); + } + if(name) { + printf("];"); + } + printf("\n"); +} + +void MatrixStack::print(const char *name) const +{ + print(mstack->top(), name); +} diff --git a/L00/src/MatrixStack.h b/L00/src/MatrixStack.h new file mode 100644 index 0000000..66278ce --- /dev/null +++ b/L00/src/MatrixStack.h @@ -0,0 +1,50 @@ +#pragma once +#ifndef _MatrixStack_H_ +#define _MatrixStack_H_ + +#include +#include +#include + +class MatrixStack +{ +public: + MatrixStack(); + virtual ~MatrixStack(); + + // glPushMatrix(): Copies the current matrix and adds it to the top of the stack + void pushMatrix(); + // glPopMatrix(): Removes the top of the stack and sets the current matrix to be the matrix that is now on top + void popMatrix(); + + // glLoadIdentity(): Sets the top matrix to be the identity + void loadIdentity(); + // glMultMatrix(): Right multiplies the top matrix + void multMatrix(const glm::mat4 &matrix); + + // glTranslate(): Right multiplies the top matrix by a translation matrix + void translate(const glm::vec3 &trans); + void translate(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(const glm::vec3 &scale); + void scale(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(float size); + // glRotate(): Right multiplies the top matrix by a rotation matrix (angle in radians) + void rotate(float angle, const glm::vec3 &axis); + void rotate(float angle, float x, float y, float z); + + // glGet(GL_MODELVIEW_MATRIX): Gets the top matrix + const glm::mat4 &topMatrix() const; + + // Prints out the specified matrix + static void print(const glm::mat4 &mat, const char *name = 0); + // Prints out the top matrix + void print(const char *name = 0) const; + +private: + std::shared_ptr< std::stack > mstack; + +}; + +#endif diff --git a/L00/src/Program.cpp b/L00/src/Program.cpp new file mode 100644 index 0000000..1e85538 --- /dev/null +++ b/L00/src/Program.cpp @@ -0,0 +1,126 @@ +#include "Program.h" + +#include +#include + +#include "GLSL.h" + +using namespace std; + +Program::Program() : + vShaderName(""), + fShaderName(""), + pid(0), + verbose(true) +{ + +} + +Program::~Program() +{ + +} + +void Program::setShaderNames(const string &v, const string &f) +{ + vShaderName = v; + fShaderName = f; +} + +bool Program::init() +{ + GLint rc; + + // Create shader handles + GLuint VS = glCreateShader(GL_VERTEX_SHADER); + GLuint FS = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + const char *vshader = GLSL::textFileRead(vShaderName.c_str()); + const char *fshader = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(VS, 1, &vshader, NULL); + glShaderSource(FS, 1, &fshader, NULL); + + // Compile vertex shader + glCompileShader(VS); + glGetShaderiv(VS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(VS); + cout << "Error compiling vertex shader " << vShaderName << endl; + } + return false; + } + + // Compile fragment shader + glCompileShader(FS); + glGetShaderiv(FS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(FS); + cout << "Error compiling fragment shader " << fShaderName << endl; + } + return false; + } + + // Create the program and link + pid = glCreateProgram(); + glAttachShader(pid, VS); + glAttachShader(pid, FS); + glLinkProgram(pid); + glGetProgramiv(pid, GL_LINK_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printProgramInfoLog(pid); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + } + return false; + } + + GLSL::checkError(GET_FILE_LINE); + return true; +} + +void Program::bind() +{ + glUseProgram(pid); +} + +void Program::unbind() +{ + glUseProgram(0); +} + +void Program::addAttribute(const string &name) +{ + attributes[name] = glGetAttribLocation(pid, name.c_str()); +} + +void Program::addUniform(const string &name) +{ + uniforms[name] = glGetUniformLocation(pid, name.c_str()); +} + +GLint Program::getAttribute(const string &name) const +{ + map::const_iterator attribute = attributes.find(name.c_str()); + if(attribute == attributes.end()) { + if(isVerbose()) { + cout << name << " is not an attribute variable" << endl; + } + return -1; + } + return attribute->second; +} + +GLint Program::getUniform(const string &name) const +{ + map::const_iterator uniform = uniforms.find(name.c_str()); + if(uniform == uniforms.end()) { + if(isVerbose()) { + cout << name << " is not a uniform variable" << endl; + } + return -1; + } + return uniform->second; +} diff --git a/L00/src/Program.h b/L00/src/Program.h new file mode 100644 index 0000000..51e58bb --- /dev/null +++ b/L00/src/Program.h @@ -0,0 +1,44 @@ +#pragma once +#ifndef __Program__ +#define __Program__ + +#include +#include + +#define GLEW_STATIC +#include + +/** + * An OpenGL Program (vertex and fragment shaders) + */ +class Program +{ +public: + Program(); + virtual ~Program(); + + void setVerbose(bool v) { verbose = v; } + bool isVerbose() const { return verbose; } + + void setShaderNames(const std::string &v, const std::string &f); + virtual bool init(); + virtual void bind(); + virtual void unbind(); + + void addAttribute(const std::string &name); + void addUniform(const std::string &name); + GLint getAttribute(const std::string &name) const; + GLint getUniform(const std::string &name) const; + +protected: + std::string vShaderName; + std::string fShaderName; + +private: + GLuint pid; + std::map attributes; + std::map uniforms; + bool verbose; +}; + +#endif diff --git a/L00/src/Shape.cpp b/L00/src/Shape.cpp new file mode 100644 index 0000000..cf80379 --- /dev/null +++ b/L00/src/Shape.cpp @@ -0,0 +1,135 @@ +#include "Shape.h" +#include + +#include "GLSL.h" +#include "Program.h" + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +using namespace std; + +Shape::Shape() : + posBufID(0), + norBufID(0), + texBufID(0) +{ +} + +Shape::~Shape() +{ +} + +void Shape::loadMesh(const string &meshName) +{ + // Load geometry + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + if(!attrib.texcoords.empty()) { + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+0]); + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+1]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } +} + +void Shape::init() +{ + // Send the position array to the GPU + glGenBuffers(1, &posBufID); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + // Send the normal array to the GPU + if(!norBuf.empty()) { + glGenBuffers(1, &norBufID); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + } + + // Send the texture array to the GPU + if(!texBuf.empty()) { + glGenBuffers(1, &texBufID); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glBufferData(GL_ARRAY_BUFFER, texBuf.size()*sizeof(float), &texBuf[0], GL_STATIC_DRAW); + } + + // Unbind the arrays + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} + +void Shape::draw(const shared_ptr prog) const +{ + // Bind position buffer + int h_pos = prog->getAttribute("aPos"); + glEnableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glVertexAttribPointer(h_pos, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + + // Bind normal buffer + int h_nor = prog->getAttribute("aNor"); + if(h_nor != -1 && norBufID != 0) { + glEnableVertexAttribArray(h_nor); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glVertexAttribPointer(h_nor, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Bind texcoords buffer + int h_tex = prog->getAttribute("aTex"); + if(h_tex != -1 && texBufID != 0) { + glEnableVertexAttribArray(h_tex); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glVertexAttribPointer(h_tex, 2, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Draw + int count = posBuf.size()/3; // number of indices to be rendered + glDrawArrays(GL_TRIANGLES, 0, count); + + // Disable and unbind + if(h_tex != -1) { + glDisableVertexAttribArray(h_tex); + } + if(h_nor != -1) { + glDisableVertexAttribArray(h_nor); + } + glDisableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} diff --git a/L00/src/Shape.h b/L00/src/Shape.h new file mode 100644 index 0000000..df2aea3 --- /dev/null +++ b/L00/src/Shape.h @@ -0,0 +1,36 @@ +#pragma once +#ifndef _SHAPE_H_ +#define _SHAPE_H_ + +#include +#include +#include + +class Program; + +/** + * A shape defined by a list of triangles + * - posBuf should be of length 3*ntris + * - norBuf should be of length 3*ntris (if normals are available) + * - texBuf should be of length 2*ntris (if texture coords are available) + * posBufID, norBufID, and texBufID are OpenGL buffer identifiers. + */ +class Shape +{ +public: + Shape(); + virtual ~Shape(); + void loadMesh(const std::string &meshName); + void init(); + void draw(const std::shared_ptr prog) const; + +private: + std::vector posBuf; + std::vector norBuf; + std::vector texBuf; + unsigned posBufID; + unsigned norBufID; + unsigned texBufID; +}; + +#endif diff --git a/L00/src/main.cpp b/L00/src/main.cpp new file mode 100644 index 0000000..f98680b --- /dev/null +++ b/L00/src/main.cpp @@ -0,0 +1,152 @@ +#define _USE_MATH_DEFINES +#include +#include + +#define GLEW_STATIC +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +#include "GLSL.h" +#include "MatrixStack.h" +#include "Program.h" +#include "Shape.h" + +using namespace std; + +GLFWwindow *window; // Main application window +string RES_DIR = ""; // Where data files live +shared_ptr prog; +shared_ptr shape; + +static void error_callback(int error, const char *description) +{ + cerr << description << endl; +} + +static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GL_TRUE); + } +} + +static void init() +{ + GLSL::checkVersion(); + + // Set background color. + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + // Enable z-buffer test. + glEnable(GL_DEPTH_TEST); + + // Initialize mesh. + shape = make_shared(); + shape->loadMesh(RES_DIR + "teapot.obj"); + shape->init(); + + // Initialize the GLSL program. + prog = make_shared(); + prog->setVerbose(false); // Set this to true when debugging. + prog->setShaderNames(RES_DIR + "simple_vert.glsl", RES_DIR + "simple_frag.glsl"); + prog->init(); + prog->addUniform("P"); + prog->addUniform("MV"); + prog->addAttribute("aPos"); + prog->addAttribute("aNor"); + + // If there were any OpenGL errors, this will print something. + // You can intersperse this line in your code to find the exact location + // of your OpenGL error. + GLSL::checkError(GET_FILE_LINE); +} + +static void render() +{ + // Get current frame buffer size. + int width, height; + glfwGetFramebufferSize(window, &width, &height); + float aspect = width/(float)height; + glViewport(0, 0, width, height); + + // Clear framebuffer. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Create matrix stacks. + auto P = make_shared(); + auto MV = make_shared(); + // Apply projection. + P->pushMatrix(); + P->multMatrix(glm::perspective((float)(45.0*M_PI/180.0), aspect, 0.01f, 100.0f)); + // Apply camera transform. + MV->pushMatrix(); + MV->translate(glm::vec3(0, -0.5, -3)); + + // Draw mesh using GLSL. + prog->bind(); + glUniformMatrix4fv(prog->getUniform("P"), 1, GL_FALSE, &P->topMatrix()[0][0]); + glUniformMatrix4fv(prog->getUniform("MV"), 1, GL_FALSE, &MV->topMatrix()[0][0]); + shape->draw(prog); + prog->unbind(); + + // Pop matrix stacks. + MV->popMatrix(); + P->popMatrix(); + + GLSL::checkError(GET_FILE_LINE); +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + cout << "Please specify the resource directory." << endl; + return 0; + } + RES_DIR = argv[1] + string("/"); + + // Set error callback. + glfwSetErrorCallback(error_callback); + // Initialize the library. + if(!glfwInit()) { + return -1; + } + // Create a windowed mode window and its OpenGL context. + window = glfwCreateWindow(640, 480, "YOUR NAME", NULL, NULL); + if(!window) { + glfwTerminate(); + return -1; + } + // Make the window's context current. + glfwMakeContextCurrent(window); + // Initialize GLEW. + glewExperimental = true; + if(glewInit() != GLEW_OK) { + cerr << "Failed to initialize GLEW" << endl; + return -1; + } + glGetError(); // A bug in glewInit() causes an error that we can safely ignore. + cout << "OpenGL version: " << glGetString(GL_VERSION) << endl; + cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; + // Set vsync. + glfwSwapInterval(1); + // Set keyboard callback. + glfwSetKeyCallback(window, key_callback); + // Initialize scene. + init(); + // Loop until the user closes the window. + while(!glfwWindowShouldClose(window)) { + // Render scene. + render(); + // Swap front and back buffers. + glfwSwapBuffers(window); + // Poll for and process events. + glfwPollEvents(); + } + // Quit program. + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/L00/src/tiny_obj_loader.h b/L00/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/L00/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/L01.zip b/L01.zip new file mode 100644 index 0000000..cb546dd Binary files /dev/null and b/L01.zip differ diff --git a/L01/.gitignore b/L01/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L01/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L01/CMakeLists.txt b/L01/CMakeLists.txt new file mode 100644 index 0000000..15573f2 --- /dev/null +++ b/L01/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L01) + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS}) + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") +ENDIF() diff --git a/L01/src/Image.cpp b/L01/src/Image.cpp new file mode 100644 index 0000000..7655b46 --- /dev/null +++ b/L01/src/Image.cpp @@ -0,0 +1,87 @@ +#include +#include +#include "Image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +using namespace std; + +Tri::Tri() +{ + vertex v1; + v1.x = 0.0; + v1.y = 0.0; + v1.z = 0.0; + vertex v2; + v2.x = 0.0; + v2.y = 0.0; + v2.z = 0.0; + vertex v3; + v3.x = 0.0; + v3.y = 0.0; + v3.z = 0.0; + v.push_back(v1); + v.push_back(v2); + v.push_back(v3); +} + +Tri::Tri(vertex &one, vertex &two, vertex &three) +{ + v.push_back(one); + v.push_back(two); + v.push_back(three); +} + +Image::Image(int w, int h) : + width(w), + height(h), + comp(3), + pixels(width*height*comp, 0) +{ +} + +Image::~Image() +{ +} + +void Image::setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) +{ + // The pixel data is laid out row by row. Each row consists of 'width' + // columns, and each column consists of 3 unsigned chars. + + // First check for bounds + if(y < 0 || y >= height) { + cout << "Row " << y << " is out of bounds" << endl; + return; + } + if(x < 0 || x >= width) { + cout << "Col " << x << " is out of bounds" << endl; + return; + } + + // Since the origin (0, 0) of the image is the upper left corner, we need + // to flip the row to make the origin be the lower left corner. + y = height - y - 1; + // index corresponding to row and col, (assuming single component image) + int index = y*width + x; + // Multiply by 3 to get the index for the rgb components. + assert(index >= 0); + assert(3*index + 2 < (int)pixels.size()); + pixels[3*index + 0] = r; + pixels[3*index + 1] = g; + pixels[3*index + 2] = b; +} + +void Image::writeToFile(const string &filename) +{ + // The distance in bytes from the first byte of a row of pixels to the + // first byte of the next row of pixels + int stride_in_bytes = width*comp*sizeof(unsigned char); + int rc = stbi_write_png(filename.c_str(), width, height, comp, &pixels[0], stride_in_bytes); + if(rc) { + cout << "Wrote to " << filename << endl; + } else { + cout << "Couldn't write to " << filename << endl; + } +} diff --git a/L01/src/Image.h b/L01/src/Image.h new file mode 100644 index 0000000..748bb6d --- /dev/null +++ b/L01/src/Image.h @@ -0,0 +1,40 @@ +#pragma once +#ifndef _IMAGE_H_ +#define _IMAGE_H_ + +#include +#include + +struct vertex +{ + float x = 0.0; + float y = 0.0; + float z = 0.0; +}; + +class Tri +{ + public: + Tri(); + Tri(vertex &one, vertex &two, vertex &three); + std::vector v; +}; + +class Image +{ +public: + Image(int width, int height); + virtual ~Image(); + void setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b); + void writeToFile(const std::string &filename); + int getWidth() const { return width; } + int getHeight() const { return height; } + +private: + int width; + int height; + int comp; + std::vector pixels; +}; + +#endif diff --git a/L01/src/main.cpp b/L01/src/main.cpp new file mode 100644 index 0000000..6f0a8d1 --- /dev/null +++ b/L01/src/main.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include "Image.h" + +// This allows you to skip the `std::` in front of C++ standard library +// functions. You can also say `using std::cout` to be more selective. +// You should never do this in a header file. +using namespace std; + +int main(int argc, char **argv) +{ + if(argc < 10) { + cout << "Usage: L01 filename width height x1 y1 x2 y2 x3 y3" << endl; + return 0; + } + // Output filename + string filename(argv[1]); + // Width of image + int width = atoi(argv[2]); + // Height of image + int height = atoi(argv[3]); + + // Initialize coordinate variables to make things easier + float x1 = atoi(argv[4]); + float y1 = atoi(argv[5]); + float x2 = atoi(argv[6]); + float y2 = atoi(argv[7]); + float x3 = atoi(argv[8]); + float y3 = atoi(argv[9]); + + // Vertex 1 + vertex v1; + v1.x = x1; + v1.y = y1; + v1.z = 0.0; + // Vertex 2 + vertex v2; + v2.x = x2; + v2.y = y2; + v2.z = 0.0; + // Vertex 3 + vertex v3; + v3.x = x3; + v3.y = y3; + v3.z = 0.0; + // Triangle + Tri t(v1, v2, v3); + +// Find xmin, xmax, ymin, ymax + float xmin = x1; + float xmax = x1; + float ymin = y1; + float ymax = y1; + if(x2 < xmin) + xmin = x2; + if(x3 < xmin) + xmin = x3; + if(x2 > xmax) + xmax = x2; + if(x3 > xmax) + xmax = x3; + if(y2 < ymin) + ymin = y2; + if(y3 < ymin) + ymin = y3; + if(y2 > ymax) + ymax = y2; + if(y3 > ymax) + ymax = y3; + + // Create the image. We're using a `shared_ptr`, a C++11 feature. + auto image = make_shared(width, height); + // Draw a rectangle + for(int y = ymin; y < ymax; ++y) { + for(int x = xmin; x < xmax; ++x) { + unsigned char r = 255; + unsigned char g = 0; + unsigned char b = 0; + image->setPixel(x, y, r, g, b); + } + } + // Write image to file + image->writeToFile(filename); + return 0; +} diff --git a/L01/src/stb_image_write.h b/L01/src/stb_image_write.h new file mode 100644 index 0000000..f07b625 --- /dev/null +++ b/L01/src/stb_image_write.h @@ -0,0 +1,1048 @@ +/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio. It could be + adapted to write to memory or a general streaming interface; let me know. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation. This library is designed + for source code compactness and simplicity, not optimal image file size + or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can define STBIW_MEMMOVE() to replace memmove() + +USAGE: + + There are four functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + There are also four equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + +CREDITS: + + PNG/BMP/TGA + Sean Barrett + HDR + Baldur Karlsson + TGA monochrome: + Jean-Sebastien Guay + misc enhancements: + Tim Kelsey + TGA RLE + Alan Hickman + initial file IO callback implementation + Emmanuel Julien + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + +LICENSE + +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#define STBIWDEF extern +extern int stbi_write_tga_with_rle; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + +#ifdef __cplusplus +} +#endif + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_tga_with_rle = 1; +#else +int stbi_write_tga_with_rle = 1; +#endif + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a, arr[1] = b, arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 1: + s->func(s->context,d,1); + break; + case 2: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + for (j = y - 1; j >= 0; --j) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson +#ifndef STBI_WRITE_NO_STDIO + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); + STBIW_FREE(scratch); + return 1; + } +} + +int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) best=d,bestloc=hlist[j]; + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; + s1 %= 65521, s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int i,j,k,p,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = j ? mapping : firstmap; + int best = 0, bestval = 0x7fffffff; + for (p=0; p < 2; ++p) { + for (k= p?best:0; k < 5; ++k) { + int type = mymap[k],est=0; + unsigned char *z = pixels + stride_bytes*j; + for (i=0; i < n; ++i) + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + for (i=n; i < x*n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i] - z[i-n]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; + case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } + } + if (p) break; + for (i=0; i < x*n; ++i) + est += abs((signed char) line_buffer[i]); + if (est < bestval) { bestval = est; best = k; } + } + } + // when we get here, best contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) best; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + f = fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ diff --git a/L01/src/triangle.cpp b/L01/src/triangle.cpp new file mode 100644 index 0000000..a8029c6 --- /dev/null +++ b/L01/src/triangle.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include "triangle.h" + +using namespace std; + +Tri::Tri() +{ + vertex v1; + v1.x = 0.0; + v1.y = 0.0; + v1.z = 0.0; + vertex v2; + v2.x = 0.0; + v2.y = 0.0; + v2.z = 0.0; + vertex v3; + v3.x = 0.0; + v3.y = 0.0; + v3.z = 0.0; + v.push_back(v1); + v.push_back(v2); + v.push_back(v3); +} + +Tri::Tri(vertex &one, vertex &two, vertex &three) : + v.push_back(one), + v.push_back(two), + v.push_back(three) +{ +} diff --git a/L01/src/triangle.h b/L01/src/triangle.h new file mode 100644 index 0000000..ee231b9 --- /dev/null +++ b/L01/src/triangle.h @@ -0,0 +1,23 @@ +#pragma once +#ifndef _TRIANGLE_H_ +#define _TRIANGLE_H_ + +#include +#include + +struct vertex +{ + float x = 0.0; + float y = 0.0; + float z = 0.0; +}; + +class Tri +{ + public: + Tri(); + Tri(vertex &one, vertex &two, vertex &three); + std::vector v; +}; + +#endif diff --git a/L02/.gitignore b/L02/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L02/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L02/CMakeFiles/3.7.2/CMakeCCompiler.cmake b/L02/CMakeFiles/3.7.2/CMakeCCompiler.cmake new file mode 100644 index 0000000..fb36007 --- /dev/null +++ b/L02/CMakeFiles/3.7.2/CMakeCCompiler.cmake @@ -0,0 +1,68 @@ +set(CMAKE_C_COMPILER "/usr/lib/hardening-wrapper/bin/cc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "6.3.1") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11") +set(CMAKE_C_COMPILE_FEATURES "c_function_prototypes;c_restrict;c_variadic_macros;c_static_assert") +set(CMAKE_C90_COMPILE_FEATURES "c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_static_assert") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_SIMULATE_VERSION "") + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_LINKER "/usr/lib/hardening-wrapper/bin/ld") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "c") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/hardening-wrapper/bin;/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1;/usr/lib;/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/L02/CMakeFiles/3.7.2/CMakeCXXCompiler.cmake b/L02/CMakeFiles/3.7.2/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..929c256 --- /dev/null +++ b/L02/CMakeFiles/3.7.2/CMakeCXXCompiler.cmake @@ -0,0 +1,69 @@ +set(CMAKE_CXX_COMPILER "/usr/lib/hardening-wrapper/bin/c++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "6.3.1") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_template_template_parameters;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_SIMULATE_VERSION "") + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_LINKER "/usr/lib/hardening-wrapper/bin/ld") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP) +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;c") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/hardening-wrapper/bin;/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1;/usr/lib;/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_C.bin b/L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000..b893f60 Binary files /dev/null and b/L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_C.bin differ diff --git a/L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_CXX.bin b/L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 0000000..e18e2ba Binary files /dev/null and b/L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_CXX.bin differ diff --git a/L02/CMakeFiles/3.7.2/CMakeSystem.cmake b/L02/CMakeFiles/3.7.2/CMakeSystem.cmake new file mode 100644 index 0000000..73db990 --- /dev/null +++ b/L02/CMakeFiles/3.7.2/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-4.8.13-1-ARCH") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "4.8.13-1-ARCH") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux-4.8.13-1-ARCH") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "4.8.13-1-ARCH") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/L02/CMakeFiles/3.7.2/CompilerIdC/CMakeCCompilerId.c b/L02/CMakeFiles/3.7.2/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..512e360 --- /dev/null +++ b/L02/CMakeFiles/3.7.2/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,561 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) +# define COMPILER_ID "Fujitsu" + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" + +#elif defined(__ARMCC_VERSION) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(SDCC) +# define COMPILER_ID "SDCC" + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) + +#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) +# define COMPILER_ID "MIPSpro" +# if defined(_SGI_COMPILER_VERSION) + /* _SGI_COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) +# else + /* _COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__sgi) +# define COMPILER_ID "MIPSpro" + +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXE) || defined(__CRAYXC) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) +# define PLATFORM_ID "IRIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + + +#if !defined(__STDC__) +# if defined(_MSC_VER) && !defined(__clang__) +# define C_DIALECT "90" +# else +# define C_DIALECT +# endif +#elif __STDC_VERSION__ >= 201000L +# define C_DIALECT "11" +#elif __STDC_VERSION__ >= 199901L +# define C_DIALECT "99" +#else +# define C_DIALECT "90" +#endif +const char* info_language_dialect_default = + "INFO" ":" "dialect_default[" C_DIALECT "]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXE) || defined(__CRAYXC) + require += info_cray[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/L02/CMakeFiles/3.7.2/CompilerIdC/a.out b/L02/CMakeFiles/3.7.2/CompilerIdC/a.out new file mode 100755 index 0000000..5f8674d Binary files /dev/null and b/L02/CMakeFiles/3.7.2/CompilerIdC/a.out differ diff --git a/L02/CMakeFiles/3.7.2/CompilerIdCXX/CMakeCXXCompilerId.cpp b/L02/CMakeFiles/3.7.2/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..a6e6bed --- /dev/null +++ b/L02/CMakeFiles/3.7.2/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,533 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) +# define COMPILER_ID "Fujitsu" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" + +#elif defined(__ARMCC_VERSION) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) +# define COMPILER_ID "MIPSpro" +# if defined(_SGI_COMPILER_VERSION) + /* _SGI_COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) +# else + /* _COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__sgi) +# define COMPILER_ID "MIPSpro" + +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXE) || defined(__CRAYXC) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) +# define PLATFORM_ID "IRIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + + +const char* info_language_dialect_default = "INFO" ":" "dialect_default[" +#if __cplusplus >= 201402L + "14" +#elif __cplusplus >= 201103L + "11" +#else + "98" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXE) || defined(__CRAYXC) + require += info_cray[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} diff --git a/L02/CMakeFiles/3.7.2/CompilerIdCXX/a.out b/L02/CMakeFiles/3.7.2/CompilerIdCXX/a.out new file mode 100755 index 0000000..4d7dcb7 Binary files /dev/null and b/L02/CMakeFiles/3.7.2/CompilerIdCXX/a.out differ diff --git a/L02/CMakeFiles/CMakeDirectoryInformation.cmake b/L02/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000..28cf3f7 --- /dev/null +++ b/L02/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/shadow8t4/Documents/CSCE441/L02") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/shadow8t4/Documents/CSCE441/L02/build") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/L02/CMakeFiles/CMakeOutput.log b/L02/CMakeFiles/CMakeOutput.log new file mode 100644 index 0000000..c2fba63 --- /dev/null +++ b/L02/CMakeFiles/CMakeOutput.log @@ -0,0 +1,544 @@ +The system is: Linux - 4.8.13-1-ARCH - x86_64 +Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. +Compiler: /usr/lib/hardening-wrapper/bin/cc +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" + +The C compiler identification is GNU, found in "/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/3.7.2/CompilerIdC/a.out" + +Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. +Compiler: /usr/lib/hardening-wrapper/bin/c++ +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" + +The CXX compiler identification is GNU, found in "/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/3.7.2/CompilerIdCXX/a.out" + +Determining if the C compiler works passed with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_a24a7/fast" +/usr/bin/make -f CMakeFiles/cmTC_a24a7.dir/build.make CMakeFiles/cmTC_a24a7.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_a24a7.dir/testCCompiler.c.o +/usr/lib/hardening-wrapper/bin/cc -o CMakeFiles/cmTC_a24a7.dir/testCCompiler.c.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp/testCCompiler.c +Linking C executable cmTC_a24a7 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_a24a7.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/cc CMakeFiles/cmTC_a24a7.dir/testCCompiler.c.o -o cmTC_a24a7 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + +Detecting C compiler ABI info compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_89404/fast" +/usr/bin/make -f CMakeFiles/cmTC_89404.dir/build.make CMakeFiles/cmTC_89404.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_89404.dir/CMakeCCompilerABI.c.o +/usr/lib/hardening-wrapper/bin/cc -o CMakeFiles/cmTC_89404.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.7/Modules/CMakeCCompilerABI.c +Linking C executable cmTC_89404 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_89404.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/cc -v CMakeFiles/cmTC_89404.dir/CMakeCCompilerABI.c.o -o cmTC_89404 -rdynamic +Using built-in specs. +COLLECT_GCC=/usr/bin/cc +COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper +Target: x86_64-pc-linux-gnu +Configured with: /build/gcc-multilib/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release +Thread model: posix +gcc version 6.3.1 20170109 (GCC) +COMPILER_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/ +LIBRARY_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-B' '/usr/lib/hardening-wrapper/bin' '-fPIE' '-pie' '-fstack-check=specific' '-fstack-protector-strong' '-v' '-o' 'cmTC_89404' '-rdynamic' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper -plugin-opt=-fresolution=/tmp/ccNP9yHN.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_89404 /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtbeginS.o -L/usr/lib/hardening-wrapper/bin -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../.. CMakeFiles/cmTC_89404.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crtn.o +COLLECT_GCC_OPTIONS='-B' '/usr/lib/hardening-wrapper/bin' '-fPIE' '-pie' '-fstack-check=specific' '-fstack-protector-strong' '-v' '-o' 'cmTC_89404' '-rdynamic' '-mtune=generic' '-march=x86-64' +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + +Parsed C implicit link information from above output: + link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command:"/usr/bin/make" "cmTC_89404/fast"] + ignore line: [/usr/bin/make -f CMakeFiles/cmTC_89404.dir/build.make CMakeFiles/cmTC_89404.dir/build] + ignore line: [make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp'] + ignore line: [Building C object CMakeFiles/cmTC_89404.dir/CMakeCCompilerABI.c.o] + ignore line: [/usr/lib/hardening-wrapper/bin/cc -o CMakeFiles/cmTC_89404.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.7/Modules/CMakeCCompilerABI.c] + ignore line: [Linking C executable cmTC_89404] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_89404.dir/link.txt --verbose=1] + ignore line: [/usr/lib/hardening-wrapper/bin/cc -v CMakeFiles/cmTC_89404.dir/CMakeCCompilerABI.c.o -o cmTC_89404 -rdynamic ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper] + ignore line: [Target: x86_64-pc-linux-gnu] + ignore line: [Configured with: /build/gcc-multilib/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release] + ignore line: [Thread model: posix] + ignore line: [gcc version 6.3.1 20170109 (GCC) ] + ignore line: [COMPILER_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-B' '/usr/lib/hardening-wrapper/bin' '-fPIE' '-pie' '-fstack-check=specific' '-fstack-protector-strong' '-v' '-o' 'cmTC_89404' '-rdynamic' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper -plugin-opt=-fresolution=/tmp/ccNP9yHN.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_89404 /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtbeginS.o -L/usr/lib/hardening-wrapper/bin -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../.. CMakeFiles/cmTC_89404.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crtn.o] + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccNP9yHN.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-o] ==> ignore + arg [cmTC_89404] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/Scrt1.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crti.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtbeginS.o] ==> ignore + arg [-L/usr/lib/hardening-wrapper/bin] ==> dir [/usr/lib/hardening-wrapper/bin] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] + arg [CMakeFiles/cmTC_89404.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [-lc] ==> lib [c] + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtendS.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crtn.o] ==> ignore + remove lib [gcc] + remove lib [gcc_s] + remove lib [gcc] + remove lib [gcc_s] + collapse library dir [/usr/lib/hardening-wrapper/bin] ==> [/usr/lib/hardening-wrapper/bin] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] ==> [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] ==> [/usr/lib] + implicit libs: [c] + implicit dirs: [/usr/lib/hardening-wrapper/bin;/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1;/usr/lib;/lib] + implicit fwks: [] + + + + +Detecting C [-std=c11] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_82150/fast" +/usr/bin/make -f CMakeFiles/cmTC_82150.dir/build.make CMakeFiles/cmTC_82150.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_82150.dir/feature_tests.c.o +/usr/lib/hardening-wrapper/bin/cc -std=c11 -o CMakeFiles/cmTC_82150.dir/feature_tests.c.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.c +Linking C executable cmTC_82150 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_82150.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/cc CMakeFiles/cmTC_82150.dir/feature_tests.c.o -o cmTC_82150 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: C_FEATURE:1c_function_prototypes + Feature record: C_FEATURE:1c_restrict + Feature record: C_FEATURE:1c_static_assert + Feature record: C_FEATURE:1c_variadic_macros + + +Detecting C [-std=c99] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_1c427/fast" +/usr/bin/make -f CMakeFiles/cmTC_1c427.dir/build.make CMakeFiles/cmTC_1c427.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_1c427.dir/feature_tests.c.o +/usr/lib/hardening-wrapper/bin/cc -std=c99 -o CMakeFiles/cmTC_1c427.dir/feature_tests.c.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.c +Linking C executable cmTC_1c427 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_1c427.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/cc CMakeFiles/cmTC_1c427.dir/feature_tests.c.o -o cmTC_1c427 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: C_FEATURE:1c_function_prototypes + Feature record: C_FEATURE:1c_restrict + Feature record: C_FEATURE:0c_static_assert + Feature record: C_FEATURE:1c_variadic_macros + + +Detecting C [-std=c90] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_6a547/fast" +/usr/bin/make -f CMakeFiles/cmTC_6a547.dir/build.make CMakeFiles/cmTC_6a547.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_6a547.dir/feature_tests.c.o +/usr/lib/hardening-wrapper/bin/cc -std=c90 -o CMakeFiles/cmTC_6a547.dir/feature_tests.c.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.c +Linking C executable cmTC_6a547 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_6a547.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/cc CMakeFiles/cmTC_6a547.dir/feature_tests.c.o -o cmTC_6a547 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: C_FEATURE:1c_function_prototypes + Feature record: C_FEATURE:0c_restrict + Feature record: C_FEATURE:0c_static_assert + Feature record: C_FEATURE:0c_variadic_macros +Determining if the CXX compiler works passed with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_f3383/fast" +/usr/bin/make -f CMakeFiles/cmTC_f3383.dir/build.make CMakeFiles/cmTC_f3383.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_f3383.dir/testCXXCompiler.cxx.o +/usr/lib/hardening-wrapper/bin/c++ -o CMakeFiles/cmTC_f3383.dir/testCXXCompiler.cxx.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp/testCXXCompiler.cxx +Linking CXX executable cmTC_f3383 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_f3383.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/c++ CMakeFiles/cmTC_f3383.dir/testCXXCompiler.cxx.o -o cmTC_f3383 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + +Detecting CXX compiler ABI info compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_ad6b8/fast" +/usr/bin/make -f CMakeFiles/cmTC_ad6b8.dir/build.make CMakeFiles/cmTC_ad6b8.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o +/usr/lib/hardening-wrapper/bin/c++ -o CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.7/Modules/CMakeCXXCompilerABI.cpp +Linking CXX executable cmTC_ad6b8 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_ad6b8.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/c++ -v CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_ad6b8 -rdynamic +Using built-in specs. +COLLECT_GCC=/usr/bin/c++ +COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper +Target: x86_64-pc-linux-gnu +Configured with: /build/gcc-multilib/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release +Thread model: posix +gcc version 6.3.1 20170109 (GCC) +COMPILER_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/ +LIBRARY_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-B' '/usr/lib/hardening-wrapper/bin' '-fPIE' '-pie' '-fstack-check=specific' '-fstack-protector-strong' '-v' '-o' 'cmTC_ad6b8' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper -plugin-opt=-fresolution=/tmp/ccJChkf9.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_ad6b8 /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtbeginS.o -L/usr/lib/hardening-wrapper/bin -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../.. CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crtn.o +COLLECT_GCC_OPTIONS='-B' '/usr/lib/hardening-wrapper/bin' '-fPIE' '-pie' '-fstack-check=specific' '-fstack-protector-strong' '-v' '-o' 'cmTC_ad6b8' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64' +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + +Parsed CXX implicit link information from above output: + link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command:"/usr/bin/make" "cmTC_ad6b8/fast"] + ignore line: [/usr/bin/make -f CMakeFiles/cmTC_ad6b8.dir/build.make CMakeFiles/cmTC_ad6b8.dir/build] + ignore line: [make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp'] + ignore line: [Building CXX object CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/usr/lib/hardening-wrapper/bin/c++ -o CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.7/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Linking CXX executable cmTC_ad6b8] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_ad6b8.dir/link.txt --verbose=1] + ignore line: [/usr/lib/hardening-wrapper/bin/c++ -v CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_ad6b8 -rdynamic ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper] + ignore line: [Target: x86_64-pc-linux-gnu] + ignore line: [Configured with: /build/gcc-multilib/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release] + ignore line: [Thread model: posix] + ignore line: [gcc version 6.3.1 20170109 (GCC) ] + ignore line: [COMPILER_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-B' '/usr/lib/hardening-wrapper/bin' '-fPIE' '-pie' '-fstack-check=specific' '-fstack-protector-strong' '-v' '-o' 'cmTC_ad6b8' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper -plugin-opt=-fresolution=/tmp/ccJChkf9.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_ad6b8 /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtbeginS.o -L/usr/lib/hardening-wrapper/bin -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../.. CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crtn.o] + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccJChkf9.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-o] ==> ignore + arg [cmTC_ad6b8] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/Scrt1.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crti.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtbeginS.o] ==> ignore + arg [-L/usr/lib/hardening-wrapper/bin] ==> dir [/usr/lib/hardening-wrapper/bin] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] + arg [CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtendS.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crtn.o] ==> ignore + remove lib [gcc_s] + remove lib [gcc] + remove lib [gcc_s] + remove lib [gcc] + collapse library dir [/usr/lib/hardening-wrapper/bin] ==> [/usr/lib/hardening-wrapper/bin] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] ==> [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] ==> [/usr/lib] + implicit libs: [stdc++;m;c] + implicit dirs: [/usr/lib/hardening-wrapper/bin;/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1;/usr/lib;/lib] + implicit fwks: [] + + + + +Detecting CXX [-std=c++14] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_e6959/fast" +/usr/bin/make -f CMakeFiles/cmTC_e6959.dir/build.make CMakeFiles/cmTC_e6959.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_e6959.dir/feature_tests.cxx.o +/usr/lib/hardening-wrapper/bin/c++ -std=c++14 -o CMakeFiles/cmTC_e6959.dir/feature_tests.cxx.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.cxx +Linking CXX executable cmTC_e6959 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_e6959.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/c++ CMakeFiles/cmTC_e6959.dir/feature_tests.cxx.o -o cmTC_e6959 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: CXX_FEATURE:1cxx_aggregate_default_initializers + Feature record: CXX_FEATURE:1cxx_alias_templates + Feature record: CXX_FEATURE:1cxx_alignas + Feature record: CXX_FEATURE:1cxx_alignof + Feature record: CXX_FEATURE:1cxx_attributes + Feature record: CXX_FEATURE:1cxx_attribute_deprecated + Feature record: CXX_FEATURE:1cxx_auto_type + Feature record: CXX_FEATURE:1cxx_binary_literals + Feature record: CXX_FEATURE:1cxx_constexpr + Feature record: CXX_FEATURE:1cxx_contextual_conversions + Feature record: CXX_FEATURE:1cxx_decltype + Feature record: CXX_FEATURE:1cxx_decltype_auto + Feature record: CXX_FEATURE:1cxx_decltype_incomplete_return_types + Feature record: CXX_FEATURE:1cxx_default_function_template_args + Feature record: CXX_FEATURE:1cxx_defaulted_functions + Feature record: CXX_FEATURE:1cxx_defaulted_move_initializers + Feature record: CXX_FEATURE:1cxx_delegating_constructors + Feature record: CXX_FEATURE:1cxx_deleted_functions + Feature record: CXX_FEATURE:1cxx_digit_separators + Feature record: CXX_FEATURE:1cxx_enum_forward_declarations + Feature record: CXX_FEATURE:1cxx_explicit_conversions + Feature record: CXX_FEATURE:1cxx_extended_friend_declarations + Feature record: CXX_FEATURE:1cxx_extern_templates + Feature record: CXX_FEATURE:1cxx_final + Feature record: CXX_FEATURE:1cxx_func_identifier + Feature record: CXX_FEATURE:1cxx_generalized_initializers + Feature record: CXX_FEATURE:1cxx_generic_lambdas + Feature record: CXX_FEATURE:1cxx_inheriting_constructors + Feature record: CXX_FEATURE:1cxx_inline_namespaces + Feature record: CXX_FEATURE:1cxx_lambdas + Feature record: CXX_FEATURE:1cxx_lambda_init_captures + Feature record: CXX_FEATURE:1cxx_local_type_template_args + Feature record: CXX_FEATURE:1cxx_long_long_type + Feature record: CXX_FEATURE:1cxx_noexcept + Feature record: CXX_FEATURE:1cxx_nonstatic_member_init + Feature record: CXX_FEATURE:1cxx_nullptr + Feature record: CXX_FEATURE:1cxx_override + Feature record: CXX_FEATURE:1cxx_range_for + Feature record: CXX_FEATURE:1cxx_raw_string_literals + Feature record: CXX_FEATURE:1cxx_reference_qualified_functions + Feature record: CXX_FEATURE:1cxx_relaxed_constexpr + Feature record: CXX_FEATURE:1cxx_return_type_deduction + Feature record: CXX_FEATURE:1cxx_right_angle_brackets + Feature record: CXX_FEATURE:1cxx_rvalue_references + Feature record: CXX_FEATURE:1cxx_sizeof_member + Feature record: CXX_FEATURE:1cxx_static_assert + Feature record: CXX_FEATURE:1cxx_strong_enums + Feature record: CXX_FEATURE:1cxx_template_template_parameters + Feature record: CXX_FEATURE:1cxx_thread_local + Feature record: CXX_FEATURE:1cxx_trailing_return_types + Feature record: CXX_FEATURE:1cxx_unicode_literals + Feature record: CXX_FEATURE:1cxx_uniform_initialization + Feature record: CXX_FEATURE:1cxx_unrestricted_unions + Feature record: CXX_FEATURE:1cxx_user_literals + Feature record: CXX_FEATURE:1cxx_variable_templates + Feature record: CXX_FEATURE:1cxx_variadic_macros + Feature record: CXX_FEATURE:1cxx_variadic_templates + + +Detecting CXX [-std=c++11] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_990df/fast" +/usr/bin/make -f CMakeFiles/cmTC_990df.dir/build.make CMakeFiles/cmTC_990df.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_990df.dir/feature_tests.cxx.o +/usr/lib/hardening-wrapper/bin/c++ -std=c++11 -o CMakeFiles/cmTC_990df.dir/feature_tests.cxx.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.cxx +Linking CXX executable cmTC_990df +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_990df.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/c++ CMakeFiles/cmTC_990df.dir/feature_tests.cxx.o -o cmTC_990df -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: CXX_FEATURE:0cxx_aggregate_default_initializers + Feature record: CXX_FEATURE:1cxx_alias_templates + Feature record: CXX_FEATURE:1cxx_alignas + Feature record: CXX_FEATURE:1cxx_alignof + Feature record: CXX_FEATURE:1cxx_attributes + Feature record: CXX_FEATURE:0cxx_attribute_deprecated + Feature record: CXX_FEATURE:1cxx_auto_type + Feature record: CXX_FEATURE:0cxx_binary_literals + Feature record: CXX_FEATURE:1cxx_constexpr + Feature record: CXX_FEATURE:0cxx_contextual_conversions + Feature record: CXX_FEATURE:1cxx_decltype + Feature record: CXX_FEATURE:0cxx_decltype_auto + Feature record: CXX_FEATURE:1cxx_decltype_incomplete_return_types + Feature record: CXX_FEATURE:1cxx_default_function_template_args + Feature record: CXX_FEATURE:1cxx_defaulted_functions + Feature record: CXX_FEATURE:1cxx_defaulted_move_initializers + Feature record: CXX_FEATURE:1cxx_delegating_constructors + Feature record: CXX_FEATURE:1cxx_deleted_functions + Feature record: CXX_FEATURE:0cxx_digit_separators + Feature record: CXX_FEATURE:1cxx_enum_forward_declarations + Feature record: CXX_FEATURE:1cxx_explicit_conversions + Feature record: CXX_FEATURE:1cxx_extended_friend_declarations + Feature record: CXX_FEATURE:1cxx_extern_templates + Feature record: CXX_FEATURE:1cxx_final + Feature record: CXX_FEATURE:1cxx_func_identifier + Feature record: CXX_FEATURE:1cxx_generalized_initializers + Feature record: CXX_FEATURE:0cxx_generic_lambdas + Feature record: CXX_FEATURE:1cxx_inheriting_constructors + Feature record: CXX_FEATURE:1cxx_inline_namespaces + Feature record: CXX_FEATURE:1cxx_lambdas + Feature record: CXX_FEATURE:0cxx_lambda_init_captures + Feature record: CXX_FEATURE:1cxx_local_type_template_args + Feature record: CXX_FEATURE:1cxx_long_long_type + Feature record: CXX_FEATURE:1cxx_noexcept + Feature record: CXX_FEATURE:1cxx_nonstatic_member_init + Feature record: CXX_FEATURE:1cxx_nullptr + Feature record: CXX_FEATURE:1cxx_override + Feature record: CXX_FEATURE:1cxx_range_for + Feature record: CXX_FEATURE:1cxx_raw_string_literals + Feature record: CXX_FEATURE:1cxx_reference_qualified_functions + Feature record: CXX_FEATURE:0cxx_relaxed_constexpr + Feature record: CXX_FEATURE:0cxx_return_type_deduction + Feature record: CXX_FEATURE:1cxx_right_angle_brackets + Feature record: CXX_FEATURE:1cxx_rvalue_references + Feature record: CXX_FEATURE:1cxx_sizeof_member + Feature record: CXX_FEATURE:1cxx_static_assert + Feature record: CXX_FEATURE:1cxx_strong_enums + Feature record: CXX_FEATURE:1cxx_template_template_parameters + Feature record: CXX_FEATURE:1cxx_thread_local + Feature record: CXX_FEATURE:1cxx_trailing_return_types + Feature record: CXX_FEATURE:1cxx_unicode_literals + Feature record: CXX_FEATURE:1cxx_uniform_initialization + Feature record: CXX_FEATURE:1cxx_unrestricted_unions + Feature record: CXX_FEATURE:1cxx_user_literals + Feature record: CXX_FEATURE:0cxx_variable_templates + Feature record: CXX_FEATURE:1cxx_variadic_macros + Feature record: CXX_FEATURE:1cxx_variadic_templates + + +Detecting CXX [-std=c++98] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_7a266/fast" +/usr/bin/make -f CMakeFiles/cmTC_7a266.dir/build.make CMakeFiles/cmTC_7a266.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_7a266.dir/feature_tests.cxx.o +/usr/lib/hardening-wrapper/bin/c++ -std=c++98 -o CMakeFiles/cmTC_7a266.dir/feature_tests.cxx.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.cxx +Linking CXX executable cmTC_7a266 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_7a266.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/c++ CMakeFiles/cmTC_7a266.dir/feature_tests.cxx.o -o cmTC_7a266 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: CXX_FEATURE:0cxx_aggregate_default_initializers + Feature record: CXX_FEATURE:0cxx_alias_templates + Feature record: CXX_FEATURE:0cxx_alignas + Feature record: CXX_FEATURE:0cxx_alignof + Feature record: CXX_FEATURE:0cxx_attributes + Feature record: CXX_FEATURE:0cxx_attribute_deprecated + Feature record: CXX_FEATURE:0cxx_auto_type + Feature record: CXX_FEATURE:0cxx_binary_literals + Feature record: CXX_FEATURE:0cxx_constexpr + Feature record: CXX_FEATURE:0cxx_contextual_conversions + Feature record: CXX_FEATURE:0cxx_decltype + Feature record: CXX_FEATURE:0cxx_decltype_auto + Feature record: CXX_FEATURE:0cxx_decltype_incomplete_return_types + Feature record: CXX_FEATURE:0cxx_default_function_template_args + Feature record: CXX_FEATURE:0cxx_defaulted_functions + Feature record: CXX_FEATURE:0cxx_defaulted_move_initializers + Feature record: CXX_FEATURE:0cxx_delegating_constructors + Feature record: CXX_FEATURE:0cxx_deleted_functions + Feature record: CXX_FEATURE:0cxx_digit_separators + Feature record: CXX_FEATURE:0cxx_enum_forward_declarations + Feature record: CXX_FEATURE:0cxx_explicit_conversions + Feature record: CXX_FEATURE:0cxx_extended_friend_declarations + Feature record: CXX_FEATURE:0cxx_extern_templates + Feature record: CXX_FEATURE:0cxx_final + Feature record: CXX_FEATURE:0cxx_func_identifier + Feature record: CXX_FEATURE:0cxx_generalized_initializers + Feature record: CXX_FEATURE:0cxx_generic_lambdas + Feature record: CXX_FEATURE:0cxx_inheriting_constructors + Feature record: CXX_FEATURE:0cxx_inline_namespaces + Feature record: CXX_FEATURE:0cxx_lambdas + Feature record: CXX_FEATURE:0cxx_lambda_init_captures + Feature record: CXX_FEATURE:0cxx_local_type_template_args + Feature record: CXX_FEATURE:0cxx_long_long_type + Feature record: CXX_FEATURE:0cxx_noexcept + Feature record: CXX_FEATURE:0cxx_nonstatic_member_init + Feature record: CXX_FEATURE:0cxx_nullptr + Feature record: CXX_FEATURE:0cxx_override + Feature record: CXX_FEATURE:0cxx_range_for + Feature record: CXX_FEATURE:0cxx_raw_string_literals + Feature record: CXX_FEATURE:0cxx_reference_qualified_functions + Feature record: CXX_FEATURE:0cxx_relaxed_constexpr + Feature record: CXX_FEATURE:0cxx_return_type_deduction + Feature record: CXX_FEATURE:0cxx_right_angle_brackets + Feature record: CXX_FEATURE:0cxx_rvalue_references + Feature record: CXX_FEATURE:0cxx_sizeof_member + Feature record: CXX_FEATURE:0cxx_static_assert + Feature record: CXX_FEATURE:0cxx_strong_enums + Feature record: CXX_FEATURE:1cxx_template_template_parameters + Feature record: CXX_FEATURE:0cxx_thread_local + Feature record: CXX_FEATURE:0cxx_trailing_return_types + Feature record: CXX_FEATURE:0cxx_unicode_literals + Feature record: CXX_FEATURE:0cxx_uniform_initialization + Feature record: CXX_FEATURE:0cxx_unrestricted_unions + Feature record: CXX_FEATURE:0cxx_user_literals + Feature record: CXX_FEATURE:0cxx_variable_templates + Feature record: CXX_FEATURE:0cxx_variadic_macros + Feature record: CXX_FEATURE:0cxx_variadic_templates diff --git a/L02/CMakeFiles/L02.dir/CXX.includecache b/L02/CMakeFiles/L02.dir/CXX.includecache new file mode 100644 index 0000000..f341202 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/CXX.includecache @@ -0,0 +1,52 @@ +#IncludeRegexLine: ^[ ]*#[ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp +iostream +- +cassert +- +Image.h +/home/shadow8t4/Documents/CSCE441/L02/src/Image.h +stb_image_write.h +/home/shadow8t4/Documents/CSCE441/L02/src/stb_image_write.h + +/home/shadow8t4/Documents/CSCE441/L02/src/Image.h +string +- +vector +- + +/home/shadow8t4/Documents/CSCE441/L02/src/main.cpp +iostream +- +string +- +vector +- +memory +- +Image.h +/home/shadow8t4/Documents/CSCE441/L02/src/Image.h +math.h +- + +/home/shadow8t4/Documents/CSCE441/L02/src/stb_image_write.h +stdio.h +- +stdarg.h +- +stdlib.h +- +string.h +- +math.h +- +assert.h +- + diff --git a/L02/CMakeFiles/L02.dir/DependInfo.cmake b/L02/CMakeFiles/L02.dir/DependInfo.cmake new file mode 100644 index 0000000..fb18f92 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/DependInfo.cmake @@ -0,0 +1,21 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp" "/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/L02.dir/src/Image.cpp.o" + "/home/shadow8t4/Documents/CSCE441/L02/src/main.cpp" "/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/L02.dir/src/main.cpp.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/L02/CMakeFiles/L02.dir/build.make b/L02/CMakeFiles/L02.dir/build.make new file mode 100644 index 0000000..5c29247 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/build.make @@ -0,0 +1,140 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/shadow8t4/Documents/CSCE441/L02 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/shadow8t4/Documents/CSCE441/L02/build + +# Include any dependencies generated for this target. +include CMakeFiles/L02.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/L02.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/L02.dir/flags.make + +CMakeFiles/L02.dir/src/Image.cpp.o: CMakeFiles/L02.dir/flags.make +CMakeFiles/L02.dir/src/Image.cpp.o: ../src/Image.cpp + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object CMakeFiles/L02.dir/src/Image.cpp.o" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/L02.dir/src/Image.cpp.o -c /home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp + +CMakeFiles/L02.dir/src/Image.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/L02.dir/src/Image.cpp.i" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp > CMakeFiles/L02.dir/src/Image.cpp.i + +CMakeFiles/L02.dir/src/Image.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/L02.dir/src/Image.cpp.s" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp -o CMakeFiles/L02.dir/src/Image.cpp.s + +CMakeFiles/L02.dir/src/Image.cpp.o.requires: + +.PHONY : CMakeFiles/L02.dir/src/Image.cpp.o.requires + +CMakeFiles/L02.dir/src/Image.cpp.o.provides: CMakeFiles/L02.dir/src/Image.cpp.o.requires + $(MAKE) -f CMakeFiles/L02.dir/build.make CMakeFiles/L02.dir/src/Image.cpp.o.provides.build +.PHONY : CMakeFiles/L02.dir/src/Image.cpp.o.provides + +CMakeFiles/L02.dir/src/Image.cpp.o.provides.build: CMakeFiles/L02.dir/src/Image.cpp.o + + +CMakeFiles/L02.dir/src/main.cpp.o: CMakeFiles/L02.dir/flags.make +CMakeFiles/L02.dir/src/main.cpp.o: ../src/main.cpp + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object CMakeFiles/L02.dir/src/main.cpp.o" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/L02.dir/src/main.cpp.o -c /home/shadow8t4/Documents/CSCE441/L02/src/main.cpp + +CMakeFiles/L02.dir/src/main.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/L02.dir/src/main.cpp.i" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/shadow8t4/Documents/CSCE441/L02/src/main.cpp > CMakeFiles/L02.dir/src/main.cpp.i + +CMakeFiles/L02.dir/src/main.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/L02.dir/src/main.cpp.s" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/shadow8t4/Documents/CSCE441/L02/src/main.cpp -o CMakeFiles/L02.dir/src/main.cpp.s + +CMakeFiles/L02.dir/src/main.cpp.o.requires: + +.PHONY : CMakeFiles/L02.dir/src/main.cpp.o.requires + +CMakeFiles/L02.dir/src/main.cpp.o.provides: CMakeFiles/L02.dir/src/main.cpp.o.requires + $(MAKE) -f CMakeFiles/L02.dir/build.make CMakeFiles/L02.dir/src/main.cpp.o.provides.build +.PHONY : CMakeFiles/L02.dir/src/main.cpp.o.provides + +CMakeFiles/L02.dir/src/main.cpp.o.provides.build: CMakeFiles/L02.dir/src/main.cpp.o + + +# Object files for target L02 +L02_OBJECTS = \ +"CMakeFiles/L02.dir/src/Image.cpp.o" \ +"CMakeFiles/L02.dir/src/main.cpp.o" + +# External object files for target L02 +L02_EXTERNAL_OBJECTS = + +L02: CMakeFiles/L02.dir/src/Image.cpp.o +L02: CMakeFiles/L02.dir/src/main.cpp.o +L02: CMakeFiles/L02.dir/build.make +L02: CMakeFiles/L02.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Linking CXX executable L02" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/L02.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/L02.dir/build: L02 + +.PHONY : CMakeFiles/L02.dir/build + +CMakeFiles/L02.dir/requires: CMakeFiles/L02.dir/src/Image.cpp.o.requires +CMakeFiles/L02.dir/requires: CMakeFiles/L02.dir/src/main.cpp.o.requires + +.PHONY : CMakeFiles/L02.dir/requires + +CMakeFiles/L02.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/L02.dir/cmake_clean.cmake +.PHONY : CMakeFiles/L02.dir/clean + +CMakeFiles/L02.dir/depend: + cd /home/shadow8t4/Documents/CSCE441/L02/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/shadow8t4/Documents/CSCE441/L02 /home/shadow8t4/Documents/CSCE441/L02 /home/shadow8t4/Documents/CSCE441/L02/build /home/shadow8t4/Documents/CSCE441/L02/build /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/L02.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/L02.dir/depend + diff --git a/L02/CMakeFiles/L02.dir/cmake_clean.cmake b/L02/CMakeFiles/L02.dir/cmake_clean.cmake new file mode 100644 index 0000000..bf61c67 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/cmake_clean.cmake @@ -0,0 +1,11 @@ +file(REMOVE_RECURSE + "CMakeFiles/L02.dir/src/Image.cpp.o" + "CMakeFiles/L02.dir/src/main.cpp.o" + "L02.pdb" + "L02" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/L02.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/L02/CMakeFiles/L02.dir/depend.internal b/L02/CMakeFiles/L02.dir/depend.internal new file mode 100644 index 0000000..f8165f0 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/depend.internal @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +CMakeFiles/L02.dir/src/Image.cpp.o + /home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp + /home/shadow8t4/Documents/CSCE441/L02/src/Image.h + /home/shadow8t4/Documents/CSCE441/L02/src/stb_image_write.h +CMakeFiles/L02.dir/src/main.cpp.o + /home/shadow8t4/Documents/CSCE441/L02/src/Image.h + /home/shadow8t4/Documents/CSCE441/L02/src/main.cpp diff --git a/L02/CMakeFiles/L02.dir/depend.make b/L02/CMakeFiles/L02.dir/depend.make new file mode 100644 index 0000000..1d05299 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/depend.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +CMakeFiles/L02.dir/src/Image.cpp.o: ../src/Image.cpp +CMakeFiles/L02.dir/src/Image.cpp.o: ../src/Image.h +CMakeFiles/L02.dir/src/Image.cpp.o: ../src/stb_image_write.h + +CMakeFiles/L02.dir/src/main.cpp.o: ../src/Image.h +CMakeFiles/L02.dir/src/main.cpp.o: ../src/main.cpp + diff --git a/L02/CMakeFiles/L02.dir/flags.make b/L02/CMakeFiles/L02.dir/flags.make new file mode 100644 index 0000000..2607a0b --- /dev/null +++ b/L02/CMakeFiles/L02.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +# compile CXX with /usr/lib/hardening-wrapper/bin/c++ +CXX_FLAGS = -std=c++11 -Wall -pedantic + +CXX_DEFINES = + +CXX_INCLUDES = + diff --git a/L02/CMakeFiles/L02.dir/link.txt b/L02/CMakeFiles/L02.dir/link.txt new file mode 100644 index 0000000..8fa74d4 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/link.txt @@ -0,0 +1 @@ +/usr/lib/hardening-wrapper/bin/c++ -std=c++11 -Wall -pedantic CMakeFiles/L02.dir/src/Image.cpp.o CMakeFiles/L02.dir/src/main.cpp.o -o L02 -rdynamic diff --git a/L02/CMakeFiles/L02.dir/progress.make b/L02/CMakeFiles/L02.dir/progress.make new file mode 100644 index 0000000..6a9dc74 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/progress.make @@ -0,0 +1,4 @@ +CMAKE_PROGRESS_1 = 1 +CMAKE_PROGRESS_2 = 2 +CMAKE_PROGRESS_3 = 3 + diff --git a/L02/CMakeFiles/L02.dir/src/Image.cpp.o b/L02/CMakeFiles/L02.dir/src/Image.cpp.o new file mode 100644 index 0000000..1a1c40c Binary files /dev/null and b/L02/CMakeFiles/L02.dir/src/Image.cpp.o differ diff --git a/L02/CMakeFiles/L02.dir/src/main.cpp.o b/L02/CMakeFiles/L02.dir/src/main.cpp.o new file mode 100644 index 0000000..c4edae3 Binary files /dev/null and b/L02/CMakeFiles/L02.dir/src/main.cpp.o differ diff --git a/L02/CMakeFiles/Makefile.cmake b/L02/CMakeFiles/Makefile.cmake new file mode 100644 index 0000000..ca445c6 --- /dev/null +++ b/L02/CMakeFiles/Makefile.cmake @@ -0,0 +1,45 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +# The generator used is: +set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +set(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "../CMakeLists.txt" + "CMakeFiles/3.7.2/CMakeCCompiler.cmake" + "CMakeFiles/3.7.2/CMakeCXXCompiler.cmake" + "CMakeFiles/3.7.2/CMakeSystem.cmake" + "/usr/share/cmake-3.7/Modules/CMakeCInformation.cmake" + "/usr/share/cmake-3.7/Modules/CMakeCXXInformation.cmake" + "/usr/share/cmake-3.7/Modules/CMakeCommonLanguageInclude.cmake" + "/usr/share/cmake-3.7/Modules/CMakeGenericSystem.cmake" + "/usr/share/cmake-3.7/Modules/CMakeLanguageInformation.cmake" + "/usr/share/cmake-3.7/Modules/CMakeSystemSpecificInformation.cmake" + "/usr/share/cmake-3.7/Modules/CMakeSystemSpecificInitialize.cmake" + "/usr/share/cmake-3.7/Modules/Compiler/GNU-C.cmake" + "/usr/share/cmake-3.7/Modules/Compiler/GNU-CXX.cmake" + "/usr/share/cmake-3.7/Modules/Compiler/GNU.cmake" + "/usr/share/cmake-3.7/Modules/Platform/Linux-GNU-C.cmake" + "/usr/share/cmake-3.7/Modules/Platform/Linux-GNU-CXX.cmake" + "/usr/share/cmake-3.7/Modules/Platform/Linux-GNU.cmake" + "/usr/share/cmake-3.7/Modules/Platform/Linux.cmake" + "/usr/share/cmake-3.7/Modules/Platform/UnixPaths.cmake" + ) + +# The corresponding makefile is: +set(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +set(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +set(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/L02.dir/DependInfo.cmake" + ) diff --git a/L02/CMakeFiles/Makefile2 b/L02/CMakeFiles/Makefile2 new file mode 100644 index 0000000..0e148b4 --- /dev/null +++ b/L02/CMakeFiles/Makefile2 @@ -0,0 +1,108 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +# The main recursive all target +all: + +.PHONY : all + +# The main recursive preinstall target +preinstall: + +.PHONY : preinstall + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/shadow8t4/Documents/CSCE441/L02 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/shadow8t4/Documents/CSCE441/L02/build + +#============================================================================= +# Target rules for target CMakeFiles/L02.dir + +# All Build rule for target. +CMakeFiles/L02.dir/all: + $(MAKE) -f CMakeFiles/L02.dir/build.make CMakeFiles/L02.dir/depend + $(MAKE) -f CMakeFiles/L02.dir/build.make CMakeFiles/L02.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles --progress-num=1,2,3 "Built target L02" +.PHONY : CMakeFiles/L02.dir/all + +# Include target in all. +all: CMakeFiles/L02.dir/all + +.PHONY : all + +# Build rule for subdir invocation for target. +CMakeFiles/L02.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles 3 + $(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/L02.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles 0 +.PHONY : CMakeFiles/L02.dir/rule + +# Convenience name for target. +L02: CMakeFiles/L02.dir/rule + +.PHONY : L02 + +# clean rule for target. +CMakeFiles/L02.dir/clean: + $(MAKE) -f CMakeFiles/L02.dir/build.make CMakeFiles/L02.dir/clean +.PHONY : CMakeFiles/L02.dir/clean + +# clean rule for target. +clean: CMakeFiles/L02.dir/clean + +.PHONY : clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/L02/CMakeFiles/TargetDirectories.txt b/L02/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..167cb32 --- /dev/null +++ b/L02/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,3 @@ +/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/rebuild_cache.dir +/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/edit_cache.dir +/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/L02.dir diff --git a/L02/CMakeFiles/cmake.check_cache b/L02/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/L02/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/L02/CMakeFiles/feature_tests.bin b/L02/CMakeFiles/feature_tests.bin new file mode 100755 index 0000000..5af7746 Binary files /dev/null and b/L02/CMakeFiles/feature_tests.bin differ diff --git a/L02/CMakeFiles/feature_tests.c b/L02/CMakeFiles/feature_tests.c new file mode 100644 index 0000000..6590dde --- /dev/null +++ b/L02/CMakeFiles/feature_tests.c @@ -0,0 +1,34 @@ + + const char features[] = {"\n" +"C_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 +"1" +#else +"0" +#endif +"c_function_prototypes\n" +"C_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +"1" +#else +"0" +#endif +"c_restrict\n" +"C_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L +"1" +#else +"0" +#endif +"c_static_assert\n" +"C_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +"1" +#else +"0" +#endif +"c_variadic_macros\n" + +}; + +int main(int argc, char** argv) { (void)argv; return features[argc]; } diff --git a/L02/CMakeFiles/feature_tests.cxx b/L02/CMakeFiles/feature_tests.cxx new file mode 100644 index 0000000..b93418c --- /dev/null +++ b/L02/CMakeFiles/feature_tests.cxx @@ -0,0 +1,405 @@ + + const char features[] = {"\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 500 && __cplusplus >= 201402L +"1" +#else +"0" +#endif +"cxx_aggregate_default_initializers\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_alias_templates\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_alignas\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_alignof\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_attributes\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_attribute_deprecated\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_auto_type\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_binary_literals\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_constexpr\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_contextual_conversions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_decltype\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_decltype_auto\n" +"CXX_FEATURE:" +#if ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40801) && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_decltype_incomplete_return_types\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_default_function_template_args\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_defaulted_functions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_defaulted_move_initializers\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_delegating_constructors\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_deleted_functions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_digit_separators\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_enum_forward_declarations\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_explicit_conversions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_extended_friend_declarations\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_extern_templates\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_final\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_func_identifier\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_generalized_initializers\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_generic_lambdas\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_inheriting_constructors\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_inline_namespaces\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_lambdas\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_lambda_init_captures\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_local_type_template_args\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_long_long_type\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_noexcept\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_nonstatic_member_init\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_nullptr\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_override\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_range_for\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_raw_string_literals\n" +"CXX_FEATURE:" +#if ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40801) && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_reference_qualified_functions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 500 && __cplusplus >= 201402L +"1" +#else +"0" +#endif +"cxx_relaxed_constexpr\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_return_type_deduction\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_right_angle_brackets\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_rvalue_references\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_sizeof_member\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_static_assert\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_strong_enums\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && __cplusplus +"1" +#else +"0" +#endif +"cxx_template_template_parameters\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_thread_local\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_trailing_return_types\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_unicode_literals\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_uniform_initialization\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_unrestricted_unions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_user_literals\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 500 && __cplusplus >= 201402L +"1" +#else +"0" +#endif +"cxx_variable_templates\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_variadic_macros\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_variadic_templates\n" + +}; + +int main(int argc, char** argv) { (void)argv; return features[argc]; } diff --git a/L02/CMakeFiles/progress.marks b/L02/CMakeFiles/progress.marks new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/L02/CMakeFiles/progress.marks @@ -0,0 +1 @@ +3 diff --git a/L02/CMakeLists.txt b/L02/CMakeLists.txt new file mode 100644 index 0000000..99e3d6d --- /dev/null +++ b/L02/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L02) + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS}) + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") +ENDIF() diff --git a/L02/src/Image.cpp b/L02/src/Image.cpp new file mode 100644 index 0000000..7655b46 --- /dev/null +++ b/L02/src/Image.cpp @@ -0,0 +1,87 @@ +#include +#include +#include "Image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +using namespace std; + +Tri::Tri() +{ + vertex v1; + v1.x = 0.0; + v1.y = 0.0; + v1.z = 0.0; + vertex v2; + v2.x = 0.0; + v2.y = 0.0; + v2.z = 0.0; + vertex v3; + v3.x = 0.0; + v3.y = 0.0; + v3.z = 0.0; + v.push_back(v1); + v.push_back(v2); + v.push_back(v3); +} + +Tri::Tri(vertex &one, vertex &two, vertex &three) +{ + v.push_back(one); + v.push_back(two); + v.push_back(three); +} + +Image::Image(int w, int h) : + width(w), + height(h), + comp(3), + pixels(width*height*comp, 0) +{ +} + +Image::~Image() +{ +} + +void Image::setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) +{ + // The pixel data is laid out row by row. Each row consists of 'width' + // columns, and each column consists of 3 unsigned chars. + + // First check for bounds + if(y < 0 || y >= height) { + cout << "Row " << y << " is out of bounds" << endl; + return; + } + if(x < 0 || x >= width) { + cout << "Col " << x << " is out of bounds" << endl; + return; + } + + // Since the origin (0, 0) of the image is the upper left corner, we need + // to flip the row to make the origin be the lower left corner. + y = height - y - 1; + // index corresponding to row and col, (assuming single component image) + int index = y*width + x; + // Multiply by 3 to get the index for the rgb components. + assert(index >= 0); + assert(3*index + 2 < (int)pixels.size()); + pixels[3*index + 0] = r; + pixels[3*index + 1] = g; + pixels[3*index + 2] = b; +} + +void Image::writeToFile(const string &filename) +{ + // The distance in bytes from the first byte of a row of pixels to the + // first byte of the next row of pixels + int stride_in_bytes = width*comp*sizeof(unsigned char); + int rc = stbi_write_png(filename.c_str(), width, height, comp, &pixels[0], stride_in_bytes); + if(rc) { + cout << "Wrote to " << filename << endl; + } else { + cout << "Couldn't write to " << filename << endl; + } +} diff --git a/L02/src/Image.h b/L02/src/Image.h new file mode 100644 index 0000000..8442ffb --- /dev/null +++ b/L02/src/Image.h @@ -0,0 +1,43 @@ +#pragma once +#ifndef _IMAGE_H_ +#define _IMAGE_H_ + +#include +#include + +struct vertex +{ + float x = 0.0; + float y = 0.0; + float z = 0.0; + float r = 0.0; + float g = 0.0; + float b = 0.0; +}; + +class Tri +{ + public: + Tri(); + Tri(vertex &one, vertex &two, vertex &three); + std::vector v; +}; + +class Image +{ +public: + Image(int width, int height); + virtual ~Image(); + void setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b); + void writeToFile(const std::string &filename); + int getWidth() const { return width; } + int getHeight() const { return height; } + +private: + int width; + int height; + int comp; + std::vector pixels; +}; + +#endif diff --git a/L02/src/main.cpp b/L02/src/main.cpp new file mode 100644 index 0000000..d80c938 --- /dev/null +++ b/L02/src/main.cpp @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include "Image.h" +#include + +// This allows you to skip the `std::` in front of C++ standard library +// functions. You can also say `using std::cout` to be more selective. +// You should never do this in a header file. +using namespace std; + +int main(int argc, char **argv) +{ + if(argc < 19) { + cout << "Usage: L01 filename width height x1 y1 r1 g1 b1 x2 y2 r2 g2 b2 x3 y3 r3 g3 b3" << endl; + return 0; + } + // Output filename + string filename(argv[1]); + // Width of image + int width = atoi(argv[2]); + // Height of image + int height = atoi(argv[3]); + + // Initialize coordinate variables to make things easier + float x1 = atoi(argv[4]); + float y1 = atoi(argv[5]); + float x2 = atoi(argv[9]); + float y2 = atoi(argv[10]); + float x3 = atoi(argv[14]); + float y3 = atoi(argv[15]); + + // Initialize rgb values again to make things easier + float r1 = atoi(argv[6]); + float b1 = atoi(argv[7]); + float g1 = atoi(argv[8]); + float r2 = atoi(argv[11]); + float g2 = atoi(argv[12]); + float b2 = atoi(argv[13]); + float r3 = atoi(argv[16]); + float g3 = atoi(argv[17]); + float b3 = atoi(argv[18]); + + // Vertex 1 + vertex v1; + v1.x = x1; + v1.y = y1; + v1.z = 0.0; + v1.r = r1; + v1.g = g1; + v1.b = b1; + + // Vertex 2 + vertex v2; + v2.x = x2; + v2.y = y2; + v2.z = 0.0; + v2.r = r2; + v2.g = g2; + v2.b = b2; + + // Vertex 3 + vertex v3; + v3.x = x3; + v3.y = y3; + v3.z = 0.0; + v3.r = r3; + v3.g = g3; + v3.b = b3; + + // Triangle + Tri t(v1, v2, v3); + + // Find xmin, xmax, ymin, ymax + float xmin = x1; + float xmax = x1; + float ymin = y1; + float ymax = y1; + if(x2 < xmin) + xmin = x2; + if(x3 < xmin) + xmin = x3; + if(x2 > xmax) + xmax = x2; + if(x3 > xmax) + xmax = x3; + if(y2 < ymin) + ymin = y2; + if(y3 < ymin) + ymin = y3; + if(y2 > ymax) + ymax = y2; + if(y3 > ymax) + ymax = y3; + + // Find total area + float area = abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2))/2.0); + + // Create the image. We're using a `shared_ptr`, a C++11 feature. + auto image = make_shared(width, height); + + // Initialize variables for holding area between points + float a1 = 0.0; + float a2 = 0.0; + float a3 = 0.0; + + // Initialize barycentric coordinate variables + float l1 = 0.0; + float l2 = 0.0; + float l3 = 0.0; + + // Draw a rectangle + for(int y = ymin; y < ymax; ++y) { + for(int x = xmin; x < xmax; ++x) { + + // Find area between point and two other vertices + a1 = abs(x1 * (y2 - y) + x2 * (y - y1) + x * (y1 - y2))/2.0; + a2 = abs(x1 * (y - y3) + x * (y3 - y1) + x3 * (y1 - y))/2.0; + a3 = abs(x * (y2 - y3) + x2 * (y3 - y) + x3 * (y - y2))/2.0; + + // Assign barycentric coordinates + l1 = a1/area; + l2 = a2/area; + l3 = a3/area; + + unsigned char r = (a1*v1.r + a2*v2.r + a3*v3.r)/area; + unsigned char g = (a1*v1.g + a2*v2.g + a3*v3.g)/area; + unsigned char b = (a1*v1.b + a2*v2.b + a3*v3.b)/area; + + // Find if point is inside triangle + //if((l1 <= 0.0 || l1 >= 1.0) || (l2 <= 0.0 || l2 >= 1.0) || (l3 <= 0.0 || l3 >= 1.0)) + if(!(l1 + l2 + l3 <= 1.0001 && l1 + l2 + l3 >= 0.9999)) + { + continue; + } + else + { + image->setPixel(x, y, r, g, b); + } + } + } + // Write image to file + image->writeToFile(filename); + return 0; +} diff --git a/L02/src/stb_image_write.h b/L02/src/stb_image_write.h new file mode 100644 index 0000000..f07b625 --- /dev/null +++ b/L02/src/stb_image_write.h @@ -0,0 +1,1048 @@ +/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio. It could be + adapted to write to memory or a general streaming interface; let me know. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation. This library is designed + for source code compactness and simplicity, not optimal image file size + or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can define STBIW_MEMMOVE() to replace memmove() + +USAGE: + + There are four functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + There are also four equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + +CREDITS: + + PNG/BMP/TGA + Sean Barrett + HDR + Baldur Karlsson + TGA monochrome: + Jean-Sebastien Guay + misc enhancements: + Tim Kelsey + TGA RLE + Alan Hickman + initial file IO callback implementation + Emmanuel Julien + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + +LICENSE + +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#define STBIWDEF extern +extern int stbi_write_tga_with_rle; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + +#ifdef __cplusplus +} +#endif + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_tga_with_rle = 1; +#else +int stbi_write_tga_with_rle = 1; +#endif + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a, arr[1] = b, arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 1: + s->func(s->context,d,1); + break; + case 2: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + for (j = y - 1; j >= 0; --j) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson +#ifndef STBI_WRITE_NO_STDIO + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); + STBIW_FREE(scratch); + return 1; + } +} + +int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) best=d,bestloc=hlist[j]; + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; + s1 %= 65521, s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int i,j,k,p,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = j ? mapping : firstmap; + int best = 0, bestval = 0x7fffffff; + for (p=0; p < 2; ++p) { + for (k= p?best:0; k < 5; ++k) { + int type = mymap[k],est=0; + unsigned char *z = pixels + stride_bytes*j; + for (i=0; i < n; ++i) + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + for (i=n; i < x*n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i] - z[i-n]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; + case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } + } + if (p) break; + for (i=0; i < x*n; ++i) + est += abs((signed char) line_buffer[i]); + if (est < bestval) { bestval = est; best = k; } + } + } + // when we get here, best contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) best; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + f = fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ diff --git a/L03.zip b/L03.zip new file mode 100644 index 0000000..1738930 Binary files /dev/null and b/L03.zip differ diff --git a/L03/.gitignore b/L03/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L03/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L03/CMakeLists.txt b/L03/CMakeLists.txt new file mode 100644 index 0000000..016f065 --- /dev/null +++ b/L03/CMakeLists.txt @@ -0,0 +1,126 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L03) + +# FOR LAB MACHINES ONLY! +# DO NOT EDIT +SET(DEF_DIR_GLM "C:\\c++\\glm") +SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1") +SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0") + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() +FILE(GLOB_RECURSE GLSL "resources/*.glsl") + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL}) + +# Get the GLM environment variable. Since GLM is a header-only library, we +# just need to add it to the include directory. +SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}") +IF(NOT GLM_INCLUDE_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}") + IF(IS_DIRECTORY ${DEF_DIR_GLM}) + MESSAGE(STATUS "Found!") + SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR}) + +# Get the GLFW environment variable. There should be a CMakeLists.txt in the +# specified directory. +SET(GLFW_DIR "$ENV{GLFW_DIR}") +IF(NOT GLFW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}") + IF(IS_DIRECTORY ${DEF_DIR_GLFW}) + MESSAGE(STATUS "Found!") + SET(GLFW_DIR ${DEF_DIR_GLFW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF) +OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF) +OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF) +IF(CMAKE_BUILD_TYPE MATCHES Release) + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release) +ELSE() + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug) +ENDIF() +INCLUDE_DIRECTORIES(${GLFW_DIR}/include) +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES}) + +# Get the GLEW environment variable. +SET(GLEW_DIR "$ENV{GLEW_DIR}") +IF(NOT GLEW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}") + IF(IS_DIRECTORY ${DEF_DIR_GLEW}) + MESSAGE(STATUS "Found!") + SET(GLEW_DIR ${DEF_DIR_GLEW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLEW_DIR}/include) +IF(WIN32) + # With prebuilt binaries + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib) +ELSE() + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a) +ENDIF() + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib) +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") + IF(APPLE) + # Add required frameworks for GLFW. + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo") + ELSE() + #Link the Linux OpenGL library + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL") + ENDIF() +ENDIF() diff --git a/L03/resources/cube.obj b/L03/resources/cube.obj new file mode 100644 index 0000000..e81edd5 --- /dev/null +++ b/L03/resources/cube.obj @@ -0,0 +1,29 @@ +# Blender v2.71 (sub 0) OBJ File: '' +# www.blender.org +v 0.500000 0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 0.500000 -0.500000 +v 0.500000 0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 0.500000 +v -0.500000 0.500000 0.500000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 1.000000 +vn 1.000000 -0.000000 -0.000000 +vn -0.000000 -1.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 1.000000 0.000000 +s off +f 2//1 3//1 4//1 +f 8//2 7//2 6//2 +f 1//3 5//3 6//3 +f 2//4 6//4 7//4 +f 7//5 8//5 4//5 +f 1//6 4//6 8//6 +f 1//1 2//1 4//1 +f 5//2 8//2 6//2 +f 2//3 1//3 6//3 +f 3//4 2//4 7//4 +f 3//5 7//5 4//5 +f 5//6 1//6 8//6 diff --git a/L03/resources/frag.glsl b/L03/resources/frag.glsl new file mode 100644 index 0000000..9d07efa --- /dev/null +++ b/L03/resources/frag.glsl @@ -0,0 +1,8 @@ +#version 120 + +varying vec3 vCol; + +void main() +{ + gl_FragColor = vec4(vCol.r, vCol.g, vCol.b, 1.0); +} diff --git a/L03/resources/vert.glsl b/L03/resources/vert.glsl new file mode 100644 index 0000000..3ecb3f4 --- /dev/null +++ b/L03/resources/vert.glsl @@ -0,0 +1,13 @@ +#version 120 + +attribute vec4 aPos; +attribute vec3 aNor; +uniform mat4 P; +uniform mat4 MV; +varying vec3 vCol; + +void main() +{ + gl_Position = P * MV * aPos; + vCol = 0.5*(aNor + 1.0); +} diff --git a/L03/src/GLSL.cpp b/L03/src/GLSL.cpp new file mode 100644 index 0000000..2969872 --- /dev/null +++ b/L03/src/GLSL.cpp @@ -0,0 +1,152 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#include "GLSL.h" +#include +#include +#include +#include + +using namespace std; + +namespace GLSL { + +const char * errorString(GLenum err) +{ + switch(err) { + case GL_NO_ERROR: + return "No error"; + case GL_INVALID_ENUM: + return "Invalid enum"; + case GL_INVALID_VALUE: + return "Invalid value"; + case GL_INVALID_OPERATION: + return "Invalid operation"; + case GL_STACK_OVERFLOW: + return "Stack overflow"; + case GL_STACK_UNDERFLOW: + return "Stack underflow"; + case GL_OUT_OF_MEMORY: + return "Out of memory"; + default: + return "No error"; + } +} + +void checkVersion() +{ + int major, minor; + major = minor = 0; + const char *verstr = (const char *)glGetString(GL_VERSION); + + if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) { + printf("Invalid GL_VERSION format %d.%d\n", major, minor); + } + if(major < 2) { + printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor); + exit(0); + } +} + +void checkError(const char *str) +{ + GLenum glErr = glGetError(); + if(glErr != GL_NO_ERROR) { + if(str) { + printf("%s: ", str); + } + printf("GL_ERROR = %s.\n", errorString(glErr)); + assert(false); + } +} + +void printShaderInfoLog(GLuint shader) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Shader InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +void printProgramInfoLog(GLuint program) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Program InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +char *textFileRead(const char *fn) +{ + FILE *fp; + char *content = NULL; + int count = 0; + if(fn != NULL) { + fp = fopen(fn,"rt"); + if(fp != NULL) { + fseek(fp, 0, SEEK_END); + count = (int)ftell(fp); + rewind(fp); + if(count > 0) { + content = (char *)malloc(sizeof(char) * (count+1)); + count = (int)fread(content,sizeof(char),count,fp); + content[count] = '\0'; + } + fclose(fp); + } else { + printf("error loading %s\n", fn); + } + } + return content; +} + +int textFileWrite(const char *fn, const char *s) +{ + FILE *fp; + int status = 0; + if(fn != NULL) { + fp = fopen(fn,"w"); + if(fp != NULL) { + if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) { + status = 1; + } + fclose(fp); + } + } + return(status); +} + +} diff --git a/L03/src/GLSL.h b/L03/src/GLSL.h new file mode 100644 index 0000000..f945fdd --- /dev/null +++ b/L03/src/GLSL.h @@ -0,0 +1,40 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#pragma once +#ifndef __GLSL__ +#define __GLSL__ + +#define GLEW_STATIC +#include + +/////////////////////////////////////////////////////////////////////////////// +// For printing out the current file and line number // +/////////////////////////////////////////////////////////////////////////////// +#include + +template +std::string NumberToString(T x) +{ + std::ostringstream ss; + ss << x; + return ss.str(); +} + +#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str() +/////////////////////////////////////////////////////////////////////////////// + +namespace GLSL { + + void checkVersion(); + void checkError(const char *str = 0); + void printProgramInfoLog(GLuint program); + void printShaderInfoLog(GLuint shader); + int textFileWrite(const char *filename, const char *s); + char *textFileRead(const char *filename); +} + +#endif diff --git a/L03/src/main.cpp b/L03/src/main.cpp new file mode 100644 index 0000000..6f625a0 --- /dev/null +++ b/L03/src/main.cpp @@ -0,0 +1,449 @@ +#include +#include +#define _USE_MATH_DEFINES +#include +#include +#include +#include + +#define GLEW_STATIC +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +#include "GLSL.h" + +using namespace std; +using namespace glm; + +GLFWwindow *window; // Main application window +string RESOURCE_DIR = "./"; // Where the resources are loaded from + +GLuint progID; +map attrIDs; +map unifIDs; +map bufIDs; +int indCount; + +// This function is called when a GLFW error occurs +static void error_callback(int error, const char *description) +{ + cerr << description << endl; +} + +// This function is called when a key is pressed +static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GL_TRUE); + } +} + +// This function is called when the mouse is clicked +static void mouse_callback(GLFWwindow *window, int button, int action, int mods) +{ + // Do nothing +} + +// If the window is resized, capture the new size and reset the viewport +static void resize_callback(GLFWwindow *window, int width, int height) +{ + glViewport(0, 0, width, height); +} + +// This function is called once to initialize the scene and OpenGL +static void init() +{ + // + // General setup + // + + // Initialize time. + glfwSetTime(0.0); + + // Set background color. + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + // Enable z-buffer test. + glEnable(GL_DEPTH_TEST); + + // + // GLSL program setup + // + + // Create shader handles + GLuint vShaderID = glCreateShader(GL_VERTEX_SHADER); + GLuint fShaderID = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + string vShaderName = RESOURCE_DIR + "vert.glsl"; + string fShaderName = RESOURCE_DIR + "frag.glsl"; + const char *vShaderText = GLSL::textFileRead(vShaderName.c_str()); + const char *fShaderText = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(vShaderID, 1, &vShaderText, NULL); + glShaderSource(fShaderID, 1, &fShaderText, NULL); + + // Compile vertex shader + int rc; + glCompileShader(vShaderID); + glGetShaderiv(vShaderID, GL_COMPILE_STATUS, &rc); + if(!rc) { + GLSL::printShaderInfoLog(vShaderID); + cout << "Error compiling vertex shader " << vShaderName << endl; + return; + } + + // Compile fragment shader + glCompileShader(fShaderID); + glGetShaderiv(fShaderID, GL_COMPILE_STATUS, &rc); + if(!rc) { + GLSL::printShaderInfoLog(fShaderID); + cout << "Error compiling fragment shader " << fShaderName << endl; + return; + } + + // Create the program and link + progID = glCreateProgram(); + glAttachShader(progID, vShaderID); + glAttachShader(progID, fShaderID); + glLinkProgram(progID); + glGetProgramiv(progID, GL_LINK_STATUS, &rc); + if(!rc) { + GLSL::printProgramInfoLog(progID); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + return; + } + + // Get vertex attribute IDs + attrIDs["aPos"] = glGetAttribLocation(progID, "aPos"); + attrIDs["aNor"] = glGetAttribLocation(progID, "aNor"); + + // Get uniform IDs + unifIDs["P"] = glGetUniformLocation(progID, "P"); + unifIDs["MV"] = glGetUniformLocation(progID, "MV"); + + // + // Vertex buffer setup + // + + // Load OBJ geometry // Load OBJ geometry + vector posBuf; + vector norBuf; + // Some obj files contain material information. + // We'll ignore them for this assignment. + string meshName = RESOURCE_DIR + "cube.obj"; + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } + indCount = posBuf.size()/3; // number of indices to be rendered + + // Generate 2 buffer IDs and put them in the bufIDs map. + GLuint tmp[2]; + glGenBuffers(2, tmp); + bufIDs["bPos"] = tmp[0]; + bufIDs["bNor"] = tmp[1]; + + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bPos"]); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bNor"]); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + assert(norBuf.size() == posBuf.size()); + + + GLSL::checkError(GET_FILE_LINE); +} + +static void printMatrix(const float *A, const char *name = 0) +{ + // OpenGL uses col-major ordering: + // [ 0 4 8 12] + // [ 1 5 9 13] + // [ 2 6 10 14] + // [ 3 7 11 15] + // The (i,j)th element is A[i+4*j]. + if(name) { + printf("%s=[\n", name); + } + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + printf("%- 5.2f ", A[i+4*j]); + } + printf("\n"); + } + if(name) { + printf("];"); + } + printf("\n"); +} + +// Sets M to be the zero matrix +static void createZeroMatrix(float *M) +{ + memset(M, 0, 16*sizeof(float)); +} + +// Sets M to be the identity matrix +static void createIdentityMatrix(float *M) +{ + // + // IMPLEMENT ME + // + createZeroMatrix(M); + M[0] = 1; + M[5] = 1; + M[10] = 1; + M[15] = 1; +} + +// Sets M to be a translation matrix +static void createTranslationMatrix(float *M, float x, float y, float z) +{ + // + // IMPLEMENT ME + // + createIdentityMatrix(M); + M[12] +=x; + M[13] +=y; + M[14] +=z; +} + +// Sets M to be a scale matrix +static void createScaleMatrix(float *M, float x, float y, float z) +{ + // + // IMPLEMENT ME + // + M[0] *= x; + M[5] *= y; + M[10] *= z; +} + +// Sets M to be an X rotation matrix +static void createRotationXMatrix(float *M, float angle) +{ + // + // IMPLEMENT ME + // + createIdentityMatrix(M); + M[5] = cos(angle); + M[6] = -sin(angle); + M[9] = sin(angle); + M[10] = cos(angle); +} + +// Sets M to be a Y rotation matrix +static void createRotationYMatrix(float *M, float angle) +{ + // + // IMPLEMENT ME + // + createIdentityMatrix(M); + M[0] = cos(angle); + M[2] = sin(angle); + M[8] = -sin(angle); + M[10] = cos(angle); +} + +// Sets M to be a Z rotation matrix +static void createRotationZMatrix(float *M, float angle) +{ + // + // IMPLEMENT ME + // + createIdentityMatrix(M); + M[0] = cos(angle); + M[1] = -sin(angle); + M[4] = sin(angle); + M[5] = cos(angle); +} + +// Sets C = A*B +static void multMatrix(float *C, const float *A, const float *B) +{ + createZeroMatrix(C); + for(int k = 0; k < 4; ++k) { + // Process kth column of C + for(int i = 0; i < 4; ++i) { + // Process ith row of C. + // The (i,k)th element of C is the dot product + // of the ith row of A and kth col of B. + + // + // IMPLEMENT ME + // + + C[k*4+i] = (A[i]*B[k*4] + A[i + 4]*B[k*4 + 1] + A[i + 8]*B[k*4 + 2] + A[i + 12]*B[k*4 + 3]); + } + } +} + +// This function is called every frame to draw the scene. +static void render() +{ + // Clear framebuffer. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Get current frame buffer size. + int width, height; + glfwGetFramebufferSize(window, &width, &height); + float aspect = width/(float)height; + + // Set up projection matrix (camera intrinsics) + mat4 P; + P = perspective((float)(45.0*M_PI/180.0), aspect, 0.01f, 100.0f); + + // Modelview matrix: camera and world + float M[16]; + + // Tell OpenGL which GLSL program to use + glUseProgram(progID); + // Pass in the current projection matrix + glUniformMatrix4fv(unifIDs["P"], 1, GL_FALSE, &P[0][0]); + // Enable the attribute + glEnableVertexAttribArray(attrIDs["aPos"]); + // Enable the attribute + glEnableVertexAttribArray(attrIDs["aNor"]); + // Bind the position buffer object to make it the currently active buffer + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bPos"]); + // Set the pointer -- the data is already on the GPU + glVertexAttribPointer(attrIDs["aPos"], 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + // Bind the color buffer object to make it the currently active buffer + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bNor"]); + // Set the pointer -- the data is already on the GPU + glVertexAttribPointer(attrIDs["aNor"], 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Send the modelview matrix and draw + createZeroMatrix(M); + // Implimented. + createIdentityMatrix(M); + // Testing + //printMatrix(A); + /* + float A[16], B[16], C[16]; + for(int i = 0; i < 16; ++i) { A[i] = i; } + for(int i = 0; i < 16; ++i) { B[i] = i*i; } + multMatrix(C, A, B); + printMatrix(A, "A"); + printMatrix(B, "B"); + printMatrix(C, "C"); + */ + float C[16]; + createRotationYMatrix(C, 30); + float I[16]; + createIdentityMatrix(I); + multMatrix(M, C, I); + M[14] += -5; + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, M); + glDrawArrays(GL_TRIANGLES, 0, indCount); + + // Unbind the buffer object + glBindBuffer(GL_ARRAY_BUFFER, 0); + // Disable the attribute + glDisableVertexAttribArray(attrIDs["aNor"]); + // Disable the attribute + glDisableVertexAttribArray(attrIDs["aPos"]); + // Unbind our GLSL program + glUseProgram(0); + + GLSL::checkError(GET_FILE_LINE); +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + cout << "Please specify the resource directory." << endl; + return 0; + } + RESOURCE_DIR = argv[1] + string("/"); + + // Set error callback. + glfwSetErrorCallback(error_callback); + // Initialize the library. + if(!glfwInit()) { + return -1; + } + // Create a windowed mode window and its OpenGL context. + window = glfwCreateWindow(640, 480, "YOUR NAME", NULL, NULL); + if(!window) { + glfwTerminate(); + return -1; + } + // Make the window's context current. + glfwMakeContextCurrent(window); + // Initialize GLEW. + glewExperimental = true; + if(glewInit() != GLEW_OK) { + cerr << "Failed to initialize GLEW" << endl; + return -1; + } + glGetError(); // A bug in glewInit() causes an error that we can safely ignore. + cout << "OpenGL version: " << glGetString(GL_VERSION) << endl; + cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; + GLSL::checkVersion(); + // Set vsync. + glfwSwapInterval(1); + // Set keyboard callback. + glfwSetKeyCallback(window, key_callback); + // Set the mouse call back. + glfwSetMouseButtonCallback(window, mouse_callback); + // Set the window resize call back. + glfwSetFramebufferSizeCallback(window, resize_callback); + // Initialize scene. + init(); + // Loop until the user closes the window. + while(!glfwWindowShouldClose(window)) { + // Render scene. + render(); + // Swap front and back buffers. + glfwSwapBuffers(window); + // Poll for and process events. + glfwPollEvents(); + } + // Quit program. + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/L03/src/tiny_obj_loader.h b/L03/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/L03/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/L04.zip b/L04.zip new file mode 100644 index 0000000..e63da6c Binary files /dev/null and b/L04.zip differ diff --git a/L04/.gitignore b/L04/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L04/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L04/CMakeLists.txt b/L04/CMakeLists.txt new file mode 100644 index 0000000..ca58509 --- /dev/null +++ b/L04/CMakeLists.txt @@ -0,0 +1,126 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L04) + +# FOR LAB MACHINES ONLY! +# DO NOT EDIT +SET(DEF_DIR_GLM "C:\\c++\\glm") +SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1") +SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0") + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() +FILE(GLOB_RECURSE GLSL "resources/*.glsl") + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL}) + +# Get the GLM environment variable. Since GLM is a header-only library, we +# just need to add it to the include directory. +SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}") +IF(NOT GLM_INCLUDE_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}") + IF(IS_DIRECTORY ${DEF_DIR_GLM}) + MESSAGE(STATUS "Found!") + SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR}) + +# Get the GLFW environment variable. There should be a CMakeLists.txt in the +# specified directory. +SET(GLFW_DIR "$ENV{GLFW_DIR}") +IF(NOT GLFW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}") + IF(IS_DIRECTORY ${DEF_DIR_GLFW}) + MESSAGE(STATUS "Found!") + SET(GLFW_DIR ${DEF_DIR_GLFW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF) +OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF) +OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF) +IF(CMAKE_BUILD_TYPE MATCHES Release) + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release) +ELSE() + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug) +ENDIF() +INCLUDE_DIRECTORIES(${GLFW_DIR}/include) +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES}) + +# Get the GLEW environment variable. +SET(GLEW_DIR "$ENV{GLEW_DIR}") +IF(NOT GLEW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}") + IF(IS_DIRECTORY ${DEF_DIR_GLEW}) + MESSAGE(STATUS "Found!") + SET(GLEW_DIR ${DEF_DIR_GLEW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLEW_DIR}/include) +IF(WIN32) + # With prebuilt binaries + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib) +ELSE() + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a) +ENDIF() + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib) +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") + IF(APPLE) + # Add required frameworks for GLFW. + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo") + ELSE() + #Link the Linux OpenGL library + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL") + ENDIF() +ENDIF() diff --git a/L04/resources/cube.obj b/L04/resources/cube.obj new file mode 100644 index 0000000..e81edd5 --- /dev/null +++ b/L04/resources/cube.obj @@ -0,0 +1,29 @@ +# Blender v2.71 (sub 0) OBJ File: '' +# www.blender.org +v 0.500000 0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 0.500000 -0.500000 +v 0.500000 0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 0.500000 +v -0.500000 0.500000 0.500000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 1.000000 +vn 1.000000 -0.000000 -0.000000 +vn -0.000000 -1.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 1.000000 0.000000 +s off +f 2//1 3//1 4//1 +f 8//2 7//2 6//2 +f 1//3 5//3 6//3 +f 2//4 6//4 7//4 +f 7//5 8//5 4//5 +f 1//6 4//6 8//6 +f 1//1 2//1 4//1 +f 5//2 8//2 6//2 +f 2//3 1//3 6//3 +f 3//4 2//4 7//4 +f 3//5 7//5 4//5 +f 5//6 1//6 8//6 diff --git a/L04/resources/frag.glsl b/L04/resources/frag.glsl new file mode 100644 index 0000000..9d07efa --- /dev/null +++ b/L04/resources/frag.glsl @@ -0,0 +1,8 @@ +#version 120 + +varying vec3 vCol; + +void main() +{ + gl_FragColor = vec4(vCol.r, vCol.g, vCol.b, 1.0); +} diff --git a/L04/resources/vert.glsl b/L04/resources/vert.glsl new file mode 100644 index 0000000..3ecb3f4 --- /dev/null +++ b/L04/resources/vert.glsl @@ -0,0 +1,13 @@ +#version 120 + +attribute vec4 aPos; +attribute vec3 aNor; +uniform mat4 P; +uniform mat4 MV; +varying vec3 vCol; + +void main() +{ + gl_Position = P * MV * aPos; + vCol = 0.5*(aNor + 1.0); +} diff --git a/L04/src/GLSL.cpp b/L04/src/GLSL.cpp new file mode 100644 index 0000000..2969872 --- /dev/null +++ b/L04/src/GLSL.cpp @@ -0,0 +1,152 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#include "GLSL.h" +#include +#include +#include +#include + +using namespace std; + +namespace GLSL { + +const char * errorString(GLenum err) +{ + switch(err) { + case GL_NO_ERROR: + return "No error"; + case GL_INVALID_ENUM: + return "Invalid enum"; + case GL_INVALID_VALUE: + return "Invalid value"; + case GL_INVALID_OPERATION: + return "Invalid operation"; + case GL_STACK_OVERFLOW: + return "Stack overflow"; + case GL_STACK_UNDERFLOW: + return "Stack underflow"; + case GL_OUT_OF_MEMORY: + return "Out of memory"; + default: + return "No error"; + } +} + +void checkVersion() +{ + int major, minor; + major = minor = 0; + const char *verstr = (const char *)glGetString(GL_VERSION); + + if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) { + printf("Invalid GL_VERSION format %d.%d\n", major, minor); + } + if(major < 2) { + printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor); + exit(0); + } +} + +void checkError(const char *str) +{ + GLenum glErr = glGetError(); + if(glErr != GL_NO_ERROR) { + if(str) { + printf("%s: ", str); + } + printf("GL_ERROR = %s.\n", errorString(glErr)); + assert(false); + } +} + +void printShaderInfoLog(GLuint shader) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Shader InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +void printProgramInfoLog(GLuint program) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Program InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +char *textFileRead(const char *fn) +{ + FILE *fp; + char *content = NULL; + int count = 0; + if(fn != NULL) { + fp = fopen(fn,"rt"); + if(fp != NULL) { + fseek(fp, 0, SEEK_END); + count = (int)ftell(fp); + rewind(fp); + if(count > 0) { + content = (char *)malloc(sizeof(char) * (count+1)); + count = (int)fread(content,sizeof(char),count,fp); + content[count] = '\0'; + } + fclose(fp); + } else { + printf("error loading %s\n", fn); + } + } + return content; +} + +int textFileWrite(const char *fn, const char *s) +{ + FILE *fp; + int status = 0; + if(fn != NULL) { + fp = fopen(fn,"w"); + if(fp != NULL) { + if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) { + status = 1; + } + fclose(fp); + } + } + return(status); +} + +} diff --git a/L04/src/GLSL.h b/L04/src/GLSL.h new file mode 100644 index 0000000..f945fdd --- /dev/null +++ b/L04/src/GLSL.h @@ -0,0 +1,40 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#pragma once +#ifndef __GLSL__ +#define __GLSL__ + +#define GLEW_STATIC +#include + +/////////////////////////////////////////////////////////////////////////////// +// For printing out the current file and line number // +/////////////////////////////////////////////////////////////////////////////// +#include + +template +std::string NumberToString(T x) +{ + std::ostringstream ss; + ss << x; + return ss.str(); +} + +#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str() +/////////////////////////////////////////////////////////////////////////////// + +namespace GLSL { + + void checkVersion(); + void checkError(const char *str = 0); + void printProgramInfoLog(GLuint program); + void printShaderInfoLog(GLuint shader); + int textFileWrite(const char *filename, const char *s); + char *textFileRead(const char *filename); +} + +#endif diff --git a/L04/src/MatrixStack.cpp b/L04/src/MatrixStack.cpp new file mode 100644 index 0000000..eaa6e6c --- /dev/null +++ b/L04/src/MatrixStack.cpp @@ -0,0 +1,114 @@ +#include "MatrixStack.h" + +#include +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +using namespace std; + +MatrixStack::MatrixStack() +{ + mstack = make_shared< stack >(); + mstack->push(glm::mat4(1.0)); +} + +MatrixStack::~MatrixStack() +{ +} + +void MatrixStack::pushMatrix() +{ + const glm::mat4 &top = mstack->top(); + mstack->push(top); + assert(mstack->size() < 100); +} + +void MatrixStack::popMatrix() +{ + assert(!mstack->empty()); + mstack->pop(); + // There should always be one matrix left. + assert(!mstack->empty()); +} + +void MatrixStack::loadIdentity() +{ + glm::mat4 &top = mstack->top(); + top = glm::mat4(1.0); +} + +void MatrixStack::translate(const glm::vec3 &t) +{ + glm::mat4 &top = mstack->top(); + top *= glm::translate(t); +} + +void MatrixStack::translate(float x, float y, float z) +{ + translate(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(const glm::vec3 &s) +{ + glm::mat4 &top = mstack->top(); + top *= glm::scale(s); +} + +void MatrixStack::scale(float x, float y, float z) +{ + scale(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(float s) +{ + scale(glm::vec3(s, s, s)); +} + +void MatrixStack::rotate(float angle, const glm::vec3 &axis) +{ + glm::mat4 &top = mstack->top(); + top *= glm::rotate(angle, axis); +} + +void MatrixStack::rotate(float angle, float x, float y, float z) +{ + rotate(angle, glm::vec3(x, y, z)); +} + +void MatrixStack::multMatrix(const glm::mat4 &matrix) +{ + glm::mat4 &top = mstack->top(); + top *= matrix; +} + +const glm::mat4 &MatrixStack::topMatrix() const +{ + return mstack->top(); +} + +void MatrixStack::print(const glm::mat4 &mat, const char *name) +{ + if(name) { + printf("%s = [\n", name); + } + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + // mat[j] returns the jth column + printf("%- 5.2f ", mat[j][i]); + } + printf("\n"); + } + if(name) { + printf("];"); + } + printf("\n"); +} + +void MatrixStack::print(const char *name) const +{ + print(mstack->top(), name); +} diff --git a/L04/src/MatrixStack.h b/L04/src/MatrixStack.h new file mode 100644 index 0000000..66278ce --- /dev/null +++ b/L04/src/MatrixStack.h @@ -0,0 +1,50 @@ +#pragma once +#ifndef _MatrixStack_H_ +#define _MatrixStack_H_ + +#include +#include +#include + +class MatrixStack +{ +public: + MatrixStack(); + virtual ~MatrixStack(); + + // glPushMatrix(): Copies the current matrix and adds it to the top of the stack + void pushMatrix(); + // glPopMatrix(): Removes the top of the stack and sets the current matrix to be the matrix that is now on top + void popMatrix(); + + // glLoadIdentity(): Sets the top matrix to be the identity + void loadIdentity(); + // glMultMatrix(): Right multiplies the top matrix + void multMatrix(const glm::mat4 &matrix); + + // glTranslate(): Right multiplies the top matrix by a translation matrix + void translate(const glm::vec3 &trans); + void translate(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(const glm::vec3 &scale); + void scale(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(float size); + // glRotate(): Right multiplies the top matrix by a rotation matrix (angle in radians) + void rotate(float angle, const glm::vec3 &axis); + void rotate(float angle, float x, float y, float z); + + // glGet(GL_MODELVIEW_MATRIX): Gets the top matrix + const glm::mat4 &topMatrix() const; + + // Prints out the specified matrix + static void print(const glm::mat4 &mat, const char *name = 0); + // Prints out the top matrix + void print(const char *name = 0) const; + +private: + std::shared_ptr< std::stack > mstack; + +}; + +#endif diff --git a/L04/src/Program.cpp b/L04/src/Program.cpp new file mode 100644 index 0000000..1e85538 --- /dev/null +++ b/L04/src/Program.cpp @@ -0,0 +1,126 @@ +#include "Program.h" + +#include +#include + +#include "GLSL.h" + +using namespace std; + +Program::Program() : + vShaderName(""), + fShaderName(""), + pid(0), + verbose(true) +{ + +} + +Program::~Program() +{ + +} + +void Program::setShaderNames(const string &v, const string &f) +{ + vShaderName = v; + fShaderName = f; +} + +bool Program::init() +{ + GLint rc; + + // Create shader handles + GLuint VS = glCreateShader(GL_VERTEX_SHADER); + GLuint FS = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + const char *vshader = GLSL::textFileRead(vShaderName.c_str()); + const char *fshader = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(VS, 1, &vshader, NULL); + glShaderSource(FS, 1, &fshader, NULL); + + // Compile vertex shader + glCompileShader(VS); + glGetShaderiv(VS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(VS); + cout << "Error compiling vertex shader " << vShaderName << endl; + } + return false; + } + + // Compile fragment shader + glCompileShader(FS); + glGetShaderiv(FS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(FS); + cout << "Error compiling fragment shader " << fShaderName << endl; + } + return false; + } + + // Create the program and link + pid = glCreateProgram(); + glAttachShader(pid, VS); + glAttachShader(pid, FS); + glLinkProgram(pid); + glGetProgramiv(pid, GL_LINK_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printProgramInfoLog(pid); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + } + return false; + } + + GLSL::checkError(GET_FILE_LINE); + return true; +} + +void Program::bind() +{ + glUseProgram(pid); +} + +void Program::unbind() +{ + glUseProgram(0); +} + +void Program::addAttribute(const string &name) +{ + attributes[name] = glGetAttribLocation(pid, name.c_str()); +} + +void Program::addUniform(const string &name) +{ + uniforms[name] = glGetUniformLocation(pid, name.c_str()); +} + +GLint Program::getAttribute(const string &name) const +{ + map::const_iterator attribute = attributes.find(name.c_str()); + if(attribute == attributes.end()) { + if(isVerbose()) { + cout << name << " is not an attribute variable" << endl; + } + return -1; + } + return attribute->second; +} + +GLint Program::getUniform(const string &name) const +{ + map::const_iterator uniform = uniforms.find(name.c_str()); + if(uniform == uniforms.end()) { + if(isVerbose()) { + cout << name << " is not a uniform variable" << endl; + } + return -1; + } + return uniform->second; +} diff --git a/L04/src/Program.h b/L04/src/Program.h new file mode 100644 index 0000000..51e58bb --- /dev/null +++ b/L04/src/Program.h @@ -0,0 +1,44 @@ +#pragma once +#ifndef __Program__ +#define __Program__ + +#include +#include + +#define GLEW_STATIC +#include + +/** + * An OpenGL Program (vertex and fragment shaders) + */ +class Program +{ +public: + Program(); + virtual ~Program(); + + void setVerbose(bool v) { verbose = v; } + bool isVerbose() const { return verbose; } + + void setShaderNames(const std::string &v, const std::string &f); + virtual bool init(); + virtual void bind(); + virtual void unbind(); + + void addAttribute(const std::string &name); + void addUniform(const std::string &name); + GLint getAttribute(const std::string &name) const; + GLint getUniform(const std::string &name) const; + +protected: + std::string vShaderName; + std::string fShaderName; + +private: + GLuint pid; + std::map attributes; + std::map uniforms; + bool verbose; +}; + +#endif diff --git a/L04/src/Shape.cpp b/L04/src/Shape.cpp new file mode 100644 index 0000000..cf80379 --- /dev/null +++ b/L04/src/Shape.cpp @@ -0,0 +1,135 @@ +#include "Shape.h" +#include + +#include "GLSL.h" +#include "Program.h" + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +using namespace std; + +Shape::Shape() : + posBufID(0), + norBufID(0), + texBufID(0) +{ +} + +Shape::~Shape() +{ +} + +void Shape::loadMesh(const string &meshName) +{ + // Load geometry + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + if(!attrib.texcoords.empty()) { + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+0]); + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+1]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } +} + +void Shape::init() +{ + // Send the position array to the GPU + glGenBuffers(1, &posBufID); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + // Send the normal array to the GPU + if(!norBuf.empty()) { + glGenBuffers(1, &norBufID); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + } + + // Send the texture array to the GPU + if(!texBuf.empty()) { + glGenBuffers(1, &texBufID); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glBufferData(GL_ARRAY_BUFFER, texBuf.size()*sizeof(float), &texBuf[0], GL_STATIC_DRAW); + } + + // Unbind the arrays + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} + +void Shape::draw(const shared_ptr prog) const +{ + // Bind position buffer + int h_pos = prog->getAttribute("aPos"); + glEnableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glVertexAttribPointer(h_pos, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + + // Bind normal buffer + int h_nor = prog->getAttribute("aNor"); + if(h_nor != -1 && norBufID != 0) { + glEnableVertexAttribArray(h_nor); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glVertexAttribPointer(h_nor, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Bind texcoords buffer + int h_tex = prog->getAttribute("aTex"); + if(h_tex != -1 && texBufID != 0) { + glEnableVertexAttribArray(h_tex); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glVertexAttribPointer(h_tex, 2, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Draw + int count = posBuf.size()/3; // number of indices to be rendered + glDrawArrays(GL_TRIANGLES, 0, count); + + // Disable and unbind + if(h_tex != -1) { + glDisableVertexAttribArray(h_tex); + } + if(h_nor != -1) { + glDisableVertexAttribArray(h_nor); + } + glDisableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} diff --git a/L04/src/Shape.h b/L04/src/Shape.h new file mode 100644 index 0000000..df2aea3 --- /dev/null +++ b/L04/src/Shape.h @@ -0,0 +1,36 @@ +#pragma once +#ifndef _SHAPE_H_ +#define _SHAPE_H_ + +#include +#include +#include + +class Program; + +/** + * A shape defined by a list of triangles + * - posBuf should be of length 3*ntris + * - norBuf should be of length 3*ntris (if normals are available) + * - texBuf should be of length 2*ntris (if texture coords are available) + * posBufID, norBufID, and texBufID are OpenGL buffer identifiers. + */ +class Shape +{ +public: + Shape(); + virtual ~Shape(); + void loadMesh(const std::string &meshName); + void init(); + void draw(const std::shared_ptr prog) const; + +private: + std::vector posBuf; + std::vector norBuf; + std::vector texBuf; + unsigned posBufID; + unsigned norBufID; + unsigned texBufID; +}; + +#endif diff --git a/L04/src/main.cpp b/L04/src/main.cpp new file mode 100644 index 0000000..2d15242 --- /dev/null +++ b/L04/src/main.cpp @@ -0,0 +1,347 @@ +#include +#include +#define _USE_MATH_DEFINES +#include +#include +#include +#include + +#define GLEW_STATIC +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include +#include + +#include "tiny_obj_loader.h" + +#include "GLSL.h" +#include "MatrixStack.h" +#include "Shape.h" +#include "Program.h" + +#define PI 3.14159 + +using namespace std; +using namespace glm; + +GLFWwindow *window; // Main application window +string RESOURCE_DIR = "./"; // Where the resources are loaded from + +GLuint progID; +map attrIDs; +map unifIDs; +map bufIDs; +int indCount; + +// This function is called when a GLFW error occurs +static void error_callback(int error, const char *description) +{ + cerr << description << endl; +} + +// This function is called when a key is pressed +static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GL_TRUE); + } +} + +// This function is called when the mouse is clicked +static void mouse_callback(GLFWwindow *window, int button, int action, int mods) +{ + // Do nothing +} + +// If the window is resized, capture the new size and reset the viewport +static void resize_callback(GLFWwindow *window, int width, int height) +{ + glViewport(0, 0, width, height); +} + +// This function is called once to initialize the scene and OpenGL +static void init() +{ + // + // General setup + // + + // Initialize time. + glfwSetTime(0.0); + + // Set background color. + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + // Enable z-buffer test. + glEnable(GL_DEPTH_TEST); + + // + // GLSL program setup + // + + // Create shader handles + GLuint vShaderID = glCreateShader(GL_VERTEX_SHADER); + GLuint fShaderID = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + string vShaderName = RESOURCE_DIR + "vert.glsl"; + string fShaderName = RESOURCE_DIR + "frag.glsl"; + const char *vShaderText = GLSL::textFileRead(vShaderName.c_str()); + const char *fShaderText = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(vShaderID, 1, &vShaderText, NULL); + glShaderSource(fShaderID, 1, &fShaderText, NULL); + + // Compile vertex shader + int rc; + glCompileShader(vShaderID); + glGetShaderiv(vShaderID, GL_COMPILE_STATUS, &rc); + if(!rc) { + GLSL::printShaderInfoLog(vShaderID); + cout << "Error compiling vertex shader " << vShaderName << endl; + return; + } + + // Compile fragment shader + glCompileShader(fShaderID); + glGetShaderiv(fShaderID, GL_COMPILE_STATUS, &rc); + if(!rc) { + GLSL::printShaderInfoLog(fShaderID); + cout << "Error compiling fragment shader " << fShaderName << endl; + return; + } + + // Create the program and link + progID = glCreateProgram(); + glAttachShader(progID, vShaderID); + glAttachShader(progID, fShaderID); + glLinkProgram(progID); + glGetProgramiv(progID, GL_LINK_STATUS, &rc); + if(!rc) { + GLSL::printProgramInfoLog(progID); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + return; + } + + // Get vertex attribute IDs + attrIDs["aPos"] = glGetAttribLocation(progID, "aPos"); + attrIDs["aNor"] = glGetAttribLocation(progID, "aNor"); + + // Get uniform IDs + unifIDs["P"] = glGetUniformLocation(progID, "P"); + unifIDs["MV"] = glGetUniformLocation(progID, "MV"); + + // + // Vertex buffer setup + // + + // Load OBJ geometry + vector posBuf; + vector norBuf; + // Some obj files contain material information. + // We'll ignore them for this assignment. + string meshName = RESOURCE_DIR + "cube.obj"; + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } + indCount = posBuf.size()/3; // number of indices to be rendered + + // Generate 2 buffer IDs and put them in the bufIDs map. + GLuint tmp[2]; + glGenBuffers(2, tmp); + bufIDs["bPos"] = tmp[0]; + bufIDs["bNor"] = tmp[1]; + + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bPos"]); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bNor"]); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + assert(norBuf.size() == posBuf.size()); + + GLSL::checkError(GET_FILE_LINE); +} + +static void renderA(MatrixStack MV) +{ + MV.pushMatrix(); + MV.translate(-1, 0, 0); + MV.rotate(-(2*PI)/16, 0, 0, 1); + MV.scale(0.5, 4, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #1 + MV.pushMatrix(); + MV.scale(2, 0.5, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #2 + MV.pushMatrix(); + MV.translate(1, 0, 0); + MV.rotate((2*PI)/16, 0, 0, 1); + MV.scale(0.5, 4, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #3 +} + +// This function is called every frame to draw the scene. +static void render() +{ + // Clear framebuffer. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Get current frame buffer size. + int width, height; + glfwGetFramebufferSize(window, &width, &height); + float aspect = width/(float)height; + + // Set up projection matrix (camera intrinsics) + mat4 P = perspective((float)(45.0*M_PI/180.0), aspect, 0.01f, 100.0f); + + // Modelview matrix: camera and world + MatrixStack MV; + + // Tell OpenGL which GLSL program to use + glUseProgram(progID); + // Pass in the current projection matrix + glUniformMatrix4fv(unifIDs["P"], 1, GL_FALSE, value_ptr(P)); + // Enable the attribute + glEnableVertexAttribArray(attrIDs["aPos"]); + // Enable the attribute + glEnableVertexAttribArray(attrIDs["aNor"]); + // Bind the position buffer object to make it the currently active buffer + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bPos"]); + // Set the pointer -- the data is already on the GPU + glVertexAttribPointer(attrIDs["aPos"], 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + // Bind the color buffer object to make it the currently active buffer + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bNor"]); + // Set the pointer -- the data is already on the GPU + glVertexAttribPointer(attrIDs["aNor"], 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + //MV.pushMatrix(); + // + // DO STUFF HERE + // + MV.loadIdentity(); + MV.pushMatrix(); + MV.translate(-2, 0, -10); + MV.rotate((-(2*PI/16)), 0, 1, 0); + MV.rotate((-(2*PI/16)), 1, 0, 0); + MV.pushMatrix(); + for(int i = 1; i <= 20; i++) + { + renderA(MV); + MV.translate(1.0, 0,-2); + MV.scale(0.75, 0.75, 0.75); + } + MV.popMatrix(); + MV.popMatrix(); + + + // Unbind the buffer object + glBindBuffer(GL_ARRAY_BUFFER, 0); + // Disable the attribute + glDisableVertexAttribArray(attrIDs["aNor"]); + // Disable the attribute + glDisableVertexAttribArray(attrIDs["aPos"]); + // Unbind our GLSL program + glUseProgram(0); + + GLSL::checkError(GET_FILE_LINE); +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + cout << "Please specify the resource directory." << endl; + return 0; + } + RESOURCE_DIR = argv[1] + string("/"); + + // Set error callback. + glfwSetErrorCallback(error_callback); + // Initialize the library. + if(!glfwInit()) { + return -1; + } + // Create a windowed mode window and its OpenGL context. + window = glfwCreateWindow(640, 480, "YOUR NAME", NULL, NULL); + if(!window) { + glfwTerminate(); + return -1; + } + // Make the window's context current. + glfwMakeContextCurrent(window); + // Initialize GLEW. + glewExperimental = true; + if(glewInit() != GLEW_OK) { + cerr << "Failed to initialize GLEW" << endl; + return -1; + } + glGetError(); // A bug in glewInit() causes an error that we can safely ignore. + cout << "OpenGL version: " << glGetString(GL_VERSION) << endl; + cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; + GLSL::checkVersion(); + // Set vsync. + glfwSwapInterval(1); + // Set keyboard callback. + glfwSetKeyCallback(window, key_callback); + // Set the mouse call back. + glfwSetMouseButtonCallback(window, mouse_callback); + // Set the window resize call back. + glfwSetFramebufferSizeCallback(window, resize_callback); + // Initialize scene. + init(); + // Loop until the user closes the window. + while(!glfwWindowShouldClose(window)) { + // Render scene. + render(); + // Swap front and back buffers. + glfwSwapBuffers(window); + // Poll for and process events. + glfwPollEvents(); + } + // Quit program. + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/L04/src/tiny_obj_loader.h b/L04/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/L04/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_