Skip to content

Instantly share code, notes, and snippets.

@adler3d
Created May 4, 2019 17:11
Show Gist options
  • Save adler3d/bee1be7196bb1682c71418cd71b820e3 to your computer and use it in GitHub Desktop.
Save adler3d/bee1be7196bb1682c71418cd71b820e3 to your computer and use it in GitHub Desktop.
// forked from https://gamedev.ru/files/?id=138400
#include <windows.h>
#include <shellapi.h>
#include <cstdint>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdarg>
#include <array>
#include <vector>
#include <map>
//==============================================================================
typedef signed char si8;
typedef unsigned char ui8;
typedef std::int16_t si16;
typedef std::uint16_t ui16;
typedef std::int32_t si32;
typedef std::uint32_t ui32;
typedef std::int64_t si64;
typedef std::uint64_t ui64;
//==============================================================================
using std::size_t;
using std::memset;
using std::memcpy;
using std::memmove;
using std::sscanf;
using std::snprintf;
using std::fopen;
using std::fgets;
using std::feof;
using std::vector;
using std::map;
using std::array;
//==============================================================================
// SIMD stuff. So far, __GNUC__-only (GCC, clang). For MSVC may make
// simd4i etc. wrapper classes around intrinsics.
// Seems straightforward, but more work.
// Built-ins are used instead of intrinsics, because it plays better
// with dynamic CPU dispatch, esp. on older GCCs.
// stdcall is to work around "calling 'function' with SSE calling convention without SSE/SSE2 enabled".
// See https://gamedev.ru/code/forum/?id=233033&page=24&m=4913696#m347 for longer write-up.
bool allow_simd;
typedef si32 __attribute__((vector_size(16))) simd4i;
typedef float __attribute__((vector_size(16))) simd4f;
#define CODE_SSE2 __attribute__((target("sse2,fpmath=sse"),stdcall))
#define CPU_HAS_SSE2() (allow_simd&&__builtin_cpu_supports("sse2"))
#define ALIGNED(n) __attribute__((aligned(n)))
static inline CODE_SSE2 simd4i load4i(const void *p) {simd4i ret; memcpy(&ret,p,sizeof(ret)); return ret;}
static inline CODE_SSE2 simd4f load4f(const void *p) {simd4f ret; memcpy(&ret,p,sizeof(ret)); return ret;}
static inline CODE_SSE2 void store4i(simd4i value,void *p) {memcpy(p,&value,sizeof(value));}
static inline CODE_SSE2 void store4f(simd4f value,void *p) {memcpy(p,&value,sizeof(value));}
static inline CODE_SSE2 simd4i fill4i(si32 x) {return simd4i{x,x,x,x};}
static inline CODE_SSE2 simd4f fill4f(float x) {return simd4f{x,x,x,x};}
template<si32 i0,si32 i1,si32 i2,si32 i3>
static inline CODE_SSE2 simd4i shuffle4i(simd4i v) {return simd4i{v[i0],v[i1],v[i2],v[i3]};}
template<si32 i0,si32 i1,si32 i2,si32 i3>
static inline CODE_SSE2 simd4f shuffle4f(simd4f v) {return simd4f{v[i0],v[i1],v[i2],v[i3]};}
static inline CODE_SSE2 simd4f cvt4if(simd4i v) {return simd4f{float(v[0]),float(v[1]),float(v[2]),float(v[3])};}
static inline CODE_SSE2 simd4i cvt4fi(simd4f v) {return simd4i{si32(v[0]),si32(v[1]),si32(v[2]),si32(v[3])};}
static inline CODE_SSE2 si32 signs4f(simd4f v) {return si32(__builtin_ia32_movmskps(v));}
static inline CODE_SSE2 si32 signs4i(simd4i v) {return signs4f((simd4f)v);}
static inline CODE_SSE2 simd4i min4i(simd4i a,simd4i b) {return a<b?a:b;}
static inline CODE_SSE2 simd4i max4i(simd4i a,simd4i b) {return a>b?a:b;}
static inline CODE_SSE2 simd4f min4f(simd4f a,simd4f b) {return __builtin_ia32_minps(a,b);}
static inline CODE_SSE2 simd4f max4f(simd4f a,simd4f b) {return __builtin_ia32_maxps(a,b);}
static inline CODE_SSE2 simd4f rcp4f(simd4f v) {return __builtin_ia32_rcpps(v);}
static inline CODE_SSE2 simd4f rsqrt4f(simd4f v) {return __builtin_ia32_rsqrtps(v);}
static inline CODE_SSE2 simd4i load2x64(const void *p0,const void *p1)
{
simd4i ret;
__asm__(
"movq %[p0],%[ret]\n\t"
"movhps %[p1],%[ret]\n\t"
:[ret]"=x"(ret)
:[p0]"m"(*(const ui8*)p0)
,[p1]"m"(*(const ui8*)p1));
return ret;
}
static inline CODE_SSE2 void store2x64(simd4i v,void *p0,void *p1)
{
__asm__(
"movq %[v],%[p0]\n\t"
"movhps %[v],%[p1]\n\t"
:
:[v]"x"(v)
,[p0]"m"(*(ui8*)p0)
,[p1]"m"(*(ui8*)p1)
:"memory");
}
//==============================================================================
static const si32 WIN_W=512;
static const si32 WIN_H=512;
static ui8 window_buffer[WIN_W*WIN_H*4];
static float depth_buffer[WIN_W*WIN_H];
static ui64 timer_frequency;
static ui64 timer_start;
static bool kdown[256],kprsd[256];
static float R[9];
static float T[3];
static float L[3];
static char model_name[8192];
static bool loaded;
static bool quit;
static bool show_help;
static float time_transform,time_triangles,time_rasterize;
static si32 pixels_touched,pixels_total,pixels_visible;
struct Model
{
vector<array<float,4> > orig_vertices;
vector<array<float,3> > orig_texcoords;
vector<array<float,3> > orig_normals;
vector<vector<array<si32,3> > > faces;
vector<float> vertices;
vector<float> normals;
vector<float> vnormals;
vector<float> fnormals;
vector<float> texcoords;
vector<si32> triangles;
float center[3];
float extents[3];
void clear();
bool load(const char *filename);
};
struct TriInfo
{
// [x/w,y/w,z/w,1/w]
ALIGNED(16) float v[3][4];
// Subpixel screen coordinates. [0..2] are vertices, [3] is pixel center of (x_min,x_max).
ALIGNED(16) si32 ix[4],iy[4];
// Barycentric coordinates at (cx,cy), and area: d[3]=d[0]+d[1]+d[2].
ALIGNED(16) si32 d[4];
// Increments. [3]=0.
ALIGNED(16) si32 ddx[4];
ALIGNED(16) si32 ddy[4];
// Bounding box.
si32 x_min,x_max;
si32 y_min,y_max;
// Inverse area.
float w;
// Biases, to incorporate fill rules.
ui8 b[3];
};
static Model model;
static ui64 load_time;
static vector<float> transformed;
static vector<TriInfo> tris;
//==============================================================================
template<typename T>
static inline T load(const void *p)
{
T ret;
memmove(&ret,p,sizeof(ret));
return ret;
}
template<typename T>
static inline void store(const T &value,void *p)
{
memmove(p,&value,sizeof(value));
}
template<typename T,typename S>
static inline T bitcast(const S &value)
{
static_assert(sizeof(T)==sizeof(S),"Size mismatch!");
T ret;
memcpy(&ret,&value,sizeof(ret));
return ret;
}
//==============================================================================
// Embedded from: http://font.gohu.org/
unsigned char font[128][11]=
{
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00},
{0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00,0x00,0x00},
{0x00,0x20,0x70,0xA8,0xA0,0x70,0x28,0xA8,0x70,0x20,0x00},
{0x00,0x00,0x48,0xA8,0x50,0x20,0x50,0xA8,0x90,0x00,0x00},
{0x00,0x00,0x60,0x90,0xA0,0x40,0xA8,0x90,0x68,0x00,0x00},
{0x00,0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x10,0x20,0x20,0x40,0x40,0x40,0x20,0x20,0x10,0x00},
{0x00,0x40,0x20,0x20,0x10,0x10,0x10,0x20,0x20,0x40,0x00},
{0x00,0x00,0x00,0x20,0xA8,0x70,0xA8,0x20,0x00,0x00,0x00},
{0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x20,0x40},
{0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00},
{0x00,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80},
{0x00,0x00,0x70,0x88,0x98,0xA8,0xC8,0x88,0x70,0x00,0x00},
{0x00,0x00,0x20,0x60,0xA0,0x20,0x20,0x20,0x20,0x00,0x00},
{0x00,0x00,0x70,0x88,0x08,0x10,0x20,0x40,0xF8,0x00,0x00},
{0x00,0x00,0x70,0x88,0x08,0x30,0x08,0x88,0x70,0x00,0x00},
{0x00,0x00,0x10,0x30,0x50,0x90,0xF8,0x10,0x10,0x00,0x00},
{0x00,0x00,0xF8,0x80,0xF0,0x08,0x08,0x88,0x70,0x00,0x00},
{0x00,0x00,0x70,0x80,0xF0,0x88,0x88,0x88,0x70,0x00,0x00},
{0x00,0x00,0xF8,0x08,0x10,0x10,0x20,0x20,0x20,0x00,0x00},
{0x00,0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00,0x00},
{0x00,0x00,0x70,0x88,0x88,0x78,0x08,0x08,0x70,0x00,0x00},
{0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x00,0x00},
{0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x20,0x40},
{0x00,0x00,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00,0x00},
{0x00,0x00,0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00,0x00},
{0x00,0x00,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00,0x00},
{0x00,0x00,0x70,0x88,0x08,0x10,0x20,0x00,0x20,0x00,0x00},
{0x00,0x00,0x70,0x88,0xB8,0xA8,0xB8,0x80,0x78,0x00,0x00},
{0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x88,0x00,0x00},
{0x00,0xF0,0x88,0x88,0xF0,0x88,0x88,0x88,0xF0,0x00,0x00},
{0x00,0x70,0x88,0x80,0x80,0x80,0x80,0x88,0x70,0x00,0x00},
{0x00,0xF0,0x88,0x88,0x88,0x88,0x88,0x88,0xF0,0x00,0x00},
{0x00,0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0xF8,0x00,0x00},
{0x00,0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x80,0x00,0x00},
{0x00,0x70,0x88,0x80,0xB8,0x88,0x88,0x88,0x70,0x00,0x00},
{0x00,0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x88,0x00,0x00},
{0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00},
{0x00,0x08,0x08,0x08,0x08,0x08,0x88,0x88,0x70,0x00,0x00},
{0x00,0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x88,0x00,0x00},
{0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00,0x00},
{0x00,0x88,0xD8,0xA8,0xA8,0x88,0x88,0x88,0x88,0x00,0x00},
{0x00,0x88,0xC8,0xC8,0xA8,0xA8,0x98,0x98,0x88,0x00,0x00},
{0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00},
{0x00,0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x80,0x00,0x00},
{0x00,0x70,0x88,0x88,0x88,0x88,0xA8,0x90,0x68,0x08,0x00},
{0x00,0xF0,0x88,0x88,0xF0,0x90,0x88,0x88,0x88,0x00,0x00},
{0x00,0x70,0x88,0x80,0x70,0x08,0x08,0x88,0x70,0x00,0x00},
{0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00},
{0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00},
{0x00,0x88,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00,0x00},
{0x00,0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x50,0x00,0x00},
{0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x88,0x00,0x00},
{0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x20,0x00,0x00},
{0x00,0xF8,0x08,0x10,0x20,0x40,0x80,0x80,0xF8,0x00,0x00},
{0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00},
{0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04},
{0x00,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xE0,0x00},
{0x00,0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x00},
{0x00,0x40,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x70,0x08,0x78,0x88,0x78,0x00,0x00},
{0x00,0x80,0x80,0x80,0xB0,0xC8,0x88,0x88,0xF0,0x00,0x00},
{0x00,0x00,0x00,0x00,0x78,0x80,0x80,0x80,0x78,0x00,0x00},
{0x00,0x08,0x08,0x08,0x78,0x88,0x88,0x98,0x68,0x00,0x00},
{0x00,0x00,0x00,0x00,0x70,0x88,0xF8,0x80,0x78,0x00,0x00},
{0x00,0x30,0x40,0x40,0x70,0x40,0x40,0x40,0x40,0x00,0x00},
{0x00,0x00,0x00,0x00,0x78,0x88,0x88,0x98,0x68,0x08,0x70},
{0x00,0x80,0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x00,0x00},
{0x00,0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x30,0x00,0x00},
{0x00,0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0xC0},
{0x00,0x80,0x80,0x80,0x90,0xA0,0xE0,0x90,0x88,0x00,0x00},
{0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x18,0x00,0x00},
{0x00,0x00,0x00,0x00,0xF0,0xA8,0xA8,0xA8,0xA8,0x00,0x00},
{0x00,0x00,0x00,0x00,0xF0,0x88,0x88,0x88,0x88,0x00,0x00},
{0x00,0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00,0x00},
{0x00,0x00,0x00,0x00,0xB0,0xC8,0x88,0x88,0xF0,0x80,0x80},
{0x00,0x00,0x00,0x00,0x78,0x88,0x88,0x98,0x68,0x08,0x08},
{0x00,0x00,0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x00,0x00},
{0x00,0x00,0x00,0x00,0x70,0x80,0x70,0x08,0xF0,0x00,0x00},
{0x00,0x40,0x40,0x40,0xF0,0x40,0x40,0x40,0x30,0x00,0x00},
{0x00,0x00,0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00,0x00},
{0x00,0x00,0x00,0x00,0x88,0x88,0x50,0x50,0x20,0x00,0x00},
{0x00,0x00,0x00,0x00,0x88,0xA8,0xA8,0xA8,0x50,0x00,0x00},
{0x00,0x00,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00,0x00},
{0x00,0x00,0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x08,0x70},
{0x00,0x00,0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00,0x00},
{0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18},
{0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00},
{0xC0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xC0},
{0x00,0x00,0x00,0x00,0x40,0xA8,0x10,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
};
//==============================================================================
static inline void set_pixel(si32 w,si32 h,si32 stride_in_bytes,ui8 *buffer,si32 x,si32 y,ui32 color)
{
if(x<0||x>=w||y<0||y>=h) return;
store(color,buffer+(y*stride_in_bytes+x*4));
}
static inline void print_char(si32 w,si32 h,si32 stride_in_bytes,ui8 *buffer,si32 x,si32 y,ui32 color,char c)
{
if(unsigned(c)<128)
{
for(si32 dy=0;dy<11;++dy)
for(si32 dx=0;dx<8;++dx)
if((font[unsigned(c)][10-dy]>>(7-dx))&1)
set_pixel(w,h,stride_in_bytes,buffer,x+dx,y+dy,color);
}
}
static inline void print_text_args(si32 w,si32 h,si32 stride_in_bytes,ui8 *buffer,si32 x,si32 y,ui32 color,const char *fmt,const va_list &args)
{
static const si32 N=4096;
char text[N];
std::vsnprintf(text,ui32(N),fmt,args);
text[N-1]=0;
for(si32 i=0;text[i];++i)
print_char(w,h,stride_in_bytes,buffer,x+6*i,y,color,text[i]);
}
static inline void print_text(si32 w,si32 h,si32 stride_in_bytes,ui8 *buffer,si32 x,si32 y,ui32 color,const char *fmt,...)
{
va_list args;
va_start(args,fmt);
print_text_args(w,h,stride_in_bytes,buffer,x,y,color,fmt,args);
va_end(args);
}
static inline void set_pixel_screen(si32 x,si32 y,ui32 color)
{
set_pixel(WIN_W,WIN_H,WIN_W*4,window_buffer,x,y,color);
}
static inline void print_text_screen(si32 x,si32 y,ui32 color,const char *fmt,...)
{
va_list args;
va_start(args,fmt);
print_text_args(WIN_W,WIN_H,WIN_W*4,window_buffer,x,y,color,fmt,args);
va_end(args);
}
//==============================================================================
static inline ui64 get_time()
{
LARGE_INTEGER t;
QueryPerformanceCounter(&t);
return ui64(t.QuadPart);
}
//==============================================================================
// out=m*v, m is row-major.
static inline void mul_mat_vec(const float *m,const float *v,float *out)
{
float ret[4];
for(int i=0;i<4;++i)
ret[i]=m[4*i+0]*v[0]+
m[4*i+1]*v[1]+
m[4*i+2]*v[2]+
m[4*i+3]*v[3];
for(int i=0;i<4;++i)
out[i]=ret[i];
}
static inline float length_vec(const float *v)
{
return std::sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
}
static inline void normalize_vec(const float *src,float *dst)
{
float x=src[0],y=src[1],z=src[2];
float d=std::sqrt(x*x+y*y+z*z);
d=1.0f/d;
dst[0]=x*d;
dst[1]=y*d;
dst[2]=z*d;
}
// out=l*r, l and r are row-major.
static void mul_mat_mat(const float *l,const float *r,float *out)
{
float ret[16];
for(int i=0;i<4;++i)
for(int j=0;j<4;++j)
ret[4*i+j]=l[4*i+0]*r[4*0+j]+
l[4*i+1]*r[4*1+j]+
l[4*i+2]*r[4*2+j]+
l[4*i+3]*r[4*3+j];
for(int i=0;i<16;++i)
out[i]=ret[i];
}
// Like glLoadIdentity, except... erm, whatever.
static inline void mat_identity(float *out)
{
for(int i=0;i<16;++i) out[i]=float(i%5==0);
}
// Like glTranslate, except row-major.
static inline void mat_translate(float x,float y,float z,float *out)
{
mat_identity(out);
out[ 3]=x;
out[ 7]=y;
out[11]=z;
}
// Like glRotate, except angle in radians, and row-major.
static inline void mat_rotate(float a,float x,float y,float z,float *out)
{
float c=std::cos(a);
float s=std::sin(a);
float b=1.0f-c;
out[ 0]=x*x*b+c; out[ 1]=x*y*b-z*s;out[ 2]=x*z*b+y*s;out[ 3]=0.0f;
out[ 4]=y*x*b+z*s;out[ 5]=y*y*b+c; out[ 6]=y*z*b-x*s;out[ 7]=0.0f;
out[ 8]=z*x*b-y*s;out[ 9]=z*y*b+x*s;out[10]=z*z*b+c; out[11]=0.0f;
out[12]=0.0f; out[13]=0.0f; out[14]=0.0f; out[15]=1.0f;
}
// Like glFrustum, except row-major.
static inline void mat_frustum(float l,float r,float b,float t,float n,float f,float *out)
{
out[ 0]= (n+n)/(r-l);out[ 1]= 0.0f; out[ 2]= (r+l)/(r-l);out[ 3]= 0.0f;
out[ 4]= 0.0f; out[ 5]= (n+n)/(t-b);out[ 6]= (t+b)/(t-b);out[ 7]= 0.0f;
out[ 8]= 0.0f; out[ 9]= 0.0f; out[10]=-(f+n)/(f-n);out[11]=-2.0f*f*n/(f-n);
out[12]= 0.0f; out[13]= 0.0f; out[14]=-1.0f; out[15]= 0.0f;
}
static inline void mat_view(float w,float h,float *out)
{
for(int i=0;i<16;++i) out[i]=0.0f;
out[ 0]=0.5f*w;out[ 3]=0.5f*w;
out[ 5]=0.5f*h;out[ 7]=0.5f*h;
out[10]=1.0f;
out[15]=1.0f;
}
//==============================================================================
void Model::clear()
{
orig_vertices.clear();
orig_vertices.push_back({0.0f,0.0f,0.0f,0.0f});
orig_texcoords.clear();
orig_texcoords.push_back({0.0f,0.0f,0.0f});
orig_normals.clear();
orig_normals.push_back({0.0f,0.0f,0.0f});
faces.clear();
vertices.clear();
texcoords.clear();
normals.clear();
vnormals.clear();
fnormals.clear();
triangles.clear();
center[0]=0.0f;center[1]=0.0f;center[2]=0.0f;
extents[0]=0.0f;extents[1]=0.0f;extents[2]=0.0f;
}
bool Model::load(const char *filename)
{
auto read_si32=[](const char *&cur,bool &e)->si32
{
long ret=0;
while(!(*cur>='0'&&*cur<='9')&&*cur) ++cur;
const char *c=cur;
while(*cur>='0'&&*cur<='9') ++cur;
if(sscanf(c,"%ld",&ret)<1) e=true;
return si32(ret);
};
bool ret=false;
char line[8192]; // Laaaame.
char s[sizeof(line)];
size_t id=0;
map<array<si32,3>,size_t> q;
ui64 t=get_time();
clear();
FILE *f=fopen(filename,"rb");
if(!f) goto fail;
while(!feof(f))
{
if(!fgets(line,int(sizeof(line)),f)) break;
if(sscanf(line,"%s",s)<1) continue;
if(s[0]=='#') continue;
if(s[0]=='v'&&s[1]=='\0')
{
array<float,4> v;
int n=sscanf(line,"v %g%g%g%g",v.data()+0,v.data()+1,v.data()+2,v.data()+3);
for(unsigned i=unsigned(n);i<4;++i) v[i]=float(i==3);
v[3]=1.0f;
orig_vertices.push_back(v);
}
if(s[0]=='v'&&s[1]=='n')
{
array<float,3> v;
int n=sscanf(line,"vn %g%g%g",v.data()+0,v.data()+1,v.data()+2);
for(unsigned i=unsigned(n);i<3;++i) v[i]=0.0f;
orig_normals.push_back(v);
}
if(s[0]=='v'&&s[1]=='t')
{
array<float,3> v;
int n=sscanf(line,"vt %g%g%g",v.data()+0,v.data()+1,v.data()+2);
for(unsigned i=unsigned(n);i<3;++i) v[i]=float(i==2);
orig_texcoords.push_back(v);
}
if(s[0]=='f')
{
const char *c=line;
faces.push_back(vector<array<si32,3> >());
while(*c)
{
bool e=false;
si32 v=0,vt=0,vn=0;
v=read_si32(c,e);
if(c[0]=='/')
{
if(c[1]=='/') vn=read_si32(c,e);
else
{
vt=read_si32(c,e);
if(c[0]=='/') vn=read_si32(c,e);
}
}
if(e) break;
if(v<0) v+=si32(orig_vertices.size());
if(vt<0) vt+=si32(orig_texcoords.size());
if(vn<0) vn+=si32(orig_normals.size());
faces.back().push_back({v,vt,vn});
}
}
}
for(const auto &f:faces)
for(const auto &c:f)
q[c]=0;
for(auto &c:q)
{
c.second=id++;
size_t vc=size_t(c.first[0]);
size_t vt=size_t(c.first[1]);
size_t vn=size_t(c.first[2]);
if(vc>=orig_vertices.size()||vt>=orig_texcoords.size()||vn>=orig_normals.size())
continue;
for(unsigned i=0;i<4;++i) vertices.push_back(orig_vertices[vc][i]);
for(unsigned i=0;i<2;++i) texcoords.push_back(orig_texcoords[vt][i]);
for(unsigned i=0;i<3;++i) normals.push_back(orig_normals[vn][i]);
}
vnormals.resize(3*q.size(),0.0f);
for(const auto &f:faces)
{
size_t n=f.size();
size_t i0=q.find(f[0])->second;
for(size_t i=1;i+1<n;++i)
{
size_t ii=q.find(f[i])->second;
size_t ij=q.find(f[i+1])->second;
triangles.push_back(si32(i0));
triangles.push_back(si32(ii));
triangles.push_back(si32(ij));
float w0=vertices[i0*4+3];
float w1=vertices[ii*4+3];
float w2=vertices[ij*4+3];
float x0=vertices[i0*4+0]/w0;
float x1=vertices[ii*4+0]/w1;
float x2=vertices[ij*4+0]/w2;
float y0=vertices[i0*4+1]/w0;
float y1=vertices[ii*4+1]/w1;
float y2=vertices[ij*4+1]/w2;
float z0=vertices[i0*4+2]/w0;
float z1=vertices[ii*4+2]/w1;
float z2=vertices[ij*4+2]/w2;
float nx=(y1-y0)*(z2-z0)-(z1-z0)*(y2-y0);
float ny=(z1-z0)*(x2-x0)-(x1-x0)*(z2-z0);
float nz=(x1-x0)*(y2-y0)-(y1-y0)*(x2-x0);
vnormals[i0*3+0]+=nx;
vnormals[i0*3+1]+=ny;
vnormals[i0*3+2]+=nz;
vnormals[ii*3+0]+=nx;
vnormals[ii*3+1]+=ny;
vnormals[ii*3+2]+=nz;
vnormals[ij*3+0]+=nx;
vnormals[ij*3+1]+=ny;
vnormals[ij*3+2]+=nz;
float dn=std::sqrt(nx*nx+ny*ny+nz*nz);
fnormals.push_back(nx/dn);
fnormals.push_back(ny/dn);
fnormals.push_back(nz/dn);
}
}
for(size_t i=0;i<q.size();++i)
{
float *v=vnormals.data()+3*i;
normalize_vec(v,v);
float *c=normals.data()+3*i;
float d=length_vec(c);
if(d==0.0f)
{
c[0]=v[0];
c[1]=v[1];
c[2]=v[2];
}
else
{
c[0]/=d;
c[1]/=d;
c[2]/=d;
}
}
if(!orig_vertices.empty())
{
float c[3][2];
for(size_t i=1;i<orig_vertices.size();++i)
for(size_t j=0;j<3;++j)
{
float t=orig_vertices[i][j]/orig_vertices[i][3];
if(i==1||t<c[j][0]) c[j][0]=t;
if(i==1||t>c[j][1]) c[j][1]=t;
}
for(size_t i=0;i<3;++i)
{
center[i]=(c[i][1]+c[i][0])/2.0f;
extents[i]=(c[i][1]-c[i][0])/2.0f;
}
}
ret=true;
fail:;
fclose(f);
transformed.resize(vertices.size());
tris.resize(triangles.size()/3);
for(si32 i=0;i<9;++i) R[i]=float(i%4==0);
for(si32 i=0;i<3;++i) T[i]=center[i];
T[2]+=2.0f*length_vec(extents);
L[0]=0.0f;L[1]=0.0f;L[2]=1.0f;
t=get_time()-t;
loaded=true;
load_time=t;
return ret;
}
//==============================================================================
static void init()
{
LARGE_INTEGER t;
QueryPerformanceCounter(&t);
timer_start=ui64(t.QuadPart);
QueryPerformanceFrequency(&t);
timer_frequency=ui64(t.QuadPart);
model.load(model_name);
}
//==============================================================================
static void triangle_setup_ref(
const float *v0,
const float *v1,
const float *v2,
TriInfo &tri)
{
// Early-out on vertices behind camera.
// If we had a proper clipping, this would not be necessary.
if((bitcast<si32>(v0[3])|bitcast<si32>(v1[3])|bitcast<si32>(v2[3]))<0)
{
tri.d[3]=-1;
return;
}
memcpy(tri.v[0],v0,sizeof(tri.v[0]));
memcpy(tri.v[1],v1,sizeof(tri.v[1]));
memcpy(tri.v[2],v2,sizeof(tri.v[2]));
for(si32 i=0;i<3;++i)
tri.v[i][3]=1.0f/tri.v[i][3];
for(si32 i=0;i<3;++i)
for(si32 j=0;j<3;++j)
tri.v[i][j]*=tri.v[i][3];
// Integer vertex coordinates (in 1/16th of pixel).
for(si32 i=0;i<3;++i)
{
tri.ix[i]=si32(16.0f*tri.v[i][0]);
tri.iy[i]=si32(16.0f*tri.v[i][1]);
}
// Early-out on non-positive area.
// No pixels would be covered anyway.
// If we needed 2-sided rendering, we would need to do something else.
if(-(tri.iy[2]-tri.iy[1])*(tri.ix[0]-tri.ix[1])+(tri.ix[2]-tri.ix[1])*(tri.iy[0]-tri.iy[1])<=0)
{
tri.d[3]=-1;
return;
}
// Bounding box.
tri.x_min=tri.ix[0];tri.x_max=tri.ix[0];
tri.y_min=tri.iy[0];tri.y_max=tri.iy[0];
if(tri.ix[1]<tri.x_min) tri.x_min=tri.ix[1];
if(tri.iy[1]<tri.y_min) tri.y_min=tri.iy[1];
if(tri.ix[2]<tri.x_min) tri.x_min=tri.ix[2];
if(tri.iy[2]<tri.y_min) tri.y_min=tri.iy[2];
if(tri.x_max<tri.ix[1]) tri.x_max=tri.ix[1];
if(tri.y_max<tri.iy[1]) tri.y_max=tri.iy[1];
if(tri.x_max<tri.ix[2]) tri.x_max=tri.ix[2];
if(tri.y_max<tri.iy[2]) tri.y_max=tri.iy[2];
tri.x_min>>=4;
tri.y_min>>=4;
tri.x_max>>=4;
tri.y_max>>=4;
tri.x_max+=1;
tri.y_max+=1;
if(tri.x_min<0) tri.x_min=0;
if(tri.y_min<0) tri.y_min=0;
//if(x_max>width) x_max=width;
//if(y_max>height) y_max=height;
// Pixel center of pixel (x_min,y_min).
tri.ix[3]=tri.x_min*16+8;
tri.iy[3]=tri.y_min*16+8;
// Barycentric coordinates.
for(si32 i=0;i<3;++i)
{
si32 j=(i+1)%3;
si32 k=(i+2)%3;
tri.d[i]=-(tri.iy[k]-tri.iy[j])*(tri.ix[3]-tri.ix[j])+(tri.ix[k]-tri.ix[j])*(tri.iy[3]-tri.iy[j]);
}
tri.d[3]=tri.d[0]+tri.d[1]+tri.d[2];
tri.w=1.0f/float(tri.d[3]);
// Biases, to incorporate fill rules.
for(si32 i=0;i<3;++i)
{
si32 j=(i+1)%3;
si32 k=(i+2)%3;
si32 b=1-si32((tri.iy[j]==tri.iy[k]&&tri.ix[k]<tri.ix[j])||(tri.iy[k]<tri.iy[j]));
tri.b[i]=ui8(b);
tri.d[i]-=b;
}
// Increments.
for(si32 i=0;i<3;++i)
{
si32 j=(i+1)%3;
si32 k=(i+2)%3;
tri.ddx[i]=-(tri.iy[k]-tri.iy[j])*16;
tri.ddy[i]=+(tri.ix[k]-tri.ix[j])*16;
}
}
static void CODE_SSE2 triangle_setup_sse2(
const float *v0,
const float *v1,
const float *v2,
TriInfo &tri)
{
ALIGNED(16) float w[4];
simd4f W=simd4f{1.0f,1.0f,1.0f,1.0f}/simd4f{v0[3],v1[3],v2[3],1.0f};
store4f(W,w);
store4f(load4f(v0)*w[0],tri.v[0]);
store4f(load4f(v1)*w[1],tri.v[1]);
store4f(load4f(v2)*w[2],tri.v[2]);
tri.v[0][3]=w[0];
tri.v[1][3]=w[1];
tri.v[2][3]=w[2];
// Integer vertex coordinates (in 1/16th of pixel).
simd4f X=simd4f{tri.v[0][0],tri.v[1][0],tri.v[2][0],0.0f};
simd4f Y=simd4f{tri.v[0][1],tri.v[1][1],tri.v[2][1],0.0f};
simd4i IX=cvt4fi(16.0f*X);
simd4i IY=cvt4fi(16.0f*Y);
store4i(IX,tri.ix);
store4i(IY,tri.iy);
// Bounding box.
ALIGNED(16) si32 m[4];
simd4i M=simd4i{tri.ix[0],~tri.ix[0],tri.iy[0],~tri.iy[0]};
M=min4i(M,simd4i{tri.ix[1],~tri.ix[1],tri.iy[1],~tri.iy[1]});
M=min4i(M,simd4i{tri.ix[2],~tri.ix[2],tri.iy[2],~tri.iy[2]});
M^=simd4i{0,-1,0,-1};
M=max4i(M,simd4i{0,-1,0,-1});
M>>=4;
M+=simd4i{0,2,0,2};
M&=simd4i{-2,-2,-2,-2};
store4i(M,m);
tri.x_min=m[0];tri.x_max=m[1];
tri.y_min=m[2];tri.y_max=m[3];
// Pixel center of pixel (x_min,y_min).
tri.ix[3]=tri.x_min*16+8;
tri.iy[3]=tri.y_min*16+8;
simd4i JX=shuffle4i<1,2,0,3>(IX),KX=shuffle4i<2,0,1,3>(IX);
simd4i JY=shuffle4i<1,2,0,3>(IY),KY=shuffle4i<2,0,1,3>(IY);
store4i(-(KY-JY)*(fill4i(tri.ix[3])-JX)+(KX-JX)*(fill4i(tri.iy[3])-JY),tri.d);
tri.d[3]=tri.d[0]+tri.d[1]+tri.d[2];
tri.w=1.0f/float(tri.d[3]);
ALIGNED(4) si32 b[4];
simd4i B=fill4i(1)+(((JY==KY)&(KX<JX))|(KY<JY));
store4i(B,b);
// Biases, to incorporate fill rules.
for(si32 i=0;i<3;++i)
{
tri.b[i]=ui8(b[i]);
tri.d[i]-=b[i];
}
ALIGNED(16) si32 dx[4],dy[4];
simd4i DX=-((KY-JY)<<4);
simd4i DY=+((KX-JX)<<4);
store4i(DX,dx);
store4i(DY,dy);
// Increments.
for(si32 i=0;i<3;++i)
{
tri.ddx[i]=dx[i];
tri.ddy[i]=dy[i];
}
}
static void setup_triangles_ref(si32 n,const si32 *id,const float *v,TriInfo *tris)
{
for(si32 i=0;i<n;++i)
triangle_setup_ref(
v+4*id[3*i+0],
v+4*id[3*i+1],
v+4*id[3*i+2],
tris[i]);
}
static void CODE_SSE2 setup_triangles_sse2(si32 n,const si32 *id,const float *v,TriInfo *tris)
{
for(si32 i=0;i<n;++i)
triangle_setup_sse2(
v+4*id[3*i+0],
v+4*id[3*i+1],
v+4*id[3*i+2],
tris[i]);
}
//==============================================================================
// Straightforward templated half-space triangle rasterizer.
// Rasterizes the triangle and invokes f(x,y,w0,w1,w2) for every
// covered pixel, where w0,w1,w2 are normalized barycentric
// coordinates (so that w0+w1+w2=1).
// Cartesian coordinate system (x - right, y - up) is assumed.
// Clockwise triangles are discarded.
// Sampling is at pixel centers.
// Rasterization honors the fill rules.
// Max surface size: 0<=w,h<2048.
// Subpixel precision: 4 bits (1/16th of pixel).
// Cf. https://fgiesen.wordpress.com/2013/02/08/triangle-rasterization-in-practice/
// for the algorithm's description.
template<typename F>
static inline void render_triangle(
const TriInfo &tri,
si32 width,si32 height,
const F &f)
{
// Bounding box.
si32 x_min=tri.x_min,x_max=tri.x_max;
si32 y_min=tri.y_min,y_max=tri.y_max;
if(x_max>width) x_max=width;
if(y_max>height) y_max=height;
// Barycentric coordinates.
si32 d0=tri.d[0];
si32 d1=tri.d[1];
si32 d2=tri.d[2];
float w=tri.w;
// Biases, to incorporate fill rules.
si32 b0=tri.b[0];
si32 b1=tri.b[1];
si32 b2=tri.b[2];
// Increments.
si32 dd0dx=tri.ddx[0];
si32 dd1dx=tri.ddx[1];
si32 dd2dx=tri.ddx[2];
si32 dd0dy=tri.ddy[0];
si32 dd1dy=tri.ddy[1];
si32 dd2dy=tri.ddy[2];
// Process pixels in bounding box.
for(si32 y=y_min;y<y_max;++y)
{
si32 d0x=d0;
si32 d1x=d1;
si32 d2x=d2;
for(si32 x=x_min;x<x_max;++x)
{
if((d0x|d1x|d2x)>=0)
{
float w0=float(d0x+b0)*w;
float w1=float(d1x+b1)*w;
float w2=float(d2x+b2)*w;
f(x,y,w0,w1,w2);
}
d0x+=dd0dx;
d1x+=dd1dx;
d2x+=dd2dx;
}
d0+=dd0dy;
d1+=dd1dy;
d2+=dd2dy;
}
}
// SIMD version of the above, working on 2x2 pixel quads.
template<typename F>
static inline CODE_SSE2 void render_triangle_2x2_sse2(
const TriInfo &tri,
si32 width,si32 height,
const F &f)
{
si32 x_min=tri.x_min,x_max=tri.x_max;
si32 y_min=tri.y_min,y_max=tri.y_max;
width&=-2;
height&=-2;
if(x_max>width) x_max=width;
if(y_max>height) y_max=height;
// Barycentric coordinates.
si32 d0=tri.d[0];
si32 d1=tri.d[1];
si32 d2=tri.d[2];
float w=tri.w;
// Biases, to incorporate fill rules.
si32 b0=tri.b[0];
si32 b1=tri.b[1];
si32 b2=tri.b[2];
// Increments.
si32 dd0dx=tri.ddx[0];
si32 dd1dx=tri.ddx[1];
si32 dd2dx=tri.ddx[2];
si32 dd0dy=tri.ddy[0];
si32 dd1dy=tri.ddy[1];
si32 dd2dy=tri.ddy[2];
simd4i D0{d0,d0+dd0dx,d0+dd0dy,d0+dd0dx+dd0dy};
simd4i D1{d1,d1+dd1dx,d1+dd1dy,d1+dd1dx+dd1dy};
simd4i D2{d2,d2+dd2dx,d2+dd2dy,d2+dd2dx+dd2dy};
simd4i DD0DX=simd4i{2,2,2,2}*dd0dx;
simd4i DD0DY=simd4i{2,2,2,2}*dd0dy;
simd4i DD1DX=simd4i{2,2,2,2}*dd1dx;
simd4i DD1DY=simd4i{2,2,2,2}*dd1dy;
simd4i DD2DX=simd4i{2,2,2,2}*dd2dx;
simd4i DD2DY=simd4i{2,2,2,2}*dd2dy;
// Process pixels in bounding box.
for(int32_t y=y_min;y<y_max;y+=2)
{
simd4i D0X=D0;
simd4i D1X=D1;
simd4i D2X=D2;
for(int32_t x=x_min;x<x_max;x+=2)
{
simd4i M=D0X|D1X|D2X;
si32 S=signs4i(M);
if(S<15)
{
simd4f W0=cvt4if(D0X+b0)*w;
simd4f W1=cvt4if(D1X+b1)*w;
simd4f W2=cvt4if(D2X+b2)*w;
f(x,y,W0,W1,W2,M);
}
D0X+=DD0DX;
D1X+=DD1DX;
D2X+=DD2DX;
}
D0+=DD0DY;
D1+=DD1DY;
D2+=DD2DY;
}
}
//==============================================================================
static void transform_vertices_ref(si32 n,const float *M,const float *src,float *dst)
{
for(si32 i=0;i<n;++i)
mul_mat_vec(M,src+i*4,dst+i*4);
}
static void CODE_SSE2 transform_vertices_sse2(si32 n,const float *M,const float *src,float *dst)
{
simd4f m0{M[ 0],M[ 4],M[ 8],M[12]};
simd4f m1{M[ 1],M[ 5],M[ 9],M[13]};
simd4f m2{M[ 2],M[ 6],M[10],M[14]};
simd4f m3{M[ 3],M[ 7],M[11],M[15]};
for(si32 i=0;i<n;++i)
{
const float *s=src+4*i;
simd4f v=s[0]*m0+s[1]*m1+s[2]*m2+s[3]*m3;
store4f(v,dst+4*i);
}
}
static void render_triangles_ref(const float *L)
{
pixels_touched=0;
pixels_total=0;
pixels_visible=0;
size_t m=model.triangles.size()/3;
TriInfo tri;
const float *dst=transformed.data();
for(size_t i=0;i<m;++i)
{
triangle_setup_ref(
dst+4*model.triangles[3*i+0],
dst+4*model.triangles[3*i+1],
dst+4*model.triangles[3*i+2],
tri);
if(tri.d[3]<=0) continue;
float q0=tri.v[0][3];
float q1=tri.v[1][3];
float q2=tri.v[2][3];
if((bitcast<si32>(q0)|bitcast<si32>(q1)|bitcast<si32>(q2))<0) continue;
const float *C0=model.normals.data()+3*model.triangles[3*i+0];
const float *C1=model.normals.data()+3*model.triangles[3*i+1];
const float *C2=model.normals.data()+3*model.triangles[3*i+2];
render_triangle(
tri,
WIN_W,WIN_H,[&](si32 x,si32 y,float w0,float w1,float w2)->void
{
si32 id=y*WIN_W+x;
float q=q0*w0+q1*w1+q2*w2;
++pixels_total;
if(q>load<float>(depth_buffer+id))
{
++pixels_visible;
float inv_q=1.0f/q;
float v0=w0*inv_q;
float v1=w1*inv_q;
float v2=w2*inv_q;
float nx=C0[0]*v0+C1[0]*v1+C2[0]*v2;
float ny=C0[1]*v0+C1[1]*v1+C2[1]*v2;
float nz=C0[2]*v0+C1[2]*v1+C2[2]*v2;
float d=std::sqrt(nx*nx+ny*ny+nz*nz);
float inv_d=1.0f/d;
nx*=inv_d;
ny*=inv_d;
nz*=inv_d;
float c=L[0]*nx+L[1]*ny+L[2]*nz;
if(!(c>0.0f)) c=0.0f;
if(c>1.0f) c=1.0f;
ui32 color=ui32(int(230.0f*c+25.5f));
color*=0x00010101ul;
color|=0xFF000000ul;
store(q,depth_buffer+id);
store(color,window_buffer+4*id);
}
});
}
pixels_touched=pixels_total;
}
static void CODE_SSE2 render_triangles_sse2(const float *L)
{
si32 mask_count[16]={0};
for(int i=0;i<16;++i) for(int j=0;j<4;++j) mask_count[i]+=!((i>>j)&1);
pixels_touched=0;
pixels_total=0;
pixels_visible=0;
size_t m=model.triangles.size()/3;
TriInfo tri;
const float *dst=transformed.data();
for(size_t i=0;i<m;++i)
{
triangle_setup_sse2(
dst+4*model.triangles[3*i+0],
dst+4*model.triangles[3*i+1],
dst+4*model.triangles[3*i+2],
tri);
if(tri.d[3]<=0) continue;
float q0=tri.v[0][3];
float q1=tri.v[1][3];
float q2=tri.v[2][3];
if((bitcast<si32>(q0)|bitcast<si32>(q1)|bitcast<si32>(q2))<0) continue;
const float *C0=model.normals.data()+3*model.triangles[3*i+0];
const float *C1=model.normals.data()+3*model.triangles[3*i+1];
const float *C2=model.normals.data()+3*model.triangles[3*i+2];
render_triangle_2x2_sse2(
tri,
WIN_W,WIN_H,[&](si32 x,si32 y,simd4f w0,simd4f w1,simd4f w2,simd4i M) CODE_SSE2 ->void
{
si32 id=y*WIN_W+x;
simd4f q=q0*w0+q1*w1+q2*w2;
simd4f depth=(simd4f)load2x64(depth_buffer+id,depth_buffer+WIN_W+id);
pixels_touched+=4;
pixels_total+=mask_count[signs4i(M)];
M=M|(q<depth);
if(signs4i(M)<15)
{
M=(M<simd4i{0,0,0,0});
pixels_visible+=mask_count[signs4i(M)];
simd4f inv_q=rcp4f(q);
simd4f v0=w0*inv_q;
simd4f v1=w1*inv_q;
simd4f v2=w2*inv_q;
simd4f nx=C0[0]*v0+C1[0]*v1+C2[0]*v2;
simd4f ny=C0[1]*v0+C1[1]*v1+C2[1]*v2;
simd4f nz=C0[2]*v0+C1[2]*v1+C2[2]*v2;
simd4f inv_d=rsqrt4f(nx*nx+ny*ny+nz*nz);
nx*=inv_d;
ny*=inv_d;
nz*=inv_d;
simd4f c=L[0]*nx+L[1]*ny+L[2]*nz;
c=min4f(max4f(c,simd4f{0.0f,0.0f,0.0f,0.0f}),simd4f{1.0f,1.0f,1.0f,1.0f});
simd4i color=cvt4fi(230.0f*c+25.5f);
color*=0x00010101;
color|=0xFF000000;
switch(signs4i(M))
{
case 0:
store2x64((simd4i)q,depth_buffer+id,depth_buffer+WIN_W+id);
store2x64(color,window_buffer+4*id,window_buffer+4*WIN_W+4*id);
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
q=(simd4f)(((simd4i)depth&M)|((simd4i)q&~M));
color=(load2x64(window_buffer+4*id,window_buffer+4*WIN_W+4*id)&M)|(color&~M);
store2x64((simd4i)q,depth_buffer+id,depth_buffer+WIN_W+id);
store2x64(color,window_buffer+4*id,window_buffer+4*WIN_W+4*id);
break;
case 15:
break;
}
}
});
}
}
static void render()
{
(void)setup_triangles_ref;
(void)setup_triangles_sse2;
memset(window_buffer,0,WIN_W*WIN_H*4);
memset(depth_buffer,0,WIN_W*WIN_H*4);
float M[16];
float C[16];
mat_identity(M);
mat_translate(-T[0],-T[1],-T[2],C);
mul_mat_mat(C,M,M);
mat_identity(C);
for(si32 i=0;i<9;++i) C[i+i/3]=R[i];
mul_mat_mat(C,M,M);
mat_frustum(-1.0f,+1.0f,-1.0f,+1.0f,2.0f,1000000.0f,C);
mul_mat_mat(C,M,M);
mat_view(WIN_W,WIN_H,C);
mul_mat_mat(C,M,M);
normalize_vec(L,L);
si32 n=si32(model.vertices.size()/4);
const float *src=model.vertices.data();
float *dst=transformed.data();
ui64 t;
t=get_time();
if(CPU_HAS_SSE2()) transform_vertices_sse2(n,M,src,dst);
else transform_vertices_ref(n,M,src,dst);
t=get_time()-t;
time_transform=float(t)/float(timer_frequency);
t=get_time();
//if(CPU_HAS_SSE2()) setup_triangles_sse2(si32(model.triangles.size()/3),model.triangles.data(),dst,tris.data());
//else setup_triangles_ref(si32(model.triangles.size()/3),model.triangles.data(),dst,tris.data());
t=get_time()-t;
time_triangles=float(t)/float(timer_frequency);
t=get_time();
if(CPU_HAS_SSE2()) render_triangles_sse2(L);
else render_triangles_ref(L);
t=get_time()-t;
time_rasterize=float(t)/float(timer_frequency);
}
//==============================================================================
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
kdown[wParam&0xFF]=1;
kprsd[wParam&0xFF]=1;
break;
case WM_KEYUP:
kdown[wParam&0xFF]=0;
break;
case WM_DROPFILES:
{
HDROP hDrop=(HDROP)wParam;
DragQueryFileA(hDrop,0,model_name,sizeof(model_name));
model_name[sizeof(model_name)-1]=0;
loaded=false;
DragFinish(hDrop);
break;
}
default:
return DefWindowProc(hwnd, Message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
(void)hInstance;
(void)hPrevInstance;
(void)lpCmdLine;
(void)nCmdShow;
static const BITMAPINFOHEADER bmih={sizeof(BITMAPINFOHEADER),WIN_W,WIN_H,1,32,BI_RGB,0,0,0,0,0};
WNDCLASSEX wcex={};
wcex.cbSize=sizeof(WNDCLASSEX);
wcex.style=CS_OWNDC;
wcex.lpfnWndProc=WndProc;
wcex.hInstance=hInstance;
wcex.lpszClassName="ObjViewer";
if(!RegisterClassEx(&wcex)) return 1;
RECT rect={0,0,WIN_W,WIN_H};
AdjustWindowRect(&rect,WS_OVERLAPPEDWINDOW&~WS_SIZEBOX,0);
HWND hwnd=CreateWindow("ObjViewer","Obj viewer",
(WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_MAXIMIZEBOX)|WS_VISIBLE,
si32(CW_USEDEFAULT),si32(CW_USEDEFAULT),rect.right-rect.left,rect.bottom-rect.top,
NULL,NULL,hInstance,NULL);
HDC hdc=GetDC(hwnd);
DragAcceptFiles(hwnd,TRUE);
MSG msg;
snprintf(model_name,sizeof(model_name),"model.obj");
init();
ui64 t=get_time();
ui64 td=t;
double spf=0.0,fps=0.0;
memset(window_buffer,0,WIN_W*WIN_H*4);
quit=false;
while(!quit)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message==WM_QUIT) {quit=true;break;}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
ui64 t0=t;
t=get_time();
spf=spf*(15.0/16.0)+(double(t-t0)/double(timer_frequency))*(1.0/16.0);
if(t-td>timer_frequency/4) {td=t;fps=1.0/spf;}
if(!loaded)
model.load(model_name);
render();
print_text_screen(16,WIN_H-16,0xFF77C077u,"Window resolution: %dx%d",int(WIN_W),int(WIN_H));
print_text_screen(16,WIN_H-32,0xFF77C077u,"Running time: %.1f",double(get_time()-timer_start)/double(timer_frequency));
print_text_screen(16,WIN_H-48,0xFF77C077u,"FPS: %.1f",fps);
print_text_screen(16,WIN_H-64,0xFF77C077u,"F1 - help");
print_text_screen(16,WIN_H-80,0xFF77C077u,"SIMD: %s",(CPU_HAS_SSE2()?"SSE2":"disabled"));
print_text_screen(16,WIN_H-96,0xFF77C077u,"Pixels visible: %d",pixels_visible);
print_text_screen(16,WIN_H-112,0xFF77C077u,"Pixels total: %d [%d]",pixels_total,pixels_touched);
print_text_screen(16,WIN_H-128,0xFF77C077u,"Vertex transform: %.3f ms",1000.0f*time_transform);
print_text_screen(16,WIN_H-142,0xFF77C077u,"Triangle setup: %.3f ms",1000.0f*time_triangles);
print_text_screen(16,WIN_H-158,0xFF77C077u,"Rasterization+shading: %.3f ms",1000.0f*time_rasterize);
print_text_screen(WIN_W-256,WIN_H-16,0xFF77C077u," Model info:");
print_text_screen(WIN_W-256,WIN_H-32,0xFF77C077u,"Vertices: %8d -> %8d",int(model.orig_vertices.size()-1),int(model.vertices.size()/4));
print_text_screen(WIN_W-256,WIN_H-48,0xFF77C077u,"Faces: %8d -> %8d",int(model.faces.size()),int(model.triangles.size()/3));
print_text_screen(WIN_W-256,WIN_H-64,0xFF77C077u,"Dimensions: %.3gx%.3gx%.3g",2.0f*model.extents[0],2.0f*model.extents[1],2.0f*model.extents[2]);
print_text_screen(WIN_W-256,WIN_H-80,0xFF77C077u,"Load time: %.3f ms",1000.0*double(load_time)/double(timer_frequency));
if(show_help)
{
print_text_screen(16,80,0xFF77C077u,"F4: toggle SIMD");
print_text_screen(16,64,0xFF77C077u,"GVBN: light position");
print_text_screen(16,48,0xFF77C077u,"YUIHJK: rotation");
print_text_screen(16,32,0xFF77C077u,"WASDRF: translation");
print_text_screen(16,16,0xFF77C077u,"Esc: quit");
}
if(kprsd[VK_ESCAPE]) {quit=true;break;}
if(kprsd[VK_F1]) {show_help=!show_help;}
if(kprsd[VK_F4]) {allow_simd=!allow_simd;}
float s=0.5f*float(spf)*length_vec(model.extents);
float r=float(spf);
float g=std::sqrt(1.0f-r*r);
if(kdown['W']) {for(si32 i=0;i<3;++i) T[i]-=s*R[6+i];}
if(kdown['S']) {for(si32 i=0;i<3;++i) T[i]+=s*R[6+i];}
if(kdown['A']) {for(si32 i=0;i<3;++i) T[i]-=s*R[0+i];}
if(kdown['D']) {for(si32 i=0;i<3;++i) T[i]+=s*R[0+i];}
if(kdown['R']) {for(si32 i=0;i<3;++i) T[i]+=s*R[3+i];}
if(kdown['F']) {for(si32 i=0;i<3;++i) T[i]-=s*R[3+i];}
if(kdown['G']) {float y=L[1],z=L[2]; L[1]=g*y+r*z; L[2]=-r*y+g*z;}
if(kdown['B']) {float y=L[1],z=L[2]; L[1]=g*y-r*z; L[2]=+r*y+g*z;}
if(kdown['V']) {float x=L[0],z=L[2]; L[0]=g*x-r*z; L[2]=+r*x+g*z;}
if(kdown['N']) {float x=L[0],z=L[2]; L[0]=g*x+r*z; L[2]=-r*x+g*z;}
if(kdown['H'])
{
float M0[16],M1[16];
mat_identity(M0);
for(si32 i=0;i<9;++i) M0[i+i/3]=R[i];
mat_rotate(-r,0.0f,1.0f,0.0f,M1);
mul_mat_mat(M1,M0,M0);
for(si32 i=0;i<9;++i) R[i]=M0[i+i/3];
}
if(kdown['K'])
{
float M0[16],M1[16];
mat_identity(M0);
for(si32 i=0;i<9;++i) M0[i+i/3]=R[i];
mat_rotate(+r,0.0f,1.0f,0.0f,M1);
mul_mat_mat(M1,M0,M0);
for(si32 i=0;i<9;++i) R[i]=M0[i+i/3];
}
if(kdown['U'])
{
float M0[16],M1[16];
mat_identity(M0);
for(si32 i=0;i<9;++i) M0[i+i/3]=R[i];
mat_rotate(-r,1.0f,0.0f,0.0f,M1);
mul_mat_mat(M1,M0,M0);
for(si32 i=0;i<9;++i) R[i]=M0[i+i/3];
}
if(kdown['J'])
{
float M0[16],M1[16];
mat_identity(M0);
for(si32 i=0;i<9;++i) M0[i+i/3]=R[i];
mat_rotate(+r,1.0f,0.0f,0.0f,M1);
mul_mat_mat(M1,M0,M0);
for(si32 i=0;i<9;++i) R[i]=M0[i+i/3];
}
if(kdown['Y'])
{
float M0[16],M1[16];
mat_identity(M0);
for(si32 i=0;i<9;++i) M0[i+i/3]=R[i];
mat_rotate(-r,0.0f,0.0f,1.0f,M1);
mul_mat_mat(M1,M0,M0);
for(si32 i=0;i<9;++i) R[i]=M0[i+i/3];
}
if(kdown['I'])
{
float M0[16],M1[16];
mat_identity(M0);
for(si32 i=0;i<9;++i) M0[i+i/3]=R[i];
mat_rotate(+r,0.0f,0.0f,1.0f,M1);
mul_mat_mat(M1,M0,M0);
for(si32 i=0;i<9;++i) R[i]=M0[i+i/3];
}
StretchDIBits(
hdc,
0,0,WIN_W,WIN_H,
0,0,WIN_W,WIN_H,
window_buffer,
(BITMAPINFO*)(&bmih),
DIB_RGB_COLORS,
SRCCOPY);
InvalidateRect(hwnd,NULL,FALSE);
char text[4096];
snprintf(text,sizeof(text),"Obj viewer: [%s]",model_name);
if(!SetWindowTextA(hwnd,text)) break;
for(si32 i=0;i<256;++i) kprsd[i]=false;
Sleep(0);
}
}
quit=true;
ReleaseDC(hwnd,hdc);
DestroyWindow(hwnd);
return 0;
}
# Max2Obj Version 4.0 Mar 10th, 2001
#
# object yad to come ...
#
# gnome from gamedev.ru
v 1.272174 2.571286 0.387827
v 1.264171 2.487582 0.387426
v 1.226320 2.533379 0.399334
v 1.180466 2.495584 0.387464
v 1.188468 2.579288 0.387865
v 1.326305 2.618703 -0.182623
v 1.226320 2.536378 -0.227036
v 1.308857 2.436183 -0.183498
v 1.126335 2.453632 -0.183414
v 1.143783 2.636152 -0.182540
v 1.297670 2.592536 0.345341
v 1.285218 2.462290 0.344718
v 1.154970 2.474741 0.344777
v 1.167422 2.604988 0.345401
v 1.268796 2.569145 0.252766
v 1.261383 2.491606 0.252395
v 1.183844 2.499019 0.252430
v 1.191257 2.576557 0.252801
v 1.277582 2.576543 0.222337
v 1.268636 2.482966 0.221889
v 1.175058 2.491912 0.221931
v 1.184004 2.585489 0.222379
v 1.315768 2.607991 0.237847
v 1.300158 2.444707 0.237065
v 1.136872 2.460316 0.237140
v 1.152482 2.623601 0.237922
v 1.320319 2.611937 0.198412
v 1.303915 2.440345 0.197590
v 1.132321 2.456749 0.197669
v 1.148725 2.628341 0.198491
v 1.325333 2.616426 0.125136
v 1.308054 2.435682 0.124270
v 1.127307 2.452961 0.124353
v 1.144586 2.633706 0.125219
v 1.362595 2.647723 0.013225
v 1.338814 2.398957 0.012033
v 1.090044 2.422738 0.012147
v 1.113826 2.671504 0.013338
v 1.390524 2.671200 -0.074931
v 1.361868 2.371451 -0.076366
v 1.062117 2.400107 -0.076229
v 1.090772 2.699855 -0.074794
v 1.399718 2.679040 -0.127406
v 1.369458 2.362509 -0.128921
v 1.052922 2.392769 -0.128777
v 1.083183 2.709300 -0.127261
# 46 vertices
vt -0.632207 1.970564 0.000000
vt -0.632207 1.992116 0.000000
vt -0.499986 2.000000 0.000000
vt -0.367766 1.992115 0.000000
vt -0.367766 1.970563 0.000000
vt -0.788313 1.046778 0.000000
vt -0.500002 1.000000 0.000000
vt -0.788314 1.093772 0.000000
vt -0.211689 1.093769 0.000000
vt -0.211690 1.046775 0.000000
vt -0.705727 1.896584 0.000000
vt -0.705726 1.930119 0.000000
vt -0.294247 1.930117 0.000000
vt -0.294249 1.896582 0.000000
vt -0.622472 1.755754 0.000000
vt -0.622471 1.775718 0.000000
vt -0.377508 1.775717 0.000000
vt -0.377509 1.755753 0.000000
vt -0.647807 1.705054 0.000000
vt -0.647806 1.729148 0.000000
vt -0.352175 1.729146 0.000000
vt -0.352175 1.705053 0.000000
vt -0.757916 1.720602 0.000000
vt -0.757916 1.762643 0.000000
vt -0.242064 1.762641 0.000000
vt -0.242064 1.720599 0.000000
vt -0.771042 1.656546 0.000000
vt -0.771041 1.700726 0.000000
vt -0.228941 1.700724 0.000000
vt -0.228941 1.656543 0.000000
vt -0.785501 1.538351 0.000000
vt -0.785501 1.584887 0.000000
vt -0.214487 1.584885 0.000000
vt -0.214485 1.538348 0.000000
vt -0.892953 1.350692 0.000000
vt -0.892952 1.414743 0.000000
vt -0.107040 1.414740 0.000000
vt -0.107041 1.350689 0.000000
vt -0.973486 1.203213 0.000000
vt -0.973486 1.280390 0.000000
vt -0.026511 1.280386 0.000000
vt -0.026511 1.203209 0.000000
vt -0.999999 1.117218 0.000000
vt -1.000000 1.198717 0.000000
vt -0.000000 1.198713 0.000000
vt -0.000002 1.117214 0.000000
# 46 texture vertices
vn 0.234870 0.186460 1.550170
vn 0.193879 -0.242285 1.548110
vn -0.000001 -0.004789 0.999988
vn -0.234872 -0.201299 1.548313
vn -0.193882 0.227447 1.550359
vn 0.360708 -0.030868 -0.754841
vn 0.632195 -0.054101 -1.322971
vn 0.360708 -0.030868 -0.754840
vn -0.034483 -0.357090 -0.756405
vn -0.360708 0.038096 -0.754510
vn 0.979348 -0.096209 0.539593
vn 0.979357 -0.096210 0.539598
vn -0.093628 -0.981930 0.535357
vn -0.979357 0.091039 0.540489
vn 1.760326 -0.165869 -0.507114
vn 1.760325 -0.165862 -0.507122
vn -0.168283 -1.757879 -0.514751
vn -1.760321 0.170713 -0.505512
vn 1.270849 -0.123110 0.336995
vn 1.270825 -0.123112 0.336999
vn -0.121487 -1.272442 0.331499
vn -1.270843 0.119876 0.338164
vn -0.363364 -0.307224 1.517503
vn -0.299954 0.356085 1.520680
vn 0.363360 0.292673 1.520373
vn 0.299950 -0.370631 1.517198
vn 1.451259 -0.139476 0.153536
vn 1.451245 -0.139471 0.153521
vn -0.138733 -1.451971 0.147236
vn -1.451254 0.137996 0.154864
vn 1.498489 -0.143703 0.093730
vn 1.498489 -0.143704 0.093733
vn -0.143254 -1.498927 0.087238
vn -1.498490 0.142798 0.095100
vn 1.225487 -0.118950 0.374781
vn 1.225493 -0.118950 0.374782
vn -0.117155 -1.227273 0.369473
vn -1.225493 0.115355 0.375904
vn 1.241959 -0.120462 0.361383
vn 1.241956 -0.120461 0.361378
vn -0.118729 -1.243681 0.356000
vn -1.241955 0.116993 0.362512
vn 1.389395 -0.133896 0.223430
vn 1.389386 -0.133896 0.223433
vn -0.132824 -1.390442 0.217415
vn -1.389395 0.131748 0.224689
# 46 vertex normals
g yad
s 2
f 12/12/12 11/11/11 1/1/1 2/2/2
s 4
f 13/13/13 12/12/12 2/2/2 4/4/4
s 2
f 14/14/14 13/13/13 4/4/4 5/5/5
s 4
f 11/11/11 14/14/14 5/5/5 1/1/1
s 1
f 16/16/16 15/15/15 11/11/11 12/12/12
s 8
f 17/17/17 16/16/16 12/12/12 13/13/13
s 1
f 18/18/18 17/17/17 13/13/13 14/14/14
s 8
f 15/15/15 18/18/18 14/14/14 11/11/11
s 1
f 20/20/20 19/19/19 15/15/15 16/16/16
s 8
f 21/21/21 20/20/20 16/16/16 17/17/17
s 1
f 22/22/22 21/21/21 17/17/17 18/18/18
s 8
f 19/19/19 22/22/22 18/18/18 15/15/15
s 2
f 24/24/24 23/23/23 19/19/19 20/20/20
f 25/25/25 24/24/24 20/20/20 21/21/21
f 26/26/26 25/25/25 21/21/21 22/22/22
f 23/23/23 26/26/26 22/22/22 19/19/19
s 1
f 28/28/28 27/27/27 23/23/23 24/24/24
s 4
f 29/29/29 28/28/28 24/24/24 25/25/25
s 1
f 30/30/30 29/29/29 25/25/25 26/26/26
s 4
f 27/27/27 30/30/30 26/26/26 23/23/23
s 1
f 32/32/32 31/31/31 27/27/27 28/28/28
s 4
f 33/33/33 32/32/32 28/28/28 29/29/29
s 1
f 34/34/34 33/33/33 29/29/29 30/30/30
s 4
f 31/31/31 34/34/34 30/30/30 27/27/27
s 25
f 36/36/36 35/35/35 31/31/31 32/32/32
s 36
f 37/37/37 36/36/36 32/32/32 33/33/33
s 1
f 38/38/38 37/37/37 33/33/33 34/34/34
s 6
f 35/35/35 38/38/38 34/34/34 31/31/31
s 24
f 40/40/40 39/39/39 35/35/35 36/36/36
s 32
f 41/41/41 40/40/40 36/36/36 37/37/37
s 1
f 42/42/42 41/41/41 37/37/37 38/38/38
s 2
f 39/39/39 42/42/42 38/38/38 35/35/35
s 16
f 44/44/44 43/43/43 39/39/39 40/40/40
s 32
f 45/45/45 44/44/44 40/40/40 41/41/41
s 1
f 46/46/46 45/45/45 41/41/41 42/42/42
s 2
f 43/43/43 46/46/46 42/42/42 39/39/39
s 1
f 8/8/8 6/6/6 43/43/43 44/44/44
s 2
f 9/9/9 8/8/8 44/44/44 45/45/45
s 4
f 10/10/10 9/9/9 45/45/45 46/46/46
s 8
f 6/6/6 10/10/10 46/46/46 43/43/43
s 1
f 2/2/2 1/1/1 3/3/3
f 4/4/4 2/2/2 3/3/3
f 5/5/5 4/4/4 3/3/3
f 1/1/1 5/5/5 3/3/3
f 7/7/7 6/6/6 8/8/8
s 2
f 7/7/7 8/8/8 9/9/9
s 4
f 7/7/7 9/9/9 10/10/10
s 8
f 7/7/7 10/10/10 6/6/6
# 48 faces
g
# object Gnome to come ...
#
v 1.067990 2.141678 -0.725496
v 1.114843 2.872938 -0.502878
v 0.866716 2.898349 -0.970399
v 0.689678 2.522195 -0.937722
v 0.476431 5.269056 -0.242958
v 0.226650 5.433019 -0.003404
v 0.050382 5.411132 -0.216112
v 0.033181 5.278732 -0.415838
v 0.625928 4.704624 -0.596104
v 1.234756 4.539438 -0.533679
v 0.930359 4.718667 -0.559948
v 0.842178 4.644725 -0.828324
v 0.362487 4.611763 -1.056519
v 0.648688 4.203690 0.365541
v 0.745434 4.227683 0.374597
v 0.637302 4.422669 -0.116947
v 0.691240 4.747296 -0.684596
v -0.540147 4.203522 0.372588
v -0.551425 4.422507 -0.109899
v -0.635903 4.228991 0.386332
v -0.562690 4.704428 -0.588416
v -0.629296 4.748779 -0.675000
v 0.583756 5.019379 -0.463146
v 0.513765 5.078629 0.525661
v 2.285233 4.300778 0.239581
v 1.085717 4.282536 0.394939
v 1.054013 4.446787 -0.067027
v 2.281360 4.334540 -0.406472
v 0.882244 3.871240 0.679585
v 0.760995 4.371079 0.387624
v 0.390437 3.829156 0.806385
v 0.269019 4.574637 0.648761
v 0.587816 4.344777 0.647864
v 0.283027 4.329619 0.837469
v 0.034910 4.637962 0.640199
v 0.115584 4.636457 0.639884
v 0.124458 4.393032 0.798217
v 0.031758 4.415410 0.591204
v 0.309214 4.409266 0.588419
v -0.245627 4.412278 0.594213
v -0.054611 4.394526 0.799954
v -0.044690 4.638313 0.833957
v -0.045961 4.639448 0.640759
v 0.116986 4.635331 0.833013
v 0.503134 4.415934 0.549733
v 0.383111 4.651614 0.531617
v 0.209780 4.749477 0.571945
v -1.012595 2.146870 -0.701923
v -0.634021 2.514269 -0.949378
v -0.808176 2.898408 -0.960074
v -1.049359 2.872720 -0.490044
v -0.407804 5.270027 -0.236827
v -0.155319 5.433160 -0.000769
v 0.029907 4.757229 -0.855643
v -1.170289 4.539072 -0.518721
v -0.866468 4.718396 -0.548817
v -0.780442 4.642742 -0.785159
v -0.304279 4.611659 -1.052312
v -0.435780 5.080390 0.533306
v -0.518668 5.020600 -0.455276
v -0.984029 4.445751 -0.040608
v -1.010151 4.280759 0.435669
v -2.211025 4.300146 0.266437
v -2.214756 4.333900 -0.379555
v -0.668859 4.370131 0.410328
v -0.801008 3.871011 0.689431
v -0.276254 3.829067 0.810229
v -0.523749 4.348615 0.657215
v -0.196043 4.578460 0.652093
v -0.210740 4.331966 0.841521
v -0.445171 4.418966 0.560447
v 0.029077 4.417452 0.555144
v -0.434576 4.028814 1.372555
v 0.527485 4.025303 1.370912
v -0.140344 4.753242 0.572135
v -0.319497 4.651933 0.540861
v -0.293374 2.229152 0.821264
v -0.293687 2.748919 0.956509
v 0.391745 2.750838 0.957894
v 0.363601 2.206352 0.806710
v -0.298303 2.521032 -0.942898
v 0.373431 2.545231 -0.953877
v 0.362963 2.894320 -1.026291
v -0.303795 2.895351 -1.023459
v -2.993125 4.021529 -0.321888
v -2.793210 3.770927 -0.336182
v -2.793108 4.366220 -0.305076
v -2.993084 4.259463 -0.309455
v -0.263661 3.528032 1.678554
v -0.488997 3.492508 1.289249
v -0.253930 3.624182 1.694413
v 0.357219 3.620965 1.694796
v 0.369333 3.527981 1.674792
v 0.601421 3.492415 1.282877
v 0.269858 0.779008 -0.949282
v 0.157265 0.969414 -0.764337
v 0.157178 0.085873 -0.799963
v 0.269801 0.113143 -0.974686
v 0.849164 0.774824 -0.870939
v 0.934762 0.963797 -0.659191
v 0.849106 0.108951 -0.896343
v 0.934674 0.080244 -0.694817
v 0.972300 0.472986 0.151506
v 0.939558 0.388396 0.127567
v 0.163378 0.382560 0.241720
v 0.139472 0.464696 0.267225
v 1.035342 0.858729 -0.565265
v 1.035260 0.381835 -0.590218
v 0.057767 0.382336 -0.694432
v 0.057849 0.864326 -0.669212
v 0.841547 2.990143 -0.923313
v 0.363578 2.990077 -0.920471
v 0.067767 2.085298 -0.944709
v 0.056770 2.024535 -0.824091
v 1.034405 2.066834 -0.689053
v 1.032999 2.966861 -0.480183
v 1.134931 1.961768 -0.594966
v 1.034291 1.267938 -0.730925
v 1.134844 1.362587 -0.626367
v 0.169164 1.379316 -0.943540
v 0.056629 1.275011 -0.863214
v 0.948656 1.373678 -0.838133
v 0.169286 1.933999 -0.914584
v 0.948713 1.967720 -0.806957
v 3.460684 4.188113 -0.263672
v 3.260165 4.260345 -0.346723
v 3.260123 4.022414 -0.359156
v 3.460669 4.085524 -0.269033
v 3.060170 4.260316 -0.345525
v 3.060129 4.022385 -0.357958
v 2.860157 4.367019 -0.338749
v 2.860056 3.771724 -0.369856
v 0.597281 4.123791 0.519789
v -0.493401 4.123875 0.526285
v 2.281276 3.856859 -0.431354
v 1.234635 3.675420 -0.578136
v 0.841710 3.655212 -0.873174
v 0.362373 3.667437 -1.105552
v 0.031482 5.029171 -0.634985
v 0.142389 0.824584 0.289585
v 0.163470 0.915363 0.269773
v 0.939650 0.921209 0.155621
v 0.970910 0.830286 0.177734
v 0.383652 2.875405 0.860157
v 0.808368 2.884441 0.791994
v 0.863975 2.781256 0.799326
v 1.037016 2.932072 0.185578
v 1.126003 2.836379 0.178491
v 1.040357 2.015189 0.299171
v 1.076684 2.086841 0.342433
v 0.064354 1.958483 0.439992
v 0.065611 1.951605 0.579792
v 0.782542 2.301627 0.617985
v 1.040220 1.216277 0.257425
v 1.139572 1.321376 0.162240
v 1.139679 1.920562 0.193553
v 0.882679 0.977302 0.294931
v 0.251184 0.972555 0.387838
v 0.919638 1.085728 0.332315
v 0.214707 1.080432 0.436026
v 0.064212 1.208952 0.400897
v 0.955844 1.310231 0.375897
v 0.177698 1.304395 0.490394
v 0.955938 1.904282 0.406939
v 0.177809 1.859075 0.519307
v 0.176560 5.421816 0.138409
v 0.318582 5.298612 0.427532
v 0.181197 5.386460 0.309649
v 0.875456 0.077618 0.969069
v 0.973094 -0.011760 0.762968
v 0.196283 -0.012102 0.772043
v 0.298630 0.077371 0.975806
v 0.875475 0.185491 0.974706
v 0.973147 0.295850 0.779042
v 0.298649 0.185238 0.981443
v 0.196336 0.295494 0.788116
v 0.969588 0.003879 0.463397
v 0.192776 0.003553 0.472471
v 0.969665 0.459893 0.487111
v 0.192854 0.459536 0.496184
v 0.939496 0.022448 0.108450
v 0.163315 0.016598 0.222644
v 0.157110 0.071387 -0.657658
v 0.934607 0.065758 -0.552554
v 3.251212 4.166525 0.267412
v 3.263211 4.233818 0.160915
v 3.263169 3.995885 0.148482
v 3.251194 4.051719 0.261412
v 3.149966 4.166509 0.268018
v 3.063215 4.233789 0.162113
v 3.149946 4.051702 0.262019
v 3.063174 3.995858 0.149680
v 3.462659 4.068173 0.063025
v 3.462675 4.170764 0.068386
v 0.432123 5.022199 0.510990
v 0.289652 5.222995 0.408351
v 0.108925 4.907098 0.614176
v 0.206751 4.877485 0.561426
v 0.350612 4.899540 0.512522
v 0.110131 4.780211 0.800562
v 2.863101 3.745197 0.137782
v 2.863204 4.340493 0.168888
v 2.285154 3.823100 0.214699
v 1.126879 3.626665 0.355262
v 0.808514 3.221884 0.824254
v 0.385236 3.211739 0.975529
v 0.845687 4.650476 -0.080526
v -0.786521 0.774613 -0.861548
v -0.870848 0.963554 -0.648787
v -0.870936 0.080007 -0.684525
v -0.786578 0.108741 -0.886909
v -0.208160 0.778961 -0.946796
v -0.094631 0.969395 -0.763197
v -0.208217 0.113096 -0.972156
v -0.094719 0.085853 -0.798934
v 0.005949 0.864320 -0.669166
v 0.005866 0.382352 -0.694415
v -0.970347 0.381574 -0.578540
v -0.970264 0.858458 -0.553558
v -0.303190 2.989992 -0.916624
v -0.780691 2.989926 -0.913838
v -0.971177 2.066558 -0.677324
v 0.004871 2.024533 -0.823806
v -0.002609 2.098733 -0.944170
v -0.967282 2.966584 -0.468268
v -0.886964 1.373446 -0.827380
v -0.971316 1.267650 -0.719241
v 0.004729 1.275000 -0.863043
v -0.108780 1.379298 -0.942019
v -0.886867 1.967488 -0.796232
v -0.108669 1.933988 -0.912998
v -1.070698 1.362276 -0.613624
v -1.070594 1.961457 -0.582207
v -3.392611 4.082135 -0.247564
v -3.193152 4.021500 -0.320608
v -3.193112 4.259435 -0.308175
v -3.392592 4.191586 -0.241845
v -2.214976 3.856230 -0.404564
v -1.170202 3.675098 -0.564101
v -0.780499 3.656494 -0.892391
v -0.304394 3.667342 -1.101558
v -0.891869 0.459717 0.498051
v -0.866052 0.388154 0.138052
v -0.088519 0.382525 0.242942
v -0.114969 0.459611 0.497453
v -0.065959 0.468007 0.266228
v -0.899607 0.470501 0.163434
v -0.896930 0.830038 0.188596
v -0.865960 0.920972 0.166107
v -0.088428 0.915342 0.270998
v -0.067091 0.824549 0.290550
v -0.763100 2.778376 0.610751
v -0.715945 2.883189 0.611548
v -0.292186 2.875282 0.864730
v -1.051967 2.835670 0.192147
v -0.963288 2.931788 0.197591
v -1.004641 2.069400 0.355795
v -0.965249 2.014908 0.310905
v 0.003205 1.936047 0.574094
v 0.012454 1.958478 0.440186
v -0.701156 2.307967 0.649766
v -1.065967 1.321081 0.174961
v -0.965386 1.216010 0.268988
v -1.065862 1.920244 0.206378
v -0.174737 0.972499 0.390111
v -0.807338 0.977069 0.304771
v -0.137715 1.080397 0.437867
v 0.012312 1.208944 0.400948
v -0.843878 1.085483 0.342604
v -0.100158 1.304353 0.491779
v -0.879649 1.309968 0.386610
v -0.100046 1.859031 0.520817
v -0.879557 1.904018 0.417773
v -0.106067 5.386776 0.311384
v -0.103592 5.421884 0.140107
v -0.242029 5.298995 0.430944
v -0.214649 0.077605 0.978186
v -0.114818 -0.011917 0.773277
v -0.891718 -0.011827 0.773875
v -0.791548 0.077675 0.978631
v -0.214630 0.185484 0.983780
v -0.114766 0.295699 0.789230
v -0.791530 0.185563 0.984225
v -0.891666 0.295789 0.789828
v -0.115046 0.003618 0.473746
v -0.891946 0.003720 0.474344
v -0.088582 0.016577 0.223941
v -0.866114 0.022202 0.119050
v -0.871003 0.065521 -0.542160
v -0.094787 0.071354 -0.656569
v -3.175531 4.050778 0.279885
v -3.190058 3.994978 0.186997
v -3.190017 4.232912 0.199431
v -3.175511 4.167727 0.285997
v -3.077016 4.050792 0.279295
v -2.990134 3.995007 0.185786
v -3.076996 4.167742 0.285407
v -2.990093 4.232941 0.198219
v -3.390368 4.172223 0.128720
v -3.390387 4.062774 0.123001
v -0.356471 5.022085 0.515867
v -0.215076 5.222923 0.411375
v -0.137160 4.875377 0.564493
v -0.037652 4.907073 0.615025
v -0.278711 4.900978 0.518909
v -0.036624 4.780198 0.801260
v -2.790159 4.339694 0.202637
v -2.790261 3.744401 0.171531
v -2.211346 3.822463 0.241636
v -1.051418 3.626378 0.367884
v -0.715841 3.220631 0.853120
v -0.290651 3.211611 0.980175
v -0.767683 4.649873 -0.063801
v -0.148122 3.711349 -1.144830
v 0.001563 3.565510 -1.144132
v 0.447648 3.882391 -1.113275
v 0.297963 4.028230 -1.113973
v 0.927046 4.212403 -0.964150
v 0.774292 4.358457 -0.920002
v 1.328973 4.570092 -0.539384
v 1.179288 4.634918 -0.539820
v 1.336245 4.360420 0.299744
v 1.186561 4.407303 0.299520
v 0.991956 3.937901 0.646723
v 0.842271 4.083740 0.646024
v 0.763427 3.758111 0.824777
v 0.613742 3.903950 0.824078
v 0.305741 3.498911 0.914212
v 0.156056 3.644750 0.913513
v -0.211128 3.251947 1.014413
v -0.360813 3.397786 1.013715
v -0.660197 2.969354 0.942674
v -0.809882 3.115192 0.941976
v -0.981261 2.885586 0.523641
v -1.130947 2.927868 0.523375
v -1.329400 2.929815 -0.279987
v -1.042041 2.928045 -0.279971
v -0.830967 3.087086 -0.877902
v -0.952784 3.129893 -0.768860
v -0.745873 3.150285 -1.021625
v -0.895557 3.296124 -1.022324
v -1.131186 2.697563 0.261275
v -1.089844 2.896794 0.262343
v -1.088069 2.726576 -0.251756
v -1.295150 2.727396 -0.251793
v -1.377203 2.898564 0.262327
v -1.336940 2.699423 0.245787
v -1.081102 2.731854 0.452338
v -1.012733 2.691209 0.466023
v -1.140811 2.214204 0.531093
v -0.881497 2.156894 0.514608
v -1.042479 2.194352 0.220597
v -1.452469 2.197898 0.241719
v -0.985239 2.231897 -0.380303
v -1.392998 2.235090 -0.380393
# 355 vertices
vt 0.637860 0.381397 0.636432
vt 0.644310 0.512255 0.609521
vt 0.609626 0.512420 0.678055
vt 0.584562 0.446458 0.670584
vt 0.546920 0.935201 0.590449
vt 0.511407 0.966280 0.557010
vt 0.430264 0.733070 0.693285
vt 0.458996 0.767300 0.664712
vt 0.575303 0.834025 0.637479
vt 0.661323 0.805521 0.626593
vt 0.618313 0.836840 0.632052
vt 0.606073 0.821326 0.670934
vt 0.479212 0.748096 0.723997
vt 0.577696 0.754639 0.493520
vt 0.591367 0.758952 0.492298
vt 0.576500 0.788770 0.565503
vt 0.577653 0.839237 0.650642
vt 0.409613 0.754639 0.493531
vt 0.408432 0.788771 0.565513
vt 0.396064 0.759249 0.491806
vt 0.407250 0.834025 0.637396
vt 0.399896 0.839547 0.650409
vt 0.562275 0.889198 0.620539
vt 0.551543 0.908734 0.476968
vt 0.809179 0.770631 0.511183
vt 0.639460 0.768812 0.489455
vt 0.635372 0.793490 0.558048
vt 0.809179 0.770631 0.605582
vt 0.610444 0.698978 0.445024
vt 0.593559 0.784331 0.491479
vt 0.582055 0.600744 0.696742
vt 0.523786 0.822575 0.455407
vt 0.568854 0.782088 0.453509
vt 0.525602 0.781154 0.426032
vt 0.484226 0.834232 0.457342
vt 0.495632 0.833967 0.457305
vt 0.503218 0.791958 0.432373
vt 0.490288 0.793991 0.462789
vt 0.529517 0.792892 0.462905
vt 0.451069 0.793459 0.462569
vt 0.477900 0.792232 0.432288
vt 0.472808 0.836075 0.429181
vt 0.472792 0.834496 0.457342
vt 0.495666 0.835546 0.429154
vt 0.556966 0.793716 0.468424
vt 0.540017 0.835060 0.472963
vt 0.508520 0.851172 0.467983
vt 0.343688 0.382465 0.634855
vt 0.397427 0.444915 0.673379
vt 0.372822 0.512475 0.678015
vt 0.338325 0.512269 0.609540
vt 0.418372 0.922460 0.590336
vt 0.457402 0.966317 0.556961
vt 0.484299 0.839392 0.676219
vt 0.321286 0.805521 0.626513
vt 0.364269 0.836841 0.631998
vt 0.376632 0.821325 0.666047
vt 0.481158 0.719924 0.749086
vt 0.417291 0.909086 0.476698
vt 0.406408 0.889453 0.620365
vt 0.347212 0.793490 0.555972
vt 0.343112 0.768810 0.485338
vt 0.173477 0.770631 0.511195
vt 0.173498 0.770631 0.605585
vt 0.391387 0.784330 0.489413
vt 0.372458 0.698977 0.445059
vt 0.498144 0.599773 0.696662
vt 0.411694 0.782816 0.453147
vt 0.458033 0.823265 0.455357
vt 0.455790 0.781590 0.425891
vt 0.422886 0.794320 0.467715
vt 0.489940 0.794019 0.468061
vt 0.423688 0.733072 0.346399
vt 0.559706 0.732468 0.345771
vt 0.459020 0.851827 0.468290
vt 0.440675 0.835180 0.472233
vt 0.444082 0.411000 0.412903
vt 0.443757 0.505726 0.366655
vt 0.540662 0.506098 0.365869
vt 0.536977 0.406870 0.414276
vt 0.444886 0.446176 0.672193
vt 0.539865 0.450357 0.673390
vt 0.538453 0.511181 0.686609
vt 0.444185 0.511368 0.686787
vt 0.063397 0.716115 0.595484
vt 0.091668 0.671848 0.595484
vt 0.091668 0.776992 0.595484
vt 0.063397 0.758141 0.595484
vt 0.447583 0.647683 0.297848
vt 0.416054 0.637836 0.354502
vt 0.448947 0.664766 0.296261
vt 0.535351 0.664221 0.295647
vt 0.537079 0.647659 0.297843
vt 0.570222 0.637794 0.354477
vt 0.525183 0.139285 0.659363
vt 0.509111 0.174523 0.633962
vt 0.509111 0.018564 0.632425
vt 0.525183 0.021762 0.657994
vt 0.607018 0.139287 0.647409
vt 0.618944 0.174525 0.617918
vt 0.607018 0.021762 0.646040
vt 0.618944 0.018563 0.616382
vt 0.623555 0.095534 0.496018
vt 0.618944 0.080412 0.498891
vt 0.509112 0.080412 0.482891
vt 0.505712 0.095114 0.479821
vt 0.633083 0.156885 0.603344
vt 0.633083 0.072653 0.603349
vt 0.494973 0.071752 0.619392
vt 0.494973 0.156885 0.619387
vt 0.606032 0.529005 0.672177
vt 0.538454 0.529005 0.672180
vt 0.496633 0.369418 0.668819
vt 0.494975 0.359824 0.650791
vt 0.633079 0.368548 0.630581
vt 0.632722 0.529005 0.607000
vt 0.647210 0.350910 0.615984
vt 0.633083 0.227441 0.630600
vt 0.647212 0.245078 0.615997
vt 0.510954 0.245076 0.663185
vt 0.494973 0.227439 0.650784
vt 0.621068 0.245077 0.647101
vt 0.510957 0.343047 0.663189
vt 0.621062 0.350001 0.647082
vt 0.975788 0.746189 0.582628
vt 0.947511 0.758142 0.595456
vt 0.947510 0.716117 0.595455
vt 0.975788 0.728069 0.582629
vt 0.919234 0.758142 0.595455
vt 0.919234 0.716117 0.595456
vt 0.890953 0.776993 0.595455
vt 0.890953 0.671849 0.595455
vt 0.570296 0.741984 0.470480
vt 0.416091 0.742025 0.470488
vt 0.809179 0.686261 0.605571
vt 0.661326 0.652919 0.626492
vt 0.606025 0.646616 0.669935
vt 0.502892 0.618886 0.647447
vt 0.484179 0.605250 0.702178
vt 0.506113 0.158712 0.479301
vt 0.509112 0.174521 0.482860
vt 0.618944 0.174523 0.498860
vt 0.623343 0.158712 0.494918
vt 0.539603 0.527140 0.381066
vt 0.599884 0.526190 0.421195
vt 0.607738 0.508084 0.419292
vt 0.632725 0.529005 0.509721
vt 0.645310 0.512087 0.509947
vt 0.633083 0.368547 0.486185
vt 0.638183 0.381567 0.480395
vt 0.494975 0.359825 0.466086
vt 0.495035 0.359900 0.445662
vt 0.596369 0.421928 0.442135
vt 0.633083 0.227438 0.486185
vt 0.647212 0.245077 0.500768
vt 0.647213 0.350909 0.500767
vt 0.610773 0.185684 0.479038
vt 0.521414 0.185684 0.466016
vt 0.615969 0.205128 0.474384
vt 0.516218 0.205128 0.459847
vt 0.494973 0.227439 0.466076
vt 0.621055 0.245075 0.469711
vt 0.510944 0.245078 0.453663
vt 0.621054 0.350000 0.469711
vt 0.510946 0.343048 0.453673
vt 0.504204 0.965610 0.536304
vt 0.524036 0.946574 0.493113
vt 0.504714 0.960959 0.511079
vt 0.609163 0.033414 0.373962
vt 0.623140 0.015776 0.403228
vt 0.513307 0.015776 0.402582
vt 0.527606 0.033415 0.373483
vt 0.609163 0.052467 0.373962
vt 0.623140 0.070108 0.403228
vt 0.527606 0.052467 0.373483
vt 0.513307 0.070106 0.402582
vt 0.622898 0.015774 0.447002
vt 0.513065 0.015776 0.446356
vt 0.622898 0.096316 0.447019
vt 0.513065 0.096314 0.446373
vt 0.618945 0.015776 0.498890
vt 0.509112 0.015774 0.482885
vt 0.508981 0.017322 0.611579
vt 0.618814 0.017321 0.595542
vt 0.945723 0.747268 0.505261
vt 0.947511 0.758142 0.521281
vt 0.947510 0.716116 0.521281
vt 0.945723 0.726990 0.505261
vt 0.931408 0.747268 0.505261
vt 0.919234 0.758142 0.521281
vt 0.931408 0.726990 0.505261
vt 0.919234 0.716117 0.521281
vt 0.975788 0.728069 0.534109
vt 0.975788 0.746189 0.534109
vt 0.540012 0.898657 0.478748
vt 0.519961 0.933077 0.495357
vt 0.494229 0.879322 0.463118
vt 0.508104 0.873623 0.470493
vt 0.528485 0.877063 0.477662
vt 0.494239 0.858687 0.434992
vt 0.890953 0.671849 0.521281
vt 0.890953 0.776993 0.521281
vt 0.809179 0.686261 0.511171
vt 0.645300 0.652919 0.490206
vt 0.599884 0.585926 0.419064
vt 0.539913 0.585519 0.397313
vt 0.605935 0.829239 0.561748
vt 0.375758 0.139286 0.647469
vt 0.363659 0.174523 0.617979
vt 0.363659 0.018562 0.616459
vt 0.375758 0.021763 0.646094
vt 0.457598 0.139285 0.659418
vt 0.473497 0.174523 0.634016
vt 0.457598 0.021763 0.658043
vt 0.473497 0.018562 0.632496
vt 0.487636 0.156883 0.619426
vt 0.487636 0.071754 0.619435
vt 0.349521 0.072654 0.603398
vt 0.349521 0.156885 0.603389
vt 0.444183 0.529006 0.672202
vt 0.376672 0.529005 0.672213
vt 0.349521 0.368546 0.630623
vt 0.487637 0.359825 0.650794
vt 0.486683 0.371787 0.668905
vt 0.349913 0.529006 0.607010
vt 0.361540 0.245080 0.647137
vt 0.349521 0.227437 0.630648
vt 0.487636 0.227437 0.650805
vt 0.471657 0.245078 0.663206
vt 0.361539 0.350004 0.647122
vt 0.471659 0.343052 0.663201
vt 0.335383 0.245074 0.616065
vt 0.335383 0.350906 0.616050
vt 0.469549 0.845060 0.000000
vt 0.469546 0.888505 0.000000
vt 0.496020 0.889136 0.000000
vt 0.468280 0.856757 0.000000
vt 0.173478 0.686262 0.605592
vt 0.321319 0.652919 0.626547
vt 0.376695 0.646616 0.674163
vt 0.525602 0.593134 0.763312
vt 0.359706 0.096330 0.447050
vt 0.363659 0.080412 0.498940
vt 0.473498 0.080409 0.482933
vt 0.469544 0.096329 0.446458
vt 0.476669 0.095682 0.480171
vt 0.358895 0.095150 0.495898
vt 0.359260 0.158712 0.494966
vt 0.363659 0.174523 0.498909
vt 0.473497 0.174521 0.482902
vt 0.476496 0.158708 0.479343
vt 0.377685 0.507718 0.417671
vt 0.384353 0.526189 0.418312
vt 0.444049 0.527140 0.380989
vt 0.337378 0.512022 0.509856
vt 0.349912 0.529006 0.509717
vt 0.343915 0.378555 0.480134
vt 0.349521 0.368545 0.486226
vt 0.486216 0.357105 0.446429
vt 0.487638 0.359824 0.466104
vt 0.386577 0.423293 0.438850
vt 0.335383 0.245076 0.500840
vt 0.349521 0.227437 0.486251
vt 0.335383 0.350905 0.500824
vt 0.461195 0.185682 0.466056
vt 0.371831 0.185683 0.479079
vt 0.466391 0.205129 0.459887
vt 0.487636 0.227436 0.466114
vt 0.366635 0.205126 0.474424
vt 0.471660 0.245075 0.453703
vt 0.361545 0.245072 0.469752
vt 0.471662 0.343046 0.453696
vt 0.361543 0.349998 0.469734
vt 0.464100 0.961022 0.511079
vt 0.464595 0.965629 0.536302
vt 0.444774 0.946656 0.493108
vt 0.455036 0.033463 0.373586
vt 0.469322 0.015811 0.402676
vt 0.359484 0.015809 0.403268
vt 0.373474 0.033462 0.374026
vt 0.455037 0.052516 0.373593
vt 0.469322 0.070143 0.402693
vt 0.373474 0.052517 0.374033
vt 0.359484 0.070141 0.403286
vt 0.469544 0.015790 0.446440
vt 0.359706 0.015790 0.447033
vt 0.473497 0.015774 0.482916
vt 0.363659 0.015776 0.498922
vt 0.363529 0.017321 0.595604
vt 0.473367 0.017319 0.611641
vt 0.482132 0.889130 0.000000
vt 0.468282 0.876741 0.000000
vt 0.483352 0.851031 0.000000
vt 0.482344 0.840842 0.000000
vt 0.497285 0.856126 0.000000
vt 0.063389 0.716117 0.521304
vt 0.482347 0.884287 0.000000
vt 0.063389 0.758142 0.521304
vt 0.483354 0.872385 0.000000
vt 0.490192 0.851033 0.000000
vt 0.428517 0.898658 0.478725
vt 0.448600 0.933077 0.495357
vt 0.459479 0.873270 0.470331
vt 0.473505 0.879321 0.463122
vt 0.439506 0.877356 0.477292
vt 0.473490 0.858687 0.435018
vt 0.091654 0.776993 0.521299
vt 0.091654 0.671849 0.521299
vt 0.173443 0.686262 0.511172
vt 0.337323 0.652919 0.490269
vt 0.384347 0.585925 0.416180
vt 0.444353 0.585518 0.397226
vt 0.377823 0.829238 0.560716
vt 0.405519 0.650007 0.686181
vt 0.605598 0.619154 0.645525
vt 0.557222 0.650775 0.684187
vt 0.417901 0.692607 0.692596
vt 0.531845 0.733558 0.692035
vt 0.502876 0.767484 0.664100
vt 0.481466 0.637009 0.741579
vt 0.624391 0.607017 0.689076
vt 0.583216 0.593279 0.762269
vt 0.544547 0.693235 0.690971
vt 0.484223 0.516225 0.279856
vt 0.525523 0.516322 0.279163
vt 0.484214 0.552554 0.445946
vt 0.525606 0.542560 0.520691
vt 0.481319 0.679544 0.748155
vt 0.583137 0.516453 0.278235
vt 0.624398 0.516547 0.277559
vt 0.624383 0.551645 0.452851
vt 0.583220 0.542697 0.519715
vt -0.545543 1.661911 0.000000
vt -0.487229 1.603807 0.000000
vt -0.313441 1.729995 0.000000
vt -0.371756 1.788099 0.000000
vt -0.140521 1.821746 0.000000
vt -0.200031 1.879850 0.000000
vt -0.018595 1.974172 0.000000
vt -0.076910 2.000000 0.000000
vt -0.000000 1.923112 0.000000
vt -0.058314 1.941791 0.000000
vt -0.101283 1.693182 0.000000
vt -0.159598 1.751287 0.000000
vt -0.190366 1.637341 0.000000
vt -0.248681 1.695445 0.000000
vt -0.368673 1.533903 0.000000
vt -0.426988 1.592008 0.000000
vt -0.570037 1.435321 0.000000
vt -0.628352 1.493425 0.000000
vt -0.732374 1.322871 0.000000
vt -0.790689 1.380975 0.000000
vt -0.857456 1.290297 0.000000
vt -0.915771 1.307143 0.000000
vt -0.952062 1.309451 0.000000
vt -0.893747 1.308746 0.000000
vt -0.811516 1.373250 0.000000
vt -0.858974 1.390096 0.000000
vt -0.667714 1.477619 0.000000
vt -0.726028 1.535723 0.000000
vt -0.928477 1.215888 0.000000
vt -0.912370 1.295261 0.000000
vt -0.911679 1.228426 0.000000
vt -0.938711 1.228753 0.000000
vt -0.970685 1.295966 0.000000
vt -0.954992 1.216659 0.000000
vt -0.908965 1.229186 0.000000
vt -0.882329 1.212966 0.000000
vt -0.932227 1.022801 0.000000
vt -0.831202 1.000000 0.000000
vt -0.893918 1.015484 0.000000
vt -1.000000 1.016857 0.000000
vt -0.871618 1.031589 0.000000
vt -0.976831 1.032861 0.000000
vt 0.612901 0.596693 0.734362
vt 0.598539 0.557466 0.538120
vt 0.589981 0.597701 0.776608
vt 0.563827 0.539992 0.518041
vt 0.464971 0.591080 0.733514
vt 0.489060 0.594572 0.776156
vt 0.479732 0.556109 0.538011
vt 0.516770 0.539462 0.517998
vt 0.593335 0.537529 0.228293
vt 0.563460 0.516682 0.223453
vt 0.485744 0.533551 0.227696
vt 0.515754 0.516042 0.223392
vt 0.496224 0.840847 0.000000
vt 0.490194 0.872388 0.000000
vt 0.496227 0.884293 0.000000
vt 0.468436 0.873206 0.000000
vt 0.468435 0.853221 0.000000
vt 0.483437 0.845055 0.000000
vt 0.483434 0.888500 0.000000
vt 0.497284 0.876111 0.000000
vt 0.483222 0.840212 0.000000
vt 0.469341 0.840217 0.000000
vt 0.497131 0.852591 0.000000
# 397 texture vertices
vn 0.597905 0.057346 -0.314209
vn 0.924694 0.333245 -0.184088
vn 1.000759 0.095984 -0.525916
vn 0.172581 -0.190744 -0.966350
vn 0.641735 0.717175 -0.271727
vn 0.331883 0.943177 -0.016441
vn 0.012384 0.922393 -0.386055
vn -0.006878 0.738873 -0.673810
vn 0.035776 0.015715 -0.307329
vn 0.511693 0.727265 -0.457444
vn 0.296141 0.130083 -2.543999
vn 0.495811 2.903300 -0.287166
vn 0.022356 0.597501 -0.133302
vn -0.620706 -0.496328 2.860696
vn 1.669057 -1.008190 -0.552593
vn 1.907326 -2.066934 -1.239492
vn 0.696335 -0.161452 -0.699322
vn -0.453126 -1.373052 -0.612591
vn 0.656248 -0.403285 -0.637730
vn -1.738991 -1.071312 -0.485642
vn -0.343393 -4.300674 -2.214071
vn -0.718852 -0.147391 -0.679359
vn 0.709341 0.594472 -0.378733
vn 1.582320 0.453249 0.084843
vn 0.059485 3.126105 0.274939
vn 0.414236 2.085068 3.200567
vn 0.435114 0.853554 0.286569
vn 0.114514 0.723233 -0.681044
vn 0.443821 0.328654 0.833672
vn -0.378738 0.692419 0.614096
vn 0.084822 0.513273 0.854023
vn 0.451937 0.885492 -0.107966
vn 0.472255 0.654171 0.207366
vn 0.601804 1.332591 1.777111
vn 0.016926 0.686945 1.055184
vn 0.021706 0.880962 1.353205
vn 0.003596 0.145955 0.224194
vn -1.338222 -0.110349 0.587323
vn -0.019379 -0.837982 -0.081909
vn -0.373676 -0.954236 2.154840
vn 0.011603 -1.131825 -0.108433
vn -0.029070 -1.571353 -0.009023
vn -0.574854 0.115769 0.810025
vn -0.028995 -1.568970 -0.008942
vn 0.664193 0.391863 0.636625
vn 0.170761 0.114674 0.978617
vn 0.385047 0.136340 0.912771
vn -0.199104 -0.103006 -0.457537
vn -0.135142 -0.333911 -0.932867
vn -0.288823 -0.149421 -0.663709
vn -2.137856 1.042155 -1.040026
vn -0.641292 0.718229 -0.269985
vn -0.313151 0.949204 -0.030784
vn 0.331671 -1.713729 -1.503446
vn -0.502176 0.724848 -0.471610
vn -0.268530 0.797086 -0.540876
vn -0.569678 3.005824 -0.311918
vn -0.039956 2.579261 -0.538050
vn -1.586442 0.426254 0.139361
vn -0.696143 0.609631 -0.379125
vn -0.420783 0.861338 0.284674
vn -0.045503 1.403343 0.483652
vn -0.151413 1.701712 0.201911
vn -0.122928 0.723295 -0.679509
vn 0.572768 0.848977 1.789420
vn -0.373014 0.329882 0.867201
vn -0.090853 0.668551 0.626809
vn -0.445409 0.652544 0.218120
vn -0.425250 0.887237 -0.178807
vn -0.494812 0.725676 0.905895
vn 0.012101 1.413137 0.678740
vn 0.024478 2.831927 1.360323
vn -0.789770 1.436691 1.143401
vn 0.006221 1.394345 0.663098
vn -0.386133 0.137143 0.912191
vn -0.143273 0.148179 0.978527
vn -0.241908 -0.526853 0.814805
vn -0.257888 0.187438 0.947819
vn 0.133929 0.165517 0.977071
vn 0.019033 -0.423925 1.523207
vn -0.060084 -0.200719 -0.977804
vn -0.013707 -0.321306 -1.546942
vn -0.011684 -0.329266 -1.566531
vn -0.023490 0.310965 -0.950131
vn -0.024834 0.210797 -4.034036
vn -0.182625 0.109336 -2.090183
vn -0.202666 0.782434 -0.588832
vn -0.022396 0.189552 -3.627440
vn -1.596020 0.015531 0.916871
vn -1.132730 -1.036093 0.750194
vn -1.920688 0.013729 1.095267
vn 0.005267 1.176384 1.471368
vn 0.008359 -0.302404 1.410714
vn 1.109432 -0.986506 0.738087
vn -1.960955 0.050131 -1.247081
vn -0.688037 0.017692 -0.437083
vn -1.519351 -1.082054 -1.270976
vn -1.405147 0.034471 -0.900348
vn 0.191403 1.414536 -1.339768
vn 0.115751 0.855442 -0.810225
vn 1.534974 0.025734 -0.647171
vn 1.658754 -0.989929 -1.035398
vn 0.174212 -0.391598 1.169597
vn 0.265190 -0.604212 1.772267
vn 0.254619 -0.489920 1.792041
vn 0.172189 -0.327419 1.215788
vn 1.520464 0.064669 -1.570071
vn 1.805762 0.106637 -2.043949
vn -1.871802 0.081897 -1.976425
vn -1.554470 0.080612 -1.535547
vn 0.508137 0.326099 -0.797155
vn 0.380267 1.018704 -2.663737
vn 0.038757 -2.868737 -2.326651
vn 0.158406 -1.421344 -0.701583
vn 0.398409 -1.034685 -1.581113
vn 0.932669 0.281291 -0.225840
vn 3.084323 1.625012 -1.480734
vn 0.671838 0.035447 -0.678203
vn 1.537587 0.081122 -1.552142
vn 0.207322 -1.464041 -1.610524
vn 0.090592 -0.639663 -0.703703
vn 0.207093 -1.464433 -1.609798
vn -1.309915 0.089961 -1.718663
vn 0.132819 1.640184 -1.475377
vn 0.742775 0.089528 -1.715539
vn 0.494640 0.142709 -2.732769
vn 0.494640 0.142716 -2.732790
vn 0.742740 0.089546 -1.715496
vn -0.021762 0.189546 -3.627280
vn -0.024202 0.210792 -4.033888
vn 0.195424 0.782525 -0.591155
vn 0.157797 0.109306 -2.092320
vn 3.205025 -0.363993 -0.221749
vn -0.006003 -1.210286 -1.001431
vn 0.107765 -0.631069 -0.768204
vn 0.642738 -0.370467 -0.670554
vn 0.526632 -0.058761 -0.848060
vn 0.213195 -0.102585 -0.971609
vn -0.004599 0.663727 -0.747961
vn 0.184728 0.247249 1.277699
vn 0.259516 0.328518 1.781400
vn 0.236064 0.498234 1.764246
vn 0.163434 0.355029 1.228710
vn 0.106692 0.199429 0.974087
vn 0.593499 0.161845 0.788394
vn 1.659163 1.055510 1.662958
vn 0.941727 0.257856 0.216011
vn 2.077092 1.884964 0.507767
vn 1.816617 -0.882982 -0.060010
vn 0.792183 -0.365755 0.488538
vn 0.213491 -1.695785 -0.015821
vn 0.385842 -2.068442 0.465066
vn 0.603130 -0.293336 0.741747
vn 1.983075 -1.061013 1.029422
vn 1.546097 -1.542966 -0.089902
vn 1.546457 1.543555 0.071354
vn 0.134377 -1.892092 0.816798
vn 0.132122 -1.860296 0.802994
vn 1.770562 -0.990939 1.123194
vn 0.307719 0.945535 2.141489
vn 0.101709 0.312580 0.707857
vn 0.224987 -1.623399 1.447554
vn 0.224978 -1.623649 1.446245
vn 1.773150 -0.069160 1.317779
vn 0.147115 1.445705 1.601677
vn 0.171599 0.971078 0.166014
vn 0.251040 0.559363 0.115045
vn 0.167347 0.920380 0.353407
vn 0.010103 -1.825163 0.796302
vn 0.005838 -1.054275 0.459963
vn 0.005828 -1.054265 0.459994
vn 0.010082 -1.825129 0.796358
vn 1.791444 -0.045697 0.868495
vn 1.034719 -0.026390 0.501630
vn 0.010685 1.732189 0.982249
vn 0.006169 1.000584 0.567377
vn -0.000298 -1.568660 -0.081884
vn -0.000273 -1.568656 -0.081951
vn 1.110755 0.000487 -0.012974
vn 0.008359 1.369438 0.769415
vn -0.000239 -1.506937 -0.078814
vn -0.000290 -1.597656 -0.083436
vn -3.101855 0.044898 0.006081
vn 0.009332 -1.429441 -0.145544
vn 2.067339 -0.012127 0.225233
vn 1.055715 -0.006196 0.115024
vn 1.055701 -0.006190 0.115013
vn 2.067366 -0.012107 0.225208
vn 0.006679 1.834612 1.160015
vn 0.002993 0.820695 0.518927
vn -1.555993 -0.064205 1.233785
vn -0.904363 -0.037316 0.717094
vn 0.630318 -1.858735 -0.100898
vn 0.630940 1.858923 0.093351
vn -0.425119 -0.105240 4.722942
vn -0.915875 0.020357 1.774765
vn 0.901801 -0.062366 1.689981
vn 0.395478 -0.071059 0.915723
vn 0.181794 -0.029983 0.982879
vn 2.386860 0.082526 0.007179
vn 1.228175 -0.977531 -0.058449
vn 0.740463 1.383661 0.067858
vn -0.203459 -1.436527 -0.073846
vn 0.226033 -1.309549 -0.051511
vn 0.576600 -0.015396 0.816881
vn 0.159018 -0.043193 0.986330
vn -0.054149 0.918213 0.392369
vn -2.123078 0.035279 -0.873985
vn -0.779761 0.013047 -0.320642
vn -1.668267 -0.987965 -1.022014
vn -1.538808 0.024428 -0.637945
vn -0.199356 1.356104 -1.283313
vn -0.134194 0.912830 -0.863836
vn 1.399583 0.036357 -0.909776
vn 1.507834 -1.082468 -1.284551
vn 1.521238 0.064813 -1.568913
vn 1.803384 0.106425 -2.037413
vn -1.878021 0.082245 -1.978665
vn -1.555128 0.080657 -1.534477
vn -0.005052 0.285263 -0.958436
vn -0.602417 0.263633 -0.753386
vn -0.310293 -0.729228 -1.858352
vn -0.270461 -2.722492 -1.719355
vn -0.124606 -0.488025 -0.863890
vn -2.457487 0.918719 -1.368747
vn -0.225911 -1.463655 -1.608179
vn -0.098721 -0.639602 -0.702755
vn -0.098711 -0.639534 -0.702707
vn -0.225921 -1.463701 -1.608297
vn -1.774285 0.069342 -1.315832
vn -0.147298 1.605219 -1.442033
vn -3.100584 -1.463111 -1.606722
vn -1.554494 0.080781 -1.535513
vn -0.616270 0.092032 -1.759208
vn -0.431157 0.144859 -2.770757
vn -0.431161 0.144858 -2.770720
vn -0.616269 0.092032 -1.759209
vn -0.120541 -0.628627 -0.768309
vn -0.661053 -0.362566 -0.656928
vn -0.572291 -0.003809 -0.820041
vn -0.169082 -0.064398 -0.983496
vn 0.039844 2.834372 0.449156
vn -0.173440 0.853538 1.495033
vn -0.228565 1.121160 1.360791
vn -0.000156 1.598971 -0.484313
vn -0.168952 -0.306730 1.245716
vn -0.143639 -0.414494 1.154843
vn -0.162201 0.348385 1.230808
vn -0.233669 0.514794 1.759763
vn -0.218191 0.344869 1.783806
vn -0.156046 0.239619 1.283013
vn -0.709462 0.134387 0.691812
vn -0.699036 -0.018569 0.714845
vn -0.299431 0.145919 0.942894
vn -0.911608 0.311235 0.268520
vn -0.920793 0.246675 0.302146
vn -0.863819 -0.589680 -0.026358
vn -1.732622 -1.209019 -0.052796
vn 0.034308 -0.935435 0.351829
vn 0.055234 -3.254519 -0.398217
vn -0.542652 -0.297856 0.785373
vn -1.546118 -1.543949 -0.071401
vn -0.675692 -0.674738 -0.031204
vn -1.536866 -0.081208 1.552899
vn -0.121975 -1.860401 0.804336
vn -0.124013 -1.892233 0.817946
vn 1.366567 -1.151798 1.542927
vn 0.451743 -0.380747 0.510041
vn -0.277514 0.929326 2.105934
vn -0.207297 -1.623875 1.448974
vn -0.207139 -1.624358 1.448552
vn 1.310984 -0.090183 1.717928
vn -0.131360 1.477344 1.638317
vn -0.152670 0.919838 0.361373
vn -0.135728 0.977787 0.159720
vn -0.248399 1.219888 0.612913
vn 0.000402 -1.824821 0.797435
vn 0.000233 -1.053912 0.460550
vn 0.000229 -1.053902 0.460560
vn 0.000393 -1.824808 0.797459
vn 1.781776 -0.046371 0.888335
vn 1.029003 -0.026780 0.513027
vn 0.000964 1.732555 0.981918
vn 0.000553 1.000621 0.567086
vn -0.000268 -1.568688 -0.081357
vn -0.000249 -1.568686 -0.081405
vn -0.000374 -1.597523 -0.082912
vn -0.000277 -1.506958 -0.078372
vn -3.105308 0.034836 0.006082
vn -0.012782 -1.708721 -0.174004
vn -2.130387 -0.017598 0.343751
vn -0.970988 -0.008021 0.156675
vn -0.970969 -0.008021 0.156671
vn -2.130405 -0.017599 0.343752
vn 0.007259 -1.928695 1.157416
vn 0.002888 -0.765019 0.459079
vn 1.457353 -0.073299 1.397796
vn 0.808437 -0.040660 0.775397
vn -0.595442 -0.092195 1.766268
vn -0.595438 -0.092192 1.766262
vn 0.543414 0.505679 6.039843
vn 0.219702 0.092843 0.971139
vn -0.382067 -0.096732 0.919058
vn -0.845449 -0.033552 1.713554
vn -0.170498 -0.027048 0.984987
vn 0.004385 1.298845 0.884428
vn 0.006259 -0.056350 1.078380
vn 0.003899 -0.035101 0.671723
vn -0.193294 -0.088328 1.697341
vn -0.199125 -0.122894 1.459906
vn -0.562736 -0.192366 0.803942
vn -0.171246 -0.058176 0.983509
vn 0.063405 0.923573 0.378145
vn -0.040373 -0.046216 -0.998115
vn -0.018845 -0.024128 -0.999531
vn 0.118680 0.117088 -0.986005
vn 0.095607 0.122864 -0.987808
vn 0.222849 0.460568 -0.859195
vn 0.203739 0.478725 -0.853998
vn 0.346367 0.744411 -0.918682
vn 0.542432 1.242525 -1.481378
vn 0.448658 1.372070 0.364726
vn 0.479644 1.533328 0.411657
vn 0.369461 0.413326 0.832262
vn 0.387259 0.401447 0.829982
vn 0.263040 0.274406 0.924938
vn 0.232102 0.242733 0.941918
vn 0.122508 0.130450 0.983857
vn 0.123774 0.131748 0.983526
vn 0.034673 0.040369 0.998583
vn -0.007431 -0.002838 0.999968
vn -0.176895 -0.172994 1.788786
vn -0.130850 -0.127965 1.323179
vn -0.901556 -2.232628 2.748429
vn -0.361905 -0.518162 0.774940
vn -0.088471 -0.899373 -0.310315
vn 1.314809 -2.119193 -0.394971
vn -0.639492 -0.489817 -0.592561
vn -0.678537 -0.373653 -0.632432
vn -0.906669 -0.843590 -0.810248
vn -0.779798 -0.803724 -0.703176
vn 0.976760 -0.008366 -0.214174
vn 0.967332 -0.164444 -0.192944
vn 1.734455 -0.378840 0.124347
vn -0.000640 -0.240247 -1.724124
vn -1.494880 -0.286216 -0.143288
vn -1.576954 -0.306402 -0.149666
vn -0.413772 -0.141467 0.899322
vn 0.826898 0.062545 0.558863
vn -0.264731 -2.293666 0.062807
vn -0.242247 -1.094173 -0.006762
vn -0.205247 -3.728268 -0.038638
vn -0.019061 -2.221423 -0.039036
vn -0.013773 -1.473857 -0.090905
vn -0.012996 -1.662149 -0.100613
# 355 vertex normals
g Gnome
s 12
f 62/62/62 55/55/55 61/61/61 60/60/60
s 3
f 66/66/66 67/67/67 65/65/65 64/64/64
s 7
f 69/69/69 70/70/70 61/61/61 63/63/63
s 245
f 75/422/75 76/423/76 60/77/60 77/424/77
s 4
f 88/88/88 81/81/81 82/82/82 90/90/90
s 59
f 92/92/92 82/82/82 85/85/85 91/91/91
s 1
f 67/67/67 100/100/100 63/63/63 55/55/55
s 5
f 105/105/105 106/106/106 68/68/68 66/66/66
s 56
f 112/427/112 64/113/64 111/426/111 108/425/108
s 1
f 119/119/119 91/91/91 118/118/118 117/117/117
s 510
f 117/117/117 89/89/89 121/121/121 122/122/122
s 1
f 125/125/125 124/124/124 123/123/123 126/126/126
f 129/129/129 128/128/128 127/127/127 130/130/130
f 133/133/133 132/132/132 131/131/131 134/134/134
f 119/119/119 136/136/136 135/135/135 137/137/137
s 2
f 120/120/120 119/119/119 137/137/137 138/138/138
s 4
f 135/135/135 139/139/139 138/138/138 137/137/137
s 1
f 140/140/140 120/120/120 138/138/138 139/139/139
f 143/143/143 142/142/142 141/141/141 144/144/144
s 2
f 142/142/142 146/146/146 145/145/145 141/141/141
s 1
f 146/146/146 148/148/148 147/147/147 145/145/145
s 4
f 141/141/141 145/145/145 147/147/147 144/144/144
s 1
f 151/151/151 150/150/150 149/149/149 152/152/152
f 148/148/148 146/146/146 153/153/153 154/154/154
f 142/142/142 143/143/143 155/155/155 156/156/156
s 24
f 158/158/158 157/157/157 49/49/49 129/129/129
s 36
f 161/161/161 160/160/160 159/159/159 47/47/47
s 193
f 157/157/157 162/162/162 48/48/48 49/49/49
s 46
f 49/49/49 50/50/50 128/128/128 129/129/129
s 34
f 50/50/50 47/47/47 159/159/159 128/128/128
s 1
f 164/164/164 161/161/161 163/163/163 165/165/165
s 4
f 164/164/164 167/167/167 166/166/166 168/168/168
s 1
f 167/167/167 160/160/160 169/169/169 166/166/166
s 2
f 160/160/160 161/161/161 170/170/170 169/169/169
s 1
f 161/161/161 164/164/164 168/168/168 170/170/170
s 8
f 169/169/169 170/170/170 168/168/168 166/166/166
s 4
f 167/167/167 164/164/164 146/146/146 142/142/142
s 1
f 173/173/173 172/172/172 171/171/171 174/174/174
f 176/176/176 175/175/175 172/172/172 173/173/173
f 89/89/89 86/86/86 114/114/114 115/115/115
f 85/85/85 82/82/82 78/78/78 79/79/79
f 136/136/136 140/140/140 139/139/139 135/135/135
f 178/178/178 177/177/177 175/175/175 176/176/176
s 2
f 180/180/180 179/179/179 140/140/140 136/136/136
s 1
f 181/181/181 74/74/74 177/177/177 178/178/178
s 37
f 182/182/182 56/56/56 74/74/74 181/181/181
s 7973
f 58/58/58 56/56/56 182/182/182 183/183/183
s 13184
f 183/183/183 182/182/182 162/162/162 157/157/157
s 28416
f 58/185/58 183/372/183 184/373/184 59/287/59
s 60424
f 183/372/183 157/370/157 158/371/158 184/373/184
s 2
f 84/84/84 86/86/86 117/117/117 118/118/118
f 84/84/84 118/118/118 91/91/91 85/85/85
s 1
f 185/374/185 54/104/54 51/53/51 69/363/69
f 185/374/185 69/363/69 63/360/63 100/366/100
f 148/148/148 143/143/143 144/144/144 147/147/147
f 188/188/188 187/187/187 186/186/186 189/189/189
s 2
f 150/150/150 148/148/148 154/154/154 149/149/149
s 12
f 146/146/146 188/188/188 189/189/189 153/153/153
s 2
f 143/143/143 151/151/151 152/152/152 155/155/155
s 12
f 187/187/187 142/142/142 156/156/156 186/186/186
s 1
f 189/189/189 186/186/186 152/152/152 149/149/149
s 6
f 153/153/153 189/189/189 149/149/149 154/154/154
s 10
f 186/186/186 156/156/156 155/155/155 152/152/152
s 1795
f 191/191/191 190/190/190 125/125/125 192/192/192
s 2051
f 193/193/193 191/191/191 192/192/192 194/194/194
s 4
f 195/195/195 161/161/161 47/47/47 196/196/196
s 3
f 162/162/162 193/193/193 194/194/194 48/48/48
s 24
f 197/197/197 195/195/195 196/196/196 198/198/198
s 232
f 192/192/192 125/125/125 126/126/126 199/199/199
s 12480
f 194/194/194 192/192/192 199/199/199 196/196/196
s 68
f 48/48/48 194/194/194 196/196/196 47/47/47
s 8248
f 196/196/196 199/199/199 126/126/126 198/198/198
s 98
f 200/200/200 164/164/164 165/165/165 201/201/201
s 1
f 161/161/161 195/195/195 202/202/202 163/163/163
s 384
f 195/195/195 200/200/200 201/201/201 202/202/202
s 4
f 163/163/163 202/202/202 201/201/201 165/165/165
s 16
f 187/187/187 188/188/188 203/203/203 204/204/204
s 1888
f 188/188/188 200/200/200 205/205/205 203/203/203
s 1
f 200/200/200 207/207/207 206/206/206 205/205/205
s 2
f 207/207/207 187/187/187 204/204/204 206/206/206
s 4
f 205/205/205 206/206/206 204/204/204 203/203/203
f 207/207/207 200/200/200 208/208/208 209/209/209
s 1152
f 200/200/200 195/195/195 210/210/210 208/208/208
s 32
f 195/195/195 197/197/197 211/211/211 210/210/210
s 2
f 197/197/197 207/207/207 209/209/209 211/211/211
s 1
f 210/210/210 211/211/211 209/209/209 208/208/208
s 12
f 213/213/213 52/52/52 212/212/212 214/214/214
s 1
f 217/217/217 216/216/216 215/215/215 218/218/218
s 2
f 216/216/216 220/220/220 219/219/219 215/215/215
s 1
f 220/220/220 222/222/222 221/221/221 219/219/219
s 2
f 222/222/222 217/217/217 218/218/218 221/221/221
s 4
f 219/219/219 221/221/221 218/218/218 215/215/215
s 1
f 224/224/224 223/223/223 216/216/216 217/217/217
s 2
f 223/223/223 225/225/225 220/220/220 216/216/216
s 1
f 225/225/225 226/226/226 222/222/222 220/220/220
s 2
f 226/226/226 224/224/224 217/217/217 222/222/222
s 1
f 228/228/228 227/227/227 223/223/223 224/224/224
s 2
f 227/227/227 150/150/150 225/225/225 223/223/223
s 4
f 150/150/150 151/151/151 226/226/226 225/225/225
s 2
f 151/151/151 228/228/228 224/224/224 226/226/226
f 151/151/151 143/143/143 229/229/229 228/228/228
s 1
f 143/143/143 148/148/148 230/230/230 229/229/229
s 2
f 148/148/148 150/150/150 227/227/227 230/230/230
s 1
f 230/230/230 227/227/227 228/228/228 229/229/229
s 72
f 207/207/207 167/167/167 142/142/142 187/187/187
s 514
f 164/164/164 200/200/200 188/188/188 146/146/146
s 64
f 197/197/197 160/160/160 167/167/167 207/207/207
s 1
f 233/233/233 232/232/232 231/231/231 234/234/234
s 2
f 232/232/232 236/236/236 235/235/235 231/231/231
s 1
f 236/236/236 238/238/238 237/237/237 235/235/235
s 2
f 238/238/238 233/233/233 234/234/234 237/237/237
s 4
f 235/235/235 237/237/237 234/234/234 231/231/231
s 2
f 233/233/233 173/173/173 174/174/174 239/239/239
f 172/172/172 232/232/232 240/240/240 171/171/171
s 4
f 232/232/232 233/233/233 239/239/239 240/240/240
s 1
f 171/171/171 240/240/240 239/239/239 174/174/174
s 2
f 238/238/238 176/176/176 173/173/173 233/233/233
s 26
f 175/175/175 236/236/236 232/232/232 172/172/172
s 1888
f 241/241/241 60/60/60 61/61/61 70/70/70
s 1280
f 242/242/242 241/241/241 70/70/70 213/213/213
s 14
f 70/70/70 51/51/51 52/52/52 213/213/213
s 4
f 86/86/86 87/87/87 116/116/116 114/114/114
s 49
f 82/82/82 83/83/83 80/80/80 78/78/78
s 4
f 83/83/83 85/85/85 79/79/79 80/80/80
s 104
f 243/243/243 82/82/82 93/93/93 244/244/244
s 3369
f 91/91/91 241/241/241 245/245/245 92/92/92
s 2656
f 241/241/241 243/243/243 244/244/244 245/245/245
s 105
f 92/92/92 245/245/245 244/244/244 93/93/93
s 128
f 82/82/82 243/243/243 246/246/246 90/90/90
s 4
f 247/247/247 178/178/178 176/176/176 238/238/238
s 24
f 177/177/177 248/248/248 236/236/236 175/175/175
s 96
f 248/248/248 247/247/247 238/238/238 236/236/236
s 2
f 179/179/179 91/91/91 120/120/120 140/140/140
f 60/60/60 241/241/241 91/91/91 179/179/179
s 1
f 249/249/249 181/181/181 178/178/178 247/247/247
s 17
f 74/74/74 71/71/71 248/248/248 177/177/177
s 64
f 71/71/71 249/249/249 247/247/247 248/248/248
s 1
f 250/250/250 182/182/182 181/181/181 249/249/249
s 64
f 72/72/72 250/250/250 249/249/249 71/71/71
s 4
f 60/77/60 64/113/64 113/428/113 77/424/77
s 29184
f 72/72/72 75/75/75 251/251/251 250/250/250
s 8196
f 182/182/182 250/250/250 193/193/193 162/162/162
s 44036
f 250/250/250 251/251/251 191/191/191 193/193/193
s 66160
f 75/422/75 77/424/77 252/430/252 251/429/251
s 250624
f 251/251/251 252/252/252 190/190/190 191/191/191
s 314
f 253/253/253 76/76/76 72/72/72 73/73/73
s 1048
f 253/253/253 73/73/73 56/56/56 57/57/57
s 3840
f 253/253/253 57/57/57 55/55/55 62/62/62
s 2561
f 253/253/253 62/62/62 60/60/60 76/76/76
s 1
f 256/256/256 255/255/255 254/254/254 257/257/257
s 2
f 255/255/255 259/259/259 258/258/258 254/254/254
s 1
f 259/259/259 261/261/261 260/260/260 258/258/258
s 4
f 254/254/254 258/258/258 260/260/260 257/257/257
s 1
f 261/261/261 259/259/259 262/262/262 263/263/263
f 255/255/255 256/256/256 264/264/264 265/265/265
s 60
f 267/267/267 266/266/266 130/130/130 96/96/96
s 36
f 266/266/266 158/158/158 129/129/129 130/130/130
s 69
f 269/269/269 268/268/268 94/94/94 270/270/270
s 4
f 160/160/160 269/269/269 270/270/270 159/159/159
s 386
f 271/271/271 267/267/267 96/96/96 97/97/97
s 17
f 130/130/130 127/127/127 95/95/95 96/96/96
s 65
f 127/127/127 270/270/270 94/94/94 95/95/95
s 1
f 128/128/128 159/159/159 270/270/270 127/127/127
s 4
f 274/274/274 273/273/273 272/272/272 275/275/275
s 2
f 273/273/273 268/268/268 276/276/276 272/272/272
s 8
f 268/268/268 269/269/269 277/277/277 276/276/276
s 2
f 269/269/269 274/274/274 275/275/275 277/277/277
s 1
f 276/276/276 277/277/277 275/275/275 272/272/272
s 2
f 268/268/268 273/273/273 278/278/278 279/279/279
s 4
f 273/273/273 274/274/274 259/259/259 255/255/255
s 1
f 282/439/282 281/438/281 280/341/280 283/440/283
f 134/281/134 131/280/131 281/438/281 282/439/282
s 3
f 110/110/110 284/284/284 132/132/132 133/133/133
s 86
f 101/101/101 285/285/285 284/284/284 110/110/110
s 8
f 59/287/59 104/368/104 67/361/67 55/184/55
s 3669
f 103/103/103 286/286/286 285/285/285 101/101/101
s 7425
f 286/286/286 267/267/267 271/271/271 285/285/285
s 513
f 59/287/59 184/373/184 287/378/287 104/368/104
s 529
f 104/368/104 287/378/287 286/377/286 103/367/103
s 513
f 184/373/184 158/371/158 266/375/266 287/378/287
s 2577
f 287/378/287 266/375/266 267/376/267 286/377/286
s 2
f 185/374/185 100/366/100 68/362/68 106/369/106
s 3
f 185/374/185 106/369/106 98/364/98 54/104/54
s 1
f 290/290/290 289/289/289 288/288/288 291/291/291
f 261/261/261 256/256/256 257/257/257 260/260/260
f 289/289/289 290/290/290 292/292/292 293/293/293
f 296/296/296 295/295/295 294/294/294 297/297/297
s 2
f 290/290/290 261/261/261 263/263/263 292/292/292
s 12
f 259/259/259 296/296/296 297/297/297 262/262/262
s 2
f 256/256/256 289/289/289 293/293/293 264/264/264
s 12
f 295/295/295 255/255/255 265/265/265 294/294/294
s 1
f 297/297/297 294/294/294 293/293/293 292/292/292
s 6
f 262/262/262 297/297/297 292/292/292 263/263/263
s 10
f 294/294/294 265/265/265 264/264/264 293/293/293
s 479
f 300/300/300 299/299/299 298/298/298 124/124/124
s 560
f 190/190/190 300/300/300 124/124/124 125/125/125
s 15378
f 299/299/299 302/302/302 301/301/301 298/298/298
s 8208
f 302/302/302 271/271/271 97/97/97 301/301/301
s 33
f 268/268/268 304/304/304 303/303/303 94/94/94
s 6
f 304/304/304 306/306/306 305/305/305 303/303/303
s 2
f 306/306/306 197/197/197 198/198/198 305/305/305
s 114693
f 124/124/124 298/298/298 307/307/307 123/123/123
s 231424
f 301/301/301 303/303/303 307/307/307 298/298/298
s 32801
f 97/97/97 94/94/94 303/303/303 301/301/301
s 16388
f 305/305/305 123/123/123 307/307/307 303/303/303
s 4
f 198/198/198 126/126/126 123/123/123 305/305/305
s 18
f 273/273/273 309/309/309 308/308/308 278/278/278
s 448
f 309/309/309 304/304/304 310/310/310 308/308/308
s 8
f 304/304/304 268/268/268 279/279/279 310/310/310
s 1
f 310/310/310 279/279/279 278/278/278 308/308/308
s 32
f 295/295/295 296/296/296 311/311/311 312/312/312
s 16
f 296/296/296 314/314/314 313/313/313 311/311/311
s 1
f 314/314/314 309/309/309 315/315/315 313/313/313
s 8080
f 309/309/309 295/295/295 312/312/312 315/315/315
s 2
f 313/313/313 315/315/315 312/312/312 311/311/311
s 8
f 309/309/309 314/314/314 316/316/316 317/317/317
s 16
f 314/314/314 306/306/306 318/318/318 316/316/316
s 256
f 306/306/306 304/304/304 319/319/319 318/318/318
s 5184
f 304/304/304 309/309/309 317/317/317 319/319/319
s 1
f 318/318/318 319/319/319 317/317/317 316/316/316
s 9
f 212/212/212 321/321/321 320/320/320 214/214/214
s 25
f 322/322/322 213/213/213 214/214/214 320/320/320
s 97
f 52/52/52 99/99/99 321/321/321 212/212/212
s 122
f 99/99/99 322/322/322 320/320/320 321/321/321
s 1
f 325/325/325 324/324/324 323/323/323 326/326/326
s 2
f 324/324/324 328/328/328 327/327/327 323/323/323
s 1
f 328/328/328 330/330/330 329/329/329 327/327/327
s 2
f 330/330/330 325/325/325 326/326/326 329/329/329
s 4
f 327/327/327 329/329/329 326/326/326 323/323/323
s 1
f 332/332/332 331/331/331 324/324/324 325/325/325
s 2
f 331/331/331 291/291/291 328/328/328 324/324/324
s 1
f 291/291/291 288/288/288 330/330/330 328/328/328
s 2
f 288/288/288 332/332/332 325/325/325 330/330/330
s 1
f 334/334/334 333/333/333 331/331/331 332/332/332
s 2
f 333/333/333 290/290/290 291/291/291 331/331/331
f 289/289/289 334/334/334 332/332/332 288/288/288
f 289/289/289 256/256/256 335/335/335 334/334/334
s 1
f 256/256/256 261/261/261 336/336/336 335/335/335
s 2
f 261/261/261 290/290/290 333/333/333 336/336/336
s 1
f 336/336/336 333/333/333 334/334/334 335/335/335
s 2562
f 309/309/309 273/273/273 255/255/255 295/295/295
s 4
f 274/274/274 314/314/314 296/296/296 259/259/259
f 269/269/269 306/306/306 314/314/314 274/274/274
s 1
f 339/343/339 338/340/338 337/339/337 340/345/340
s 14
f 338/340/338 342/433/342 341/346/341 337/339/337
s 1
f 342/433/342 344/435/344 343/434/343 341/346/341
s 14
f 344/435/344 339/343/339 340/345/340 343/434/343
s 16
f 341/346/341 343/434/343 340/345/340 337/339/337
f 338/340/338 339/343/339 345/436/345 346/437/346
s 8
f 339/343/339 282/337/282 283/338/283 345/436/345
s 32
f 281/438/281 338/441/338 346/443/346 280/341/280
s 1
f 283/338/283 280/283/280 346/437/346 345/436/345
s 108
f 344/435/344 134/282/134 282/337/282 339/343/339
s 44
f 131/280/131 342/442/342 338/441/338 281/438/281
s 768
f 64/64/64 347/347/347 105/105/105 66/66/66
s 3328
f 347/347/347 348/348/348 322/322/322 105/105/105
s 2176
f 348/348/348 242/242/242 213/213/213 322/322/322
s 68
f 98/98/98 105/105/105 322/322/322 99/99/99
s 193
f 87/87/87 89/89/89 115/115/115 116/116/116
s 684
f 89/89/89 350/350/350 349/349/349 121/121/121
s 12848
f 350/350/350 347/347/347 351/351/351 349/349/349
s 129936
f 347/347/347 117/117/117 122/122/122 351/351/351
s 65588
f 351/351/351 122/122/122 121/121/121 349/349/349
s 443392
f 347/347/347 241/241/241 242/242/242 348/348/348
s 1
f 243/243/243 350/350/350 352/352/352 246/246/246
s 256
f 350/350/350 89/89/89 88/88/88 352/352/352
s 2
f 246/246/246 352/352/352 88/88/88 90/90/90
s 393217
f 241/241/241 347/347/347 350/350/350 243/243/243
s 272
f 354/354/354 353/353/353 344/344/344 342/342/342
s 96
f 353/353/353 133/133/133 134/134/134 344/344/344
s 64
f 132/132/132 354/354/354 342/342/342 131/131/131
s 524288
f 117/117/117 180/180/180 136/136/136 119/119/119
f 347/347/347 64/64/64 180/180/180 117/117/117
s 272
f 355/355/355 109/109/109 353/353/353 354/354/354
s 33
f 109/109/109 110/110/110 133/133/133 353/353/353
s 1
f 284/284/284 355/355/355 354/354/354 132/132/132
s 256
f 356/356/356 108/108/108 109/109/109 355/355/355
s 1
f 285/285/285 356/356/356 355/355/355 284/284/284
s 2
f 160/160/160 197/197/197 306/306/306 269/269/269
s 377344
f 108/108/108 356/356/356 357/357/357 112/112/112
s 512
f 285/285/285 271/271/271 302/302/302 356/356/356
s 791168
f 356/356/356 302/302/302 299/299/299 357/357/357
s 3145801
f 77/424/77 113/428/113 358/432/358 252/430/252
s 1081456
f 113/428/113 112/427/112 357/431/357 358/432/358
s 14680616
f 252/252/252 358/358/358 300/300/300 190/190/190
s 33098052
f 358/358/358 357/357/357 299/299/299 300/300/300
s 1
f 359/359/359 111/111/111 64/64/64 65/65/65
s 33
f 359/359/359 65/65/65 67/67/67 102/102/102
s 236
f 359/359/359 102/102/102 101/101/101 107/107/107
s 1262
f 359/359/359 107/107/107 108/108/108 111/111/111
s 1
f 64/64/64 60/60/60 179/179/179 180/180/180
f 362/381/362 361/380/361 360/379/360 363/382/363
f 364/383/364 362/381/362 363/382/363 365/384/365
f 366/385/366 364/383/364 365/384/365 367/386/367
s 2
f 368/387/368 366/385/366 367/386/367 369/388/369
s 1
f 370/389/370 368/387/368 369/388/369 371/390/371
f 372/391/372 370/389/370 371/390/371 373/392/373
f 374/393/374 372/391/372 373/392/373 375/394/375
f 376/395/376 374/393/374 375/394/375 377/396/377
f 378/397/378 376/395/376 377/396/377 379/398/379
s 14
f 380/399/380 378/397/378 379/398/379 381/400/381
s 2
f 384/403/384 383/402/383 382/401/382 385/404/385
f 386/405/386 384/403/384 385/404/385 387/406/387
s 1
f 361/380/361 386/405/386 387/406/387 360/379/360
s 115
f 383/402/383 389/408/389 388/407/388 390/409/390
s 4
f 382/401/382 383/402/383 390/409/390 391/410/391
s 1
f 392/411/392 382/401/382 391/410/391 393/412/393
s 8100
f 380/399/380 381/400/381 394/413/394 395/414/395
s 24656
f 389/408/389 380/399/380 395/414/395 388/407/388
s 102540
f 381/400/381 392/411/392 393/412/393 394/413/394
s 8
f 398/417/398 397/416/397 396/415/396 399/418/399
f 400/419/400 398/417/398 399/418/399 401/420/401
s 131616
f 395/414/395 394/413/394 396/415/396 397/416/397
s 57472
f 388/407/388 395/414/395 397/416/397 398/417/398
s 199684
f 394/413/394 393/412/393 399/418/399 396/415/396
s 32899
f 390/409/390 388/407/388 398/417/398 400/419/400
s 4
f 391/410/391 390/409/390 400/419/400 401/420/401
s 1
f 393/412/393 391/410/391 401/420/401 399/418/399
f 48/48/48 47/47/47 49/49/49
s 6
f 49/49/49 47/47/47 50/50/50
s 1
f 52/54/52 51/53/51 53/59/53
f 51/53/51 54/104/54 53/59/53
f 56/56/56 55/55/55 57/57/57
s 2
f 58/58/58 55/55/55 56/56/56
f 59/287/59 55/184/55 58/185/58
s 12
f 61/61/61 55/55/55 63/63/63
s 3
f 66/66/66 68/68/68 67/67/67
s 7
f 69/69/69 51/51/51 70/70/70
s 3
f 72/72/72 71/71/71 73/73/73
s 5
f 73/73/73 71/71/71 74/74/74
s 30
f 56/56/56 73/73/73 74/74/74
s 245
f 76/423/76 75/422/75 72/421/72
s 1
f 79/79/79 78/78/78 80/80/80
s 3
f 82/82/82 81/81/81 83/83/83
s 0
f 81/81/81 84/84/84 83/83/83
s 4
f 84/84/84 85/85/85 83/83/83
f 86/86/86 84/84/84 87/87/87
f 81/81/81 88/88/88 89/89/89
s 59
f 92/92/92 93/93/93 82/82/82
s 1
f 95/95/95 94/94/94 96/96/96
s 2
f 96/96/96 94/94/94 97/97/97
s 1
f 54/104/54 98/364/98 53/59/53
f 98/364/98 99/365/99 53/59/53
f 67/67/67 68/68/68 100/100/100
s 6
f 67/67/67 101/101/101 102/102/102
s 8
f 103/103/103 101/101/101 67/67/67
f 104/368/104 103/367/103 67/361/67
s 3
f 99/365/99 52/54/52 53/59/53
s 5
f 105/105/105 98/98/98 106/106/106
s 3
f 108/108/108 107/107/107 109/109/109
s 1
f 107/107/107 110/110/110 109/109/109
s 13
f 101/101/101 110/110/110 107/107/107
s 56
f 112/427/112 113/428/113 64/113/64
s 1
f 115/115/115 114/114/114 116/116/116
s 0
f 84/84/84 81/81/81 87/87/87
s 3
f 81/81/81 89/89/89 87/87/87
s 1
f 119/119/119 120/120/120 91/91/91
s 510
f 89/89/89 117/117/117 86/86/86
# 358 faces
g
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment