⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ms3d.cpp

📁 用DirectX制作高级动画-[Advanced.Animation.with.DirectX]
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
  Milkshape 3D Model Loading Class by Jim Adams

  Milkshape 3D .ms3d file format:
    Header
    # Vertices
    Vertex data
    # Faces
    Face data
    # Groups
    Group data
    # Materials
    Material data
    Animation FPS
    CurrentTime
    Total Frames
    # Bones
    Bone Data
*/
#include <windows.h>
#include <stdio.h>
#include "d3d8.h"
#include "d3dx8.h"
#include "texture.h"
#include "mesh.h"
#include "MS3D.h"

BOOL LoadMS3D(cMeshGroup *MeshGroup, char *Filename,
              char *TexturePath, char *DefaultTexture, 
              IDirect3DDevice8 *pDevice, cTextureManager *pManager)
{
  char *Names[2];
  Names[0] = Filename;
  Names[1] = Filename;

  return LoadMS3D(MeshGroup, Filename, 1, (char**)&Names, TexturePath, DefaultTexture, pDevice, pManager);
}

BOOL LoadMS3D(cMeshGroup *MeshGroup, char *Filename,
              DWORD NumAnimations, char **AnimFilenames,
              char *TexturePath, char *DefaultTexture, 
              IDirect3DDevice8 *pDevice, cTextureManager *pManager)
{
  FILE           *fp;
  sMS3DHeader     Header;

  DWORD           i, j, k, Num, Pos, AnimPos;
  
  unsigned short  msNumVertices;
  sMS3DVertex    *msVertices = NULL;
  sMeshVertex    *Vertices;

  unsigned short  msNumFaces;
  sMS3DFace      *msFaces = NULL;
  unsigned short *Indices;

  unsigned short  msNumGroups;
  sMS3DGroup     *msGroups = NULL;

  unsigned short  msNumMaterials;
  sMS3DMaterial  *msMaterials = NULL;

  unsigned short  msNumBones;
  sMS3DBone      *msBones = NULL;

  float           msAnimationFPS;
  float           msCurrentTime;
  int             msTotalFrames;

  cMeshContainer      *Mesh = NULL;
  cAnimationContainer *Anim = NULL;

  // Error checking
  if(MeshGroup == NULL || Filename == NULL || pDevice == NULL || pManager == NULL)
    return FALSE;

  // Free a prior model
  MeshGroup->Free();

  // Assign mesh type
  MeshGroup->m_Type = MESH_BONES;

  // Assign device and texture manager
  MeshGroup->m_Device  = pDevice;
  MeshGroup->m_Manager = pManager;

  // Open file and read header
  if((fp=fopen(Filename, "rb"))==NULL)
    return FALSE;
  fread(&Header, 1, sizeof(sMS3DHeader), fp);

  // Make sure header is valid
  if(memcmp(Header.Signature, "MS3D000000", 10)) {
    fclose(fp);
    return FALSE;
  }

  // Read data into some temporary buffers

  // Read vertex data
  fread(&msNumVertices, 1, sizeof(short), fp);
  if(msNumVertices) {
    msVertices = new sMS3DVertex[msNumVertices];
    for(i=0;i<msNumVertices;i++) {
      fread(&msVertices[i], 1, sizeof(sMS3DVertex), fp);

      // Assign to bone # 0 if none assigned
      if(msVertices[i].Bone == -1)
        msVertices[i].Bone = 0;
    }
  }

  // Read face data
  fread(&msNumFaces, 1, sizeof(short), fp);
  if(msNumFaces) {
    msFaces = new sMS3DFace[msNumFaces];
    for(i=0;i<msNumFaces;i++)
      fread(&msFaces[i], 1, sizeof(sMS3DFace), fp);
  }

  // Read groups
  fread(&msNumGroups, 1, sizeof(short), fp);
  if(msNumGroups) {
    msGroups = new sMS3DGroup[msNumGroups];
    for(i=0;i<msNumGroups;i++) {
      fread(&msGroups[i], 1, sizeof(msGroups[i].Header), fp);
      if((Num = msGroups[i].Header.NumFaces)) {
        msGroups[i].Indices = new unsigned short[Num];
        for(j=0;j<Num;j++)
          fread(&msGroups[i].Indices[j], 1, sizeof(short), fp);
      }
      fread(&msGroups[i].Material, 1, sizeof(char), fp);

      // Change group material to 0 if none assigned (-1)
      if(msGroups[i].Material == -1)
        msGroups[i].Material = 0;
    }
  }

  // Read materials, creating a default one if none in file
  fread(&msNumMaterials, 1, sizeof(short), fp);
  if(!msNumMaterials) {
    // Create a single material and color it white
    msNumMaterials = 1;
    msMaterials = new sMS3DMaterial[1];
    ZeroMemory(&msMaterials[0], sizeof(sMS3DMaterial));
    msMaterials[0].Diffuse[0] = msMaterials[0].Diffuse[1] = msMaterials[0].Diffuse[2] = 1.0f;

    // Set all groups to use material #0
    // If there are no materials, set all groups to 
    // use material #0
    if(msNumGroups) {
      for(i=0;i<msNumGroups;i++)
        msGroups[i].Material = 0;
    }
  } else {
    // Read in all materials from file
    msMaterials = new sMS3DMaterial[msNumMaterials];
    for(i=0;i<msNumMaterials;i++)
      fread(&msMaterials[i], 1, sizeof(sMS3DMaterial), fp);
  }

  // Record position of animation data in file (for loading animations)
  AnimPos = ftell(fp);

  // Read in FPS, current editor time, and # frames
  fread(&msAnimationFPS, 1, sizeof(float), fp);
  fread(&msCurrentTime, 1, sizeof(float), fp);
  fread(&msTotalFrames, 1, sizeof(int), fp);

  // Read in bones, skipping keyframe data
  fread(&msNumBones, 1, sizeof(short), fp);
  if(msNumBones) {
    msBones = new sMS3DBone[msNumBones];
    for(i=0;i<msNumBones;i++) {
      fread(&msBones[i], 1, sizeof(msBones[i].Header), fp);

      // Skip by position key frames
      if((Num = msBones[i].Header.NumRotFrames))
        fseek(fp, Num * sizeof(sMS3DKeyFrame), SEEK_CUR);

      // Skip by animation key frames
      if((Num=msBones[i].Header.NumPosFrames))
        fseek(fp, Num * sizeof(sMS3DKeyFrame), SEEK_CUR);
    }
  }

  // Close file
  fclose(fp);

  // At this point, the entire Milkshape 3D model is loaded
  // in memory. You need to parse this data into a
  // cMeshContainer object now.

  // Create a single mesh to use
  MeshGroup->m_NumMeshes = 1;
  MeshGroup->m_Meshes = Mesh = new cMeshContainer();
  
  // Name the mesh by clipping out mesh filename (without path and extension)
  Mesh->m_Name = CleanMS3DName(Filename);

  // Store mesh values ////////////////////////////////////
  // Notice that the number of vertices is based on the number
  // of faces. The reason being is that Milkshape 3D stores
  // texture coordinates based on faces, so a single vertex
  // may have multiple texture coordinates. Same goes for normals.
  Mesh->m_NumVertices  = (DWORD)msNumFaces * 3;
  Mesh->m_NumFaces     = (DWORD)msNumFaces;
  Mesh->m_NumBones     = (DWORD)msNumBones;
  Mesh->m_NumMaterials = (DWORD)msNumMaterials;

  // Create the bone hierarchy ////////////////////////////
  if(Mesh->m_NumBones) {
    Mesh->m_Bones = new cBoneHierarchy();

    // Create each bone in the hierarchy
    Mesh->m_Bones->m_Bones = new cBoneContainer[Mesh->m_NumBones]();

    // Create the bone matrices
    Mesh->m_Bones->m_matCombined        = new D3DXMATRIX[Mesh->m_NumBones];
    Mesh->m_Bones->m_matTransformations = new D3DXMATRIX[Mesh->m_NumBones];
    Mesh->m_Bones->m_matInversed        = new D3DXMATRIX[Mesh->m_NumBones];

    for(i=0;i<Mesh->m_NumBones;i++) {

      // Point bones to matrices
      Mesh->m_Bones->m_Bones[i].m_matCombined       = &Mesh->m_Bones->m_matCombined[i];
      Mesh->m_Bones->m_Bones[i].m_matTransformation = &Mesh->m_Bones->m_matTransformations[i];

      // Build the hierarchy
      Mesh->m_Bones->m_Bones[i].m_Name = strdup(msBones[i].Header.Name);
      for(j=0;j<Mesh->m_NumBones;j++) {

        // Match parent
        if(i != j && msBones[i].Header.Parent[0] && !stricmp(msBones[i].Header.Parent, msBones[j].Header.Name)) {
          // i = current bone, j = parent bone

          // Link sibling
          Mesh->m_Bones->m_Bones[i].m_Sibling = Mesh->m_Bones->m_Bones[j].m_Child;

          // Link child
          Mesh->m_Bones->m_Bones[j].m_Child = &Mesh->m_Bones->m_Bones[i];
        }
      }

      // Create default pose and store in transformation matrix
      D3DXMATRIX matX, matY, matZ, matXYZ, matWorld;

      D3DXMatrixRotationX(&matX, msBones[i].Header.Rotation[0]);
      D3DXMatrixRotationY(&matY, msBones[i].Header.Rotation[1]);
      D3DXMatrixRotationZ(&matZ, msBones[i].Header.Rotation[2]);
      D3DXMatrixTranslation(&matXYZ, 
                             msBones[i].Header.Position[0], 
                             msBones[i].Header.Position[1], 
                             msBones[i].Header.Position[2]);
      D3DXMatrixMultiply(&matWorld, &matX, &matY);
      D3DXMatrixMultiply(&matWorld, &matWorld, &matZ);
      D3DXMatrixMultiply(&Mesh->m_Bones->m_matTransformations[i], &matWorld, &matXYZ);
    }

    // Since the mesh has been converted from right-handed
    // to left-handed coordinates, the bones than also need
    // to be flipped. Since the bones are based off
    // transformation matrices, than the root bone matrix
    // must be 'reflected' in order to be correct.
    // To reflect a matrix, you need to construct a splitting
    // plane that defines where to reflect.
    D3DXPLANE  planeReflect;
    D3DXMATRIX matReflect;
    D3DXPlaneFromPoints(&planeReflect, 
                        &D3DXVECTOR3(0.0f, 0.0f, 0.0f),
                        &D3DXVECTOR3(0.0f, 0.0f, 1.0f),
                        &D3DXVECTOR3(0.0f, 1.0f, 1.0f));
    D3DXMatrixReflect(&matReflect, &planeReflect);
    D3DXMatrixMultiply(&Mesh->m_Bones->m_matTransformations[0],
                       &Mesh->m_Bones->m_matTransformations[0],
                       &matReflect);

    // Update the bone hierarchy and store inversed matrices
    Mesh->m_Bones->m_Bones[0].UpdateHierarchy();

    // Inverse the combined matrices and store
    for(i=0;i<Mesh->m_NumBones;i++)
      D3DXMatrixInverse(&Mesh->m_Bones->m_matInversed[i], NULL, &Mesh->m_Bones->m_matCombined[i]);
  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -