Esempio n. 1
0
        /// <summary>
        /// Read surface data<para/>
        /// Чтение поверхностей
        /// </summary>
        /// <param name="f">Stream<para/>Поток</param>
        /// <param name="numGeoms">Surface count<para/>Количество поверхностей</param>
        void ReadGeometry(BinaryReader f, int numGeoms)
        {
            Surfaces = new Geometry[numGeoms];
            for (int i = 0; i < numGeoms; i++)
            {
                Geometry g = new Geometry();

                // Header data
                // Заголовок
                ChunkHeader h = ReadHeader(f);
                if (h.Type != ChunkType.Geometry)
                {
                    throw new Exception("[ModelFile] Unexpected chunk: " + h.Type);
                }
                h = ReadHeader(f);
                if (h.Type != ChunkType.Struct)
                {
                    throw new Exception("[ModelFile] Unexpected chunk: " + h.Type);
                }

                // Surface flags
                // Флаги поверхности
                g.Flags = f.ReadUInt16();

                // Texture coordinates
                // Текстурные координаты
                int texCoords = f.ReadByte();
                if ((g.Flags & (int)GeometryFlags.TextureCoords) > 0)
                {
                    texCoords = 1;
                }
                bool nativeGeom = f.ReadBoolean();

                int triCount  = f.ReadInt32();
                int vertCount = f.ReadInt32();
                f.BaseStream.Position += 4;

                // Skip some vertex data
                // Пропуск некоторой информации
                if (h.Version < 0x1003)
                {
                    f.BaseStream.Position += 12;
                }

                if (!nativeGeom)
                {
                    // Vertex colors
                    // Цвета вершин
                    if ((g.Flags & (int)GeometryFlags.Colors) > 0)
                    {
                        g.Colors = f.ReadBytes(vertCount * 4);
                        for (int ci = 3; ci < g.Colors.Length; ci += 4)
                        {
                            if (g.Colors[ci] < 255)
                            {
                                g.HasAlpha = true;
                                break;
                            }
                        }
                    }

                    // First texcoord set
                    // Первый набор текстурных координат
                    if ((g.Flags & (int)GeometryFlags.TextureCoords) > 0)
                    {
                        g.TextureCoords = new float[vertCount * 2];
                        for (int c = 0; c < g.TextureCoords.Length; c++)
                        {
                            g.TextureCoords[c] = f.ReadSingle();
                        }
                    }

                    // Second coord set
                    // Второй набор координат
                    if ((g.Flags & (int)GeometryFlags.SecondTexCoords) > 0)
                    {
                        for (int cd = 0; cd < texCoords; cd++)
                        {
                            float[] coords = new float[vertCount * 2];
                            for (int c = 0; c < coords.Length; c++)
                            {
                                coords[c] = f.ReadSingle();
                            }
                            if (cd == 0)
                            {
                                g.TextureCoords = coords;
                            }
                            else if (cd == 1)
                            {
                                g.SecondTextureCoords = coords;
                            }
                        }
                    }

                    // Indices
                    // Вершинные индексы
                    g.Indices = new ushort[triCount * 4];
                    for (int c = 0; c < g.Indices.Length; c++)
                    {
                        g.Indices[c] = f.ReadUInt16();
                    }
                }


                // Bounding sphere
                // Сфера для отсечения
                g.SpherePos = new float[3];
                for (int c = 0; c < 3; c++)
                {
                    g.SpherePos[c] = f.ReadSingle();
                }
                g.SphereRadius = f.ReadSingle();

                // Skipping vertex flags
                // Пропускаем флаги вершин
                f.BaseStream.Position += 8;

                if (!nativeGeom)
                {
                    // Reading vertex positions
                    // Чтение позиций вершин
                    g.Vertices = new float[vertCount * 3];
                    for (int v = 0; v < g.Vertices.Length; v++)
                    {
                        g.Vertices[v] = f.ReadSingle();
                    }

                    // Reading normals
                    // Чтение нормалей
                    if ((g.Flags & (int)GeometryFlags.Normals) > 0)
                    {
                        g.Normals = new float[vertCount * 3];
                        for (int vn = 0; vn < vertCount * 3; vn++)
                        {
                            g.Normals[vn] = f.ReadSingle();
                        }
                    }
                }

                // Reading materials
                // Чтение материалов
                h = ReadHeader(f);
                if (h.Type != ChunkType.MaterialList)
                {
                    throw new Exception("[ModelFile] Unexpected chunk: " + h.Type);
                }
                h = ReadHeader(f);
                if (h.Type != ChunkType.Struct)
                {
                    throw new Exception("[ModelFile] Unexpected chunk: " + h.Type);
                }

                // Material count
                // Количество материалов
                int materialNum = f.ReadInt32();
                f.BaseStream.Position += (materialNum * 4);

                // Reading materials
                // Чтение материалов
                ReadMaterials(g, f, materialNum);

                // Reading extension
                // Чтение расширения
                h = ReadHeader(f);
                if (h.Type != ChunkType.Extension)
                {
                    throw new Exception("[ModelFile] Unexpected chunk: " + h.Type);
                }
                if (h.Size > 0)
                {
                    int ops = (int)(f.BaseStream.Position + h.Size);
                    while (true)
                    {
                        if (f.BaseStream.Position >= ops)
                        {
                            break;
                        }
                        h = ReadHeader(f);
                        switch (h.Type)
                        {
                        // Binary mesh
                        case ChunkType.BinMesh:
                            int splitMode = f.ReadInt32();
                            if (splitMode != 0 && splitMode != 1)
                            {
                                throw new Exception("[ModelFile] Unknown splitting mode: " + splitMode);
                            }
                            int numSplits = f.ReadInt32();
                            f.BaseStream.Position += 4;
                            g.Binary = new BinaryMesh[numSplits];
                            bool hasData = h.Size > 12 + numSplits * 8;
                            for (int sp = 0; sp < numSplits; sp++)
                            {
                                int        numInds  = f.ReadInt32();
                                int        matIndex = f.ReadInt32();
                                BinaryMesh bn       = new BinaryMesh();
                                bn.BinaryMaterial = g.Materials[matIndex];
                                bn.Mode           = (SplitMode)splitMode;
                                if (hasData)
                                {
                                    bn.Indices = new ushort[numInds];
                                    for (int vr = 0; vr < numInds; vr++)
                                    {
                                        bn.Indices[vr] = (ushort)f.ReadUInt32();
                                    }
                                }
                                g.Binary[sp] = bn;
                            }
                            break;

                        // Skinning info
                        // Данные скиннинга
                        case ChunkType.Skin:

                            // Number of bones
                            // Количество костей
                            g.BoneCount = f.ReadByte();
                            int usedBones = f.ReadByte();

                            // Number of bones per single vertex
                            // Количество костей на одну вершинуы
                            g.MaxBonesPerVertex    = f.ReadByte();
                            f.BaseStream.Position += 1;

                            if (usedBones > 0)
                            {
                                f.BaseStream.Position += usedBones;
                            }

                            // Indices and weights
                            // Индексы и веса
                            int numVerts = g.Vertices.Length / 3;
                            g.Bones   = f.ReadBytes(numVerts * 4);
                            g.Weights = new float[numVerts * 4];
                            for (int b = 0; b < g.Weights.Length; b++)
                            {
                                g.Weights[b] = f.ReadSingle();
                            }

                            // Skip matrices - we build our own
                            // Пропускаем матрицы - мы построим свои
                            if (g.MaxBonesPerVertex == 0)
                            {
                                f.BaseStream.Position += 4 * g.BoneCount;
                            }
                            f.BaseStream.Position += g.BoneCount * 64;

                            // Skipping zeroes
                            // Пропуск нескольких нулей
                            if (usedBones > 0)
                            {
                                f.BaseStream.Position += 12;
                            }

                            break;

                        default:
                            f.BaseStream.Position += h.Size;
                            break;
                        }
                    }
                }

                Surfaces[i] = g;
            }
        }
