📄 meshloader.cs
字号:
try
{
// Managed Direct3D mobile uses different Fvf defines than
// managed Direct3D for the desktop
// when this code is linked against the desktop version
// this will convert the Fvf to match MD3DM constants
// when this code is linked against MD3DM this section will
// not have changed anything.
// determine the necessary Fvf
sourceVertexFormat = mesh.VertexFormat;
int textureCount;
sourceFormat = VertexFormats.Position;
flexibleVertexFormat = 0;
if ((sourceVertexFormat & VertexFormats.Normal) != 0)
{
flexibleVertexFormat |= md3dmFvfNormal;
sourceFormat |= VertexFormats.Normal;
}
if ((sourceVertexFormat & VertexFormats.Diffuse) != 0)
{
flexibleVertexFormat |= md3dmFvfDiffuse;
sourceFormat |= VertexFormats.Diffuse;
}
if ((sourceVertexFormat & VertexFormats.Specular) != 0)
{
flexibleVertexFormat |= md3dmFvfDiffuse;
sourceFormat |= VertexFormats.Specular;
}
// determine number of textures
textureCount = (int)(sourceVertexFormat &
VertexFormats.TextureCountMask) >>
(int)VertexFormats.TextureCountShift;
//limit to 4 textures
if (textureCount > 4)
textureCount = 4;
// continue setting up necessary fvf
sourceFormat |= (VertexFormats)(textureCount <<
(int)VertexFormats.TextureCountShift);
flexibleVertexFormat |=
(textureCount << md3dmFvfTextureCountShift);
if (sourceFormat != sourceVertexFormat)
{
mesh = mesh.Clone(mesh.Options.Value, sourceFormat,
mesh.Device);
tempMesh = (IDisposable)mesh;
}
attributeRanges = mesh.GetAttributeTable();
if (attributeRanges == null)
{
throw new MeshSerializationException(
"No Attribute table present");
}
// determine number of vertices and create buffer
numberVertices = mesh.NumberVertices;
vertices = new byte[numberVertices *
VertexInformation.GetFormatSize(sourceFormat)];
// copy vertices to buffer
mesh.VertexBuffer.Lock(0, vertices.Length,
LockFlags.None).Read(vertices, 0, vertices.Length);
mesh.VertexBuffer.Unlock();
// determine number of indices
numberIndices = mesh.NumberFaces * 3;
// create index data buffer
indices = new byte[numberIndices *
(mesh.Options.Use32Bit ? 4 : 2)];
// fill index data into buffer
mesh.IndexBuffer.Lock(0, indices.Length,
LockFlags.None).Read(indices, 0, indices.Length);
mesh.IndexBuffer.Unlock();
// write the data out to file
MeshLoader.SaveMeshData(stream, flexibleVertexFormat,
numberVertices, vertices,
numberIndices, indices, attributeRanges, materials,
textures);
}
finally
{
if (tempMesh != null)
{
tempMesh.Dispose();
}
}
}
/// <summary>
/// Serializes mesh data to a custom format
/// </summary>
/// <param name="stream">The stream to which to serialize</param>
/// <param name="flexibleVertexFormat">The Fvf of the vertex data
/// </param>
/// <param name="numberVertices">The number of vertices in the vertex
/// data</param>
/// <param name="vertices">The buffer of vertex data</param>
/// <param name="numberIndices">The number of indices in the index
/// data</param>
/// <param name="indices">The buffer of index data</param>
/// <param name="attributeRanges">The attribute ranges to
/// serialize</param>
/// <param name="materials">The materials for the mesh subparts
/// </param>
/// <param name="textures">The texture filenames for the mesh
/// subparts</param>
///
public static void SaveMeshData(Stream stream,
int flexibleVertexFormat, int numberVertices,
byte [] vertices, int numberIndices,
byte [] indices, AttributeRange [] attributeRanges,
Material [] materials, string [] textures)
{
if(numberIndices <= 0)
throw new ArgumentException("NumberIndices <= 0");
if(numberVertices <= 0)
throw new ArgumentException("NumberVertices <= 0");
// calculate the size of the vertex buffer
int bytesVertices = vertices.Length;
// verify 16 or 32 bit indices
int bytesPerIndex = indices.Length / numberIndices;
if ((bytesPerIndex != 2) && (bytesPerIndex != 4))
throw new MeshSerializationException(
"Indices are neither 16 nor 32 bit");
int is16BitIndices = (bytesPerIndex == 2) ? 1 : 0;
// verify the same number of materials as texture names
if (materials.Length != textures.Length)
throw new MeshSerializationException(
"The number of textures must" +
" match the number of materials");
// determine the number of materials and attribue ranges
int numberMaterials = materials.Length;
int numberAttrRanges = attributeRanges.Length;
// determine the offsets
int offsetVertex = sizeofHeader;
int offsetIndices = offsetVertex + vertices.Length;
int offsetAttrRange = offsetIndices + indices.Length;
int offsetMaterial = offsetAttrRange + numberAttrRanges *
sizeofAttributeRange;
// go to the beginning of the stream
stream.Seek(0, SeekOrigin.Begin);
// write the header
stream.Write(BitConverter.GetBytes(magicNumber), 0, 4);
stream.Write(BitConverter.GetBytes(versionNumber), 0, 4);
stream.Write(BitConverter.GetBytes(flexibleVertexFormat), 0, 4);
stream.Write(BitConverter.GetBytes(numberVertices), 0, 4);
stream.Write(BitConverter.GetBytes(numberIndices), 0, 4);
stream.Write(BitConverter.GetBytes(is16BitIndices), 0, 4);
stream.Write(BitConverter.GetBytes(numberMaterials), 0, 4);
stream.Write(BitConverter.GetBytes(numberAttrRanges), 0, 4);
stream.Write(BitConverter.GetBytes(offsetVertex), 0, 4);
stream.Write(BitConverter.GetBytes(offsetIndices), 0, 4);
stream.Write(BitConverter.GetBytes(offsetAttrRange), 0, 4);
stream.Write(BitConverter.GetBytes(offsetMaterial), 0, 4);
// write a 0 length for BytesMaterials right now
// the correct value will be filled in once it is known
stream.Write(BitConverter.GetBytes(0), 0, 4);
// write the vertex and index information
stream.Write(vertices, 0, vertices.Length);
stream.Write(indices, 0, indices.Length);
// write the attribute range information
foreach (AttributeRange attr in attributeRanges)
{
stream.Write(BitConverter.GetBytes(attr.AttributeId), 0, 4);
stream.Write(BitConverter.GetBytes(attr.FaceStart), 0, 4);
stream.Write(BitConverter.GetBytes(attr.FaceCount), 0, 4);
stream.Write(BitConverter.GetBytes(attr.VertexStart), 0, 4);
stream.Write(BitConverter.GetBytes(attr.VertexCount), 0, 4);
}
// write the material information
for (int i = 0; i < materials.Length; i++)
{
stream.Write(BitConverter.GetBytes(
materials[i].DiffuseColor.Red ), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].DiffuseColor.Green), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].DiffuseColor.Blue ), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].DiffuseColor.Alpha), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].AmbientColor.Red ), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].AmbientColor.Green), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].AmbientColor.Blue ), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].AmbientColor.Alpha), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].SpecularColor.Red ), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].SpecularColor.Green), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].SpecularColor.Blue ), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].SpecularColor.Alpha), 0, 4);
stream.Write(BitConverter.GetBytes(
materials[i].SpecularSharpness), 0, 4);
if (textures[i] != null)
{
byte [] rgb = Encoding.Unicode.GetBytes(textures[i]);
stream.Write(BitConverter.GetBytes(rgb.Length), 0, 4);
stream.Write(rgb, 0, rgb.Length);
}
else
stream.Write(BitConverter.GetBytes((int)0), 0, 4);
}
// go back to fill in the length of the materials section
long currentPosition = stream.Position;
int bytesMaterials = (int)(stream.Position - offsetMaterial);
stream.Seek((int)48, SeekOrigin.Begin);
stream.Write(BitConverter.GetBytes(0), 0, 4);
stream.Seek(currentPosition, SeekOrigin.Begin);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -