diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 0000000..f8b4888 --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": null +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000..2ae2e41 Binary files /dev/null and b/.vs/slnx.sqlite differ diff --git a/FrameBuffer.cs b/FrameBuffer.cs deleted file mode 100644 index ce19694..0000000 --- a/FrameBuffer.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Print image to screen. - * - * Just 'draw' the byte array to the buffer. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.IO; - -namespace ConsoleGraphics -{ - class FrameBuffer : Program - { - private static int lastTime; - private static int numRenderings = 0; - private const short sampleSize = 100; - private string lastFrame = ""; - Stream s = Console.OpenStandardOutput(); - - private void vSync(short targetFrameRate, int delay, int startDrawTime) - { - //Synchronize frames and display framerate to the lower right corner of the render window - int targetDelay = 1000 / targetFrameRate; - if (delay < targetDelay && VSYNC_ON)//we're too fast - { - System.Threading.Thread.Sleep(targetDelay - delay); - } - - if (numRenderings == sampleSize) - { - int y = Environment.TickCount - lastTime; - if (y != 0) - printch((sampleSize * 1000 / y).ToString().ToCharArray(), RENDER_WIDTH - 50, RENDER_HEIGHT + 1); - numRenderings = 0; - } - } - - public void drawFrame(byte[,] image, int a = 0, int b = 0) - { - //use cudafy / multithreading to paint quickly, also invoke writetoconsole? - byte[] bufImg = new byte[RENDER_HEIGHT * RENDER_WIDTH]; - - for (int x = 0; x < RENDER_WIDTH; x++) - for (int y = 0; y < RENDER_HEIGHT; y++) - bufImg[x+y*RENDER_WIDTH] = image[x,y]; - int beginRender = Environment.TickCount; - - Console.SetCursorPosition(a, b); - //.Flush(); - //string iString = bufImg.ToString(); - //byte[] b = Encoding.UTF8.GetBytes(iString); - //if (string.Compare(lastFrame, iString) != 0) - //{ - s.Write(bufImg, 0, bufImg.Length); - // lastFrame = iString; - //} - int endRender = Environment.TickCount - beginRender; - - vSync(MAX_FPS, endRender, beginRender); - - if (numRenderings == 0) - lastTime = Environment.TickCount; - - numRenderings++; - } - } -} diff --git a/Game.cs b/Game.cs new file mode 100644 index 0000000..b67affe --- /dev/null +++ b/Game.cs @@ -0,0 +1,190 @@ +using System; +using System.Threading; +using System.IO; +using ConsoleGraphics.Maths; +using ConsoleGraphics.Render; +using ConsoleGraphics.Utils; + +namespace ConsoleGraphics +{ + public static class Game + { + //special characters:█ ▄ ▀ ■ + //public bool FRAMERATE_ON = true; + + public static bool USE_VSYNC = false; + public static ThreeState renderState = new ThreeState(0); + public const short RENDER_WIDTH = 300; + public const short RENDER_HEIGHT = 100; + public const short MAX_FPS = 1000; + public const float PI = (float)3.1415926535; + + //static char[, ,] numerals = new char[9, 8, 10]; + public static char[] levels; + + public static volatile Mesh ActiveMesh = null; + public static Light light1 = new Light(0, 0, 0, 700); + + public static void Main(string[] args) + { + try + { + ActiveMesh = Mesh.LoadMeshFromFile(@"Resources\Meshes\link.obj"); + } + catch(Exception e) + { + Console.WriteLine($"Failed to load mesh: {e.Message}"); + Console.Read(); + return; + } + + //BrightnessInit.go(); + //BrightnessInit.sortstuff(); + GameInit(RENDER_WIDTH, RENDER_HEIGHT, "render"); + ActiveMesh.Translate(new Vector3(-800, -300, -8)); + //someShape.rotate((float)0.25); + + FrameBuffer.DrawFrame(Rasterizer.RenderSolid(ActiveMesh)); + //Console.ReadLine(); + //someShape.rotate((float)(3.1415)); + + // render loop + while (true) + { + //light1.intensity = (int)((double)800 * Math.Sin(4*i)); + //someShape.rotate(0.005, 0); + //someShape.rotate(0.005, 1); + //someShape.rotate(0.005, 2); + //someShape.translate(new Mesh.point3((float)Math.Sin(i), 0, 0)); + // buffer.drawFrame(drawLine(new byte[RENDER_HEIGHT * RENDER_WIDTH], a1, a2)); + if (renderState.x == 0) + FrameBuffer.DrawFrame(Rasterizer.RenderSolid(ActiveMesh)); + else if (renderState.x == 1) + FrameBuffer.DrawFrame(Rasterizer.RenderVertices(ActiveMesh)); + else if (renderState.x == 2) + FrameBuffer.DrawFrame(Rasterizer.RenderWire(ActiveMesh)); + + //light1.coords.x = 1000 * (float)Math.Sin(i); + // light1.coords.y = 1000 * (float)Math.Sin(i); + //light1.coords.z = 100 * (float)Math.Sin(i); + //someShape.rotate((float)0.005, 0); + //someShape.rotate((float)0.005, 1); + } + } + + private static void GameInit(short width, short height, string title) + { + Console.Title = title; + Console.CursorVisible = false; + Console.BackgroundColor = ConsoleColor.Black; + + SetConsoleSize(width, height); + + //clear colors from user preset. + Console.Clear(); + Console.SetCursorPosition(0, height); + Console.Write(new String('▄', RENDER_WIDTH)); + Console.ForegroundColor = ConsoleColor.Cyan; + + StreamReader levelsReader = new StreamReader("Resources\\levels.txt"); + + levels = new char[256]; + int index = 0; + while (!levelsReader.EndOfStream && index < 256) + { + string e1 = levelsReader.ReadLine(); + levels[index] = Char.Parse(e1); + index++; + } + + Thread inputThread = new Thread(MainGetInput); + inputThread.Start(); + //Thread soundPlayer = new Thread(playSound); + //soundPlayer.Start(); + } + + private static void SetConsoleSize(short width, short height) + { + // loop forever. only return when the window size and buffer size is set + while (true) + { + try + { + Console.SetWindowSize(width, height + 15); + Console.SetBufferSize(width, height + 15); + // exit the function allowing everything else to initialise + return; + } + catch (ArgumentOutOfRangeException) + { + Console.WriteLine("Decrease your font size and press enter"); + Console.WriteLine("You can resize the font using 'CTRL + MouseWheel'"); + Console.ReadLine(); + } + } + } + + private static byte[,] LoadTexture(string loc) + { + byte[,] loadedTexture = new byte[2, 2]; + return (loadedTexture); + } + + public static void printch(char[] charId, int x, int y) + { + Console.SetCursorPosition(0, RENDER_HEIGHT + 4); + Console.Write(new string(' ', 10)); + Console.SetCursorPosition(0, RENDER_HEIGHT + 4); + Console.Write(charId); + } + + private static void MainGetInput() + { + //Console.TreatControlCAsInput = true; + + while (true) + { + ConsoleKeyInfo keyInfo = Console.ReadKey(); + if (keyInfo.Key == ConsoleKey.Escape) + { + Environment.Exit(0); + return; + } + + switch (keyInfo.Key) + { + case ConsoleKey.Spacebar: + renderState.changeState(); + break; + case ConsoleKey.W: + ActiveMesh.Translate(0, 0, 0.1f); + break; + case ConsoleKey.A: + ActiveMesh.Translate(-10.0f, 0, 0); + break; + case ConsoleKey.S: + ActiveMesh.Translate(0, 0, -0.1f); + break; + case ConsoleKey.D: + ActiveMesh.Translate(10.0f, 0, 0); + break; + case ConsoleKey.R: + ActiveMesh.Rotate(0.01, 0); + break; + case ConsoleKey.T: + ActiveMesh.Rotate(0.01, 1); + break; + case ConsoleKey.Y: + ActiveMesh.Rotate(0.01, 2); + break; + case ConsoleKey.Q: + ActiveMesh.Translate(0, -10.0f, 0); + break; + case ConsoleKey.E: + ActiveMesh.Translate(0, 10.0f, 0); + break; + } + } + } + } +} diff --git a/Material.cs b/Material.cs deleted file mode 100644 index 027a3ba..0000000 --- a/Material.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Drawing; -using System.IO; - -namespace ConsoleGraphics -{ - class Material - //convert textures - { - public byte[,] bitmapColorsCached; - public int SIZE; - - public Material(string fileName) - { - Bitmap sourceBmp = (Bitmap)Image.FromFile(fileName, true);//load character set (digits 1->9..) - bitmapColorsCached = new byte[sourceBmp.Width, sourceBmp.Height]; - SIZE = sourceBmp.Width; - for (int i = 0; i < sourceBmp.Width; i++) - for (int j = 0; j < sourceBmp.Height; j++) - { - Color c = sourceBmp.GetPixel(i, j); - bitmapColorsCached[i,j] = (byte)((c.R + c.B + c.G) / 3); - } - } - } -} diff --git a/Maths/MathHelper.cs b/Maths/MathHelper.cs new file mode 100644 index 0000000..767b215 --- /dev/null +++ b/Maths/MathHelper.cs @@ -0,0 +1,51 @@ +namespace ConsoleGraphics.Maths +{ + /// + /// A helper class that contains useful function for doing maths + /// + public class MathHelper + { + /// + /// Swaps the values of the 2 given floats + /// + /// + /// + public static void Swap(ref float x, ref float y) + { + float temp = x; + x = y; + y = temp; + } + + /// + /// Swaps the values of the 2 given integers + /// + /// + /// + public static void Swap(ref int x, ref int y) + { + int temp = x; + x = y; + y = temp; + } + + /// + /// Clamps the given value between the given min and max value. + /// + /// e.g. Clamp(420, 50, 500) return 420, Clamp(100, 5, 50) return 50, Clamp( + /// + /// + /// + /// + /// + /// + public static float Clamp(float value, float min, float max) + { + if (value > max) + return max; + if (value < min) + return min; + return value; + } + } +} diff --git a/Maths/Matrix.cs b/Maths/Matrix.cs new file mode 100644 index 0000000..0d024f2 --- /dev/null +++ b/Maths/Matrix.cs @@ -0,0 +1,34 @@ +namespace ConsoleGraphics.Maths +{ + /// + /// Matrix. N x N matricies + /// + public class Matrix + { + /// + /// Row,Column + /// + public float[,] M; + + public Matrix(float[,] vals, int rows, int cols) + { + M = new float[rows, cols]; + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < cols; j++) + { + M[i, j] = vals[i, j]; + } + } + } + + public Vector3 Multiply(Vector3 vector) + { + Vector3 pNew; + pNew.X = vector.X * M[0, 0] + vector.Y * M[0, 1] + vector.Z * M[0, 2]; + pNew.Y = vector.X * M[1, 0] + vector.Y * M[1, 1] + vector.Z * M[1, 2]; + pNew.Z = vector.X * M[2, 0] + vector.Y * M[2, 1] + vector.Z * M[2, 2]; + return pNew; + } + } +} diff --git a/Maths/Triangle.cs b/Maths/Triangle.cs new file mode 100644 index 0000000..f3bf472 --- /dev/null +++ b/Maths/Triangle.cs @@ -0,0 +1,34 @@ +namespace ConsoleGraphics.Maths +{ + /// + /// A face that contains a indexes which can be used to point to vertices, texture coordinates, and a material + /// + public struct Triangle + { + /// + /// An array of indexes which point to a vertex somewhere else + /// + public int[] VertexIds; + /// + /// An array of indexes which point to a texture coordinate somewhere else + /// + public int[] UVIds; + /// + /// An index that points to a material somewhere else + /// + public int MaterialId; + + public Triangle(int v1, int v2, int v3, int vt1, int vt2, int vt3, int mid) + { + VertexIds = new int[3]; + VertexIds[0] = v1; + VertexIds[1] = v2; + VertexIds[2] = v3; + UVIds = new int[3]; + UVIds[0] = vt1; + UVIds[1] = vt2; + UVIds[2] = vt3; + MaterialId = mid; + } + } +} diff --git a/Maths/Vector2.cs b/Maths/Vector2.cs new file mode 100644 index 0000000..aaa76b1 --- /dev/null +++ b/Maths/Vector2.cs @@ -0,0 +1,13 @@ +namespace ConsoleGraphics.Maths +{ + public struct Vector2 + { + public float X, Y; + + public Vector2(float x, float y) + { + X = x; + Y = y; + } + } +} diff --git a/Maths/Vector3.cs b/Maths/Vector3.cs new file mode 100644 index 0000000..fc46b1a --- /dev/null +++ b/Maths/Vector3.cs @@ -0,0 +1,108 @@ +using System; + +namespace ConsoleGraphics.Maths +{ + /// + /// A struct containing an X, Y and Z value, and basic functions for manipulating those values, e.g. the dot product, normalisation, etc + /// + public struct Vector3 + { + public float X, Y, Z; + + public Vector3(float x, float y, float z = 0) + { + X = x; + Y = y; + Z = z; + } + + /// + /// Adds the given XYZ values to this vector instance's XYZ values + /// + /// + /// + /// + public void Add(float x, float y, float z) + { + this.X += x; + this.Y += y; + this.Z += z; + } + + /// + /// Adds the XYZ values of the given vector to this vector instance's XYZ values + /// + /// + /// + /// + public void Add(Vector3 v) + { + Add(v.X, v.Y, v.Z); + } + + /// + /// Returns the dot product between this vector instance and the given vector + /// + /// + /// + public float Dot(Vector3 v) + { + return X * v.X + Y * v.Y + Z * v.Z; + } + + /// + /// Returns the squared magnitude of this vector instance + /// + /// + public float MagnitudeSquared() + { + return X * X + Y * Y + Z * Z; + } + + /// + /// Returns the magnitude of this vector instance + /// + /// + public float Magnitude() + { + return (float)Math.Sqrt(MagnitudeSquared()); + } + + public static Vector3 Normalize(Vector3 a) + { + float norm = (float)Math.Sqrt(a.X * a.X + a.Y * a.Y + a.Z * a.Z); + return (new Vector3(a.X / norm, a.Y / norm, a.Z / norm)); + } + + public static Vector3 Cross(Vector3 a, Vector3 b) + { + Vector3 resultant; + resultant.X = a.Y * b.Z - a.Z * b.Y; + resultant.Y = a.Z * b.X - a.X * b.Z; + resultant.Z = a.X * b.Y - a.Y * b.X; + return (resultant); + } + + /// + /// Returns a new vector where the XYZ values of a and b have been added + /// + /// + /// + /// + public static Vector3 Add(Vector3 a, Vector3 b) + { + return (new Vector3((a.X + b.X), (a.Y + b.Y), (a.Z + b.Z))); + } + + /// + /// Returns a new vector which contains the dot product between the a and b vector + /// + /// + /// + /// + public static float Dot(Vector3 a, Vector3 b) + { + return (a.X * b.X + a.Y * b.Y + a.Z * b.Z); + } + } +} diff --git a/Matrix.cs b/Matrix.cs deleted file mode 100644 index 22719a9..0000000 --- a/Matrix.cs +++ /dev/null @@ -1,67 +0,0 @@ -/* - * N x N matricies - * Define & perform basic operations on matricies. - * - */ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ConsoleGraphics -{ - class Matrix : Program - { - public float[,] m_i;//row,col - - public Matrix(float[,] vals, int rows, int cols) - { - m_i = new float[rows, cols]; - for (int i = 0; i < rows; i++) - { - for (int j = 0; j < cols; j++) - { - m_i[i, j] = vals[i, j]; - } - } - } - - public static float magnitude(Mesh.point3 a) - { - return((float)Math.Sqrt(dot(a,a))); - } - public static Mesh.point3 normalize(Mesh.point3 a) - { - float norm = (float)Math.Sqrt(a.x * a.x + a.y * a.y + a.z * a.z); - return (new Mesh.point3(a.x/norm, a.y/norm, a.z/norm)); - } - public static Mesh.point3 cross(Mesh.point3 a, Mesh.point3 b) - { - Mesh.point3 resultant; - resultant.x = a.y * b.z - a.z * b.y; - resultant.y = a.z * b.x - a.x * b.z; - resultant.z = a.x * b.y - a.y * b.x; - return (resultant); - } - - public static Mesh.point3 add(Mesh.point3 a, Mesh.point3 b) - { - return (new Mesh.point3((a.x + b.x), (a.y + b.y), (a.z + b.z))); - } - - public static float dot(Mesh.point3 a, Mesh.point3 b) - { - return (a.x * b.x + a.y * b.y + a.z * b.z); - } - - public Mesh.point3 multiply(Mesh.point3 vector) - { - Mesh.point3 pNew; - pNew.x = vector.x * m_i[0, 0] + vector.y * m_i[0, 1] + vector.z * m_i[0, 2]; - pNew.y = vector.x * m_i[1, 0] + vector.y * m_i[1, 1] + vector.z * m_i[1, 2]; - pNew.z = vector.x * m_i[2, 0] + vector.y * m_i[2, 1] + vector.z * m_i[2, 2]; - return (pNew); - } - } -} diff --git a/Mesh.cs b/Mesh.cs deleted file mode 100644 index c038743..0000000 --- a/Mesh.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* Mesh - all the things that define a mesh. triangles, edges, verticies... later UVs... - * - * - */ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ConsoleGraphics -{ - class Mesh : Program - { - public Mesh(point3[] meshVerts, triangle[] meshFaces, point2[] meshUvs, Material[] mtls = null) - { - verts = meshVerts; - vertCount = verts.Length; - faces = meshFaces; - faceCount = faces.Length; - uvVerts = meshUvs; - matIDs = mtls; - } - - public struct triangle - { - public int[] vertIDs; - public int[] uvIds; - public int matID; - public triangle(int v1, int v2, int v3, int vt1, int vt2, int vt3, int mid) - { - vertIDs = new int[3]; - vertIDs[0] = v1; - vertIDs[1] = v2; - vertIDs[2] = v3; - uvIds = new int[3]; - uvIds[0] = vt1; - uvIds[1] = vt2; - uvIds[2] = vt3; - matID = mid; - } - }; - - public struct point3 - { - public float x, y, z; - public point3(float newX, float newY, float newZ = 0) - { - x = newX; - y = newY; - z = newZ; - } - }; - - public struct point2 - { - public float x, y; - public point2(float newX, float newY) - { - x = newX; - y = newY; - } - }; - - public point3[] verts; - public triangle[] faces; - public point2[] uvVerts; - public int vertCount; - public int faceCount; - public Material[] matIDs; - public void translate(point3 translation) - { - for (int i = 0; i < verts.Length; i++) - { - verts[i] = Matrix.add(verts[i], translation); - } - } - - public void rotate(double angle, byte dir) - { - //Rotate about centerpoint of the shape: translate the center of our shape to the origin, rotate, translate back. - float cosAngle = (float)Math.Cos(angle); - float sinAngle = (float)Math.Sin(angle); - Matrix rotMtrx = null; - point3 startCoords = verts[0]; - translate(new Mesh.point3(-startCoords.x, -startCoords.y, -startCoords.z)); - #region rotations - /* Rotate about X Axis {{1,0, 0}, - {0, cosAngle,sinAngle*100}, - {0, -sinAngle/100, cosAngle}}, 3, 3); - - - * Rotate about Y Axis {{cosAngle,0,-sinAngle*100}, - {0, 1, 0}, - {sinAngle, 0, cosAngle}}, 3, 3); - Rotate about Z axis - * {{cosAngle,-sinAngle,0}, - {sinAngle, cosAngle,0}, - {0, 0, 1}},3,3); - */ - #endregion - int x = Environment.TickCount; - - if (dir == 0) - rotMtrx = new Matrix(new float[,] {{1,0,0}, - {0, cosAngle,sinAngle*100}, - {0, -sinAngle/100, cosAngle}}, 3, 3); - else if (dir == 1) - rotMtrx = new Matrix(new float[,] {{cosAngle,0,-sinAngle*100}, - {0, 1, 0}, - {sinAngle/100, 0, cosAngle}}, 3, 3); - else - rotMtrx = new Matrix(new float[,] {{cosAngle,-sinAngle,0}, - {sinAngle, cosAngle,0}, - {0, 0, 1}}, 3, 3); - x = Environment.TickCount - x; - - for (int i = 0; i < vertCount; i++) - { - verts[i] = rotMtrx.multiply(verts[i]); - } - translate(new Mesh.point3(startCoords.x, startCoords.y, startCoords.z)); - } - } -} diff --git a/Program.cs b/Program.cs deleted file mode 100644 index 65e0314..0000000 --- a/Program.cs +++ /dev/null @@ -1,238 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.IO; -using System.Drawing; - -namespace ConsoleGraphics -{ - class Program - { - //special characters:█ ▄ ▀ ■ - - public bool VSYNC_ON = false; - public static threeState ts = new threeState(0); - // public bool FRAMERATE_ON = true; - public const short RENDER_WIDTH = 300; - public const short RENDER_HEIGHT = 100; - public const short MAX_FPS = 1000; - public const float pi = (float)3.1415926535; - static char[, ,] numerals = new char[9, 8, 10]; - public static char[] levels; - - public struct threeState - { - public byte x; - public threeState(byte initialState) - { - x = 0; - } - public void changeState() - { - x = (byte)((x + 1) % 3); - } - } - - public struct light - { - public Mesh.point3 coords; - public float intensity; - public light(float x, float y, float z, float setIntensity) - { - coords = new Mesh.point3(x, y, z); - intensity = setIntensity; - } - }; - - static void init(short width, short height, string title) - { - Console.Title = title; - Console.CursorVisible = false; - Console.BackgroundColor = ConsoleColor.Black; - reTry: - try - { - Console.SetWindowSize(width, height + 15); - Console.SetBufferSize(width, height + 15); - } - catch (ArgumentOutOfRangeException) - { - Console.WriteLine("Decrease your font size and press enter"); - Console.ReadLine(); - goto reTry; - } - Console.Clear();//clear colors from user preset. - Console.SetCursorPosition(0, height); - Console.Write(new String('▄', RENDER_WIDTH)); - Console.ForegroundColor = ConsoleColor.Cyan; - - StreamReader r = new StreamReader("levels.txt"); - - levels = new char[256]; - int index = 0; - while (!r.EndOfStream && index < 256) - { - string e1 = r.ReadLine(); - levels[index] = Char.Parse(e1); - index++; - } - - Thread cin = new Thread(getInput); - cin.Start(); - //Thread soundPlayer = new Thread(playSound); - //soundPlayer.Start(); - } - - static byte[,] loadTex(string loc) - { - byte[,] loadedTexture = new byte[2, 2]; - return (loadedTexture); - } - - static Mesh loadObj(string loc) - { - StreamReader r = new StreamReader(loc + ".obj"); - List loadedVerts = new List(); - List loadedUvs = new List(); - List loadedFaces = new List(); - List loadedUvFaces = new List(); - List mtls = new List(); - int vertCount = 0; - int faceCount = 0; - - while (!r.EndOfStream) - { - string e1 = r.ReadLine(); - if (e1 != "") - { - if (e1[0] == 'v' && e1[1] == 't')//texture verticies - { - string temp = e1.Substring(3, e1.Length - 3); - string[] coords = temp.Split(' '); - Mesh.point2 p = new Mesh.point2(float.Parse(coords[0]), float.Parse(coords[1])); - loadedUvs.Add(p); - } - else if (e1[0] == 'v')//vertex - { - vertCount++; - string temp = e1.Substring(3, e1.Length - 3); - string[] coords = temp.Split(' '); - Mesh.point3 p = new Mesh.point3(float.Parse(coords[0]) * 100, float.Parse(coords[1]) * 100, float.Parse(coords[2])); - //if z is positive it's off screen, z=0 we clip - loadedVerts.Add(p); - } - else if (e1[0] == 'u') - {//use this mtl for rest of faces faces material - Material m = new Material(e1.Substring(7, e1.Length - 7)); - mtls.Add(m); - } - else if (e1[0] == 'f')//edge - { - faceCount++; - string temp = e1.Substring(2, e1.Length - 2); - string[] coords = temp.Split(' ', '/'); - Mesh.triangle f = new Mesh.triangle(int.Parse(coords[0]) - 1, int.Parse(coords[2]) - 1, int.Parse(coords[4]) - 1, /*UV ID's*/ int.Parse(coords[1]) - 1, int.Parse(coords[3]) - 1, int.Parse(coords[5]) - 1, mtls.Count); - // Mesh.triangle uvf = new Mesh.triangle(int.Parse(coords[1]), int.Parse(coords[3]), int.Parse(coords[5])); - loadedFaces.Add(f); - // loadedUvFaces.Add(uvf); - } - } - } - return (new Mesh(loadedVerts.ToArray(), loadedFaces.ToArray(), loadedUvs.ToArray(), mtls.ToArray())); - } - - public static Mesh someShape = loadObj("link"); - public static light light1 = new light(0, 0, 0, 700); - - public static void Main(string[] args) - { - //BrightnessInit.go(); - //BrightnessInit.sortstuff(); - init(RENDER_WIDTH, RENDER_HEIGHT, "render"); - FrameBuffer buffer = new FrameBuffer(); - Rasterizer rast = new Rasterizer(); - someShape.translate(new Mesh.point3(-800, -300, -8)); - //someShape.rotate((float)0.25); - - buffer.drawFrame(rast.renderSolid()); - Console.ReadLine(); - //someShape.rotate((float)(3.1415)); - for (double i = 0; i < 1000; i += 0.01) - { - //light1.intensity = (int)((double)800 * Math.Sin(4*i)); - //someShape.rotate(0.005, 0); - //someShape.rotate(0.005, 1); - //someShape.rotate(0.005, 2); - //someShape.translate(new Mesh.point3((float)Math.Sin(i), 0, 0)); - // buffer.drawFrame(drawLine(new byte[RENDER_HEIGHT * RENDER_WIDTH], a1, a2)); - if (ts.x == 0) - buffer.drawFrame(rast.renderSolid()); - else if (ts.x == 2) - buffer.drawFrame(rast.renderWire(someShape)); - else if (ts.x == 1) - buffer.drawFrame(rast.renderVerts(someShape)); - - //light1.coords.x = 1000 * (float)Math.Sin(i); - // light1.coords.y = 1000 * (float)Math.Sin(i); - //light1.coords.z = 100 * (float)Math.Sin(i); - //someShape.rotate((float)0.005, 0); - //someShape.rotate((float)0.005, 1); - } - Console.ReadLine(); - } - - static void getInput() - { - ConsoleKeyInfo cki; - // Console.TreatControlCAsInput = true; - do - { - cki = Console.ReadKey(); - switch (cki.Key) - { - case ConsoleKey.Spacebar: - ts.changeState(); - break; - case ConsoleKey.W: - someShape.translate(new Mesh.point3(0, 0, (float)0.1)); - break; - case ConsoleKey.A: - someShape.translate(new Mesh.point3(-10, 0, 0)); - break; - case ConsoleKey.S: - someShape.translate(new Mesh.point3(0, 0, (float)-0.1)); - break; - case ConsoleKey.D: - someShape.translate(new Mesh.point3(10, 0, 0)); - break; - case ConsoleKey.R: - someShape.rotate(0.01, 0); - break; - case ConsoleKey.T: - someShape.rotate(0.01, 1); - break; - case ConsoleKey.Y: - someShape.rotate(0.01, 2); - break; - case ConsoleKey.Q: - someShape.translate(new Mesh.point3(0, -10, 0)); - break; - case ConsoleKey.E: - someShape.translate(new Mesh.point3(0, 10, 0)); - break; - } - } while (cki.Key != ConsoleKey.Escape); - } - - public static void printch(char[] charId, int x, int y) - { - Console.SetCursorPosition(0, RENDER_HEIGHT + 4); - Console.Write(new string(' ', 10)); - Console.SetCursorPosition(0, RENDER_HEIGHT + 4); - Console.Write(charId); - } - } -} diff --git a/Rasterize.cs b/Rasterize.cs deleted file mode 100644 index 9a58540..0000000 --- a/Rasterize.cs +++ /dev/null @@ -1,366 +0,0 @@ -/* Rasterization - all the grunt work! - * Determine pixle 'colors'.. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Drawing; - -namespace ConsoleGraphics -{ - class Rasterizer : Program - { - public static int[,] zBuffer = new int[RENDER_WIDTH, RENDER_HEIGHT]; - - void swap(ref float x, ref float y) - { - float temp = x; - x = y; - y = temp; - } - - void swap(ref int x, ref int y) - { - int temp = x; - x = y; - y = temp; - } - - float clamp(float val, float min, float max) - { - return (Math.Max(Math.Min(val, max), min)); - } - - public byte[,] renderVerts(Mesh someShape) - { - byte[,] image = new byte[RENDER_WIDTH, RENDER_HEIGHT];// - - for (int x = 0; x < RENDER_WIDTH; x++) - for (int y = 0; y < RENDER_HEIGHT; y++) - image[x, y] = 32; - - foreach (Mesh.triangle f in someShape.faces) - { - for (int i = 0; i < 3; i++)//each vertex - { - double depth = someShape.verts[f.vertIDs[i]].z; - int P_x1 = (int)(someShape.verts[f.vertIDs[i]].x / depth); - int P_y1 = (int)(someShape.verts[f.vertIDs[i]].y / depth); - - if (P_y1 < RENDER_HEIGHT - 1 && P_y1 >= 0 && P_x1 < RENDER_WIDTH - 1 && P_x1 >= 0)//the vert is in bounds with the screen - image[P_x1, P_y1] = 177; - } - } - return (image); - } - - public byte[,] renderWire(Mesh someShape) - { - byte[,] image = new byte[RENDER_WIDTH, RENDER_HEIGHT];// - - for (int x = 0; x < RENDER_WIDTH; x++) - for (int y = 0; y < RENDER_HEIGHT; y++) - image[x, y] = 32; - - foreach (Mesh.triangle f in someShape.faces) - { - for (int i = 0; i < 3; i++)//each vertex - { - double depth = someShape.verts[f.vertIDs[i]].z; - int P_x1 = (int)((RENDER_WIDTH / 2) + someShape.verts[f.vertIDs[i]].x / depth); - int P_y1 = (int)(((RENDER_HEIGHT - 15) / 2) + someShape.verts[f.vertIDs[i]].y / depth); - - if (P_y1 < RENDER_HEIGHT - 1 && P_y1 >= 0 && P_x1 < RENDER_WIDTH - 1 && P_x1 >= 0)//the vert is in bounds with the screen - for (int j = 0; j < 2; j++)//each of the 2 neighboring verts - { - double depth2 = someShape.verts[f.vertIDs[j]].z; - int P_x = (int)((RENDER_WIDTH / 2) + someShape.verts[f.vertIDs[j]].x / depth2); - int P_y = (int)(((RENDER_HEIGHT - 15) / 2) + someShape.verts[f.vertIDs[j]].y / depth2); - - if (P_y < RENDER_HEIGHT - 1 && P_y >= 0 && P_x < RENDER_WIDTH - 1 && P_x >= 0) - image = drawLine(image, P_x, P_y, P_x1, P_y1, true); - } - } - } - return (image); - } - Mesh.triangle targFace; - public byte[,] renderSolid() - { - byte[,] image = new byte[RENDER_WIDTH, RENDER_HEIGHT];// - - for (int x = 0; x < RENDER_WIDTH; x++) - for (int y = 0; y < RENDER_HEIGHT; y++) - { - image[x, y] = 32; //space character is drawn faster than the null character (0) - zBuffer[x, y] = -100; //far clipping plane - } - - foreach (Mesh.triangle f in someShape.faces) - { - targFace = f; - Mesh.point3 a = Matrix.add(someShape.verts[f.vertIDs[0]], new Mesh.point3(-someShape.verts[f.vertIDs[2]].x, -someShape.verts[f.vertIDs[2]].y, -someShape.verts[f.vertIDs[2]].z)); - Mesh.point3 b = Matrix.add(someShape.verts[f.vertIDs[0]], new Mesh.point3(-someShape.verts[f.vertIDs[1]].x, -someShape.verts[f.vertIDs[1]].y, -someShape.verts[f.vertIDs[1]].z)); - Mesh.point3 surfaceNorm1 = Matrix.cross(a, b); - - surfaceNorm1 = Matrix.normalize(surfaceNorm1); - - Mesh.point3 lightNorm1 = Matrix.add(light1.coords, new Mesh.point3(-someShape.verts[f.vertIDs[0]].x, -someShape.verts[f.vertIDs[0]].y, -someShape.verts[f.vertIDs[0]].z));//arbitrary vert - lightNorm1 = Matrix.normalize(lightNorm1); - //////////////////////////////////// - Mesh.point3 a1 = Matrix.add(someShape.verts[f.vertIDs[1]], new Mesh.point3(-someShape.verts[f.vertIDs[2]].x, -someShape.verts[f.vertIDs[2]].y, -someShape.verts[f.vertIDs[2]].z)); - Mesh.point3 b1 = Matrix.add(someShape.verts[f.vertIDs[1]], new Mesh.point3(-someShape.verts[f.vertIDs[0]].x, -someShape.verts[f.vertIDs[0]].y, -someShape.verts[f.vertIDs[0]].z)); - Mesh.point3 surfaceNorm2 = Matrix.cross(a1, b1); - - surfaceNorm2 = Matrix.normalize(surfaceNorm2); - - Mesh.point3 lightNorm2 = Matrix.add(light1.coords, new Mesh.point3(-someShape.verts[f.vertIDs[1]].x, -someShape.verts[f.vertIDs[1]].y, -someShape.verts[f.vertIDs[1]].z));//arbitrary vert - lightNorm2 = Matrix.normalize(lightNorm2); - ////////////////////////////////////////////// - Mesh.point3 a2 = Matrix.add(someShape.verts[f.vertIDs[2]], new Mesh.point3(-someShape.verts[f.vertIDs[0]].x, -someShape.verts[f.vertIDs[0]].y, -someShape.verts[f.vertIDs[0]].z)); - Mesh.point3 b2 = Matrix.add(someShape.verts[f.vertIDs[2]], new Mesh.point3(-someShape.verts[f.vertIDs[1]].x, -someShape.verts[f.vertIDs[1]].y, -someShape.verts[f.vertIDs[1]].z)); - Mesh.point3 surfaceNorm3 = Matrix.cross(a2, b2); - - surfaceNorm3 = Matrix.normalize(surfaceNorm3); - - Mesh.point3 lightNorm3 = Matrix.add(light1.coords, new Mesh.point3(-someShape.verts[f.vertIDs[2]].x, -someShape.verts[f.vertIDs[2]].y, -someShape.verts[f.vertIDs[2]].z));//arbitrary vert - lightNorm3 = Matrix.normalize(lightNorm3); - //////////////////////////////////////////// - - //perspective projection - float[] depth = {someShape.verts[f.vertIDs[0]].z, - someShape.verts[f.vertIDs[1]].z, - someShape.verts[f.vertIDs[2]].z}; - - if (depth[0] < 0 && depth[1] < 0 && depth[2] < 0) - { //>= one vertex is in screen - int x0 = (int)((RENDER_WIDTH / 2) + someShape.verts[f.vertIDs[0]].x / depth[0]); - int y0 = (int)(((RENDER_HEIGHT - 15) / 2) + someShape.verts[f.vertIDs[0]].y / depth[0]); - - int x1 = (int)((RENDER_WIDTH / 2) + someShape.verts[f.vertIDs[1]].x / depth[1]); - int y1 = (int)(((RENDER_HEIGHT - 15) / 2) + someShape.verts[f.vertIDs[1]].y / depth[1]); - - int x2 = (int)((RENDER_WIDTH / 2) + someShape.verts[f.vertIDs[2]].x / depth[2]); - int y2 = (int)(((RENDER_HEIGHT - 15) / 2) + someShape.verts[f.vertIDs[2]].y / depth[2]); - - - Mesh.point2[] uvs = new Mesh.point2[] { someShape.uvVerts[f.uvIds[0]], - someShape.uvVerts[f.uvIds[1]], - someShape.uvVerts[f.uvIds[2]] - }; - Mesh.point3[] projPoints = new Mesh.point3[] {new Mesh.point3(x0, y0, depth[0]), - new Mesh.point3(x1, y1, depth[1]), - new Mesh.point3(x2, y2, depth[2])}; - - byte[] colors = {(byte)(light1.intensity * Math.Max(0, Matrix.dot(surfaceNorm1, lightNorm1))), - (byte)(light1.intensity * Math.Max(0, Matrix.dot(surfaceNorm2, lightNorm2))), - (byte)(light1.intensity * Math.Max(0, Matrix.dot(surfaceNorm3, lightNorm3)))}; - - image = drawTriangle(image, projPoints, uvs, colors); - } - } - return (image); - } - - private byte[,] drawTriangle(byte[,] image, Mesh.point3[] points, Mesh.point2[] uvs, byte[] brightness = null) - { - /* - * A - * B------- - * C - * - */ - //sort by lowest y value (highest on screen) - Mesh.point3[] unsortedPoints = new Mesh.point3[3]; - points.CopyTo(unsortedPoints, 0); - - if (points[1].y < points[0].y) - {//swap point[1] and point[0] - swap(ref points[0].y, ref points[1].y); - swap(ref points[0].x, ref points[1].x); - } - if (points[2].y < points[0].y) - {//swap point[0] and point[2] - swap(ref points[0].y, ref points[2].y); - swap(ref points[0].x, ref points[2].x); - } - if (points[2].y < points[1].y) - {//swap point[1] & point[2] - swap(ref points[1].y, ref points[2].y); - swap(ref points[1].x, ref points[2].x); - } - - if (points[0].y == points[1].y) - {//flat top - image = fillFlatTop(image, points, unsortedPoints, brightness, uvs); - } - else if (points[1].y == points[2].y) - {//flat bottom - image = fillFlatBottom(image, points, unsortedPoints, brightness, uvs); - } - else - {//nontrivial - Mesh.point3 midpoint = new Mesh.point3((int)(Math.Ceiling(points[0].x + ((float)(points[1].y - points[0].y) / (float)(points[2].y - points[0].y)) * (points[2].x - points[0].x))), points[1].y); - fillFlatBottom(image, new Mesh.point3[] { points[0], points[1], midpoint }, unsortedPoints, brightness, uvs); - fillFlatTop(image, new Mesh.point3[] { points[1], midpoint, points[2] }, unsortedPoints, brightness, uvs); - } - return (image); - } - - private byte[,] fillFlatTop(byte[,] image, Mesh.point3[] sortedPoints, Mesh.point3[] unsortedPoints, byte[] brightness, Mesh.point2[] uvs = null) - { - float startX = sortedPoints[2].x; - float endX = sortedPoints[2].x; - - float invslope1 = (float)(sortedPoints[2].x - sortedPoints[0].x) / (float)(sortedPoints[2].y - sortedPoints[0].y); - float invslope2 = (float)(sortedPoints[2].x - sortedPoints[1].x) / (float)(sortedPoints[2].y - sortedPoints[1].y); - - for (int scanlineY = (int)sortedPoints[2].y; scanlineY > sortedPoints[0].y; scanlineY--) - { - drawLine(image, (int)startX, scanlineY, (int)endX, scanlineY, false, unsortedPoints, brightness, uvs); - startX -= invslope1; - endX -= invslope2; - } - return (image); - } - - private byte[,] fillFlatBottom(byte[,] image, Mesh.point3[] sortedPoints, Mesh.point3[] unsortedPoints, byte[] brightness, Mesh.point2[] uvs = null) - { - float invslope1 = (float)(sortedPoints[2].x - sortedPoints[0].x) / (float)(sortedPoints[2].y - sortedPoints[0].y); - float invslope2 = (float)(sortedPoints[0].x - sortedPoints[1].x) / (float)(sortedPoints[0].y - sortedPoints[1].y); - - float curx1 = sortedPoints[0].x; - float curx2 = sortedPoints[0].x; - - for (int scanlineY = (int)sortedPoints[0].y; scanlineY <= sortedPoints[1].y; scanlineY++) - { - drawLine(image, (int)curx1, scanlineY, (int)curx2, scanlineY, false, unsortedPoints, brightness, uvs); - curx1 += invslope1; - curx2 += invslope2; - } - return (image); - } - - public byte[,] drawLine(byte[,] image, /*start*/int x0, int y0, int x1, int y1,/*end*/ bool drawWireFrame, Mesh.point3[] unsortedPoints = null, byte[] color = null, Mesh.point2[] uvs = null) - { - float rise = y1 - y0; - float run = x1 - x0; - byte txl = 219; - //if (color != null) - //{ - // color[0] = 0; - // color[1] = 50; - // color[2] = 100; - //} - if (run == 0) - { - if (drawWireFrame) - txl = 124;// | - - if (y0 > y1) - swap(ref y0, ref y1); - - while (y0 < y1)//DRAW - { - image[x0, y0] = txl; - y0++; - } - return (image); - } - - float m = rise / run; - - if (-1 <= rise / run && rise / run <= 1) - { - - if (drawWireFrame) - { - if (rise / run > 0.5) - txl = 92;// / - else if (rise / run < -0.5) - txl = 47;// \ - else - txl = 95;// - - } - - if (x0 > x1) - { - swap(ref x0, ref x1); - swap(ref y0, ref y1); - } - - float y = y0; - float x = x0; - float denom = 0; - if (!drawWireFrame) - denom = ((unsortedPoints[1].y - unsortedPoints[2].y) * (unsortedPoints[0].x - unsortedPoints[2].x) + (unsortedPoints[2].x - unsortedPoints[1].x) * (unsortedPoints[0].y - unsortedPoints[2].y)); - - while (x <= x1 && y < RENDER_HEIGHT && x < RENDER_WIDTH && y >= 0) - { - if (x > 0)//clipping logic < ^ - { - int xtoi = (int)x; - int ytoi = (int)y; - if (drawWireFrame) - { - image[xtoi, ytoi] = txl; - y += m; - } - else//HERE'S WHERE WE DRAW TRIANGLES! - { - float b1 = (((unsortedPoints[1].y - unsortedPoints[2].y) * (x - unsortedPoints[2].x)) + ((unsortedPoints[2].x - unsortedPoints[1].x) * (y - unsortedPoints[2].y))) / denom; - float b2 = (((unsortedPoints[2].y - unsortedPoints[0].y) * (x - unsortedPoints[2].x)) + ((unsortedPoints[0].x - unsortedPoints[2].x) * (y - unsortedPoints[2].y))) / denom; - float b3 = 1 - b1 - b2; - - int interpolatedZ = (int)(b1 * unsortedPoints[0].z + b2 * unsortedPoints[1].z + b3 * unsortedPoints[2].z); - - if (interpolatedZ > zBuffer[xtoi, ytoi]) - { // use barycentric interpolation to do everything.. - float interpU = (float)(b1 * uvs[0].x + b2 * uvs[1].x + b3 * uvs[2].x); - float interpV = (float)(b1 * uvs[0].y + b2 * uvs[1].y + b3 * uvs[2].y); - float interpBright = color[1];// + b2 * (float)color[1] + b3 * (float)color[2]); - Material someMat = someShape.matIDs[targFace.matID-1]; - int xpos = Math.Min(Math.Max((int)(interpU * someMat.SIZE), 0), someMat.SIZE-1); - int ypos = Math.Min(Math.Max((int)(interpV * someMat.SIZE), 0), someMat.SIZE-1); - - byte fa = someMat.bitmapColorsCached[(int)clamp(xpos, 0, someMat.SIZE-1), (int)clamp(ypos, 0, someMat.SIZE-1)]; - image[xtoi, ytoi] = (byte)(Convert.ToInt32(levels[(int)clamp(fa + interpBright, 0, 255)])); - zBuffer[xtoi, ytoi] = interpolatedZ; - } - } - } - x++; - } - } - else - { - if (run / rise > 0.5) - txl = 92;// / - else if (run / rise < -0.5) - txl = 47;// \ - else - txl = 124;// - - - if (y0 > y1) - { - swap(ref x0, ref x1); - swap(ref y0, ref y1); - } - - float x = x0; - float invSlope = 1 / m; - - while (y0 < y1) - { - image[(int)x, y0] = txl; - x += invSlope; - y0++; - } - } - return (image); - } - } -} diff --git a/Render/FrameBuffer.cs b/Render/FrameBuffer.cs new file mode 100644 index 0000000..f999177 --- /dev/null +++ b/Render/FrameBuffer.cs @@ -0,0 +1,78 @@ +using System; +using System.IO; +using System.Threading; + +namespace ConsoleGraphics.Render +{ + /// + /// Draws a buffer (an array of bytes) to the console buffer/screen + /// + public static class FrameBuffer + { + private static int LastRenderTick; + private static int numRenderings = 0; + private const short sampleSize = 100; + //private string lastFrame = ""; + + /// + /// STDOUT + /// + public static Stream ConsoleOutput = Console.OpenStandardOutput(); + + // defining it static. saves creating a 30000 byte long array every time the game renders + // probably makes the garbage collector happier too lol + private static byte[] ViewportBuffer = new byte[Game.RENDER_HEIGHT * Game.RENDER_WIDTH]; + + public static void DrawFrame(byte[,] image, int a = 0, int b = 0) + { + //use cudafy / multithreading to paint quickly, also invoke writetoconsole? + + for (int x = 0; x < Game.RENDER_WIDTH; x++) + { + for (int y = 0; y < Game.RENDER_HEIGHT; y++) + { + ViewportBuffer[x + y * Game.RENDER_WIDTH] = image[x, y]; + } + } + + Console.SetCursorPosition(a, b); + + int beginRender = Environment.TickCount; + //.Flush(); + //string iString = bufImg.ToString(); + //byte[] b = Encoding.UTF8.GetBytes(iString); + //if (string.Compare(lastFrame, iString) != 0) + //{ + ConsoleOutput.Write(ViewportBuffer, 0, ViewportBuffer.Length); + // lastFrame = iString; + //} + int endRender = Environment.TickCount - beginRender; + + VerticalSync(Game.MAX_FPS, endRender, beginRender); + + if (numRenderings == 0) + LastRenderTick = Environment.TickCount; + + numRenderings++; + } + + public static void VerticalSync(short targetFrameRate, int delay, int startDrawTime) + { + //Synchronize frames and display framerate to the lower right corner of the render window + int targetDelay = 1000 / targetFrameRate; + //we're too fast + if (delay < targetDelay && Game.USE_VSYNC) + { + Thread.Sleep(targetDelay - delay); + } + + if (numRenderings == sampleSize) + { + int ticksElapsed = Environment.TickCount - LastRenderTick; + if (ticksElapsed != 0) + Game.printch((sampleSize * 1000 / ticksElapsed).ToString().ToCharArray(), Game.RENDER_WIDTH - 50, Game.RENDER_HEIGHT + 1); + numRenderings = 0; + } + } + } +} diff --git a/Render/Light.cs b/Render/Light.cs new file mode 100644 index 0000000..6861d02 --- /dev/null +++ b/Render/Light.cs @@ -0,0 +1,16 @@ +using ConsoleGraphics.Maths; + +namespace ConsoleGraphics.Render +{ + public struct Light + { + public Vector3 Coordinates; + public float Intensity; + + public Light(float x, float y, float z, float intensity) + { + Coordinates = new Vector3(x, y, z); + Intensity = intensity; + } + } +} diff --git a/Render/Material.cs b/Render/Material.cs new file mode 100644 index 0000000..b6b9d17 --- /dev/null +++ b/Render/Material.cs @@ -0,0 +1,27 @@ +using System.Drawing; + +namespace ConsoleGraphics.Render +{ + //convert textures + public class Material + { + public byte[,] BitmapColorsCached; + public int Size; + + public Material(string fileName) + { + //load character set (digits 1->9..) + Bitmap sourceBmp = (Bitmap)Image.FromFile(fileName, true); + BitmapColorsCached = new byte[sourceBmp.Width, sourceBmp.Height]; + Size = sourceBmp.Width; + for (int w = 0; w < sourceBmp.Width; w++) + { + for (int h = 0; h < sourceBmp.Height; h++) + { + Color c = sourceBmp.GetPixel(w, h); + BitmapColorsCached[w, h] = (byte)((c.R + c.B + c.G) / 3); + } + } + } + } +} diff --git a/Render/Mesh.cs b/Render/Mesh.cs new file mode 100644 index 0000000..01fb1fe --- /dev/null +++ b/Render/Mesh.cs @@ -0,0 +1,159 @@ +/* Mesh - all the things that define a mesh. triangles, edges, verticies... later UVs... + * + * + */ +using System; +using System.Collections.Generic; +using System.IO; +using ConsoleGraphics.Maths; + +namespace ConsoleGraphics.Render +{ + public class Mesh + { + public Vector3[] Vertices; + public Triangle[] Faces; + public Vector2[] UVs; + public Material[] Materials; + public int VerticesCount; + public int FacesCount; + + public Mesh(Vector3[] meshVerts, Triangle[] meshFaces, Vector2[] meshUvs, Material[] mats = null) + { + Vertices = meshVerts; + VerticesCount = Vertices.Length; + Faces = meshFaces; + FacesCount = Faces.Length; + UVs = meshUvs; + Materials = mats; + } + + public static Mesh LoadMeshFromFile(string fileName) + { + StreamReader reader = new StreamReader(fileName); + List loadedVerts = new List(); + List loadedUvs = new List(); + List loadedFaces = new List(); + //List loadedUvFaces = new List(); + List mtls = new List(); + int vertCount = 0; + int faceCount = 0; + + while (!reader.EndOfStream) + { + string e1 = reader.ReadLine(); + if (e1 != "") + { + if (e1[0] == 'v' && e1[1] == 't')//texture verticies + { + string temp = e1.Substring(3, e1.Length - 3); + string[] coords = temp.Split(' '); + Vector2 p = new Vector2(float.Parse(coords[0]), float.Parse(coords[1])); + loadedUvs.Add(p); + } + else if (e1[0] == 'v')//vertex + { + vertCount++; + string temp = e1.Substring(3, e1.Length - 3); + string[] coords = temp.Split(' '); + Vector3 p = new Vector3(float.Parse(coords[0]) * 100, float.Parse(coords[1]) * 100, float.Parse(coords[2])); + //if z is positive it's off screen, z=0 we clip + loadedVerts.Add(p); + } + else if (e1[0] == 'u') + {//use this mtl for rest of faces faces material + Material m = new Material(e1.Substring(7, e1.Length - 7)); + mtls.Add(m); + } + else if (e1[0] == 'f')//edge + { + faceCount++; + string temp = e1.Substring(2, e1.Length - 2); + string[] coords = temp.Split(' ', '/'); + Triangle f = new Triangle(int.Parse(coords[0]) - 1, int.Parse(coords[2]) - 1, int.Parse(coords[4]) - 1, /*UV ID's*/ int.Parse(coords[1]) - 1, int.Parse(coords[3]) - 1, int.Parse(coords[5]) - 1, mtls.Count); + // Triangle uvf = new Triangle(int.Parse(coords[1]), int.Parse(coords[3]), int.Parse(coords[5])); + loadedFaces.Add(f); + // loadedUvFaces.Add(uvf); + } + } + } + return (new Mesh(loadedVerts.ToArray(), loadedFaces.ToArray(), loadedUvs.ToArray(), mtls.ToArray())); + } + + public void Translate(Vector3 translation) + { + for (int i = 0; i < Vertices.Length; i++) + { + Vertices[i].Add(translation); + } + } + + public void Translate(float x, float y, float z) + { + for (int i = 0; i < Vertices.Length; i++) + { + Vertices[i].Add(x, y, z); + } + } + + public void Rotate(double angle, byte dir) + { + //Rotate about centerpoint of the shape: translate the center of our shape to the origin, rotate, translate back. + float cosAngle = (float)Math.Cos(angle); + float sinAngle = (float)Math.Sin(angle); + Vector3 startCoords = Vertices[0]; + Translate(new Vector3(-startCoords.X, -startCoords.Y, -startCoords.Z)); + #region rotations + /* Rotate about X Axis {{1,0, 0}, + {0, cosAngle,sinAngle*100}, + {0, -sinAngle/100, cosAngle}}, 3, 3); + + + * Rotate about Y Axis {{cosAngle,0,-sinAngle*100}, + {0, 1, 0}, + {sinAngle, 0, cosAngle}}, 3, 3); + Rotate about Z axis + * {{cosAngle,-sinAngle,0}, + {sinAngle, cosAngle,0}, + {0, 0, 1}},3,3); + */ + #endregion + int x = Environment.TickCount; + + Matrix rotationMatrix; + if (dir == 0) + rotationMatrix = new Matrix( + new float[,] + { + {1, 0, 0}, + {0, cosAngle, sinAngle * 100}, + {0, -sinAngle / 100, cosAngle} + }, 3, 3); + else if (dir == 1) + rotationMatrix = new Matrix( + new float[,] + { + {cosAngle, 0, -sinAngle * 100}, + {0, 1, 0}, + {sinAngle / 100, 0, cosAngle} + }, 3, 3); + else + rotationMatrix = new Matrix( + new float[,] + { + {cosAngle, -sinAngle, 0}, + {sinAngle, cosAngle, 0}, + {0, 0, 1} + }, 3, 3); + + x = Environment.TickCount - x; + + for (int i = 0; i < VerticesCount; i++) + { + Vertices[i] = rotationMatrix.Multiply(Vertices[i]); + } + + Translate(new Vector3(startCoords.X, startCoords.Y, startCoords.Z)); + } + } +} diff --git a/Render/Rasterize.cs b/Render/Rasterize.cs new file mode 100644 index 0000000..8e543b2 --- /dev/null +++ b/Render/Rasterize.cs @@ -0,0 +1,379 @@ +/* Rasterization - all the grunt work! + * Determine pixle 'colors'.. + */ + +using System; +using ConsoleGraphics.Maths; + +namespace ConsoleGraphics.Render +{ + public class Rasterizer + { + public static int[,] zBuffer = new int[Game.RENDER_WIDTH, Game.RENDER_HEIGHT]; + + private static Triangle TargetFace; + + public static byte[,] RenderVertices(Mesh someShape) + { + byte[,] image = new byte[Game.RENDER_WIDTH, Game.RENDER_HEIGHT]; + + for (int x = 0; x < Game.RENDER_WIDTH; x++) + for (int y = 0; y < Game.RENDER_HEIGHT; y++) + image[x, y] = 32; + + foreach (Triangle f in someShape.Faces) + { + // each vertex + for (int i = 0; i < 3; i++) + { + double depth = someShape.Vertices[f.VertexIds[i]].Z; + int P_x1 = (int)(someShape.Vertices[f.VertexIds[i]].X / depth); + int P_y1 = (int)(someShape.Vertices[f.VertexIds[i]].Y / depth); + + //the vert is in bounds with the screen + if (P_y1 < Game.RENDER_HEIGHT - 1 && P_y1 >= 0 && P_x1 < Game.RENDER_WIDTH - 1 && P_x1 >= 0) + image[P_x1, P_y1] = 177; + } + } + return (image); + } + + public static byte[,] RenderWire(Mesh someShape) + { + byte[,] image = new byte[Game.RENDER_WIDTH, Game.RENDER_HEIGHT];// + + for (int x = 0; x < Game.RENDER_WIDTH; x++) + for (int y = 0; y < Game.RENDER_HEIGHT; y++) + image[x, y] = 32; + + foreach (Triangle f in someShape.Faces) + { + for (int i = 0; i < 3; i++)//each vertex + { + double depth = someShape.Vertices[f.VertexIds[i]].Z; + int P_x1 = (int)((Game.RENDER_WIDTH / 2) + someShape.Vertices[f.VertexIds[i]].X / depth); + int P_y1 = (int)(((Game.RENDER_HEIGHT - 15) / 2) + someShape.Vertices[f.VertexIds[i]].Y / depth); + + //the vert is in bounds with the screen + if (P_y1 < Game.RENDER_HEIGHT - 1 && P_y1 >= 0 && P_x1 < Game.RENDER_WIDTH - 1 && P_x1 >= 0) + { + //each of the 2 neighboring verts + for (int j = 0; j < 2; j++) + { + double depth2 = someShape.Vertices[f.VertexIds[j]].Z; + int P_x = (int)((Game.RENDER_WIDTH / 2) + someShape.Vertices[f.VertexIds[j]].X / depth2); + int P_y = (int)(((Game.RENDER_HEIGHT - 15) / 2) + someShape.Vertices[f.VertexIds[j]].Y / depth2); + + if (P_y < Game.RENDER_HEIGHT - 1 && P_y >= 0 && P_x < Game.RENDER_WIDTH - 1 && P_x >= 0) + image = DrawLine(image, P_x, P_y, P_x1, P_y1, true); + } + } + } + } + return (image); + } + + public static byte[,] RenderSolid(Mesh someShape) + { + byte[,] image = new byte[Game.RENDER_WIDTH, Game.RENDER_HEIGHT]; + + for (int x = 0; x < Game.RENDER_WIDTH; x++) + { + for (int y = 0; y < Game.RENDER_HEIGHT; y++) + { + image[x, y] = 32; //space character is drawn faster than the null character (0) + zBuffer[x, y] = -100; //far clipping plane + } + } + + foreach (Triangle f in someShape.Faces) + { + TargetFace = f; + Vector3 a = Vector3.Add(someShape.Vertices[f.VertexIds[0]], new Vector3(-someShape.Vertices[f.VertexIds[2]].X, -someShape.Vertices[f.VertexIds[2]].Y, -someShape.Vertices[f.VertexIds[2]].Z)); + Vector3 b = Vector3.Add(someShape.Vertices[f.VertexIds[0]], new Vector3(-someShape.Vertices[f.VertexIds[1]].X, -someShape.Vertices[f.VertexIds[1]].Y, -someShape.Vertices[f.VertexIds[1]].Z)); + Vector3 surfaceNorm1 = Vector3.Cross(a, b); + + surfaceNorm1 = Vector3.Normalize(surfaceNorm1); + + Vector3 lightNorm1 = Vector3.Add(Game.light1.Coordinates, new Vector3(-someShape.Vertices[f.VertexIds[0]].X, -someShape.Vertices[f.VertexIds[0]].Y, -someShape.Vertices[f.VertexIds[0]].Z));//arbitrary vert + lightNorm1 = Vector3.Normalize(lightNorm1); + //////////////////////////////////// + Vector3 a1 = Vector3.Add(someShape.Vertices[f.VertexIds[1]], new Vector3(-someShape.Vertices[f.VertexIds[2]].X, -someShape.Vertices[f.VertexIds[2]].Y, -someShape.Vertices[f.VertexIds[2]].Z)); + Vector3 b1 = Vector3.Add(someShape.Vertices[f.VertexIds[1]], new Vector3(-someShape.Vertices[f.VertexIds[0]].X, -someShape.Vertices[f.VertexIds[0]].Y, -someShape.Vertices[f.VertexIds[0]].Z)); + Vector3 surfaceNorm2 = Vector3.Cross(a1, b1); + + surfaceNorm2 = Vector3.Normalize(surfaceNorm2); + + Vector3 lightNorm2 = Vector3.Add(Game.light1.Coordinates, new Vector3(-someShape.Vertices[f.VertexIds[1]].X, -someShape.Vertices[f.VertexIds[1]].Y, -someShape.Vertices[f.VertexIds[1]].Z));//arbitrary vert + lightNorm2 = Vector3.Normalize(lightNorm2); + ////////////////////////////////////////////// + Vector3 a2 = Vector3.Add(someShape.Vertices[f.VertexIds[2]], new Vector3(-someShape.Vertices[f.VertexIds[0]].X, -someShape.Vertices[f.VertexIds[0]].Y, -someShape.Vertices[f.VertexIds[0]].Z)); + Vector3 b2 = Vector3.Add(someShape.Vertices[f.VertexIds[2]], new Vector3(-someShape.Vertices[f.VertexIds[1]].X, -someShape.Vertices[f.VertexIds[1]].Y, -someShape.Vertices[f.VertexIds[1]].Z)); + Vector3 surfaceNorm3 = Vector3.Cross(a2, b2); + + surfaceNorm3 = Vector3.Normalize(surfaceNorm3); + + Vector3 lightNorm3 = Vector3.Add(Game.light1.Coordinates, new Vector3(-someShape.Vertices[f.VertexIds[2]].X, -someShape.Vertices[f.VertexIds[2]].Y, -someShape.Vertices[f.VertexIds[2]].Z));//arbitrary vert + lightNorm3 = Vector3.Normalize(lightNorm3); + //////////////////////////////////////////// + + //perspective projection + float[] depth = {someShape.Vertices[f.VertexIds[0]].Z, + someShape.Vertices[f.VertexIds[1]].Z, + someShape.Vertices[f.VertexIds[2]].Z}; + + if (depth[0] < 0 && depth[1] < 0 && depth[2] < 0) + { //>= one vertex is in screen + int x0 = (int)((Game.RENDER_WIDTH / 2) + someShape.Vertices[f.VertexIds[0]].X / depth[0]); + int y0 = (int)(((Game.RENDER_HEIGHT - 15) / 2) + someShape.Vertices[f.VertexIds[0]].Y / depth[0]); + + int x1 = (int)((Game.RENDER_WIDTH / 2) + someShape.Vertices[f.VertexIds[1]].X / depth[1]); + int y1 = (int)(((Game.RENDER_HEIGHT - 15) / 2) + someShape.Vertices[f.VertexIds[1]].Y / depth[1]); + + int x2 = (int)((Game.RENDER_WIDTH / 2) + someShape.Vertices[f.VertexIds[2]].X / depth[2]); + int y2 = (int)(((Game.RENDER_HEIGHT - 15) / 2) + someShape.Vertices[f.VertexIds[2]].Y / depth[2]); + + + Vector2[] uvs = new Vector2[] + { + someShape.UVs[f.UVIds[0]], + someShape.UVs[f.UVIds[1]], + someShape.UVs[f.UVIds[2]] + }; + + Vector3[] projPoints = new Vector3[] + { + new Vector3(x0, y0, depth[0]), + new Vector3(x1, y1, depth[1]), + new Vector3(x2, y2, depth[2]) + }; + + byte[] colors = new byte[] + { + (byte)(Game.light1.Intensity * Math.Max(0, Vector3.Dot(surfaceNorm1, lightNorm1))), + (byte)(Game.light1.Intensity * Math.Max(0, Vector3.Dot(surfaceNorm2, lightNorm2))), + (byte)(Game.light1.Intensity * Math.Max(0, Vector3.Dot(surfaceNorm3, lightNorm3))) + }; + + image = DrawTriangle(image, projPoints, uvs, colors); + } + } + return image; + } + + private static byte[,] DrawTriangle(byte[,] image, Vector3[] points, Vector2[] uvs, byte[] brightness = null) + { + /* + * A + * B------- + * C + * + */ + //sort by lowest y value (highest on screen) + Vector3[] unsortedPoints = new Vector3[3]; + points.CopyTo(unsortedPoints, 0); + + if (points[1].Y < points[0].Y) + {//swap point[1] and point[0] + MathHelper.Swap(ref points[0].Y, ref points[1].Y); + MathHelper.Swap(ref points[0].X, ref points[1].X); + } + if (points[2].Y < points[0].Y) + {//swap point[0] and point[2] + MathHelper.Swap(ref points[0].Y, ref points[2].Y); + MathHelper.Swap(ref points[0].X, ref points[2].X); + } + if (points[2].Y < points[1].Y) + {//swap point[1] & point[2] + MathHelper.Swap(ref points[1].Y, ref points[2].Y); + MathHelper.Swap(ref points[1].X, ref points[2].X); + } + + if (points[0].Y == points[1].Y) + {//flat top + image = FillFlatTop(image, points, unsortedPoints, brightness, uvs); + } + else if (points[1].Y == points[2].Y) + {//flat bottom + image = FillFlatBottom(image, points, unsortedPoints, brightness, uvs); + } + else + {//nontrivial + Vector3 midpoint = new Vector3((int)(Math.Ceiling(points[0].X + ((float)(points[1].Y - points[0].Y) / (float)(points[2].Y - points[0].Y)) * (points[2].X - points[0].X))), points[1].Y); + FillFlatBottom(image, new Vector3[] { points[0], points[1], midpoint }, unsortedPoints, brightness, uvs); + FillFlatTop(image, new Vector3[] { points[1], midpoint, points[2] }, unsortedPoints, brightness, uvs); + } + return (image); + } + + private static byte[,] FillFlatTop(byte[,] image, Vector3[] sortedPoints, Vector3[] unsortedPoints, byte[] brightness, Vector2[] uvs = null) + { + float startX = sortedPoints[2].X; + float endX = sortedPoints[2].X; + + float invslope1 = (float)(sortedPoints[2].X - sortedPoints[0].X) / (float)(sortedPoints[2].Y - sortedPoints[0].Y); + float invslope2 = (float)(sortedPoints[2].X - sortedPoints[1].X) / (float)(sortedPoints[2].Y - sortedPoints[1].Y); + + for (int scanlineY = (int)sortedPoints[2].Y; scanlineY > sortedPoints[0].Y; scanlineY--) + { + DrawLine(image, (int)startX, scanlineY, (int)endX, scanlineY, false, unsortedPoints, brightness, uvs); + startX -= invslope1; + endX -= invslope2; + } + return (image); + } + + private static byte[,] FillFlatBottom( + byte[,] image, + Vector3[] sortedPoints, + Vector3[] unsortedPoints, + byte[] brightness, + Vector2[] uvs = null) + { + float invslope1 = (float)(sortedPoints[2].X - sortedPoints[0].X) / (float)(sortedPoints[2].Y - sortedPoints[0].Y); + float invslope2 = (float)(sortedPoints[0].X - sortedPoints[1].X) / (float)(sortedPoints[0].Y - sortedPoints[1].Y); + + float curx1 = sortedPoints[0].X; + float curx2 = sortedPoints[0].X; + + for (int scanlineY = (int)sortedPoints[0].Y; scanlineY <= sortedPoints[1].Y; scanlineY++) + { + DrawLine(image, (int)curx1, scanlineY, (int)curx2, scanlineY, false, unsortedPoints, brightness, uvs); + curx1 += invslope1; + curx2 += invslope2; + } + return (image); + } + + public static byte[,] DrawLine( + byte[,] image, + // start + int x0, int y0, + int x1, int y1, + // end + bool drawWireFrame, + Vector3[] unsortedPoints = null, + byte[] color = null, + Vector2[] uvs = null) + { + float rise = y1 - y0; + float run = x1 - x0; + byte txl = 219; + //if (color != null) + //{ + // color[0] = 0; + // color[1] = 50; + // color[2] = 100; + //} + if (run == 0) + { + if (drawWireFrame) + txl = 124;// | + + if (y0 > y1) + MathHelper.Swap(ref y0, ref y1); + + while (y0 < y1)//DRAW + { + image[x0, y0] = txl; + y0++; + } + return (image); + } + + float m = rise / run; + + if (-1 <= rise / run && rise / run <= 1) + { + + if (drawWireFrame) + { + if (rise / run > 0.5) + txl = 92;// / + else if (rise / run < -0.5) + txl = 47;// \ + else + txl = 95;// - + } + + if (x0 > x1) + { + MathHelper.Swap(ref x0, ref x1); + MathHelper.Swap(ref y0, ref y1); + } + + float y = y0; + float x = x0; + float denom = 0; + if (!drawWireFrame) + denom = ((unsortedPoints[1].Y - unsortedPoints[2].Y) * (unsortedPoints[0].X - unsortedPoints[2].X) + (unsortedPoints[2].X - unsortedPoints[1].X) * (unsortedPoints[0].Y - unsortedPoints[2].Y)); + + while (x <= x1 && y < Game.RENDER_HEIGHT && x < Game.RENDER_WIDTH && y >= 0) + { + if (x > 0)//clipping logic < ^ + { + int xtoi = (int)x; + int ytoi = (int)y; + if (drawWireFrame) + { + image[xtoi, ytoi] = txl; + y += m; + } + else + { + //HERE'S WHERE WE DRAW TRIANGLES! + float b1 = (((unsortedPoints[1].Y - unsortedPoints[2].Y) * (x - unsortedPoints[2].X)) + ((unsortedPoints[2].X - unsortedPoints[1].X) * (y - unsortedPoints[2].Y))) / denom; + float b2 = (((unsortedPoints[2].Y - unsortedPoints[0].Y) * (x - unsortedPoints[2].X)) + ((unsortedPoints[0].X - unsortedPoints[2].X) * (y - unsortedPoints[2].Y))) / denom; + float b3 = 1 - b1 - b2; + + int interpolatedZ = (int)(b1 * unsortedPoints[0].Z + b2 * unsortedPoints[1].Z + b3 * unsortedPoints[2].Z); + + if (interpolatedZ > zBuffer[xtoi, ytoi]) + { + // use barycentric interpolation to do everything.. + float interpU = (float)(b1 * uvs[0].X + b2 * uvs[1].X + b3 * uvs[2].X); + float interpV = (float)(b1 * uvs[0].Y + b2 * uvs[1].Y + b3 * uvs[2].Y); + float interpBright = color[1];// + b2 * (float)color[1] + b3 * (float)color[2]); + Material material = Game.ActiveMesh.Materials[TargetFace.MaterialId - 1]; + + int xpos = Math.Min(Math.Max((int)(interpU * material.Size), 0), material.Size - 1); + int ypos = Math.Min(Math.Max((int)(interpV * material.Size), 0), material.Size - 1); + + byte fa = material.BitmapColorsCached[(int)MathHelper.Clamp(xpos, 0, material.Size - 1), (int)MathHelper.Clamp(ypos, 0, material.Size - 1)]; + image[xtoi, ytoi] = (byte)(Convert.ToInt32(Game.levels[(int)MathHelper.Clamp(fa + interpBright, 0, 255)])); + zBuffer[xtoi, ytoi] = interpolatedZ; + } + } + } + x++; + } + } + else + { + if (run / rise > 0.5) + txl = 92;// / + else if (run / rise < -0.5) + txl = 47;// \ + else + txl = 124;// - + + if (y0 > y1) + { + MathHelper.Swap(ref x0, ref x1); + MathHelper.Swap(ref y0, ref y1); + } + + float x = x0; + float invSlope = 1 / m; + + while (y0 < y1) + { + image[(int)x, y0] = txl; + x += invSlope; + y0++; + } + } + return (image); + } + } +} diff --git a/Resources/Meshes/link.obj b/Resources/Meshes/link.obj new file mode 100644 index 0000000..4b1ace9 --- /dev/null +++ b/Resources/Meshes/link.obj @@ -0,0 +1,1340 @@ +# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware +# File Created: 10.01.2015 11:09:19 + +# +# object Regroup24 +# + +v 0.6500 3.7043 0.1008 +v 0.5093 3.7324 0.2711 +v 0.4631 3.6402 0.3538 +v 0.2454 3.3350 0.1493 +v 0.2538 3.2557 0.5010 +v 0.0148 3.2065 0.3867 +v -0.3575 3.4402 0.1700 +v -0.3551 3.3859 0.4216 +v -0.3724 3.5410 0.4660 +v -0.2984 3.3805 0.6717 +v -0.2391 3.2557 0.5010 +v -0.1771 3.2376 0.6692 +v -0.2266 3.3350 0.1493 +v 0.0001 3.1298 0.6558 +v -0.2525 3.5116 0.7146 +v -0.2625 3.6870 0.7385 +v 0.0001 3.5293 0.7754 +v -0.3898 3.7002 0.5074 +v -0.0835 3.3643 0.7914 +v 0.0001 3.4326 0.9066 +v -0.4437 3.6402 0.3538 +v 0.1952 3.2370 0.6694 +v 0.1006 3.3640 0.7910 +v 0.0001 3.7097 0.7920 +v -0.0313 3.8689 0.7830 +v -0.1495 3.9362 0.7218 +v 0.3140 3.3805 0.6717 +v 0.2685 3.5107 0.7154 +v 0.1156 3.9497 0.7369 +v 0.2803 3.6862 0.7394 +v 0.4182 3.7002 0.5074 +v 0.3888 3.5409 0.4666 +v 0.3718 3.3859 0.4216 +v -0.6353 3.7054 0.1015 +v -0.4942 3.7324 0.2711 +v -0.0994 3.3517 0.0201 +v 0.3725 3.4400 0.1705 +v 0.1283 3.3524 0.0219 +v -0.0985 3.2386 -0.0081 +v 0.1320 3.2386 -0.0081 +v 0.1972 3.1373 0.1448 +v 0.0001 3.0061 0.3165 +v -0.1777 3.1373 0.1448 +v 0.1438 2.1895 0.2657 +v 0.0001 2.2184 -0.2293 +v -0.1670 2.1887 0.2638 +v 0.4045 1.9710 0.0343 +v 0.3971 2.2023 0.0498 +v -0.1690 1.8902 0.2460 +v -0.4167 2.1994 0.0479 +v -0.4228 1.9710 0.0343 +v 0.1470 1.8902 0.2460 +v 0.0001 1.9902 -0.2582 +v -0.0305 4.1649 0.7574 +v 0.0065 4.2353 1.0055 +v 0.0395 4.2251 0.6670 +v 0.2261 3.9369 1.0735 +v 0.3460 4.1908 0.7374 +v 0.5075 3.8941 0.7437 +v 0.5150 3.5445 0.7498 +v 0.2975 3.6246 0.9042 +v 0.4138 4.0891 0.5413 +v -0.4365 3.5391 0.7632 +v -0.5406 3.8380 0.6363 +v -0.3481 3.6452 0.8526 +v -0.2905 3.9799 1.0519 +v -0.0996 4.2112 1.0295 +v -0.1185 4.2251 0.6670 +v -0.4369 4.1037 0.6108 +v 0.0091 3.3358 -0.1591 +v 0.3366 3.4630 0.0013 +v -0.3206 3.4640 -0.0009 +v 0.1944 3.0332 0.2829 +v -0.2425 3.2223 -0.0503 +v -0.2006 3.0332 0.2829 +v 0.0001 2.8189 0.4559 +v 0.2211 3.2223 -0.0503 +v 0.0001 3.2593 0.7577 +v 0.3546 2.9628 0.4124 +v 0.2646 3.3363 -0.0869 +v -0.3615 2.9628 0.4127 +v -0.2473 3.3363 -0.1090 +v 0.0001 4.4341 0.3208 +v -0.2971 4.3602 0.1926 +v 0.0001 4.4821 -0.1856 +v 0.3144 4.3602 0.1926 +v 0.4781 4.2168 -0.1794 +v -0.4619 4.2168 -0.1794 +v -0.4527 3.7130 -0.1694 +v 0.4696 3.7116 -0.1661 +v -0.5317 3.0904 0.1047 +v -0.5577 3.0459 -0.1571 +v -0.5683 2.8166 -0.1824 +v -0.2924 2.4178 -0.3895 +v -0.6009 2.3787 -0.1960 +v 0.5605 2.8166 -0.1824 +v 0.5923 2.3787 -0.1960 +v 0.2824 2.4178 -0.3895 +v 0.0001 2.5555 0.5125 +v -0.3173 2.1172 0.4856 +v 0.3073 2.1172 0.4856 +v 0.6261 2.7180 0.0008 +v 0.5652 2.7107 0.3069 +v 0.5825 2.3508 0.1888 +v -0.2834 3.0914 -0.1868 +v -0.5899 2.3508 0.1888 +v -0.4289 1.9806 0.2741 +v 0.4181 1.9806 0.2741 +v -0.5652 2.7107 0.3070 +v -0.5382 2.9454 0.2761 +v 0.5384 2.9454 0.2762 +v -0.6335 2.7180 0.0008 +v 0.5320 3.0904 0.1047 +v 0.0001 1.9957 -0.0645 +v 0.4173 2.1454 -0.3814 +v -0.4298 2.1454 -0.3814 +v 0.2749 3.0914 -0.1868 +v 0.5575 3.0459 -0.1571 +v -0.5964 2.6538 -0.1795 +v -0.5850 2.4241 -0.0510 +v 0.5964 2.6538 -0.1803 +v 0.5851 2.4243 -0.0538 +v -0.3823 3.5667 -0.4784 +v 0.3903 3.5667 -0.4784 +v 0.2851 3.7159 -0.6525 +v 0.2905 3.5394 -0.0945 +v -0.2806 3.7159 -0.6525 +v 0.0001 3.7098 -0.8376 +v -0.2836 3.5394 -0.0945 +v 0.2970 3.2345 -0.5518 +v 0.0114 3.2172 -0.3064 +v -0.2717 3.2345 -0.5518 +v 0.0001 2.8602 -0.5945 +v 0.0088 3.2931 -0.8176 +v -0.4272 1.9463 -0.1506 +v 0.4116 1.9463 -0.1510 +v -0.3998 1.8717 0.1756 +v -0.3223 1.9184 -0.2891 +v 0.6075 1.1533 -0.1356 +v 0.6252 1.6673 -0.0918 +v 0.7651 1.2474 0.0888 +v 0.4753 1.8045 0.1205 +v 0.4442 1.3427 0.5996 +v 0.6779 1.3491 0.4073 +v 0.2949 1.1058 -0.2049 +v 0.4742 1.5854 -0.2767 +v 0.2592 1.5098 -0.3445 +v 0.2364 1.3125 0.6031 +v 0.1564 1.8345 0.2917 +v 0.0349 1.6952 0.3177 +v 0.0001 1.3786 0.2859 +v 0.0001 1.3434 -0.5335 +v 0.3860 1.8717 0.1756 +v 0.5543 1.8395 0.0233 +v 0.0352 1.7029 -0.4445 +v 0.3076 1.9184 -0.2891 +v 0.0414 1.8419 -0.3975 +v -0.7843 1.2474 0.0888 +v -0.4711 1.5854 -0.2767 +v -0.6101 1.1533 -0.1356 +v -0.4981 1.3427 0.5996 +v -0.5002 1.8045 0.1205 +v -0.7192 1.3491 0.4073 +v -0.2504 1.5098 -0.3445 +v -0.2936 1.1061 -0.2060 +v -0.6351 1.6673 -0.0918 +v -0.2905 1.3125 0.6031 +v -0.1699 1.8345 0.2919 +v -0.0462 1.6944 0.3146 +v -0.5683 1.8395 0.0233 +v -0.0511 1.7029 -0.4445 +v -0.0574 1.8419 -0.3975 +v 0.3669 0.5949 0.4079 +v 0.1074 0.7729 0.0465 +v 0.2581 0.3109 -0.0222 +v 0.2503 0.3707 -0.2076 +v 0.3183 0.8381 -0.2049 +v 0.5227 0.4206 -0.2834 +v 0.6660 0.6512 0.3267 +v 0.3568 0.7591 0.3005 +v 0.5643 0.7974 0.2441 +v 0.6560 0.8763 -0.0878 +v 0.6474 0.3841 -0.1308 +v 0.5029 0.2752 0.0655 +v 0.2171 0.8500 0.0713 +v 0.3398 0.9269 -0.0631 +v 0.5643 0.9154 -0.0161 +v 0.4760 0.0149 -0.3733 +v 0.1870 0.0143 0.0759 +v 0.3252 0.1550 0.3433 +v 0.5876 0.2785 0.2208 +v 0.2116 0.0173 -0.2542 +v 0.7396 0.0115 -0.1727 +v 0.8469 0.1524 0.1097 +v 0.5773 0.0071 0.5454 +v 0.2939 0.0107 0.3538 +v 0.8757 0.0076 0.0919 +v 0.6789 0.1808 0.4272 +v 0.8312 0.0059 0.4311 +v 0.3511 0.9560 0.3969 +v 0.5533 0.9947 0.3415 +v 0.3175 1.1236 -0.0066 +v 0.5645 1.1095 0.1034 +v 0.2027 1.0429 0.2015 +v 0.2279 1.0698 0.2428 +v 0.3638 1.0581 0.1120 +v 0.5113 1.2343 0.3911 +v 0.3234 1.1973 0.4439 +v 0.5330 1.1301 0.1580 +v 0.4816 1.4650 -0.0181 +v 0.2363 1.4470 -0.0890 +v 0.1566 1.4343 0.0823 +v 0.5000 1.4371 0.2679 +v 0.2308 1.3887 0.3437 +v 0.8832 2.4410 0.0089 +v 0.8694 2.3330 -0.0968 +v 0.8359 2.4247 -0.1333 +v 0.7617 2.3497 0.2301 +v 0.7375 2.4769 0.1133 +v 0.9566 2.3269 0.1115 +v 0.6206 2.4234 0.0410 +v 0.6278 2.2247 0.1094 +v 0.7246 2.2901 -0.1053 +v 0.7001 2.3592 -0.1351 +v 0.9174 2.1939 -0.0606 +v 0.8454 1.8851 0.1941 +v 0.7173 2.1413 -0.0469 +v 0.9522 1.9197 0.1994 +v 0.7735 1.9567 0.2996 +v 0.9647 2.0000 0.2952 +v 0.8626 2.0135 0.3633 +v 0.7062 2.5424 -0.1761 +v 0.8296 2.5442 0.1063 +v 0.6372 2.6072 0.1816 +v 0.8679 2.5743 -0.0818 +v 1.1037 1.5774 0.3775 +v 0.8769 1.5347 0.5967 +v 0.6960 1.6892 0.4880 +v 1.0247 1.7881 0.6604 +v 0.9322 1.9818 0.5498 +v 1.1546 1.7148 0.3738 +v 1.1061 1.8395 0.2604 +v 0.8877 2.0259 0.3737 +v 0.7540 1.9545 0.3154 +v 0.8576 1.8862 0.1687 +v 0.9167 1.6631 0.3033 +v 0.6549 1.8655 0.4703 +v 0.9761 1.7458 0.1736 +v 0.9915 1.9568 0.2277 +v 0.7793 2.7864 0.1381 +v 0.7598 2.8999 0.1175 +v 0.5384 2.9454 0.2760 +v 0.8153 2.8149 -0.0433 +v 1.0201 2.5364 0.0521 +v -0.8359 2.4247 -0.1333 +v -0.8694 2.3330 -0.0968 +v -0.8832 2.4410 0.0089 +v -0.7375 2.4769 0.1133 +v -0.7617 2.3497 0.2301 +v -0.9566 2.3269 0.1115 +v -0.6278 2.2247 0.1094 +v -0.6206 2.4234 0.0410 +v -0.7001 2.3592 -0.1351 +v -0.7246 2.2901 -0.1053 +v -0.9174 2.1939 -0.0606 +v -0.9522 1.9197 0.1994 +v -0.7173 2.1413 -0.0469 +v -0.8454 1.8851 0.1941 +v -0.7735 1.9567 0.2996 +v -0.9647 2.0000 0.2952 +v -0.8626 2.0135 0.3633 +v -0.7062 2.5424 -0.1761 +v -0.6372 2.6072 0.1816 +v -0.8296 2.5442 0.1063 +v -0.8679 2.5743 -0.0818 +v -0.6960 1.6892 0.4880 +v -0.8769 1.5347 0.5967 +v -1.1037 1.5774 0.3775 +v -1.0247 1.7881 0.6604 +v -0.9322 1.9818 0.5498 +v -1.1061 1.8395 0.2604 +v -1.1546 1.7148 0.3738 +v -0.8877 2.0259 0.3737 +v -0.8576 1.8862 0.1687 +v -0.7540 1.9545 0.3154 +v -0.6549 1.8655 0.4703 +v -0.9167 1.6631 0.3033 +v -0.9761 1.7458 0.1736 +v -0.9915 1.9568 0.2277 +v -0.7598 2.8999 0.1175 +v -0.7793 2.7864 0.1381 +v -0.8153 2.8149 -0.0433 +v -1.0201 2.5364 0.0521 +v -0.2581 0.3109 -0.0222 +v -0.1074 0.7729 0.0465 +v -0.3669 0.5949 0.4079 +v -0.2503 0.3707 -0.2076 +v -0.3183 0.8381 -0.2049 +v -0.5227 0.4206 -0.2834 +v -0.3568 0.7591 0.3005 +v -0.6660 0.6512 0.3267 +v -0.5643 0.7974 0.2441 +v -0.6560 0.8763 -0.0878 +v -0.6474 0.3841 -0.1308 +v -0.5029 0.2752 0.0655 +v -0.3398 0.9269 -0.0631 +v -0.2171 0.8500 0.0713 +v -0.5643 0.9154 -0.0161 +v -0.4760 0.0149 -0.3733 +v -0.1870 0.0143 0.0759 +v -0.5876 0.2785 0.2208 +v -0.3252 0.1550 0.3433 +v -0.2116 0.0173 -0.2542 +v -0.7396 0.0115 -0.1727 +v -0.8469 0.1524 0.1097 +v -0.2939 0.0107 0.3538 +v -0.5773 0.0071 0.5454 +v -0.8757 0.0076 0.0919 +v -0.6789 0.1808 0.4272 +v -0.8312 0.0059 0.4311 +v -0.5533 0.9947 0.3415 +v -0.3511 0.9560 0.3969 +v -0.5645 1.1095 0.1034 +v -0.3175 1.1236 -0.0066 +v -0.2027 1.0429 0.2015 +v -0.3638 1.0581 0.1120 +v -0.2279 1.0698 0.2428 +v -0.5113 1.2343 0.3911 +v -0.3234 1.1973 0.4439 +v -0.5330 1.1301 0.1580 +v -0.4816 1.4650 -0.0181 +v -0.2363 1.4470 -0.0890 +v -0.1566 1.4343 0.0823 +v -0.5000 1.4371 0.2679 +v -0.2308 1.3887 0.3437 +# 335 vertices + +vt 0.2135 0.0260 0.0000 +vt 0.2591 0.0428 0.0000 +vt 0.2222 0.0676 0.0000 +vt 0.1124 0.1603 0.0000 +vt 0.0642 0.1761 0.0000 +vt 0.0951 0.2220 0.0000 +vt 0.3095 0.2325 0.0000 +vt 0.2772 0.2438 0.0000 +vt 0.3622 0.2162 0.0000 +vt 0.2576 0.2373 0.0000 +vt 0.1799 0.2519 0.0000 +vt 0.1533 0.2468 0.0000 +vt 0.2235 0.2329 0.0000 +vt 0.0528 0.2394 0.0000 +vt 0.3151 0.2047 0.0000 +vt 0.4101 0.1722 0.0000 +vt 0.2625 0.1615 0.0000 +vt 0.4512 0.1876 0.0000 +vt 0.1970 0.2081 0.0000 +vt 0.2097 0.1811 0.0000 +vt 0.4310 0.2082 0.0000 +vt 0.0654 0.1897 0.0000 +vt 0.1534 0.1797 0.0000 +vt 0.3574 0.1263 0.0000 +vt 0.4512 0.1014 0.0000 +vt 0.5152 0.1062 0.0000 +vt 0.1137 0.1432 0.0000 +vt 0.1924 0.1250 0.0000 +vt 0.4595 0.0628 0.0000 +vt 0.2820 0.0889 0.0000 +vt 0.2590 0.0646 0.0000 +vt 0.1837 0.0996 0.0000 +vt 0.1063 0.1323 0.0000 +vt 0.5156 0.2228 0.0000 +vt 0.4944 0.1969 0.0000 +vt 0.2041 0.2096 0.0000 +vt 0.1379 0.1203 0.0000 +vt 0.1505 0.1745 0.0000 +vt 0.1389 0.2343 0.0000 +vt 0.0845 0.1988 0.0000 +vt 0.0316 0.2012 0.0000 +vt 0.0265 0.2483 0.0000 +vt 0.1201 0.2589 0.0000 +vt 0.8245 0.3764 0.0000 +vt 0.8552 0.3620 0.0000 +vt 0.8515 0.3759 0.0000 +vt 0.8046 0.3199 0.0000 +vt 0.7671 0.3625 0.0000 +vt 0.8032 0.3704 0.0000 +vt 0.7088 0.3112 0.0000 +vt 0.7312 0.3699 0.0000 +vt 0.7296 0.3196 0.0000 +vt 0.8257 0.3108 0.0000 +vt 0.7671 0.3118 0.0000 +vt 0.7104 0.3767 0.0000 +vt 0.7941 0.8715 0.0000 +vt 0.8152 0.8743 0.0000 +vt 0.7814 0.8715 0.0000 +vt 0.8160 0.8556 0.0000 +vt 0.8060 0.8547 0.0000 +vt 0.8423 0.8531 0.0000 +vt 0.7907 0.8603 0.0000 +vt 0.8108 0.8388 0.0000 +vt 0.8341 0.8195 0.0000 +vt 0.8449 0.8323 0.0000 +vt 0.7768 0.8511 0.0000 +vt 0.7868 0.8236 0.0000 +vt 0.7717 0.8262 0.0000 +vt 0.7991 0.8293 0.0000 +vt 0.8044 0.8213 0.0000 +vt 0.7821 0.8149 0.0000 +vt 0.7931 0.8223 0.0000 +vt 0.7682 0.8166 0.0000 +vt 0.8315 0.8149 0.0000 +vt 0.7989 0.8237 0.0000 +vt 0.8328 0.8250 0.0000 +vt 0.7977 0.8469 0.0000 +vt 0.8299 0.8463 0.0000 +vt 0.8102 0.8661 0.0000 +vt 0.8077 0.8496 0.0000 +vt 0.7849 0.8640 0.0000 +vt 0.7730 0.8618 0.0000 +vt 0.7773 0.8412 0.0000 +vt 0.8004 0.8431 0.0000 +vt 0.7773 0.8669 0.0000 +vt 0.8175 0.8526 0.0000 +vt 0.8327 0.8278 0.0000 +vt 0.8955 0.8308 0.0000 +vt 0.7126 0.9067 0.0000 +vt 0.7122 0.9055 0.0000 +vt 0.6562 0.8658 0.0000 +vt 0.7125 0.9010 0.0000 +vt 0.6316 0.8917 0.0000 +vt 0.7138 0.8403 0.0000 +vt 0.6525 0.8642 0.0000 +vt 0.7151 0.8399 0.0000 +vt 0.3771 0.6591 0.0000 +vt 0.4945 0.6355 0.0000 +vt 0.4423 0.7310 0.0000 +vt 0.5454 0.6962 0.0000 +vt 0.5968 0.6356 0.0000 +vt 0.5452 0.7879 0.0000 +vt 0.6480 0.7314 0.0000 +vt 0.7153 0.6600 0.0000 +vt 0.6163 0.0332 0.0000 +vt 0.6640 0.0716 0.0000 +vt 0.5685 0.0716 0.0000 +vt 0.5873 0.2558 0.0000 +vt 0.5703 0.1607 0.0000 +vt 0.5767 0.1372 0.0000 +vt 0.5790 0.1445 0.0000 +vt 0.5685 0.1681 0.0000 +vt 0.5986 0.1305 0.0000 +vt 0.5726 0.1759 0.0000 +vt 0.5985 0.1597 0.0000 +vt 0.5777 0.2146 0.0000 +vt 0.5713 0.1746 0.0000 +vt 0.5984 0.2161 0.0000 +vt 0.5848 0.2442 0.0000 +vt 0.5982 0.2580 0.0000 +vt 0.8853 0.6459 0.0000 +vt 0.8556 0.6355 0.0000 +vt 0.8881 0.6562 0.0000 +vt 0.8883 0.6804 0.0000 +vt 0.8605 0.7261 0.0000 +vt 0.8915 0.7259 0.0000 +vt 0.7747 0.6804 0.0000 +vt 0.7715 0.7259 0.0000 +vt 0.8027 0.7261 0.0000 +vt 0.8316 0.6925 0.0000 +vt 0.8631 0.7384 0.0000 +vt 0.8002 0.7384 0.0000 +vt 0.7682 0.6867 0.0000 +vt 0.7726 0.7205 0.0000 +vt 0.8597 0.6522 0.0000 +vt 0.8906 0.7205 0.0000 +vt 0.8743 0.7572 0.0000 +vt 0.7891 0.7572 0.0000 +vt 0.8860 0.6572 0.0000 +vt 0.7770 0.6572 0.0000 +vt 0.8948 0.6867 0.0000 +vt 0.8316 0.6665 0.0000 +vt 0.8116 0.6480 0.0000 +vt 0.7777 0.6459 0.0000 +vt 0.8514 0.6480 0.0000 +vt 0.8310 0.7629 0.0000 +vt 0.7891 0.7542 0.0000 +vt 0.8743 0.7542 0.0000 +vt 0.8035 0.6522 0.0000 +vt 0.7750 0.6562 0.0000 +vt 0.8089 0.6355 0.0000 +vt 0.9088 0.3283 0.0000 +vt 0.9347 0.3327 0.0000 +vt 0.9121 0.3504 0.0000 +vt 0.9135 0.3216 0.0000 +vt 0.9509 0.3223 0.0000 +vt 0.9443 0.3530 0.0000 +vt 0.9735 0.3592 0.0000 +vt 0.9692 0.3308 0.0000 +vt 0.9684 0.3675 0.0000 +vt 0.9263 0.3658 0.0000 +vt 0.5507 0.8617 0.0000 +vt 0.5279 0.8750 0.0000 +vt 0.5279 0.8465 0.0000 +vt 0.5470 0.8498 0.0000 +vt 0.5470 0.8828 0.0000 +vt 0.5319 0.8403 0.0000 +vt 0.5279 0.8961 0.0000 +vt 0.5496 0.8399 0.0000 +vt 0.5645 0.8636 0.0000 +vt 0.5620 0.8770 0.0000 +vt 0.5742 0.8681 0.0000 +vt 0.5654 0.8482 0.0000 +vt 0.4749 0.8399 0.0000 +vt 0.3867 0.9042 0.0000 +vt 0.4750 0.9042 0.0000 +vt 0.3879 0.8399 0.0000 +vt 0.6367 0.1288 0.0000 +vt 0.5886 0.1338 0.0000 +vt 0.5890 0.1288 0.0000 +vt 0.6846 0.1341 0.0000 +vt 0.6838 0.1286 0.0000 +vt 0.5916 0.1410 0.0000 +vt 0.6180 0.1379 0.0000 +vt 0.6005 0.1390 0.0000 +vt 0.6978 0.2376 0.0000 +vt 0.7052 0.1822 0.0000 +vt 0.7052 0.2450 0.0000 +vt 0.6893 0.1737 0.0000 +vt 0.6623 0.2482 0.0000 +vt 0.6931 0.2461 0.0000 +vt 0.6657 0.2279 0.0000 +vt 0.6966 0.1777 0.0000 +vt 0.6741 0.1748 0.0000 +vt 0.6393 0.2442 0.0000 +vt 0.6584 0.1476 0.0000 +vt 0.6446 0.1649 0.0000 +vt 0.6397 0.2053 0.0000 +vt 0.6394 0.2172 0.0000 +vt 0.6844 0.1441 0.0000 +vt 0.7033 0.1498 0.0000 +vt 0.6445 0.1708 0.0000 +vt 0.6755 0.1425 0.0000 +vt 0.6454 0.1528 0.0000 +vt 0.6875 0.1377 0.0000 +vt 0.5724 0.2532 0.0000 +vt 0.5865 0.1723 0.0000 +vt 0.5844 0.2452 0.0000 +vt 0.6193 0.2589 0.0000 +vt 0.5938 0.1674 0.0000 +vt 0.5889 0.2558 0.0000 +vt 0.6089 0.1691 0.0000 +vt 0.6164 0.2339 0.0000 +vt 0.5744 0.1790 0.0000 +vt 0.6422 0.2545 0.0000 +vt 0.6249 0.1363 0.0000 +vt 0.6428 0.2071 0.0000 +vt 0.6386 0.1578 0.0000 +vt 0.6426 0.2217 0.0000 +vt 0.5802 0.1377 0.0000 +vt 0.6382 0.1650 0.0000 +vt 0.6377 0.1431 0.0000 +vt 0.6080 0.1297 0.0000 +vt 0.5963 0.1236 0.0000 +vt 0.6815 0.1413 0.0000 +vt 0.6543 0.1378 0.0000 +vt 0.6421 0.1506 0.0000 +vt 0.6314 0.1701 0.0000 +vt 0.6307 0.1506 0.0000 +vt 0.7008 0.1472 0.0000 +vt 0.6414 0.1640 0.0000 +vt 0.6319 0.1642 0.0000 +vt 0.6366 0.2080 0.0000 +vt 0.6554 0.1451 0.0000 +vt 0.5723 0.1468 0.0000 +vt 0.6414 0.1701 0.0000 +vt 0.6362 0.2206 0.0000 +vt 0.6177 0.1450 0.0000 +vt 0.6726 0.1392 0.0000 +vt 0.1171 0.8175 0.0000 +vt 0.0996 0.8137 0.0000 +vt 0.1074 0.9276 0.0000 +vt 0.0971 0.9343 0.0000 +vt 0.0895 0.8288 0.0000 +vt 0.1582 0.8282 0.0000 +vt 0.1511 0.9341 0.0000 +vt 0.1676 0.9337 0.0000 +vt 0.1274 0.8172 0.0000 +vt 0.1151 0.8003 0.0000 +vt 0.1286 0.8000 0.0000 +vt 0.1449 0.8111 0.0000 +vt 0.1397 0.9273 0.0000 +vt 0.1232 0.9292 0.0000 +vt 0.0981 0.8030 0.0000 +vt 0.0894 0.8016 0.0000 +vt 0.1581 0.8009 0.0000 +vt 0.1460 0.8016 0.0000 +vt 0.8961 0.2518 0.0000 +vt 0.8864 0.1335 0.0000 +vt 0.8902 0.1363 0.0000 +vt 0.8510 0.2514 0.0000 +vt 0.8561 0.1236 0.0000 +vt 0.8322 0.1284 0.0000 +vt 0.8033 0.2053 0.0000 +vt 0.8046 0.1568 0.0000 +vt 0.8615 0.1271 0.0000 +vt 0.7586 0.2512 0.0000 +vt 0.8033 0.2515 0.0000 +vt 0.7682 0.1938 0.0000 +vt 0.7144 0.9075 0.0000 +vt 0.7152 0.9064 0.0000 +vt 0.7131 0.9080 0.0000 +vt 0.7135 0.9053 0.0000 +vt 0.9034 0.5146 0.0000 +vt 0.9377 0.5020 0.0000 +vt 0.9412 0.5360 0.0000 +vt 0.9496 0.5254 0.0000 +vt 0.9455 0.5426 0.0000 +vt 0.9465 0.5156 0.0000 +vt 0.9546 0.5330 0.0000 +vt 0.9510 0.5622 0.0000 +vt 0.9070 0.5309 0.0000 +vt 0.9021 0.5563 0.0000 +vt 0.9344 0.5805 0.0000 +vt 0.9309 0.5801 0.0000 +vt 0.9057 0.5775 0.0000 +vt 0.9081 0.5372 0.0000 +vt 0.9493 0.5614 0.0000 +vt 0.8939 0.5549 0.0000 +vt 0.9094 0.5780 0.0000 +vt 0.9499 0.5624 0.0000 +vt 0.9433 0.3160 0.0000 +vt 0.9536 0.3109 0.0000 +vt 0.9714 0.3317 0.0000 +vt 0.9377 0.3407 0.0000 +vt 0.9207 0.3279 0.0000 +vt 0.9700 0.3185 0.0000 +vt 0.9081 0.3108 0.0000 +# 298 texture coords + +g Regroup24 +usemtl Resources\Textures\YoungLink.bmp +f 1/1 2/2 3/3 +f 4/4 5/5 6/6 +f 7/7 8/8 9/9 +f 10/10 11/11 12/12 +f 11/11 10/10 8/8 +f 8/8 7/7 11/11 +f 11/11 13/13 6/6 +f 11/11 14/14 12/12 +f 15/15 16/16 9/9 +f 16/16 15/15 17/17 +f 9/9 16/16 18/18 +f 15/15 19/19 17/17 +f 20/20 17/17 19/19 +f 9/9 18/18 21/21 +f 14/14 5/5 22/22 +f 20/20 23/23 17/17 +f 24/24 16/16 17/17 +f 25/25 26/26 24/24 +f 27/27 28/28 23/23 +f 16/16 24/24 26/26 +f 29/29 30/30 31/31 +f 29/29 24/24 30/30 +f 16/16 26/26 18/18 +f 28/28 30/30 17/17 +f 32/32 30/30 28/28 +f 30/30 32/32 31/31 +f 30/30 24/24 17/17 +f 27/27 5/5 33/33 +f 23/23 28/28 17/17 +f 27/27 22/22 5/5 +f 27/27 32/32 28/28 +f 34/34 21/21 35/35 +f 34/34 35/35 7/7 +f 10/10 19/19 15/15 +f 27/27 33/33 32/32 +f 36/36 13/13 7/7 +f 10/10 15/15 9/9 +f 14/14 11/11 6/6 +f 6/6 5/5 14/14 +f 5/5 4/4 37/37 +f 4/4 38/38 37/37 +f 8/8 10/10 9/9 +f 13/13 11/11 7/7 +f 33/33 5/5 37/37 +f 1/1 37/37 2/2 +f 33/33 37/37 32/32 +f 29/29 25/25 24/24 +f 39/39 13/13 36/36 +f 40/40 4/4 41/41 +f 40/40 36/36 38/38 +f 42/42 4/4 6/6 +f 42/42 13/13 43/43 +f 39/39 36/36 40/40 +f 4/4 42/42 41/41 +f 13/13 42/42 6/6 +f 13/13 39/39 43/43 +f 4/4 40/40 38/38 +f 44/44 45/45 46/46 +f 47/47 45/48 48/49 +f 49/50 50/51 51/52 +f 52/53 48/49 44/44 +f 45/48 47/47 53/54 +f 45/48 44/44 48/49 +f 48/49 52/53 47/47 +f 45/48 51/52 50/51 +f 46/55 45/48 50/51 +f 50/51 49/50 46/55 +f 51/52 45/48 53/54 +f 54/56 55/57 56/58 +f 55/57 54/56 25/59 +f 55/57 29/60 57/61 +f 55/57 57/61 58/62 +f 59/63 58/62 57/61 +f 55/57 58/62 56/58 +f 60/64 59/63 61/65 +f 59/63 62/66 58/62 +f 3/67 2/68 31/69 +f 31/69 32/70 3/67 +f 60/64 2/68 59/63 +f 60/64 61/65 29/60 +f 56/58 58/62 62/66 +f 60/64 31/69 2/68 +f 59/63 2/68 62/66 +f 60/64 29/60 31/69 +f 59/63 57/61 61/65 +f 61/65 57/61 29/60 +f 55/57 25/59 29/60 +f 21/71 18/72 35/73 +f 63/74 64/75 35/73 +f 65/76 26/77 66/78 +f 65/76 18/72 26/77 +f 67/79 25/80 54/81 +f 63/74 65/76 64/75 +f 66/78 26/77 67/79 +f 67/79 26/77 25/80 +f 63/74 18/72 65/76 +f 54/81 68/82 67/79 +f 64/75 65/76 66/78 +f 64/75 66/78 69/83 +f 67/79 69/83 66/78 +f 67/79 68/82 69/83 +f 63/74 35/73 18/72 +f 64/75 69/83 35/73 +f 38/84 70/85 71/86 +f 37/87 38/84 71/86 +f 72/86 7/87 35/88 +f 71/86 2/88 37/87 +f 72/86 36/84 7/87 +f 36/84 70/85 38/84 +f 70/85 36/84 72/86 +f 41/89 42/89 73/89 +f 43/89 74/89 75/89 +f 40/89 74/89 39/89 +f 42/89 76/90 73/89 +f 41/89 77/89 40/89 +f 77/89 74/89 40/89 +f 43/89 75/89 42/89 +f 74/89 43/89 39/89 +f 75/89 76/90 42/89 +f 77/89 41/89 73/89 +f 21/91 7/92 9/93 +f 34/94 7/92 21/91 +f 3/95 32/93 37/92 +f 1/96 3/95 37/92 +f 27/97 23/98 22/99 +f 78/100 23/98 19/101 +f 14/102 22/99 78/100 +f 78/100 22/99 23/98 +f 12/103 19/101 10/104 +f 12/103 14/102 78/100 +f 12/103 78/100 19/101 +f 20/105 19/106 23/107 +f 79/108 80/108 77/108 +f 74/108 81/108 75/108 +f 82/108 74/108 77/108 +f 82/108 77/108 80/108 +f 73/108 76/108 79/108 +f 77/108 73/108 79/108 +f 82/108 81/108 74/108 +f 75/108 81/108 76/108 +f 68/109 83/110 84/111 +f 83/110 68/109 56/109 +f 54/112 56/109 68/109 +f 84/111 83/110 85/113 +f 86/111 56/109 62/114 +f 87/115 62/114 2/116 +f 86/111 87/115 85/113 +f 86/111 85/113 83/110 +f 86/111 62/114 87/115 +f 86/111 83/110 56/109 +f 69/117 84/111 88/115 +f 85/113 88/115 84/111 +f 35/116 88/115 89/118 +f 88/115 35/116 69/117 +f 90/118 71/119 70/120 +f 89/118 70/120 72/119 +f 90/118 2/116 71/119 +f 2/116 90/118 87/115 +f 35/116 89/118 72/119 +f 68/109 84/111 69/117 +f 91/121 74/122 92/123 +f 93/124 94/125 95/126 +f 96/127 97/128 98/129 +f 99/130 100/131 101/132 +f 102/133 103/127 104/134 +f 94/125 92/123 105/135 +f 100/131 106/136 107/137 +f 104/134 101/132 108/138 +f 109/124 99/130 110/139 +f 111/140 99/130 103/127 +f 112/141 95/126 106/136 +f 109/124 112/141 106/136 +f 76/142 111/140 73/143 +f 113/144 73/143 111/140 +f 76/142 110/139 99/130 +f 110/139 76/142 75/145 +f 114/146 115/147 108/138 +f 108/138 97/128 104/134 +f 105/135 98/129 94/125 +f 114/146 116/148 115/147 +f 107/137 116/148 114/146 +f 117/149 98/129 105/135 +f 118/150 98/129 117/149 +f 95/126 107/137 106/136 +f 95/126 94/125 116/148 +f 114/146 108/138 107/137 +f 92/123 74/122 105/135 +f 115/147 98/129 97/128 +f 74/122 117/149 105/135 +f 77/151 118/150 117/149 +f 101/132 107/137 108/138 +f 77/151 117/149 74/122 +f 115/147 94/125 98/129 +f 100/131 107/137 101/132 +f 97/128 102/133 104/134 +f 116/148 94/125 115/147 +f 73/143 113/144 77/151 +f 101/132 103/127 99/130 +f 74/122 91/121 75/145 +f 97/128 96/127 102/133 +f 112/141 93/124 95/126 +f 75/145 91/121 110/139 +f 99/130 111/140 76/142 +f 94/125 93/124 92/123 +f 103/127 101/132 104/134 +f 100/131 109/124 106/136 +f 107/137 95/126 116/148 +f 109/124 100/131 99/130 +f 118/150 77/151 113/144 +f 97/128 108/138 115/147 +f 98/129 118/150 96/127 +f 93/152 119/153 92/154 +f 119/153 93/152 112/155 +f 109/152 120/156 112/155 +f 120/156 119/153 112/155 +f 121/157 96/158 118/159 +f 96/158 121/157 102/160 +f 121/157 122/161 102/160 +f 122/161 103/158 102/160 +f 123/162 89/163 88/164 +f 87/164 124/162 125/165 +f 124/162 90/163 126/166 +f 88/164 127/165 123/162 +f 85/167 127/165 88/164 +f 125/165 85/167 87/164 +f 70/168 126/166 90/163 +f 85/167 125/165 128/169 +f 89/163 123/162 129/166 +f 127/165 85/167 128/169 +f 129/166 70/168 89/163 +f 90/163 124/162 87/164 +f 70/168 129/166 126/166 +f 130/170 126/166 131/171 +f 129/166 132/170 131/171 +f 133/172 131/171 132/170 +f 134/173 132/170 127/165 +f 130/170 125/165 124/162 +f 134/173 127/165 128/169 +f 130/170 134/173 125/165 +f 130/170 131/171 133/172 +f 132/170 134/173 133/172 +f 126/166 129/166 131/171 +f 125/165 134/173 128/169 +f 127/165 132/170 123/162 +f 126/166 130/170 124/162 +f 134/173 130/170 133/172 +f 132/170 129/166 123/162 +f 44/174 49/175 52/176 +f 49/175 44/174 46/177 +f 53/178 135/179 51/180 +f 136/181 53/178 47/182 +f 51/180 137/183 49/184 +f 135/179 53/178 138/185 +f 139/186 140/187 141/188 +f 142/189 143/190 144/191 +f 145/192 146/193 139/186 +f 146/193 140/187 139/186 +f 141/188 142/189 144/191 +f 147/194 146/193 145/192 +f 140/187 142/189 141/188 +f 148/195 149/196 150/197 +f 150/197 151/198 148/195 +f 152/199 147/194 145/192 +f 142/189 140/187 153/200 +f 153/200 140/187 154/201 +f 147/194 155/202 156/203 +f 156/203 155/202 157/204 +f 136/205 146/193 156/203 +f 156/203 146/193 147/194 +f 153/200 143/190 142/189 +f 140/187 136/205 154/201 +f 149/196 148/195 143/190 +f 149/196 143/190 153/200 +f 147/194 152/199 155/202 +f 136/205 140/187 146/193 +f 158/206 159/207 160/208 +f 161/209 162/210 163/211 +f 160/208 164/212 165/213 +f 166/214 159/207 158/206 +f 163/211 166/214 158/206 +f 159/207 164/212 160/208 +f 162/210 166/214 163/211 +f 167/215 168/216 161/209 +f 151/217 169/218 167/215 +f 164/212 152/219 165/213 +f 166/214 162/210 170/220 +f 170/220 162/210 137/113 +f 171/221 164/212 172/222 +f 172/222 164/212 138/223 +f 159/207 135/224 164/212 +f 164/212 135/224 138/223 +f 162/210 168/216 137/113 +f 135/224 166/214 170/220 +f 168/216 167/215 169/218 +f 161/209 168/216 162/210 +f 152/219 164/212 171/221 +f 166/214 135/224 159/207 +f 153/225 47/182 52/226 +f 157/227 171/228 172/229 +f 47/182 153/225 154/230 +f 53/178 172/229 138/185 +f 150/231 169/232 151/233 +f 47/182 154/230 136/181 +f 52/226 149/234 153/225 +f 137/183 51/180 170/235 +f 53/178 157/227 172/229 +f 171/228 155/236 152/237 +f 49/184 137/183 168/238 +f 53/178 156/239 157/227 +f 51/180 135/179 170/235 +f 49/184 149/234 52/226 +f 171/228 157/227 155/236 +f 168/238 150/231 149/234 +f 168/238 149/234 49/184 +f 169/232 150/231 168/238 +f 53/178 136/181 156/239 +f 51/180 135/179 53/178 +f 47/182 53/178 136/181 +f 49/184 137/183 51/180 +f 138/185 53/178 135/179 +f 141/188 140/187 139/186 +f 144/191 143/190 142/189 +f 139/186 146/193 145/192 +f 139/186 140/187 146/193 +f 144/191 142/189 141/188 +f 145/192 146/193 147/194 +f 141/188 142/189 140/187 +f 150/197 149/196 148/195 +f 148/195 151/198 150/197 +f 145/192 147/194 152/199 +f 153/200 140/187 142/189 +f 154/201 140/187 153/200 +f 156/203 155/202 147/194 +f 157/204 155/202 156/203 +f 156/203 146/193 136/205 +f 147/194 146/193 156/203 +f 142/189 143/190 153/200 +f 154/201 136/205 140/187 +f 143/190 148/195 149/196 +f 153/200 143/190 149/196 +f 155/202 152/199 147/194 +f 146/193 140/187 136/205 +f 160/208 159/207 158/206 +f 163/211 162/210 161/209 +f 165/213 164/212 160/208 +f 158/206 159/207 166/214 +f 158/206 166/214 163/211 +f 160/208 164/212 159/207 +f 163/211 166/214 162/210 +f 161/209 168/216 167/215 +f 167/215 169/218 151/217 +f 165/213 152/219 164/212 +f 170/220 162/210 166/214 +f 137/113 162/210 170/220 +f 172/222 164/212 171/221 +f 138/223 164/212 172/222 +f 164/212 135/224 159/207 +f 138/223 135/224 164/212 +f 137/113 168/216 162/210 +f 170/220 166/214 135/224 +f 169/218 167/215 168/216 +f 162/210 168/216 161/209 +f 171/221 164/212 152/219 +f 159/207 135/224 166/214 +f 52/226 47/182 153/225 +f 172/229 171/228 157/227 +f 154/230 153/225 47/182 +f 138/185 172/229 53/178 +f 151/233 169/232 150/231 +f 136/181 154/230 47/182 +f 153/225 149/234 52/226 +f 170/235 51/180 137/183 +f 172/229 157/227 53/178 +f 152/237 155/236 171/228 +f 168/238 137/183 49/184 +f 157/227 156/239 53/178 +f 170/235 135/179 51/180 +f 52/226 149/234 49/184 +f 155/236 157/227 171/228 +f 149/234 150/231 168/238 +f 49/184 149/234 168/238 +f 168/238 150/231 169/232 +f 156/239 136/181 53/178 +f 173/240 174/241 175/242 +f 176/243 175/242 174/241 +f 174/241 177/244 176/243 +f 177/245 178/246 176/247 +f 173/240 179/248 180/249 +f 180/249 179/248 181/250 +f 179/248 182/251 181/250 +f 182/251 183/252 178/246 +f 179/248 184/253 183/252 +f 184/253 173/240 175/242 +f 185/254 186/255 177/244 +f 179/248 173/240 184/253 +f 183/252 182/251 179/248 +f 186/256 187/257 177/245 +f 174/241 173/240 180/249 +f 177/245 182/251 178/246 +f 180/249 185/254 174/241 +f 187/257 181/250 182/251 +f 185/254 177/244 174/241 +f 177/245 187/257 182/251 +f 188/258 176/259 178/260 +f 189/261 175/262 176/259 +f 184/263 190/264 191/265 +f 192/258 176/259 188/258 +f 176/259 192/258 189/261 +f 175/262 190/264 184/263 +f 188/258 178/260 193/261 +f 183/266 193/261 178/260 +f 194/264 183/266 191/265 +f 191/265 183/266 184/263 +f 175/262 189/261 190/264 +f 193/261 183/266 194/264 +f 193/261 189/261 188/258 +f 188/258 189/261 192/258 +f 195/267 190/264 196/268 +f 193/261 194/264 197/268 +f 198/269 194/264 191/265 +f 198/269 190/264 195/267 +f 193/261 196/268 189/261 +f 197/268 196/268 193/261 +f 199/267 194/264 198/269 +f 198/269 195/267 199/267 +f 190/264 198/269 191/265 +f 194/264 199/267 197/268 +f 196/268 197/268 195/267 +f 195/267 197/268 199/267 +f 190/264 189/261 196/268 +f 200/270 180/270 201/270 +f 201/270 180/270 181/270 +f 187/271 202/271 203/271 +f 202/271 185/271 204/271 +f 203/271 201/270 181/270 +f 185/271 202/271 186/271 +f 185/271 180/270 204/271 +f 181/270 187/271 203/271 +f 200/270 204/271 180/270 +f 202/271 187/271 186/271 +f 204/271 205/270 206/271 +f 201/270 203/271 207/270 +f 207/270 208/270 201/270 +f 201/270 208/270 200/270 +f 205/270 204/271 208/270 +f 206/271 203/271 202/271 +f 203/271 209/270 207/270 +f 208/270 204/271 200/270 +f 209/270 203/271 206/271 +f 204/271 206/271 202/271 +f 210/89 207/270 209/270 +f 210/89 209/270 211/89 +f 211/89 205/270 212/89 +f 213/270 207/270 210/89 +f 211/89 209/270 206/271 +f 205/270 211/89 206/271 +f 212/89 205/270 214/270 +f 214/270 205/270 208/270 +f 214/270 208/270 213/270 +f 213/270 208/270 207/270 +f 215/89 216/90 217/90 +f 218/272 215/89 219/89 +f 215/89 218/272 220/89 +f 218/272 221/89 222/89 +f 217/90 223/89 224/89 +f 221/89 223/89 222/89 +f 221/89 218/272 219/89 +f 216/90 223/89 217/90 +f 225/273 215/89 220/89 +f 223/89 221/89 224/89 +f 216/90 215/89 225/273 +f 226/271 227/89 228/271 +f 228/271 227/89 225/273 +f 222/89 227/89 229/270 +f 229/270 227/89 226/271 +f 225/273 220/89 228/271 +f 228/271 220/89 230/270 +f 218/272 222/89 231/270 +f 231/270 222/89 229/270 +f 227/89 216/90 225/273 +f 222/89 223/89 227/89 +f 231/270 220/89 218/272 +f 223/89 216/90 227/89 +f 229/270 230/270 231/270 +f 230/270 220/89 231/270 +f 228/271 230/270 226/271 +f 226/271 230/270 229/270 +f 224/273 122/89 232/90 +f 219/89 233/89 234/89 +f 215/89 235/90 233/89 +f 217/273 235/90 215/89 +f 122/89 224/273 221/89 +f 233/89 219/89 215/89 +f 234/89 221/89 219/89 +f 217/273 232/90 235/90 +f 122/89 121/90 232/90 +f 121/90 235/90 232/90 +f 232/90 217/273 224/273 +f 221/89 234/89 122/89 +f 236/274 237/275 238/276 +f 236/274 239/277 237/275 +f 238/278 237/279 239/280 +f 240/281 238/278 239/280 +f 240/281 241/282 242/283 +f 242/283 243/284 240/281 +f 244/285 243/284 245/286 +f 239/277 241/282 240/281 +f 241/282 236/274 242/283 +f 239/277 236/274 241/282 +f 246/287 247/288 245/286 +f 248/289 245/286 242/283 +f 238/276 247/288 246/287 +f 248/289 246/287 245/286 +f 238/276 246/287 236/274 +f 236/274 246/287 248/289 +f 243/284 242/283 249/290 +f 242/283 236/274 248/289 +f 249/290 242/283 245/286 +f 243/284 249/290 245/286 +f 240/281 243/284 247/288 +f 238/278 240/281 247/291 +f 244/285 245/286 247/288 +f 243/284 244/285 247/288 +f 250/292 251/293 252/294 +f 103/158 122/161 234/295 +f 250/292 103/158 233/296 +f 233/296 103/158 234/295 +f 113/297 252/294 251/293 +f 251/293 118/159 113/297 +f 118/159 253/292 121/157 +f 118/159 251/293 253/292 +f 103/158 250/292 252/294 +f 254/298 250/292 233/296 +f 254/298 253/292 250/292 +f 233/296 235/296 254/298 +f 253/292 254/298 235/296 +f 251/293 250/292 253/292 +f 235/296 121/157 253/292 +f 255/90 256/90 257/89 +f 258/89 257/89 259/272 +f 260/89 259/272 257/89 +f 261/89 262/89 259/272 +f 263/89 264/89 255/90 +f 261/89 264/89 262/89 +f 258/89 259/272 262/89 +f 255/90 264/89 256/90 +f 260/89 257/89 265/273 +f 263/89 262/89 264/89 +f 265/273 257/89 256/90 +f 266/271 267/89 268/271 +f 265/273 267/89 266/271 +f 269/270 267/89 261/89 +f 268/271 267/89 269/270 +f 266/271 260/89 265/273 +f 270/270 260/89 266/271 +f 271/270 261/89 259/272 +f 269/270 261/89 271/270 +f 265/273 256/90 267/89 +f 267/89 264/89 261/89 +f 259/272 260/89 271/270 +f 267/89 256/90 264/89 +f 271/270 270/270 269/270 +f 271/270 260/89 270/270 +f 268/271 270/270 266/271 +f 269/270 270/270 268/271 +f 272/90 120/89 263/273 +f 273/89 274/89 258/89 +f 274/89 275/90 257/89 +f 257/89 275/90 255/273 +f 262/89 263/273 120/89 +f 257/89 258/89 274/89 +f 258/89 262/89 273/89 +f 275/90 272/90 255/273 +f 272/90 119/90 120/89 +f 272/90 275/90 119/90 +f 263/273 255/273 272/90 +f 120/89 273/89 262/89 +f 276/276 277/275 278/274 +f 277/275 279/277 278/274 +f 279/280 277/279 276/278 +f 279/280 276/278 280/281 +f 281/283 282/282 280/281 +f 280/281 283/284 281/283 +f 284/286 283/284 285/285 +f 280/281 282/282 279/277 +f 281/283 278/274 282/282 +f 282/282 278/274 279/277 +f 284/286 286/288 287/287 +f 281/283 284/286 288/289 +f 287/287 286/288 276/276 +f 284/286 287/287 288/289 +f 278/274 287/287 276/276 +f 288/289 287/287 278/274 +f 289/290 281/283 283/284 +f 288/289 278/274 281/283 +f 284/286 281/283 289/290 +f 284/286 289/290 283/284 +f 286/288 283/284 280/281 +f 286/291 280/281 276/278 +f 286/288 284/286 285/285 +f 286/288 285/285 283/284 +f 110/294 290/293 291/292 +f 273/295 120/161 109/158 +f 274/296 109/158 291/292 +f 273/295 109/158 274/296 +f 290/293 110/294 91/297 +f 91/297 92/159 290/293 +f 119/157 292/292 92/159 +f 292/292 290/293 92/159 +f 110/294 291/292 109/158 +f 274/296 291/292 293/298 +f 291/292 292/292 293/298 +f 293/298 275/296 274/296 +f 275/296 293/298 292/292 +f 292/292 291/292 290/293 +f 292/292 119/157 275/296 +f 294/242 295/241 296/240 +f 295/241 294/242 297/243 +f 297/243 298/244 295/241 +f 297/247 299/246 298/245 +f 300/249 301/248 296/240 +f 302/250 301/248 300/249 +f 302/250 303/251 301/248 +f 299/246 304/252 303/251 +f 304/252 305/253 301/248 +f 294/242 296/240 305/253 +f 298/244 306/255 307/254 +f 305/253 296/240 301/248 +f 301/248 303/251 304/252 +f 298/245 308/257 306/256 +f 300/249 296/240 295/241 +f 299/246 303/251 298/245 +f 295/241 307/254 300/249 +f 303/251 302/250 308/257 +f 295/241 298/244 307/254 +f 303/251 308/257 298/245 +f 299/260 297/259 309/258 +f 297/259 294/262 310/261 +f 311/265 312/264 305/263 +f 309/258 297/259 313/258 +f 310/261 313/258 297/259 +f 305/263 312/264 294/262 +f 314/261 299/260 309/258 +f 299/260 314/261 304/266 +f 311/265 304/266 315/264 +f 305/263 304/266 311/265 +f 312/264 310/261 294/262 +f 315/264 304/266 314/261 +f 309/258 310/261 314/261 +f 313/258 310/261 309/258 +f 316/268 312/264 317/267 +f 318/268 315/264 314/261 +f 311/265 315/264 319/269 +f 317/267 312/264 319/269 +f 310/261 316/268 314/261 +f 314/261 316/268 318/268 +f 319/269 315/264 320/267 +f 320/267 317/267 319/269 +f 311/265 319/269 312/264 +f 318/268 320/267 315/264 +f 317/267 318/268 316/268 +f 320/267 318/268 317/267 +f 316/268 310/261 312/264 +f 321/270 300/270 322/270 +f 302/270 300/270 321/270 +f 323/271 324/271 308/271 +f 325/271 307/271 324/271 +f 302/270 321/270 323/271 +f 306/271 324/271 307/271 +f 325/271 300/270 307/271 +f 323/271 308/271 302/270 +f 300/270 325/271 322/270 +f 306/271 308/271 324/271 +f 326/271 327/270 325/271 +f 328/270 323/271 321/270 +f 321/270 329/270 328/270 +f 322/270 329/270 321/270 +f 329/270 325/271 327/270 +f 324/271 323/271 326/271 +f 328/270 330/270 323/271 +f 322/270 325/271 329/270 +f 326/271 323/271 330/270 +f 324/271 326/271 325/271 +f 330/270 328/270 331/89 +f 332/89 330/270 331/89 +f 333/89 327/270 332/89 +f 331/89 328/270 334/270 +f 326/271 330/270 332/89 +f 326/271 332/89 327/270 +f 335/270 327/270 333/89 +f 329/270 327/270 335/270 +f 334/270 329/270 335/270 +f 328/270 329/270 334/270 +# 693 faces diff --git a/YoungLink.bmp b/Resources/Textures/YoungLink.bmp similarity index 100% rename from YoungLink.bmp rename to Resources/Textures/YoungLink.bmp diff --git a/levels.txt b/Resources/levels.txt similarity index 100% rename from levels.txt rename to Resources/levels.txt diff --git a/Utils/ThreeState.cs b/Utils/ThreeState.cs new file mode 100644 index 0000000..ddd511d --- /dev/null +++ b/Utils/ThreeState.cs @@ -0,0 +1,17 @@ +namespace ConsoleGraphics.Utils +{ + public struct ThreeState + { + public byte x; + + public ThreeState(byte initialState) + { + x = 0; + } + + public void changeState() + { + x = (byte)((x + 1) % 3); + } + } +} diff --git a/csbuild.csproj b/csbuild.csproj index d2c9584..42aaf39 100644 --- a/csbuild.csproj +++ b/csbuild.csproj @@ -42,16 +42,22 @@ - - - - - - + + + + + + + + + + + + - + Always @@ -62,12 +68,12 @@ - + Always - + Always diff --git a/link.obj b/link.obj deleted file mode 100644 index ae433c9..0000000 --- a/link.obj +++ /dev/null @@ -1,1340 +0,0 @@ -# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware -# File Created: 10.01.2015 11:09:19 - -# -# object Regroup24 -# - -v 0.6500 3.7043 0.1008 -v 0.5093 3.7324 0.2711 -v 0.4631 3.6402 0.3538 -v 0.2454 3.3350 0.1493 -v 0.2538 3.2557 0.5010 -v 0.0148 3.2065 0.3867 -v -0.3575 3.4402 0.1700 -v -0.3551 3.3859 0.4216 -v -0.3724 3.5410 0.4660 -v -0.2984 3.3805 0.6717 -v -0.2391 3.2557 0.5010 -v -0.1771 3.2376 0.6692 -v -0.2266 3.3350 0.1493 -v 0.0001 3.1298 0.6558 -v -0.2525 3.5116 0.7146 -v -0.2625 3.6870 0.7385 -v 0.0001 3.5293 0.7754 -v -0.3898 3.7002 0.5074 -v -0.0835 3.3643 0.7914 -v 0.0001 3.4326 0.9066 -v -0.4437 3.6402 0.3538 -v 0.1952 3.2370 0.6694 -v 0.1006 3.3640 0.7910 -v 0.0001 3.7097 0.7920 -v -0.0313 3.8689 0.7830 -v -0.1495 3.9362 0.7218 -v 0.3140 3.3805 0.6717 -v 0.2685 3.5107 0.7154 -v 0.1156 3.9497 0.7369 -v 0.2803 3.6862 0.7394 -v 0.4182 3.7002 0.5074 -v 0.3888 3.5409 0.4666 -v 0.3718 3.3859 0.4216 -v -0.6353 3.7054 0.1015 -v -0.4942 3.7324 0.2711 -v -0.0994 3.3517 0.0201 -v 0.3725 3.4400 0.1705 -v 0.1283 3.3524 0.0219 -v -0.0985 3.2386 -0.0081 -v 0.1320 3.2386 -0.0081 -v 0.1972 3.1373 0.1448 -v 0.0001 3.0061 0.3165 -v -0.1777 3.1373 0.1448 -v 0.1438 2.1895 0.2657 -v 0.0001 2.2184 -0.2293 -v -0.1670 2.1887 0.2638 -v 0.4045 1.9710 0.0343 -v 0.3971 2.2023 0.0498 -v -0.1690 1.8902 0.2460 -v -0.4167 2.1994 0.0479 -v -0.4228 1.9710 0.0343 -v 0.1470 1.8902 0.2460 -v 0.0001 1.9902 -0.2582 -v -0.0305 4.1649 0.7574 -v 0.0065 4.2353 1.0055 -v 0.0395 4.2251 0.6670 -v 0.2261 3.9369 1.0735 -v 0.3460 4.1908 0.7374 -v 0.5075 3.8941 0.7437 -v 0.5150 3.5445 0.7498 -v 0.2975 3.6246 0.9042 -v 0.4138 4.0891 0.5413 -v -0.4365 3.5391 0.7632 -v -0.5406 3.8380 0.6363 -v -0.3481 3.6452 0.8526 -v -0.2905 3.9799 1.0519 -v -0.0996 4.2112 1.0295 -v -0.1185 4.2251 0.6670 -v -0.4369 4.1037 0.6108 -v 0.0091 3.3358 -0.1591 -v 0.3366 3.4630 0.0013 -v -0.3206 3.4640 -0.0009 -v 0.1944 3.0332 0.2829 -v -0.2425 3.2223 -0.0503 -v -0.2006 3.0332 0.2829 -v 0.0001 2.8189 0.4559 -v 0.2211 3.2223 -0.0503 -v 0.0001 3.2593 0.7577 -v 0.3546 2.9628 0.4124 -v 0.2646 3.3363 -0.0869 -v -0.3615 2.9628 0.4127 -v -0.2473 3.3363 -0.1090 -v 0.0001 4.4341 0.3208 -v -0.2971 4.3602 0.1926 -v 0.0001 4.4821 -0.1856 -v 0.3144 4.3602 0.1926 -v 0.4781 4.2168 -0.1794 -v -0.4619 4.2168 -0.1794 -v -0.4527 3.7130 -0.1694 -v 0.4696 3.7116 -0.1661 -v -0.5317 3.0904 0.1047 -v -0.5577 3.0459 -0.1571 -v -0.5683 2.8166 -0.1824 -v -0.2924 2.4178 -0.3895 -v -0.6009 2.3787 -0.1960 -v 0.5605 2.8166 -0.1824 -v 0.5923 2.3787 -0.1960 -v 0.2824 2.4178 -0.3895 -v 0.0001 2.5555 0.5125 -v -0.3173 2.1172 0.4856 -v 0.3073 2.1172 0.4856 -v 0.6261 2.7180 0.0008 -v 0.5652 2.7107 0.3069 -v 0.5825 2.3508 0.1888 -v -0.2834 3.0914 -0.1868 -v -0.5899 2.3508 0.1888 -v -0.4289 1.9806 0.2741 -v 0.4181 1.9806 0.2741 -v -0.5652 2.7107 0.3070 -v -0.5382 2.9454 0.2761 -v 0.5384 2.9454 0.2762 -v -0.6335 2.7180 0.0008 -v 0.5320 3.0904 0.1047 -v 0.0001 1.9957 -0.0645 -v 0.4173 2.1454 -0.3814 -v -0.4298 2.1454 -0.3814 -v 0.2749 3.0914 -0.1868 -v 0.5575 3.0459 -0.1571 -v -0.5964 2.6538 -0.1795 -v -0.5850 2.4241 -0.0510 -v 0.5964 2.6538 -0.1803 -v 0.5851 2.4243 -0.0538 -v -0.3823 3.5667 -0.4784 -v 0.3903 3.5667 -0.4784 -v 0.2851 3.7159 -0.6525 -v 0.2905 3.5394 -0.0945 -v -0.2806 3.7159 -0.6525 -v 0.0001 3.7098 -0.8376 -v -0.2836 3.5394 -0.0945 -v 0.2970 3.2345 -0.5518 -v 0.0114 3.2172 -0.3064 -v -0.2717 3.2345 -0.5518 -v 0.0001 2.8602 -0.5945 -v 0.0088 3.2931 -0.8176 -v -0.4272 1.9463 -0.1506 -v 0.4116 1.9463 -0.1510 -v -0.3998 1.8717 0.1756 -v -0.3223 1.9184 -0.2891 -v 0.6075 1.1533 -0.1356 -v 0.6252 1.6673 -0.0918 -v 0.7651 1.2474 0.0888 -v 0.4753 1.8045 0.1205 -v 0.4442 1.3427 0.5996 -v 0.6779 1.3491 0.4073 -v 0.2949 1.1058 -0.2049 -v 0.4742 1.5854 -0.2767 -v 0.2592 1.5098 -0.3445 -v 0.2364 1.3125 0.6031 -v 0.1564 1.8345 0.2917 -v 0.0349 1.6952 0.3177 -v 0.0001 1.3786 0.2859 -v 0.0001 1.3434 -0.5335 -v 0.3860 1.8717 0.1756 -v 0.5543 1.8395 0.0233 -v 0.0352 1.7029 -0.4445 -v 0.3076 1.9184 -0.2891 -v 0.0414 1.8419 -0.3975 -v -0.7843 1.2474 0.0888 -v -0.4711 1.5854 -0.2767 -v -0.6101 1.1533 -0.1356 -v -0.4981 1.3427 0.5996 -v -0.5002 1.8045 0.1205 -v -0.7192 1.3491 0.4073 -v -0.2504 1.5098 -0.3445 -v -0.2936 1.1061 -0.2060 -v -0.6351 1.6673 -0.0918 -v -0.2905 1.3125 0.6031 -v -0.1699 1.8345 0.2919 -v -0.0462 1.6944 0.3146 -v -0.5683 1.8395 0.0233 -v -0.0511 1.7029 -0.4445 -v -0.0574 1.8419 -0.3975 -v 0.3669 0.5949 0.4079 -v 0.1074 0.7729 0.0465 -v 0.2581 0.3109 -0.0222 -v 0.2503 0.3707 -0.2076 -v 0.3183 0.8381 -0.2049 -v 0.5227 0.4206 -0.2834 -v 0.6660 0.6512 0.3267 -v 0.3568 0.7591 0.3005 -v 0.5643 0.7974 0.2441 -v 0.6560 0.8763 -0.0878 -v 0.6474 0.3841 -0.1308 -v 0.5029 0.2752 0.0655 -v 0.2171 0.8500 0.0713 -v 0.3398 0.9269 -0.0631 -v 0.5643 0.9154 -0.0161 -v 0.4760 0.0149 -0.3733 -v 0.1870 0.0143 0.0759 -v 0.3252 0.1550 0.3433 -v 0.5876 0.2785 0.2208 -v 0.2116 0.0173 -0.2542 -v 0.7396 0.0115 -0.1727 -v 0.8469 0.1524 0.1097 -v 0.5773 0.0071 0.5454 -v 0.2939 0.0107 0.3538 -v 0.8757 0.0076 0.0919 -v 0.6789 0.1808 0.4272 -v 0.8312 0.0059 0.4311 -v 0.3511 0.9560 0.3969 -v 0.5533 0.9947 0.3415 -v 0.3175 1.1236 -0.0066 -v 0.5645 1.1095 0.1034 -v 0.2027 1.0429 0.2015 -v 0.2279 1.0698 0.2428 -v 0.3638 1.0581 0.1120 -v 0.5113 1.2343 0.3911 -v 0.3234 1.1973 0.4439 -v 0.5330 1.1301 0.1580 -v 0.4816 1.4650 -0.0181 -v 0.2363 1.4470 -0.0890 -v 0.1566 1.4343 0.0823 -v 0.5000 1.4371 0.2679 -v 0.2308 1.3887 0.3437 -v 0.8832 2.4410 0.0089 -v 0.8694 2.3330 -0.0968 -v 0.8359 2.4247 -0.1333 -v 0.7617 2.3497 0.2301 -v 0.7375 2.4769 0.1133 -v 0.9566 2.3269 0.1115 -v 0.6206 2.4234 0.0410 -v 0.6278 2.2247 0.1094 -v 0.7246 2.2901 -0.1053 -v 0.7001 2.3592 -0.1351 -v 0.9174 2.1939 -0.0606 -v 0.8454 1.8851 0.1941 -v 0.7173 2.1413 -0.0469 -v 0.9522 1.9197 0.1994 -v 0.7735 1.9567 0.2996 -v 0.9647 2.0000 0.2952 -v 0.8626 2.0135 0.3633 -v 0.7062 2.5424 -0.1761 -v 0.8296 2.5442 0.1063 -v 0.6372 2.6072 0.1816 -v 0.8679 2.5743 -0.0818 -v 1.1037 1.5774 0.3775 -v 0.8769 1.5347 0.5967 -v 0.6960 1.6892 0.4880 -v 1.0247 1.7881 0.6604 -v 0.9322 1.9818 0.5498 -v 1.1546 1.7148 0.3738 -v 1.1061 1.8395 0.2604 -v 0.8877 2.0259 0.3737 -v 0.7540 1.9545 0.3154 -v 0.8576 1.8862 0.1687 -v 0.9167 1.6631 0.3033 -v 0.6549 1.8655 0.4703 -v 0.9761 1.7458 0.1736 -v 0.9915 1.9568 0.2277 -v 0.7793 2.7864 0.1381 -v 0.7598 2.8999 0.1175 -v 0.5384 2.9454 0.2760 -v 0.8153 2.8149 -0.0433 -v 1.0201 2.5364 0.0521 -v -0.8359 2.4247 -0.1333 -v -0.8694 2.3330 -0.0968 -v -0.8832 2.4410 0.0089 -v -0.7375 2.4769 0.1133 -v -0.7617 2.3497 0.2301 -v -0.9566 2.3269 0.1115 -v -0.6278 2.2247 0.1094 -v -0.6206 2.4234 0.0410 -v -0.7001 2.3592 -0.1351 -v -0.7246 2.2901 -0.1053 -v -0.9174 2.1939 -0.0606 -v -0.9522 1.9197 0.1994 -v -0.7173 2.1413 -0.0469 -v -0.8454 1.8851 0.1941 -v -0.7735 1.9567 0.2996 -v -0.9647 2.0000 0.2952 -v -0.8626 2.0135 0.3633 -v -0.7062 2.5424 -0.1761 -v -0.6372 2.6072 0.1816 -v -0.8296 2.5442 0.1063 -v -0.8679 2.5743 -0.0818 -v -0.6960 1.6892 0.4880 -v -0.8769 1.5347 0.5967 -v -1.1037 1.5774 0.3775 -v -1.0247 1.7881 0.6604 -v -0.9322 1.9818 0.5498 -v -1.1061 1.8395 0.2604 -v -1.1546 1.7148 0.3738 -v -0.8877 2.0259 0.3737 -v -0.8576 1.8862 0.1687 -v -0.7540 1.9545 0.3154 -v -0.6549 1.8655 0.4703 -v -0.9167 1.6631 0.3033 -v -0.9761 1.7458 0.1736 -v -0.9915 1.9568 0.2277 -v -0.7598 2.8999 0.1175 -v -0.7793 2.7864 0.1381 -v -0.8153 2.8149 -0.0433 -v -1.0201 2.5364 0.0521 -v -0.2581 0.3109 -0.0222 -v -0.1074 0.7729 0.0465 -v -0.3669 0.5949 0.4079 -v -0.2503 0.3707 -0.2076 -v -0.3183 0.8381 -0.2049 -v -0.5227 0.4206 -0.2834 -v -0.3568 0.7591 0.3005 -v -0.6660 0.6512 0.3267 -v -0.5643 0.7974 0.2441 -v -0.6560 0.8763 -0.0878 -v -0.6474 0.3841 -0.1308 -v -0.5029 0.2752 0.0655 -v -0.3398 0.9269 -0.0631 -v -0.2171 0.8500 0.0713 -v -0.5643 0.9154 -0.0161 -v -0.4760 0.0149 -0.3733 -v -0.1870 0.0143 0.0759 -v -0.5876 0.2785 0.2208 -v -0.3252 0.1550 0.3433 -v -0.2116 0.0173 -0.2542 -v -0.7396 0.0115 -0.1727 -v -0.8469 0.1524 0.1097 -v -0.2939 0.0107 0.3538 -v -0.5773 0.0071 0.5454 -v -0.8757 0.0076 0.0919 -v -0.6789 0.1808 0.4272 -v -0.8312 0.0059 0.4311 -v -0.5533 0.9947 0.3415 -v -0.3511 0.9560 0.3969 -v -0.5645 1.1095 0.1034 -v -0.3175 1.1236 -0.0066 -v -0.2027 1.0429 0.2015 -v -0.3638 1.0581 0.1120 -v -0.2279 1.0698 0.2428 -v -0.5113 1.2343 0.3911 -v -0.3234 1.1973 0.4439 -v -0.5330 1.1301 0.1580 -v -0.4816 1.4650 -0.0181 -v -0.2363 1.4470 -0.0890 -v -0.1566 1.4343 0.0823 -v -0.5000 1.4371 0.2679 -v -0.2308 1.3887 0.3437 -# 335 vertices - -vt 0.2135 0.0260 0.0000 -vt 0.2591 0.0428 0.0000 -vt 0.2222 0.0676 0.0000 -vt 0.1124 0.1603 0.0000 -vt 0.0642 0.1761 0.0000 -vt 0.0951 0.2220 0.0000 -vt 0.3095 0.2325 0.0000 -vt 0.2772 0.2438 0.0000 -vt 0.3622 0.2162 0.0000 -vt 0.2576 0.2373 0.0000 -vt 0.1799 0.2519 0.0000 -vt 0.1533 0.2468 0.0000 -vt 0.2235 0.2329 0.0000 -vt 0.0528 0.2394 0.0000 -vt 0.3151 0.2047 0.0000 -vt 0.4101 0.1722 0.0000 -vt 0.2625 0.1615 0.0000 -vt 0.4512 0.1876 0.0000 -vt 0.1970 0.2081 0.0000 -vt 0.2097 0.1811 0.0000 -vt 0.4310 0.2082 0.0000 -vt 0.0654 0.1897 0.0000 -vt 0.1534 0.1797 0.0000 -vt 0.3574 0.1263 0.0000 -vt 0.4512 0.1014 0.0000 -vt 0.5152 0.1062 0.0000 -vt 0.1137 0.1432 0.0000 -vt 0.1924 0.1250 0.0000 -vt 0.4595 0.0628 0.0000 -vt 0.2820 0.0889 0.0000 -vt 0.2590 0.0646 0.0000 -vt 0.1837 0.0996 0.0000 -vt 0.1063 0.1323 0.0000 -vt 0.5156 0.2228 0.0000 -vt 0.4944 0.1969 0.0000 -vt 0.2041 0.2096 0.0000 -vt 0.1379 0.1203 0.0000 -vt 0.1505 0.1745 0.0000 -vt 0.1389 0.2343 0.0000 -vt 0.0845 0.1988 0.0000 -vt 0.0316 0.2012 0.0000 -vt 0.0265 0.2483 0.0000 -vt 0.1201 0.2589 0.0000 -vt 0.8245 0.3764 0.0000 -vt 0.8552 0.3620 0.0000 -vt 0.8515 0.3759 0.0000 -vt 0.8046 0.3199 0.0000 -vt 0.7671 0.3625 0.0000 -vt 0.8032 0.3704 0.0000 -vt 0.7088 0.3112 0.0000 -vt 0.7312 0.3699 0.0000 -vt 0.7296 0.3196 0.0000 -vt 0.8257 0.3108 0.0000 -vt 0.7671 0.3118 0.0000 -vt 0.7104 0.3767 0.0000 -vt 0.7941 0.8715 0.0000 -vt 0.8152 0.8743 0.0000 -vt 0.7814 0.8715 0.0000 -vt 0.8160 0.8556 0.0000 -vt 0.8060 0.8547 0.0000 -vt 0.8423 0.8531 0.0000 -vt 0.7907 0.8603 0.0000 -vt 0.8108 0.8388 0.0000 -vt 0.8341 0.8195 0.0000 -vt 0.8449 0.8323 0.0000 -vt 0.7768 0.8511 0.0000 -vt 0.7868 0.8236 0.0000 -vt 0.7717 0.8262 0.0000 -vt 0.7991 0.8293 0.0000 -vt 0.8044 0.8213 0.0000 -vt 0.7821 0.8149 0.0000 -vt 0.7931 0.8223 0.0000 -vt 0.7682 0.8166 0.0000 -vt 0.8315 0.8149 0.0000 -vt 0.7989 0.8237 0.0000 -vt 0.8328 0.8250 0.0000 -vt 0.7977 0.8469 0.0000 -vt 0.8299 0.8463 0.0000 -vt 0.8102 0.8661 0.0000 -vt 0.8077 0.8496 0.0000 -vt 0.7849 0.8640 0.0000 -vt 0.7730 0.8618 0.0000 -vt 0.7773 0.8412 0.0000 -vt 0.8004 0.8431 0.0000 -vt 0.7773 0.8669 0.0000 -vt 0.8175 0.8526 0.0000 -vt 0.8327 0.8278 0.0000 -vt 0.8955 0.8308 0.0000 -vt 0.7126 0.9067 0.0000 -vt 0.7122 0.9055 0.0000 -vt 0.6562 0.8658 0.0000 -vt 0.7125 0.9010 0.0000 -vt 0.6316 0.8917 0.0000 -vt 0.7138 0.8403 0.0000 -vt 0.6525 0.8642 0.0000 -vt 0.7151 0.8399 0.0000 -vt 0.3771 0.6591 0.0000 -vt 0.4945 0.6355 0.0000 -vt 0.4423 0.7310 0.0000 -vt 0.5454 0.6962 0.0000 -vt 0.5968 0.6356 0.0000 -vt 0.5452 0.7879 0.0000 -vt 0.6480 0.7314 0.0000 -vt 0.7153 0.6600 0.0000 -vt 0.6163 0.0332 0.0000 -vt 0.6640 0.0716 0.0000 -vt 0.5685 0.0716 0.0000 -vt 0.5873 0.2558 0.0000 -vt 0.5703 0.1607 0.0000 -vt 0.5767 0.1372 0.0000 -vt 0.5790 0.1445 0.0000 -vt 0.5685 0.1681 0.0000 -vt 0.5986 0.1305 0.0000 -vt 0.5726 0.1759 0.0000 -vt 0.5985 0.1597 0.0000 -vt 0.5777 0.2146 0.0000 -vt 0.5713 0.1746 0.0000 -vt 0.5984 0.2161 0.0000 -vt 0.5848 0.2442 0.0000 -vt 0.5982 0.2580 0.0000 -vt 0.8853 0.6459 0.0000 -vt 0.8556 0.6355 0.0000 -vt 0.8881 0.6562 0.0000 -vt 0.8883 0.6804 0.0000 -vt 0.8605 0.7261 0.0000 -vt 0.8915 0.7259 0.0000 -vt 0.7747 0.6804 0.0000 -vt 0.7715 0.7259 0.0000 -vt 0.8027 0.7261 0.0000 -vt 0.8316 0.6925 0.0000 -vt 0.8631 0.7384 0.0000 -vt 0.8002 0.7384 0.0000 -vt 0.7682 0.6867 0.0000 -vt 0.7726 0.7205 0.0000 -vt 0.8597 0.6522 0.0000 -vt 0.8906 0.7205 0.0000 -vt 0.8743 0.7572 0.0000 -vt 0.7891 0.7572 0.0000 -vt 0.8860 0.6572 0.0000 -vt 0.7770 0.6572 0.0000 -vt 0.8948 0.6867 0.0000 -vt 0.8316 0.6665 0.0000 -vt 0.8116 0.6480 0.0000 -vt 0.7777 0.6459 0.0000 -vt 0.8514 0.6480 0.0000 -vt 0.8310 0.7629 0.0000 -vt 0.7891 0.7542 0.0000 -vt 0.8743 0.7542 0.0000 -vt 0.8035 0.6522 0.0000 -vt 0.7750 0.6562 0.0000 -vt 0.8089 0.6355 0.0000 -vt 0.9088 0.3283 0.0000 -vt 0.9347 0.3327 0.0000 -vt 0.9121 0.3504 0.0000 -vt 0.9135 0.3216 0.0000 -vt 0.9509 0.3223 0.0000 -vt 0.9443 0.3530 0.0000 -vt 0.9735 0.3592 0.0000 -vt 0.9692 0.3308 0.0000 -vt 0.9684 0.3675 0.0000 -vt 0.9263 0.3658 0.0000 -vt 0.5507 0.8617 0.0000 -vt 0.5279 0.8750 0.0000 -vt 0.5279 0.8465 0.0000 -vt 0.5470 0.8498 0.0000 -vt 0.5470 0.8828 0.0000 -vt 0.5319 0.8403 0.0000 -vt 0.5279 0.8961 0.0000 -vt 0.5496 0.8399 0.0000 -vt 0.5645 0.8636 0.0000 -vt 0.5620 0.8770 0.0000 -vt 0.5742 0.8681 0.0000 -vt 0.5654 0.8482 0.0000 -vt 0.4749 0.8399 0.0000 -vt 0.3867 0.9042 0.0000 -vt 0.4750 0.9042 0.0000 -vt 0.3879 0.8399 0.0000 -vt 0.6367 0.1288 0.0000 -vt 0.5886 0.1338 0.0000 -vt 0.5890 0.1288 0.0000 -vt 0.6846 0.1341 0.0000 -vt 0.6838 0.1286 0.0000 -vt 0.5916 0.1410 0.0000 -vt 0.6180 0.1379 0.0000 -vt 0.6005 0.1390 0.0000 -vt 0.6978 0.2376 0.0000 -vt 0.7052 0.1822 0.0000 -vt 0.7052 0.2450 0.0000 -vt 0.6893 0.1737 0.0000 -vt 0.6623 0.2482 0.0000 -vt 0.6931 0.2461 0.0000 -vt 0.6657 0.2279 0.0000 -vt 0.6966 0.1777 0.0000 -vt 0.6741 0.1748 0.0000 -vt 0.6393 0.2442 0.0000 -vt 0.6584 0.1476 0.0000 -vt 0.6446 0.1649 0.0000 -vt 0.6397 0.2053 0.0000 -vt 0.6394 0.2172 0.0000 -vt 0.6844 0.1441 0.0000 -vt 0.7033 0.1498 0.0000 -vt 0.6445 0.1708 0.0000 -vt 0.6755 0.1425 0.0000 -vt 0.6454 0.1528 0.0000 -vt 0.6875 0.1377 0.0000 -vt 0.5724 0.2532 0.0000 -vt 0.5865 0.1723 0.0000 -vt 0.5844 0.2452 0.0000 -vt 0.6193 0.2589 0.0000 -vt 0.5938 0.1674 0.0000 -vt 0.5889 0.2558 0.0000 -vt 0.6089 0.1691 0.0000 -vt 0.6164 0.2339 0.0000 -vt 0.5744 0.1790 0.0000 -vt 0.6422 0.2545 0.0000 -vt 0.6249 0.1363 0.0000 -vt 0.6428 0.2071 0.0000 -vt 0.6386 0.1578 0.0000 -vt 0.6426 0.2217 0.0000 -vt 0.5802 0.1377 0.0000 -vt 0.6382 0.1650 0.0000 -vt 0.6377 0.1431 0.0000 -vt 0.6080 0.1297 0.0000 -vt 0.5963 0.1236 0.0000 -vt 0.6815 0.1413 0.0000 -vt 0.6543 0.1378 0.0000 -vt 0.6421 0.1506 0.0000 -vt 0.6314 0.1701 0.0000 -vt 0.6307 0.1506 0.0000 -vt 0.7008 0.1472 0.0000 -vt 0.6414 0.1640 0.0000 -vt 0.6319 0.1642 0.0000 -vt 0.6366 0.2080 0.0000 -vt 0.6554 0.1451 0.0000 -vt 0.5723 0.1468 0.0000 -vt 0.6414 0.1701 0.0000 -vt 0.6362 0.2206 0.0000 -vt 0.6177 0.1450 0.0000 -vt 0.6726 0.1392 0.0000 -vt 0.1171 0.8175 0.0000 -vt 0.0996 0.8137 0.0000 -vt 0.1074 0.9276 0.0000 -vt 0.0971 0.9343 0.0000 -vt 0.0895 0.8288 0.0000 -vt 0.1582 0.8282 0.0000 -vt 0.1511 0.9341 0.0000 -vt 0.1676 0.9337 0.0000 -vt 0.1274 0.8172 0.0000 -vt 0.1151 0.8003 0.0000 -vt 0.1286 0.8000 0.0000 -vt 0.1449 0.8111 0.0000 -vt 0.1397 0.9273 0.0000 -vt 0.1232 0.9292 0.0000 -vt 0.0981 0.8030 0.0000 -vt 0.0894 0.8016 0.0000 -vt 0.1581 0.8009 0.0000 -vt 0.1460 0.8016 0.0000 -vt 0.8961 0.2518 0.0000 -vt 0.8864 0.1335 0.0000 -vt 0.8902 0.1363 0.0000 -vt 0.8510 0.2514 0.0000 -vt 0.8561 0.1236 0.0000 -vt 0.8322 0.1284 0.0000 -vt 0.8033 0.2053 0.0000 -vt 0.8046 0.1568 0.0000 -vt 0.8615 0.1271 0.0000 -vt 0.7586 0.2512 0.0000 -vt 0.8033 0.2515 0.0000 -vt 0.7682 0.1938 0.0000 -vt 0.7144 0.9075 0.0000 -vt 0.7152 0.9064 0.0000 -vt 0.7131 0.9080 0.0000 -vt 0.7135 0.9053 0.0000 -vt 0.9034 0.5146 0.0000 -vt 0.9377 0.5020 0.0000 -vt 0.9412 0.5360 0.0000 -vt 0.9496 0.5254 0.0000 -vt 0.9455 0.5426 0.0000 -vt 0.9465 0.5156 0.0000 -vt 0.9546 0.5330 0.0000 -vt 0.9510 0.5622 0.0000 -vt 0.9070 0.5309 0.0000 -vt 0.9021 0.5563 0.0000 -vt 0.9344 0.5805 0.0000 -vt 0.9309 0.5801 0.0000 -vt 0.9057 0.5775 0.0000 -vt 0.9081 0.5372 0.0000 -vt 0.9493 0.5614 0.0000 -vt 0.8939 0.5549 0.0000 -vt 0.9094 0.5780 0.0000 -vt 0.9499 0.5624 0.0000 -vt 0.9433 0.3160 0.0000 -vt 0.9536 0.3109 0.0000 -vt 0.9714 0.3317 0.0000 -vt 0.9377 0.3407 0.0000 -vt 0.9207 0.3279 0.0000 -vt 0.9700 0.3185 0.0000 -vt 0.9081 0.3108 0.0000 -# 298 texture coords - -g Regroup24 -usemtl YoungLink.bmp -f 1/1 2/2 3/3 -f 4/4 5/5 6/6 -f 7/7 8/8 9/9 -f 10/10 11/11 12/12 -f 11/11 10/10 8/8 -f 8/8 7/7 11/11 -f 11/11 13/13 6/6 -f 11/11 14/14 12/12 -f 15/15 16/16 9/9 -f 16/16 15/15 17/17 -f 9/9 16/16 18/18 -f 15/15 19/19 17/17 -f 20/20 17/17 19/19 -f 9/9 18/18 21/21 -f 14/14 5/5 22/22 -f 20/20 23/23 17/17 -f 24/24 16/16 17/17 -f 25/25 26/26 24/24 -f 27/27 28/28 23/23 -f 16/16 24/24 26/26 -f 29/29 30/30 31/31 -f 29/29 24/24 30/30 -f 16/16 26/26 18/18 -f 28/28 30/30 17/17 -f 32/32 30/30 28/28 -f 30/30 32/32 31/31 -f 30/30 24/24 17/17 -f 27/27 5/5 33/33 -f 23/23 28/28 17/17 -f 27/27 22/22 5/5 -f 27/27 32/32 28/28 -f 34/34 21/21 35/35 -f 34/34 35/35 7/7 -f 10/10 19/19 15/15 -f 27/27 33/33 32/32 -f 36/36 13/13 7/7 -f 10/10 15/15 9/9 -f 14/14 11/11 6/6 -f 6/6 5/5 14/14 -f 5/5 4/4 37/37 -f 4/4 38/38 37/37 -f 8/8 10/10 9/9 -f 13/13 11/11 7/7 -f 33/33 5/5 37/37 -f 1/1 37/37 2/2 -f 33/33 37/37 32/32 -f 29/29 25/25 24/24 -f 39/39 13/13 36/36 -f 40/40 4/4 41/41 -f 40/40 36/36 38/38 -f 42/42 4/4 6/6 -f 42/42 13/13 43/43 -f 39/39 36/36 40/40 -f 4/4 42/42 41/41 -f 13/13 42/42 6/6 -f 13/13 39/39 43/43 -f 4/4 40/40 38/38 -f 44/44 45/45 46/46 -f 47/47 45/48 48/49 -f 49/50 50/51 51/52 -f 52/53 48/49 44/44 -f 45/48 47/47 53/54 -f 45/48 44/44 48/49 -f 48/49 52/53 47/47 -f 45/48 51/52 50/51 -f 46/55 45/48 50/51 -f 50/51 49/50 46/55 -f 51/52 45/48 53/54 -f 54/56 55/57 56/58 -f 55/57 54/56 25/59 -f 55/57 29/60 57/61 -f 55/57 57/61 58/62 -f 59/63 58/62 57/61 -f 55/57 58/62 56/58 -f 60/64 59/63 61/65 -f 59/63 62/66 58/62 -f 3/67 2/68 31/69 -f 31/69 32/70 3/67 -f 60/64 2/68 59/63 -f 60/64 61/65 29/60 -f 56/58 58/62 62/66 -f 60/64 31/69 2/68 -f 59/63 2/68 62/66 -f 60/64 29/60 31/69 -f 59/63 57/61 61/65 -f 61/65 57/61 29/60 -f 55/57 25/59 29/60 -f 21/71 18/72 35/73 -f 63/74 64/75 35/73 -f 65/76 26/77 66/78 -f 65/76 18/72 26/77 -f 67/79 25/80 54/81 -f 63/74 65/76 64/75 -f 66/78 26/77 67/79 -f 67/79 26/77 25/80 -f 63/74 18/72 65/76 -f 54/81 68/82 67/79 -f 64/75 65/76 66/78 -f 64/75 66/78 69/83 -f 67/79 69/83 66/78 -f 67/79 68/82 69/83 -f 63/74 35/73 18/72 -f 64/75 69/83 35/73 -f 38/84 70/85 71/86 -f 37/87 38/84 71/86 -f 72/86 7/87 35/88 -f 71/86 2/88 37/87 -f 72/86 36/84 7/87 -f 36/84 70/85 38/84 -f 70/85 36/84 72/86 -f 41/89 42/89 73/89 -f 43/89 74/89 75/89 -f 40/89 74/89 39/89 -f 42/89 76/90 73/89 -f 41/89 77/89 40/89 -f 77/89 74/89 40/89 -f 43/89 75/89 42/89 -f 74/89 43/89 39/89 -f 75/89 76/90 42/89 -f 77/89 41/89 73/89 -f 21/91 7/92 9/93 -f 34/94 7/92 21/91 -f 3/95 32/93 37/92 -f 1/96 3/95 37/92 -f 27/97 23/98 22/99 -f 78/100 23/98 19/101 -f 14/102 22/99 78/100 -f 78/100 22/99 23/98 -f 12/103 19/101 10/104 -f 12/103 14/102 78/100 -f 12/103 78/100 19/101 -f 20/105 19/106 23/107 -f 79/108 80/108 77/108 -f 74/108 81/108 75/108 -f 82/108 74/108 77/108 -f 82/108 77/108 80/108 -f 73/108 76/108 79/108 -f 77/108 73/108 79/108 -f 82/108 81/108 74/108 -f 75/108 81/108 76/108 -f 68/109 83/110 84/111 -f 83/110 68/109 56/109 -f 54/112 56/109 68/109 -f 84/111 83/110 85/113 -f 86/111 56/109 62/114 -f 87/115 62/114 2/116 -f 86/111 87/115 85/113 -f 86/111 85/113 83/110 -f 86/111 62/114 87/115 -f 86/111 83/110 56/109 -f 69/117 84/111 88/115 -f 85/113 88/115 84/111 -f 35/116 88/115 89/118 -f 88/115 35/116 69/117 -f 90/118 71/119 70/120 -f 89/118 70/120 72/119 -f 90/118 2/116 71/119 -f 2/116 90/118 87/115 -f 35/116 89/118 72/119 -f 68/109 84/111 69/117 -f 91/121 74/122 92/123 -f 93/124 94/125 95/126 -f 96/127 97/128 98/129 -f 99/130 100/131 101/132 -f 102/133 103/127 104/134 -f 94/125 92/123 105/135 -f 100/131 106/136 107/137 -f 104/134 101/132 108/138 -f 109/124 99/130 110/139 -f 111/140 99/130 103/127 -f 112/141 95/126 106/136 -f 109/124 112/141 106/136 -f 76/142 111/140 73/143 -f 113/144 73/143 111/140 -f 76/142 110/139 99/130 -f 110/139 76/142 75/145 -f 114/146 115/147 108/138 -f 108/138 97/128 104/134 -f 105/135 98/129 94/125 -f 114/146 116/148 115/147 -f 107/137 116/148 114/146 -f 117/149 98/129 105/135 -f 118/150 98/129 117/149 -f 95/126 107/137 106/136 -f 95/126 94/125 116/148 -f 114/146 108/138 107/137 -f 92/123 74/122 105/135 -f 115/147 98/129 97/128 -f 74/122 117/149 105/135 -f 77/151 118/150 117/149 -f 101/132 107/137 108/138 -f 77/151 117/149 74/122 -f 115/147 94/125 98/129 -f 100/131 107/137 101/132 -f 97/128 102/133 104/134 -f 116/148 94/125 115/147 -f 73/143 113/144 77/151 -f 101/132 103/127 99/130 -f 74/122 91/121 75/145 -f 97/128 96/127 102/133 -f 112/141 93/124 95/126 -f 75/145 91/121 110/139 -f 99/130 111/140 76/142 -f 94/125 93/124 92/123 -f 103/127 101/132 104/134 -f 100/131 109/124 106/136 -f 107/137 95/126 116/148 -f 109/124 100/131 99/130 -f 118/150 77/151 113/144 -f 97/128 108/138 115/147 -f 98/129 118/150 96/127 -f 93/152 119/153 92/154 -f 119/153 93/152 112/155 -f 109/152 120/156 112/155 -f 120/156 119/153 112/155 -f 121/157 96/158 118/159 -f 96/158 121/157 102/160 -f 121/157 122/161 102/160 -f 122/161 103/158 102/160 -f 123/162 89/163 88/164 -f 87/164 124/162 125/165 -f 124/162 90/163 126/166 -f 88/164 127/165 123/162 -f 85/167 127/165 88/164 -f 125/165 85/167 87/164 -f 70/168 126/166 90/163 -f 85/167 125/165 128/169 -f 89/163 123/162 129/166 -f 127/165 85/167 128/169 -f 129/166 70/168 89/163 -f 90/163 124/162 87/164 -f 70/168 129/166 126/166 -f 130/170 126/166 131/171 -f 129/166 132/170 131/171 -f 133/172 131/171 132/170 -f 134/173 132/170 127/165 -f 130/170 125/165 124/162 -f 134/173 127/165 128/169 -f 130/170 134/173 125/165 -f 130/170 131/171 133/172 -f 132/170 134/173 133/172 -f 126/166 129/166 131/171 -f 125/165 134/173 128/169 -f 127/165 132/170 123/162 -f 126/166 130/170 124/162 -f 134/173 130/170 133/172 -f 132/170 129/166 123/162 -f 44/174 49/175 52/176 -f 49/175 44/174 46/177 -f 53/178 135/179 51/180 -f 136/181 53/178 47/182 -f 51/180 137/183 49/184 -f 135/179 53/178 138/185 -f 139/186 140/187 141/188 -f 142/189 143/190 144/191 -f 145/192 146/193 139/186 -f 146/193 140/187 139/186 -f 141/188 142/189 144/191 -f 147/194 146/193 145/192 -f 140/187 142/189 141/188 -f 148/195 149/196 150/197 -f 150/197 151/198 148/195 -f 152/199 147/194 145/192 -f 142/189 140/187 153/200 -f 153/200 140/187 154/201 -f 147/194 155/202 156/203 -f 156/203 155/202 157/204 -f 136/205 146/193 156/203 -f 156/203 146/193 147/194 -f 153/200 143/190 142/189 -f 140/187 136/205 154/201 -f 149/196 148/195 143/190 -f 149/196 143/190 153/200 -f 147/194 152/199 155/202 -f 136/205 140/187 146/193 -f 158/206 159/207 160/208 -f 161/209 162/210 163/211 -f 160/208 164/212 165/213 -f 166/214 159/207 158/206 -f 163/211 166/214 158/206 -f 159/207 164/212 160/208 -f 162/210 166/214 163/211 -f 167/215 168/216 161/209 -f 151/217 169/218 167/215 -f 164/212 152/219 165/213 -f 166/214 162/210 170/220 -f 170/220 162/210 137/113 -f 171/221 164/212 172/222 -f 172/222 164/212 138/223 -f 159/207 135/224 164/212 -f 164/212 135/224 138/223 -f 162/210 168/216 137/113 -f 135/224 166/214 170/220 -f 168/216 167/215 169/218 -f 161/209 168/216 162/210 -f 152/219 164/212 171/221 -f 166/214 135/224 159/207 -f 153/225 47/182 52/226 -f 157/227 171/228 172/229 -f 47/182 153/225 154/230 -f 53/178 172/229 138/185 -f 150/231 169/232 151/233 -f 47/182 154/230 136/181 -f 52/226 149/234 153/225 -f 137/183 51/180 170/235 -f 53/178 157/227 172/229 -f 171/228 155/236 152/237 -f 49/184 137/183 168/238 -f 53/178 156/239 157/227 -f 51/180 135/179 170/235 -f 49/184 149/234 52/226 -f 171/228 157/227 155/236 -f 168/238 150/231 149/234 -f 168/238 149/234 49/184 -f 169/232 150/231 168/238 -f 53/178 136/181 156/239 -f 51/180 135/179 53/178 -f 47/182 53/178 136/181 -f 49/184 137/183 51/180 -f 138/185 53/178 135/179 -f 141/188 140/187 139/186 -f 144/191 143/190 142/189 -f 139/186 146/193 145/192 -f 139/186 140/187 146/193 -f 144/191 142/189 141/188 -f 145/192 146/193 147/194 -f 141/188 142/189 140/187 -f 150/197 149/196 148/195 -f 148/195 151/198 150/197 -f 145/192 147/194 152/199 -f 153/200 140/187 142/189 -f 154/201 140/187 153/200 -f 156/203 155/202 147/194 -f 157/204 155/202 156/203 -f 156/203 146/193 136/205 -f 147/194 146/193 156/203 -f 142/189 143/190 153/200 -f 154/201 136/205 140/187 -f 143/190 148/195 149/196 -f 153/200 143/190 149/196 -f 155/202 152/199 147/194 -f 146/193 140/187 136/205 -f 160/208 159/207 158/206 -f 163/211 162/210 161/209 -f 165/213 164/212 160/208 -f 158/206 159/207 166/214 -f 158/206 166/214 163/211 -f 160/208 164/212 159/207 -f 163/211 166/214 162/210 -f 161/209 168/216 167/215 -f 167/215 169/218 151/217 -f 165/213 152/219 164/212 -f 170/220 162/210 166/214 -f 137/113 162/210 170/220 -f 172/222 164/212 171/221 -f 138/223 164/212 172/222 -f 164/212 135/224 159/207 -f 138/223 135/224 164/212 -f 137/113 168/216 162/210 -f 170/220 166/214 135/224 -f 169/218 167/215 168/216 -f 162/210 168/216 161/209 -f 171/221 164/212 152/219 -f 159/207 135/224 166/214 -f 52/226 47/182 153/225 -f 172/229 171/228 157/227 -f 154/230 153/225 47/182 -f 138/185 172/229 53/178 -f 151/233 169/232 150/231 -f 136/181 154/230 47/182 -f 153/225 149/234 52/226 -f 170/235 51/180 137/183 -f 172/229 157/227 53/178 -f 152/237 155/236 171/228 -f 168/238 137/183 49/184 -f 157/227 156/239 53/178 -f 170/235 135/179 51/180 -f 52/226 149/234 49/184 -f 155/236 157/227 171/228 -f 149/234 150/231 168/238 -f 49/184 149/234 168/238 -f 168/238 150/231 169/232 -f 156/239 136/181 53/178 -f 173/240 174/241 175/242 -f 176/243 175/242 174/241 -f 174/241 177/244 176/243 -f 177/245 178/246 176/247 -f 173/240 179/248 180/249 -f 180/249 179/248 181/250 -f 179/248 182/251 181/250 -f 182/251 183/252 178/246 -f 179/248 184/253 183/252 -f 184/253 173/240 175/242 -f 185/254 186/255 177/244 -f 179/248 173/240 184/253 -f 183/252 182/251 179/248 -f 186/256 187/257 177/245 -f 174/241 173/240 180/249 -f 177/245 182/251 178/246 -f 180/249 185/254 174/241 -f 187/257 181/250 182/251 -f 185/254 177/244 174/241 -f 177/245 187/257 182/251 -f 188/258 176/259 178/260 -f 189/261 175/262 176/259 -f 184/263 190/264 191/265 -f 192/258 176/259 188/258 -f 176/259 192/258 189/261 -f 175/262 190/264 184/263 -f 188/258 178/260 193/261 -f 183/266 193/261 178/260 -f 194/264 183/266 191/265 -f 191/265 183/266 184/263 -f 175/262 189/261 190/264 -f 193/261 183/266 194/264 -f 193/261 189/261 188/258 -f 188/258 189/261 192/258 -f 195/267 190/264 196/268 -f 193/261 194/264 197/268 -f 198/269 194/264 191/265 -f 198/269 190/264 195/267 -f 193/261 196/268 189/261 -f 197/268 196/268 193/261 -f 199/267 194/264 198/269 -f 198/269 195/267 199/267 -f 190/264 198/269 191/265 -f 194/264 199/267 197/268 -f 196/268 197/268 195/267 -f 195/267 197/268 199/267 -f 190/264 189/261 196/268 -f 200/270 180/270 201/270 -f 201/270 180/270 181/270 -f 187/271 202/271 203/271 -f 202/271 185/271 204/271 -f 203/271 201/270 181/270 -f 185/271 202/271 186/271 -f 185/271 180/270 204/271 -f 181/270 187/271 203/271 -f 200/270 204/271 180/270 -f 202/271 187/271 186/271 -f 204/271 205/270 206/271 -f 201/270 203/271 207/270 -f 207/270 208/270 201/270 -f 201/270 208/270 200/270 -f 205/270 204/271 208/270 -f 206/271 203/271 202/271 -f 203/271 209/270 207/270 -f 208/270 204/271 200/270 -f 209/270 203/271 206/271 -f 204/271 206/271 202/271 -f 210/89 207/270 209/270 -f 210/89 209/270 211/89 -f 211/89 205/270 212/89 -f 213/270 207/270 210/89 -f 211/89 209/270 206/271 -f 205/270 211/89 206/271 -f 212/89 205/270 214/270 -f 214/270 205/270 208/270 -f 214/270 208/270 213/270 -f 213/270 208/270 207/270 -f 215/89 216/90 217/90 -f 218/272 215/89 219/89 -f 215/89 218/272 220/89 -f 218/272 221/89 222/89 -f 217/90 223/89 224/89 -f 221/89 223/89 222/89 -f 221/89 218/272 219/89 -f 216/90 223/89 217/90 -f 225/273 215/89 220/89 -f 223/89 221/89 224/89 -f 216/90 215/89 225/273 -f 226/271 227/89 228/271 -f 228/271 227/89 225/273 -f 222/89 227/89 229/270 -f 229/270 227/89 226/271 -f 225/273 220/89 228/271 -f 228/271 220/89 230/270 -f 218/272 222/89 231/270 -f 231/270 222/89 229/270 -f 227/89 216/90 225/273 -f 222/89 223/89 227/89 -f 231/270 220/89 218/272 -f 223/89 216/90 227/89 -f 229/270 230/270 231/270 -f 230/270 220/89 231/270 -f 228/271 230/270 226/271 -f 226/271 230/270 229/270 -f 224/273 122/89 232/90 -f 219/89 233/89 234/89 -f 215/89 235/90 233/89 -f 217/273 235/90 215/89 -f 122/89 224/273 221/89 -f 233/89 219/89 215/89 -f 234/89 221/89 219/89 -f 217/273 232/90 235/90 -f 122/89 121/90 232/90 -f 121/90 235/90 232/90 -f 232/90 217/273 224/273 -f 221/89 234/89 122/89 -f 236/274 237/275 238/276 -f 236/274 239/277 237/275 -f 238/278 237/279 239/280 -f 240/281 238/278 239/280 -f 240/281 241/282 242/283 -f 242/283 243/284 240/281 -f 244/285 243/284 245/286 -f 239/277 241/282 240/281 -f 241/282 236/274 242/283 -f 239/277 236/274 241/282 -f 246/287 247/288 245/286 -f 248/289 245/286 242/283 -f 238/276 247/288 246/287 -f 248/289 246/287 245/286 -f 238/276 246/287 236/274 -f 236/274 246/287 248/289 -f 243/284 242/283 249/290 -f 242/283 236/274 248/289 -f 249/290 242/283 245/286 -f 243/284 249/290 245/286 -f 240/281 243/284 247/288 -f 238/278 240/281 247/291 -f 244/285 245/286 247/288 -f 243/284 244/285 247/288 -f 250/292 251/293 252/294 -f 103/158 122/161 234/295 -f 250/292 103/158 233/296 -f 233/296 103/158 234/295 -f 113/297 252/294 251/293 -f 251/293 118/159 113/297 -f 118/159 253/292 121/157 -f 118/159 251/293 253/292 -f 103/158 250/292 252/294 -f 254/298 250/292 233/296 -f 254/298 253/292 250/292 -f 233/296 235/296 254/298 -f 253/292 254/298 235/296 -f 251/293 250/292 253/292 -f 235/296 121/157 253/292 -f 255/90 256/90 257/89 -f 258/89 257/89 259/272 -f 260/89 259/272 257/89 -f 261/89 262/89 259/272 -f 263/89 264/89 255/90 -f 261/89 264/89 262/89 -f 258/89 259/272 262/89 -f 255/90 264/89 256/90 -f 260/89 257/89 265/273 -f 263/89 262/89 264/89 -f 265/273 257/89 256/90 -f 266/271 267/89 268/271 -f 265/273 267/89 266/271 -f 269/270 267/89 261/89 -f 268/271 267/89 269/270 -f 266/271 260/89 265/273 -f 270/270 260/89 266/271 -f 271/270 261/89 259/272 -f 269/270 261/89 271/270 -f 265/273 256/90 267/89 -f 267/89 264/89 261/89 -f 259/272 260/89 271/270 -f 267/89 256/90 264/89 -f 271/270 270/270 269/270 -f 271/270 260/89 270/270 -f 268/271 270/270 266/271 -f 269/270 270/270 268/271 -f 272/90 120/89 263/273 -f 273/89 274/89 258/89 -f 274/89 275/90 257/89 -f 257/89 275/90 255/273 -f 262/89 263/273 120/89 -f 257/89 258/89 274/89 -f 258/89 262/89 273/89 -f 275/90 272/90 255/273 -f 272/90 119/90 120/89 -f 272/90 275/90 119/90 -f 263/273 255/273 272/90 -f 120/89 273/89 262/89 -f 276/276 277/275 278/274 -f 277/275 279/277 278/274 -f 279/280 277/279 276/278 -f 279/280 276/278 280/281 -f 281/283 282/282 280/281 -f 280/281 283/284 281/283 -f 284/286 283/284 285/285 -f 280/281 282/282 279/277 -f 281/283 278/274 282/282 -f 282/282 278/274 279/277 -f 284/286 286/288 287/287 -f 281/283 284/286 288/289 -f 287/287 286/288 276/276 -f 284/286 287/287 288/289 -f 278/274 287/287 276/276 -f 288/289 287/287 278/274 -f 289/290 281/283 283/284 -f 288/289 278/274 281/283 -f 284/286 281/283 289/290 -f 284/286 289/290 283/284 -f 286/288 283/284 280/281 -f 286/291 280/281 276/278 -f 286/288 284/286 285/285 -f 286/288 285/285 283/284 -f 110/294 290/293 291/292 -f 273/295 120/161 109/158 -f 274/296 109/158 291/292 -f 273/295 109/158 274/296 -f 290/293 110/294 91/297 -f 91/297 92/159 290/293 -f 119/157 292/292 92/159 -f 292/292 290/293 92/159 -f 110/294 291/292 109/158 -f 274/296 291/292 293/298 -f 291/292 292/292 293/298 -f 293/298 275/296 274/296 -f 275/296 293/298 292/292 -f 292/292 291/292 290/293 -f 292/292 119/157 275/296 -f 294/242 295/241 296/240 -f 295/241 294/242 297/243 -f 297/243 298/244 295/241 -f 297/247 299/246 298/245 -f 300/249 301/248 296/240 -f 302/250 301/248 300/249 -f 302/250 303/251 301/248 -f 299/246 304/252 303/251 -f 304/252 305/253 301/248 -f 294/242 296/240 305/253 -f 298/244 306/255 307/254 -f 305/253 296/240 301/248 -f 301/248 303/251 304/252 -f 298/245 308/257 306/256 -f 300/249 296/240 295/241 -f 299/246 303/251 298/245 -f 295/241 307/254 300/249 -f 303/251 302/250 308/257 -f 295/241 298/244 307/254 -f 303/251 308/257 298/245 -f 299/260 297/259 309/258 -f 297/259 294/262 310/261 -f 311/265 312/264 305/263 -f 309/258 297/259 313/258 -f 310/261 313/258 297/259 -f 305/263 312/264 294/262 -f 314/261 299/260 309/258 -f 299/260 314/261 304/266 -f 311/265 304/266 315/264 -f 305/263 304/266 311/265 -f 312/264 310/261 294/262 -f 315/264 304/266 314/261 -f 309/258 310/261 314/261 -f 313/258 310/261 309/258 -f 316/268 312/264 317/267 -f 318/268 315/264 314/261 -f 311/265 315/264 319/269 -f 317/267 312/264 319/269 -f 310/261 316/268 314/261 -f 314/261 316/268 318/268 -f 319/269 315/264 320/267 -f 320/267 317/267 319/269 -f 311/265 319/269 312/264 -f 318/268 320/267 315/264 -f 317/267 318/268 316/268 -f 320/267 318/268 317/267 -f 316/268 310/261 312/264 -f 321/270 300/270 322/270 -f 302/270 300/270 321/270 -f 323/271 324/271 308/271 -f 325/271 307/271 324/271 -f 302/270 321/270 323/271 -f 306/271 324/271 307/271 -f 325/271 300/270 307/271 -f 323/271 308/271 302/270 -f 300/270 325/271 322/270 -f 306/271 308/271 324/271 -f 326/271 327/270 325/271 -f 328/270 323/271 321/270 -f 321/270 329/270 328/270 -f 322/270 329/270 321/270 -f 329/270 325/271 327/270 -f 324/271 323/271 326/271 -f 328/270 330/270 323/271 -f 322/270 325/271 329/270 -f 326/271 323/271 330/270 -f 324/271 326/271 325/271 -f 330/270 328/270 331/89 -f 332/89 330/270 331/89 -f 333/89 327/270 332/89 -f 331/89 328/270 334/270 -f 326/271 330/270 332/89 -f 326/271 332/89 327/270 -f 335/270 327/270 333/89 -f 329/270 327/270 335/270 -f 334/270 329/270 335/270 -f 328/270 329/270 334/270 -# 693 faces