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

📄 ms3d.cpp

📁 用DirectX制作高级动画-[Advanced.Animation.with.DirectX]
💻 CPP
📖 第 1 页 / 共 2 页
字号:

  // Create materials and ranges //////////////////////////
  Mesh->m_Ranges    = new cMeshRange[Mesh->m_NumMaterials]();
  Mesh->m_Materials = new D3DMATERIAL8[Mesh->m_NumMaterials];
  Mesh->m_Textures  = new IDirect3DTexture8*[Mesh->m_NumMaterials];
  for(i=0;i<Mesh->m_NumMaterials;i++) {
    Mesh->m_Materials[i].Diffuse.r  = msMaterials[i].Diffuse[0];
    Mesh->m_Materials[i].Diffuse.g  = msMaterials[i].Diffuse[1];
    Mesh->m_Materials[i].Diffuse.b  = msMaterials[i].Diffuse[2];

    Mesh->m_Materials[i].Ambient.r  = msMaterials[i].Ambient[0];
    Mesh->m_Materials[i].Ambient.g  = msMaterials[i].Ambient[1];
    Mesh->m_Materials[i].Ambient.b  = msMaterials[i].Ambient[2];

    Mesh->m_Materials[i].Specular.r = msMaterials[i].Specular[0];
    Mesh->m_Materials[i].Specular.g = msMaterials[i].Specular[1];
    Mesh->m_Materials[i].Specular.b = msMaterials[i].Specular[2];

    Mesh->m_Materials[i].Emissive.r = msMaterials[i].Emissive[0];
    Mesh->m_Materials[i].Emissive.g = msMaterials[i].Emissive[1];
    Mesh->m_Materials[i].Emissive.b = msMaterials[i].Emissive[2];

    Mesh->m_Materials[i].Power = msMaterials[i].Shininess;

    Mesh->m_Textures[i] = NULL;
    if(msMaterials[i].Texture[0]) {
      char TextureFilename[MAX_PATH];
      sprintf(TextureFilename, "%s%s", TexturePath, msMaterials[i].Texture);
      Mesh->m_Textures[i] = pManager->Get(TextureFilename, 0, pDevice);
    }
  }

  // Build vertex data ////////////////////////////////////
  pDevice->CreateVertexBuffer(Mesh->m_NumVertices * sizeof(sMeshVertex), 0, MESHFVF, D3DPOOL_MANAGED, &Mesh->m_VertexBuffer);
  Mesh->m_VertexBuffer->Lock(0, 0, (BYTE**)&Vertices, 0);
  Pos = 0;
  for(i=0;i<Mesh->m_NumFaces;i++) {
    for(j=0;j<3;j++) {
      // Store vertex coordinates
      // Notice that x is reversed to change
      // from right-handed to left-handed coordinates
      Vertices[Pos].x = -msVertices[msFaces[i].Indices[j]].Pos[0];
      Vertices[Pos].y =  msVertices[msFaces[i].Indices[j]].Pos[1];
      Vertices[Pos].z =  msVertices[msFaces[i].Indices[j]].Pos[2];

      // Store vertex normals
      // Ditto on reversal of normal's x
      Vertices[Pos].nx = -msFaces[i].Normal[j][0];
      Vertices[Pos].ny =  msFaces[i].Normal[j][1];
      Vertices[Pos].nz =  msFaces[i].Normal[j][2];

      // Store vertex texture coordinates
      Vertices[Pos].u = msFaces[i].u[j];
      Vertices[Pos].v = msFaces[i].v[j];

      // Assign bone, defaulting to #0 if none assigned.
      // Multiply bone index by 3 to put in constant memory
      Vertices[Pos].Bone = (float)msVertices[msFaces[i].Indices[j]].Bone * 3.0f;

      // Go to next vertex/index
      Pos++;
    }
  }
  Mesh->m_VertexBuffer->Unlock();

  // Indices are built by materials and groups - not by the
  // face array. Go through each material and looking for 
  // matching groups. For each matching group, add those
  // indices belonging to the group.
  pDevice->CreateIndexBuffer(Mesh->m_NumFaces * 3 * sizeof(short), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &Mesh->m_IndexBuffer);
  Mesh->m_IndexBuffer->Lock(0, 0, (BYTE**)&Indices, 0);
  Pos = 0;
  for(i=0;i<Mesh->m_NumMaterials;i++) {

    // Store starting position of material range
    Mesh->m_Ranges[i].m_StartFace = Pos;

    // Scan through each group looking for matching materials
    Num = 0;
    for(j=0;j<msNumGroups;j++) {
      if((DWORD)msGroups[j].Material == i) {

        // Store indices in index buffer.
        // Notice that order reversed, as Milkshape 3D
        // uses right-hand system, not left as we do here.
        for(k=0;k<msGroups[j].Header.NumFaces;k++) {
          DWORD Face = msGroups[j].Indices[k] * 3;
          Indices[Pos++] = msGroups[j].Indices[k] * 3 + 2;
          Indices[Pos++] = msGroups[j].Indices[k] * 3 + 1;
          Indices[Pos++] = msGroups[j].Indices[k] * 3 + 0;
        }

        // Increase face count
        Num += msGroups[j].Header.NumFaces;
      }
    }

    // Store # faces
    Mesh->m_Ranges[i].m_NumFaces = Num;
  }
  Mesh->m_IndexBuffer->Unlock();

  // Load animations //////////////////////////////////////
  for(i=0;i<NumAnimations;i++)
    LoadMS3DAnimation(MeshGroup, Mesh, AnimFilenames[i*2], AnimFilenames[i*2+1], AnimPos);

  // Release all used data
  delete [] msVertices;
  delete [] msFaces;
  delete [] msGroups;
  delete [] msMaterials;
  delete [] msBones;

  // Return success
  return TRUE;
}

BOOL LoadMS3DAnimation(cMeshGroup *MeshGroup, 
                       cMeshContainer *Mesh,
                       char *Filename, char *Name,
                       DWORD Pos)
{
  FILE                *fp;
  cAnimationContainer *Anim = NULL;
  float                msAnimationFPS, msCurrentTime;
  int                  msTotalFrames;
  unsigned short       msNumBones;
  sMS3DBone           *msBones = NULL;
  DWORD                i, j, Num, NumFrames=0;

  // Error checking
  if(MeshGroup == NULL || Filename == NULL || Name == NULL || !Mesh->m_NumBones)
    return FALSE;

  // Open file and seek to start of bone data
  if((fp=fopen(Filename, "rb"))==NULL)
    return FALSE;
  fseek(fp, Pos, SEEK_SET);

  // Get animation FPS, editor time, and total frames
  fread(&msAnimationFPS, 1, sizeof(float), fp);
  fread(&msCurrentTime, 1, sizeof(float), fp);
  fread(&msTotalFrames, 1, sizeof(int), fp);

  // Read in # of bones and compare to # in mesh
  fread(&msNumBones, 1, sizeof(short), fp);
  if((DWORD)msNumBones != Mesh->m_NumBones) {
    fclose(fp);
    return FALSE;
  }
    
  // Read in bone data
  msBones = new sMS3DBone[Mesh->m_NumBones];
  for(i=0;i<Mesh->m_NumBones;i++) {
    fread(&msBones[i], 1, sizeof(msBones[i].Header), fp);

    // Read in animation rotation keys
    if((Num = msBones[i].Header.NumRotFrames)) {
      // Store highest keyframe #
      if(Num > NumFrames)
        NumFrames = Num;

      // Create and read in keyframe data
      msBones[i].RotKeyFrames = new sMS3DKeyFrame[Num];
      for(j=0;j<Num;j++)
        fread(&msBones[i].RotKeyFrames[j], 1, sizeof(sMS3DKeyFrame), fp);
    }

    // Read in animation position keys
    if((Num=msBones[i].Header.NumPosFrames)) {
      // Store highest keyframe #
      if(Num > NumFrames)
        NumFrames = Num;

      // Create and read in keyframe data
      msBones[i].PosKeyFrames = new sMS3DKeyFrame[Num];
      for(j=0;j<Num;j++)
        fread(&msBones[i].PosKeyFrames[j], 1, sizeof(sMS3DKeyFrame), fp);
    }
  }

  // Close file
  fclose(fp);

  // Don't go any further if there is no keyframes
  if(!NumFrames) {
    delete [] msBones;
    return FALSE;
  }

  // Build animation data
  Anim = new cAnimationContainer();

  // Assign a name to animation
  Anim->m_Name = strdup(Name);

  // Allocate the frames (using # of position keys as length)
  Anim->m_NumFrames = (DWORD)NumFrames;
  Anim->m_Frames = new cAnimationFrame[Anim->m_NumFrames]();

  // Go through each frame and create transformation matrices
  for(i=0;i<Anim->m_NumFrames;i++) {

    // Point frame to next (for linked list)
    if(i < Anim->m_NumFrames-1)
      Anim->m_Frames[i].m_Next = &Anim->m_Frames[i+1];

    // Allocate the matrices
    Anim->m_Frames[i].m_matTransformations = new D3DXMATRIX[Mesh->m_NumBones];

    // Store the time of this frame (from 1st bone Position key)
    Anim->m_Frames[i].m_Time = (DWORD)(msBones[0].PosKeyFrames[i].Time * msAnimationFPS) * 30;

    // Store length of animation based on last time
    Anim->m_Length = Anim->m_Frames[i].m_Time + 1;

    // Go through each bone and create transformation matrix
    for(j=0;j<Mesh->m_NumBones;j++) {

      // Calculate the bone's orientation 
      D3DXMATRIX matX, matY, matZ, matXYZ, matWorld;

      D3DXMatrixRotationX(&matX, msBones[j].RotKeyFrames[i].Value[0]);
      D3DXMatrixRotationY(&matY, msBones[j].RotKeyFrames[i].Value[1]);
      D3DXMatrixRotationZ(&matZ, msBones[j].RotKeyFrames[i].Value[2]);
      D3DXMatrixTranslation(&matXYZ,
                            msBones[j].PosKeyFrames[i].Value[0],
                            msBones[j].PosKeyFrames[i].Value[1],
                            msBones[j].PosKeyFrames[i].Value[2]);
      D3DXMatrixMultiply(&matWorld, &matX, &matY);
      D3DXMatrixMultiply(&matWorld, &matWorld, &matZ);
      D3DXMatrixMultiply(&matWorld, &matWorld, &matXYZ);

      // Combine the frame's transformation matrix to
      // the bone's transformation matrix to obtain 
      // the final transformation matrix.
      D3DXMatrixMultiply(&Anim->m_Frames[i].m_matTransformations[j], 
                         &matWorld,
                         &Mesh->m_Bones->m_matTransformations[j]);
    }
  }

  // Free used resources
  delete [] msBones;

  // Link animation into list (as last in list)
  if(MeshGroup->m_Animations == NULL)
    MeshGroup->m_Animations = Anim;
  else {
    // Scan to end of list and link in
    cAnimationContainer *AnimPtr = MeshGroup->m_Animations;
    while(AnimPtr->m_Next != NULL)
      AnimPtr = AnimPtr->m_Next;
    AnimPtr->m_Next = Anim;
  }
  MeshGroup->m_NumAnimations++;

  return TRUE;
}

char *CleanMS3DName(char *Name)
{
  char *NewName, *NamePtr, *Ptr;

  // Error checking
  if(Name == NULL)
    return NULL;

  // Find beginning of filename (remove path)
  if((Ptr = strrchr(Name, '\\')) == NULL)
    Ptr = Name;

  // Allocate some memory to save new name
  NamePtr = NewName = new char[strlen(Ptr)];

  // Copy over until a period or EOL found
  while(Ptr && *Ptr != '.')
    *NamePtr++ = *Ptr++;
  *NamePtr = 0;

  // Return resulting string
  return strdup(NewName);
}

⌨️ 快捷键说明

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