📄 meshloader.cs
字号:
//---------------------------------------------------------------------
// This file is part of the Microsoft .NET Framework SDK Code Samples.
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation. See these other
//materials for detailed information regarding Microsoft code samples.
//
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//---------------------------------------------------------------------
using System;
using System.IO;
using System.Text;
using System.Globalization;
using Microsoft.WindowsMobile.DirectX;
using Microsoft.WindowsMobile.DirectX.Direct3D;
namespace Microsoft.Samples.MD3DM
{
/// <summary>
/// An exception thrown by the mesh loader if an error occurs
/// during loading/saving
/// </summary>
public class MeshSerializationException : Exception
{
public MeshSerializationException() {}
public MeshSerializationException(string message) : base(message) {}
public MeshSerializationException(string message, Exception inner) :
base(message, inner) {}
}
/// <summary>
/// This class implements loading and saving functionality to/from a
/// custom binary mesh format
/// </summary>
sealed public class MeshLoader
{
// The mesh loader's binary format looks like this:
// Offset Size Name Description
// 0 4 Magic Number 'xofm'
// 4 4 Version The version MUST be 0x0001000
// 8 4 Fvf Flexible Vertex Format MUST be a
// valid D3DM fvf
// 12 4 NumVertices The number of vertices
// 16 4 NumIndices The number of indices
// 20 4 Is16BitIndices If 0 then the indices are 32 bit,
// if 1 the indices are 16 bit. Else
// the file is invalid
// 24 4 NumMaterials The number of materials
// 28 4 NumAttrRanges The number of attribute ranges
// 32 4 OffsetVertex Offset to VertexData from the
// beginning of the file
// 36 4 OffsetIndices Offset to Indices from the beginning
// of the file
// 40 4 OffsetAttrRange Offset to the attribute range data
// from the beginning of the file.
// 44 4 OffsetMaterial Offset to the start of the material
// data from the beginning of the file.
// 48 4 BytesMaterials The size in bytes of the materials
// region
//
// Vertices are stored at their offset in a contiguous array of bytes.
//
// Indices are stored at their offset in a contiguous array of bytes.
//
// Attribute Ranges are stored in the following format
//
// 0 4 AttribId The attribute id for this range
// 4 4 FaceStart The starting face
// 8 4 FaceCount The count of faces
// 12 4 VertexStart The starting vertex
// 16 4 VertexCount The count of vertices
//
// Materials are stored one after another in the following format
// 0 16 Diffuse color (Stored as RGBA as consecutive 32bit
// floats)
// 16 16 Ambient color (Stored as RGBA as consecutive 32bit
// floats)
// 32 16 Specular color (Stored as RGBA as consecutive 32bit
// floats)
// 48 4 Power (32 bit float)
// 52 4 Filename length in bytes
// 56 (FilenameLength) Texture filename encoded as UTF-16.
//
//
//
/// <summary>
/// A private contructor because this class should never be
/// instantiated
/// </summary>
private MeshLoader() {}
/// <summary>
/// The magic number which is used to verify a file contains the
/// binary mesh format
/// </summary>
private static readonly int magicNumber = 0x27391874;
/// <summary>
/// The current version of this format
/// </summary>
private static readonly int versionNumber = 0x1000;
/// <summary>
/// The size of header information in bytes for this format
/// </summary>
private static readonly int sizeofHeader = 52;
/// <summary>
/// The size of the attribute range in bytes for this format
/// </summary>
private static readonly int sizeofAttributeRange = 20;
/// <summary>
/// The size of an encoded material excluding the variable length
/// string. This size does include space for the value which encodes
/// the string length though.
/// </summary>
private static readonly int sizeofMaterial = 56;
/// <summary>
/// The vertex format constants in md3dm for normal, diffuse,
/// specular, and textureCountShift. Referencing VertexFormats.XXX
/// doesn't work when linked against Micorosft.DirectX because the
/// constants are different than those in md3dm.
/// </summary>
private static readonly int md3dmFvfNormal = 0x0008;
private static readonly int md3dmFvfDiffuse = 0x0040;
private static readonly int md3dmFvfSpecular = 0x0080;
private static readonly int md3dmFvfTextureCountShift = 0x0008;
/// <summary>
/// Loads a mesh from the given stream
/// </summary>
/// <param name="device">A d3d mobile device which will be displaying
/// the mesh</param>
/// <param name="stream">The stream containing serialized mesh data
/// </param>
/// <param name="flags">Option flags</param>
/// <param name="materials">Output array is filled with any needed
/// materials</param>
/// <param name="textures">Output array is filled with the filenames
/// of any needed textures</param>
/// <returns></returns>
public static Mesh LoadMesh(Device device, Stream stream,
MeshFlags flags, out Material [] materials,
out string [] textures)
{
if(device == null)
throw new ArgumentException("Argument device was invalid");
if(stream == null)
throw new ArgumentException("Argument stream was invalid");
byte [] rgb;
byte [] rgbIb;
byte [] rgbVb;
Mesh meshRet;
VertexBuffer vb;
IndexBuffer ib;
int fileMagicNumber;
int fileVersion;
VertexFormats flexibleVertexFormat;
int numberVertices;
int numberIndices;
int is16BitIndices;
int numberMaterials;
int numberAttrRanges;
int offsetVertex;
int offsetIndices;
int offsetAttrRange;
int offsetMaterial;
int bytesMaterials;
int bytesIndices;
int [] attributeTable;
AttributeRange [] attributeRanges;
rgb = new byte [512];
stream.Seek(0, SeekOrigin.Begin);
// Read header, any errors will be propagated up
stream.Read(rgb, 0, sizeofHeader);
// read and verify magic number
fileMagicNumber = BitConverter.ToInt32(rgb, 0);
if(fileMagicNumber != magicNumber)
throw new MeshSerializationException(
"The serialized data does not represent a mesh");
// read and verify version
fileVersion = BitConverter.ToInt32(rgb, 4);
if(fileVersion != versionNumber)
throw new MeshSerializationException(
"The format version was not recognized");
flexibleVertexFormat = (VertexFormats)
BitConverter.ToInt32(rgb, 8);
numberVertices = BitConverter.ToInt32(rgb, 12);
numberIndices = BitConverter.ToInt32(rgb, 16);
is16BitIndices = BitConverter.ToInt32(rgb, 20);
numberMaterials = BitConverter.ToInt32(rgb, 24);
numberAttrRanges = BitConverter.ToInt32(rgb, 28);
offsetVertex = BitConverter.ToInt32(rgb, 32);
offsetIndices = BitConverter.ToInt32(rgb, 36);
offsetAttrRange = BitConverter.ToInt32(rgb, 40);
offsetMaterial = BitConverter.ToInt32(rgb, 44);
bytesMaterials = BitConverter.ToInt32(rgb, 48);
// verify number of vertices
if(numberVertices < 0)
throw new MeshSerializationException(
String.Format(CultureInfo.InvariantCulture,
"Invalid number of vertices: {0}", numberVertices));
// verify number of indices
if(numberIndices < 0 || numberIndices % 3 != 0)
throw new MeshSerializationException(
String.Format(CultureInfo.InvariantCulture,
"Invalid number of indices: {0}", numberIndices));
// verify number of materials
if(numberMaterials < 0)
throw new MeshSerializationException(
String.Format(CultureInfo.InvariantCulture,
"Invalid number of materials: {0}", numberMaterials));
// verify number of attribute ranges
if(numberAttrRanges < 0)
throw new MeshSerializationException(
String.Format(CultureInfo.InvariantCulture,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -