/// <summary> /// Чтение модели с диска, если она не закеширована /// </summary> /// <param name="fname">Имя файла</param> /// <returns>Кешированная модель</returns> static MorphMeshComponent ReadModel(string fname) { // Открытие файла byte[] data = FileSystem.Read(fname); BinaryReader f = new BinaryReader(new MemoryStream(data)); // Чтение заголовка string fourcc = new string(f.ReadChars(4)); int version = f.ReadInt32(); if (fourcc != "IDP2" || version != 8) { f.Close(); return(null); } // Размер текстуры и одного кадра float skinWidth = f.ReadInt32(); float skinHeight = f.ReadInt32(); int frameSize = f.ReadInt32(); // Чтение размеров и отступов f.BaseStream.Position += 4; int vertexNum = f.ReadInt32(); int texCoordNum = f.ReadInt32(); int trisNum = f.ReadInt32(); f.BaseStream.Position += 4; int frameNum = f.ReadInt32(); f.BaseStream.Position += 4; int texCoordOffset = f.ReadInt32(); int trisOffset = f.ReadInt32(); int frameOffset = f.ReadInt32(); // Чтение текстурных координат Vec2[] texCoords = new Vec2[texCoordNum]; f.BaseStream.Position = texCoordOffset; for (int i = 0; i < texCoordNum; i++) { texCoords[i].X = (float)f.ReadInt16() / skinWidth; texCoords[i].Y = (float)f.ReadInt16() / skinHeight; } // Чтение треугольников ushort[] indices = new ushort[trisNum * 3]; ushort[] coordAssoc = new ushort[trisNum * 3]; f.BaseStream.Position = trisOffset; for (int i = 0; i < trisNum; i++) { int tri = i * 3; indices[tri + 0] = f.ReadUInt16(); indices[tri + 1] = f.ReadUInt16(); indices[tri + 2] = f.ReadUInt16(); coordAssoc[tri + 0] = f.ReadUInt16(); coordAssoc[tri + 1] = f.ReadUInt16(); coordAssoc[tri + 2] = f.ReadUInt16(); } // Чтение кадров Vec3[][] verts = new Vec3[frameNum][]; Vec3[][] norms = new Vec3[frameNum][]; f.BaseStream.Position = frameOffset; for (int fr = 0; fr < frameNum; fr++) { // Создание массивов verts[fr] = new Vec3[vertexNum]; norms[fr] = new Vec3[vertexNum]; // Размер и позиция float sx, sy, sz, ox, oy, oz; sx = f.ReadSingle(); sy = f.ReadSingle(); sz = f.ReadSingle(); ox = f.ReadSingle(); oy = f.ReadSingle(); oz = f.ReadSingle(); // Имя кадра f.BaseStream.Position += 16; // Чтение вершин for (int vr = 0; vr < vertexNum; vr++) { // Чтение вершины float px, py, pz; px = (float)f.ReadByte() * sx + ox; py = (float)f.ReadByte() * sy + oy; pz = (float)f.ReadByte() * sz + oz; verts[fr][vr] = new Vec3(-py, pz, px) * 0.015f; // Чтение нормали byte nidx = f.ReadByte(); Vec3 nv = normalList[nidx]; norms[fr][vr] = new Vec3(-nv.Y, nv.Z, nv.X); } } f.Close(); // Теперь, из-за того, что имеет место использование // одних и тех же вершин, но с разными текстурными // координатами, требуется создать копии для каждой // вершины под свои координаты // Поиск всех использованных текстурных координат каждой вершиной int totalVerts = 0; List <int>[] usedCoords = new List <int> [vertexNum]; for (int i = 0; i < indices.Length; i++) { if (usedCoords[indices[i]] == null) { usedCoords[indices[i]] = new List <int>(); } if (!usedCoords[indices[i]].Contains(coordAssoc[i])) { usedCoords[indices[i]].Add(coordAssoc[i]); totalVerts++; } } // Заполнение массива ассоциаций вершин и текстурных координат Vec2[] coords = new Vec2[totalVerts]; int[] vertexAssoc = new int[totalVerts]; int assocIndex = 0; int vertexIndex = 0; foreach (List <int> il in usedCoords) { for (int i = 0; i < il.Count; i++) { vertexAssoc[assocIndex + i] = vertexIndex; coords[assocIndex + i] = texCoords[il[i]]; } assocIndex += il.Count; vertexIndex++; } // Перестройка массива индексов for (int i = 0; i < indices.Length; i++) { int idx = 0; int tex = coordAssoc[i]; foreach (List <int> ac in usedCoords) { if (ac.Contains(tex)) { idx += ac.IndexOf(tex); break; } idx += ac.Count; } indices[i] = (ushort)idx; } // Перестройка кадров MorphMeshComponent.Frame[] morphFrames = new MorphMeshComponent.Frame[frameNum]; for (int fr = 0; fr < frameNum; fr++) { // Переассоциация вершин Vec3[] frameVerts = new Vec3[totalVerts]; Vec3[] frameNorms = new Vec3[totalVerts]; for (int vr = 0; vr < totalVerts; vr++) { frameVerts[vr] = verts[fr][vertexAssoc[vr]]; frameNorms[vr] = norms[fr][vertexAssoc[vr]]; } // Создание кадра MorphMeshComponent.MorphFrame frame = new MorphMeshComponent.MorphFrame(); frame.Time = fr; frame.Vertices = frameVerts; frame.Normals = frameNorms; morphFrames[fr] = frame; } // Создание компонента MorphMeshComponent mmesh = new MorphMeshComponent(); mmesh.TexCoords = coords; mmesh.Indices = indices; mmesh.Frames = morphFrames; return(mmesh); }
/// <summary> /// Чтение модели с диска, если она не закеширована /// </summary> /// <param name="fname">Имя файла</param> /// <returns>Кешированная модель</returns> static CachedEntry ReadModel(string fname) { // Открытие файла byte[] data = FileSystem.Read(fname); BinaryReader f = new BinaryReader(new MemoryStream(data)); // Чтение заголовка string fourcc = new string(f.ReadChars(4)); int version = f.ReadInt32(); if (fourcc != "IDP3" || version != 15) { f.Close(); return(null); } // Пропуск имени модели и флагов f.BaseStream.Position += 72; // Значения количества int tagNum = f.ReadInt32(); int surfaceNum = f.ReadInt32(); // Пропуск скинов f.BaseStream.Position += 8; // Отступы в файле int tagOffset = f.ReadInt32(); int surfaceOffset = f.ReadInt32(); // Кешированная запись CachedEntry entry = new CachedEntry(); // Массивы мешей entry.Surfaces = new MorphMeshComponent[surfaceNum]; // Чтение поверхностей f.BaseStream.Position = surfaceOffset; for (int surfIndex = 0; surfIndex < surfaceNum; surfIndex++) { // Пропуск ненужных данных f.BaseStream.Position += 72; // Чтение размеров int frameNum = f.ReadInt32(); int shaderNum = f.ReadInt32(); int vertexNum = f.ReadInt32(); int triangleNum = f.ReadInt32(); // Пропуск отступов и шейдеров f.BaseStream.Position += 20; f.BaseStream.Position += 68 * shaderNum; // Индексы ushort[] indices = new ushort[triangleNum * 3]; for (int i = 0; i < indices.Length; i++) { indices[i] = (ushort)f.ReadInt32(); } // Текстурные координаты Vec2[] texCoords = new Vec2[vertexNum]; for (int i = 0; i < texCoords.Length; i++) { texCoords[i].X = f.ReadSingle(); texCoords[i].Y = f.ReadSingle(); } // Кадры MorphMeshComponent.MorphFrame[] frames = new MorphMeshComponent.MorphFrame[frameNum]; for (int frameIndex = 0; frameIndex < frameNum; frameIndex++) { // Необходимые массивы Vec3[] verts = new Vec3[vertexNum]; Vec3[] norms = new Vec3[vertexNum]; // Чтение вершин и нормалей for (int i = 0; i < vertexNum; i++) { // Позиция float px, py, pz, nx, ny, nz; px = (float)f.ReadInt16() * VERTEX_SCALE; py = (float)f.ReadInt16() * VERTEX_SCALE; pz = (float)f.ReadInt16() * VERTEX_SCALE; verts[i] = new Vec3(-py, pz, px); // Нормаль float lng = (float)f.ReadByte() * NORMAL_MULT; float lat = (float)f.ReadByte() * NORMAL_MULT; nx = (float)(Math.Cos(lat) * Math.Sin(lng)); ny = (float)(Math.Sin(lat) * Math.Sin(lng)); nz = (float)(Math.Cos(lng)); norms[i] = new Vec3(-ny, nz, nx); } // Сохранение кадра MorphMeshComponent.MorphFrame frame = new MorphMeshComponent.MorphFrame(); frame.Time = frameIndex; frame.Vertices = verts; frame.Normals = norms; frames[frameIndex] = frame; } // Поверхность MorphMeshComponent surface = new MorphMeshComponent(); surface.Frames = frames; surface.TexCoords = texCoords; surface.Indices = indices; entry.Surfaces[surfIndex] = surface; } return(entry); }