Esempio n. 2
0
		/// <summary>
		/// Read surface data<para/>
		/// Чтение поверхностей
		/// </summary>
		/// <param name="f">Stream<para/>Поток</param>
		/// <param name="numGeoms">Surface count<para/>Количество поверхностей</param>
		void ReadGeometry(BinaryReader f, int numGeoms) {
			Surfaces = new Geometry[numGeoms];
			for (int i = 0; i < numGeoms; i++) {
				Geometry g = new Geometry();

				// Header data
				// Заголовок
				ChunkHeader h = ReadHeader(f);
				if (h.Type != ChunkType.Geometry) {
					throw new Exception("[ModelFile] Unexpected chunk: " + h.Type);
				}
				h = ReadHeader(f);
				if (h.Type != ChunkType.Struct) {
					throw new Exception("[ModelFile] Unexpected chunk: " + h.Type);
				}

				// Surface flags
				// Флаги поверхности
				g.Flags = f.ReadUInt16();

				// Texture coordinates
				// Текстурные координаты
				int texCoords = f.ReadByte();
				if ((g.Flags & (int)GeometryFlags.TextureCoords) > 0) {
					texCoords = 1;
				}
				bool nativeGeom = f.ReadBoolean();

				int triCount = f.ReadInt32();
				int vertCount = f.ReadInt32();
				f.BaseStream.Position += 4;

				// Skip some vertex data
				// Пропуск некоторой информации
				if (h.Version<0x1003) {
					f.BaseStream.Position += 12;
				}

				if (!nativeGeom) {
					// Vertex colors
					// Цвета вершин
					if ((g.Flags & (int)GeometryFlags.Colors) > 0) {
						g.Colors = f.ReadBytes(vertCount * 4);
						for (int ci = 3; ci < g.Colors.Length; ci+=4) {
							if (g.Colors[ci]<255) {
								g.HasAlpha = true;
								break;
							}
						}
					}

					// First texcoord set
					// Первый набор текстурных координат
					if ((g.Flags & (int)GeometryFlags.TextureCoords) > 0) {
						g.TextureCoords = new float[vertCount * 2];
						for (int c = 0; c < g.TextureCoords.Length; c++) {
							g.TextureCoords[c] = f.ReadSingle();
						}
					}

					// Second coord set
					// Второй набор координат
					if ((g.Flags & (int)GeometryFlags.SecondTexCoords) > 0) {
						for (int cd = 0; cd < texCoords; cd++) {
							float[] coords = new float[vertCount * 2];
							for (int c = 0; c < coords.Length; c++) {
								coords[c] = f.ReadSingle();
							}
							if (cd == 0) {
								g.TextureCoords = coords;
							} else if (cd == 1) {
								g.SecondTextureCoords = coords;
							}
						}
					}

					// Indices
					// Вершинные индексы
					g.Indices = new ushort[triCount * 4];
					for (int c = 0; c < g.Indices.Length; c++) {
						g.Indices[c] = f.ReadUInt16();
					}
				}
				

				// Bounding sphere
				// Сфера для отсечения
				g.SpherePos = new float[3];
				for (int c = 0; c < 3; c++) {
					g.SpherePos[c] = f.ReadSingle();
				}
				g.SphereRadius = f.ReadSingle();

				// Skipping vertex flags
				// Пропускаем флаги вершин
				f.BaseStream.Position += 8;

				if (!nativeGeom) {
					// Reading vertex positions
					// Чтение позиций вершин
					g.Vertices = new float[vertCount * 3];
					for (int v = 0; v < g.Vertices.Length; v++) {
						g.Vertices[v] = f.ReadSingle();
					}

					// Reading normals
					// Чтение нормалей
					if ((g.Flags & (int)GeometryFlags.Normals) > 0) {
						g.Normals = new float[vertCount * 3];
						for (int vn = 0; vn < vertCount * 3; vn++) {
							g.Normals[vn] = f.ReadSingle();
						}
					}
				}

				// Reading materials
				// Чтение материалов
				h = ReadHeader(f);
				if (h.Type != ChunkType.MaterialList) {
					throw new Exception("[ModelFile] Unexpected chunk: " + h.Type);
				}
				h = ReadHeader(f);
				if (h.Type != ChunkType.Struct) {
					throw new Exception("[ModelFile] Unexpected chunk: " + h.Type);
				}

				// Material count
				// Количество материалов
				int materialNum = f.ReadInt32();
				f.BaseStream.Position += (materialNum * 4);

				// Reading materials
				// Чтение материалов
				ReadMaterials(g, f, materialNum);

				// Reading extension
				// Чтение расширения
				h = ReadHeader(f);
				if (h.Type != ChunkType.Extension) {
					throw new Exception("[ModelFile] Unexpected chunk: " + h.Type);
				}
				if (h.Size > 0) {
					int ops = (int)(f.BaseStream.Position + h.Size);
					while (true) {
						if (f.BaseStream.Position >= ops) {
							break;
						}
						h = ReadHeader(f);
						switch (h.Type) {

							// Binary mesh
							case ChunkType.BinMesh:
								int splitMode = f.ReadInt32();
								if (splitMode != 0 && splitMode != 1) {
									throw new Exception("[ModelFile] Unknown splitting mode: " + splitMode);
								}
								int numSplits = f.ReadInt32();
								f.BaseStream.Position += 4;
								g.Binary = new BinaryMesh[numSplits];
								bool hasData = h.Size > 12 + numSplits * 8;
								for (int sp = 0; sp < numSplits; sp++) {
									int numInds = f.ReadInt32();
									int matIndex = f.ReadInt32();
									BinaryMesh bn = new BinaryMesh();
									bn.BinaryMaterial = g.Materials[matIndex];
									bn.Mode = (SplitMode)splitMode;
									if (hasData) {
										bn.Indices = new ushort[numInds];
										for (int vr = 0; vr < numInds; vr++) {
											bn.Indices[vr] = (ushort)f.ReadUInt32();
										}
									}
									g.Binary[sp] = bn;
								}
								break;

							// Skinning info
							// Данные скиннинга
							case ChunkType.Skin:

								// Number of bones
								// Количество костей
								g.BoneCount = f.ReadByte();
								int usedBones = f.ReadByte();

								// Number of bones per single vertex
								// Количество костей на одну вершинуы
								g.MaxBonesPerVertex = f.ReadByte();
								f.BaseStream.Position += 1;

								if (usedBones>0) {
									f.BaseStream.Position += usedBones;
								}

								// Indices and weights
								// Индексы и веса
								int numVerts = g.Vertices.Length / 3;
								g.Bones = f.ReadBytes(numVerts * 4);
								g.Weights = new float[numVerts * 4];
								for (int b = 0; b < g.Weights.Length; b++) {
									g.Weights[b] = f.ReadSingle();
								}

								// Skip matrices - we build our own
								// Пропускаем матрицы - мы построим свои
								if (g.MaxBonesPerVertex == 0) {
									f.BaseStream.Position += 4 * g.BoneCount;
								}
								f.BaseStream.Position += g.BoneCount * 64;

								// Skipping zeroes
								// Пропуск нескольких нулей
								if (usedBones>0) {
									f.BaseStream.Position += 12;
								}

								break;

							default:
								f.BaseStream.Position += h.Size;
								break;
						}
					}
				}

				Surfaces[i] = g;
			}
		}