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

📄 3ds.h

📁 粒子效果演示(附代码) 利用C++所提供的一些标准容器很容易实现粒子效果. 简单的说就是,将粒子数据写在一个类里面,有一个粒子源,不停地生成粒子,然后放入一个stl::list中(push
💻 H
📖 第 1 页 / 共 3 页
字号:
// 打开一个3ds文件,读出其中的内容,并释放内存
bool CLoad3DS::Import3DS(t3DModel *pModel, char *strFileName)
{
  char strMessage[255] = {0};

  // 打开一个3ds文件
  m_FilePointer = fopen(strFileName, "rb");

  // 确保所获得的文件指针合法
  if(!m_FilePointer) 
  {
    sprintf(strMessage, "Unable to find the file: %s!", strFileName);
    MessageBox(NULL, strMessage, "Error", MB_OK);
    return false;
  }

  // 当文件打开之后,首先应该将文件最开始的数据块读出以判断是否是一个3ds文件
  // 如果是3ds文件的话,第一个块ID应该是PRIMARY

  // 将文件的第一块读出并判断是否是3ds文件
  ReadChunk(m_CurrentChunk);

  // 确保是3ds文件
  if (m_CurrentChunk->ID != PRIMARY)
  {
    sprintf(strMessage, "Unable to load PRIMARY chuck from file: %s!", strFileName);
    MessageBox(NULL, strMessage, "Error", MB_OK);
    return false;
  }

  // 现在开始读入数据,ProcessNextChunk()是一个递归函数

  // 通过调用下面的递归函数,将对象读出
  ProcessNextChunk(pModel, m_CurrentChunk);

  // 在读完整个3ds文件之后,计算顶点的法线
  ComputeNormals(pModel);

  // 释放内存空间
  CleanUp();

  return true;
}

// 下面的函数释放所有的内存空间,并关闭文件
void CLoad3DS::CleanUp()
{

  fclose(m_FilePointer);            // 关闭当前的文件指针
  delete m_CurrentChunk;            // 释放当前块
  delete m_TempChunk;              // 释放临时块
}

// 下面的函数读出3ds文件的主要部分
void CLoad3DS::ProcessNextChunk(t3DModel *pModel, tChunk *pPreviousChunk)
{
  t3DObject newObject = {0};          // 用来添加到对象链表
  tMaterialInfo newTexture = {0};        // 用来添加到材质链表
  unsigned int version = 0;          // 保存文件版本
  int buffer[50000] = {0};          // 用来跳过不需要的数据

  m_CurrentChunk = new tChunk;        // 为新的块分配空间    

  // 下面每读一个新块,都要判断一下块的ID,如果该块是需要的读入的,则继续进行
  // 如果是不需要读入的块,则略过

  // 继续读入子块,直到达到预定的长度
  while (pPreviousChunk->bytesRead < pPreviousChunk->length)
  {
    // 读入下一个块
    ReadChunk(m_CurrentChunk);

    // 判断块的ID号
    switch (m_CurrentChunk->ID)
    {
    case VERSION:              // 文件版本号
      
      // 在该块中有一个无符号短整型数保存了文件的版本
      
      // 读入文件的版本号,并将字节数添加到bytesRead变量中
      m_CurrentChunk->bytesRead += fread(&version, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);

      // 如果文件版本号大于3,给出一个警告信息
      if (version > 0x03)
        MessageBox(NULL, "This 3DS file is over version 3 so it may load incorrectly", "Warning", MB_OK);
      break;

    case OBJECTINFO:            // 网格版本信息
      
      // 读入下一个块
      ReadChunk(m_TempChunk);

      // 获得网格的版本号
      m_TempChunk->bytesRead += fread(&version, 1, m_TempChunk->length - m_TempChunk->bytesRead, m_FilePointer);

      // 增加读入的字节数
      m_CurrentChunk->bytesRead += m_TempChunk->bytesRead;

      // 进入下一个块
      ProcessNextChunk(pModel, m_CurrentChunk);
      break;

    case MATERIAL:              // 材质信息

      // 材质的数目递增
      pModel->numOfMaterials++;

      // 在纹理链表中添加一个空白纹理结构
      pModel->pMaterials.push_back(newTexture);

      // 进入材质装入函数
      ProcessNextMaterialChunk(pModel, m_CurrentChunk);
      break;

    case OBJECT:              // 对象的名称
        
      // 该块是对象信息块的头部,保存了对象了名称

      // 对象数递增
      pModel->numOfObjects++;
    
      // 添加一个新的tObject节点到对象链表中
      pModel->pObject.push_back(newObject);
      
      // 初始化对象和它的所有数据成员
      memset(&(pModel->pObject[pModel->numOfObjects - 1]), 0, sizeof(t3DObject));

      // 获得并保存对象的名称,然后增加读入的字节数
      m_CurrentChunk->bytesRead += GetString(pModel->pObject[pModel->numOfObjects - 1].strName);
      
      // 进入其余的对象信息的读入
      ProcessNextObjectChunk(pModel, &(pModel->pObject[pModel->numOfObjects - 1]), m_CurrentChunk);
      break;

    case EDITKEYFRAME:

      // 跳过关键帧块的读入,增加需要读入的字节数
      m_CurrentChunk->bytesRead += fread(buffer, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
      break;

    default: 
      
      // 跳过所有忽略的块的内容的读入,增加需要读入的字节数
      m_CurrentChunk->bytesRead += fread(buffer, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
      break;
    }

    // 增加从最后块读入的字节数
    pPreviousChunk->bytesRead += m_CurrentChunk->bytesRead;
  }

  // 释放当前块的内存空间
  delete m_CurrentChunk;
  m_CurrentChunk = pPreviousChunk;
}

// 下面的函数处理所有的文件中对象的信息
void CLoad3DS::ProcessNextObjectChunk(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk)
{
  int buffer[50000] = {0};          // 用于读入不需要的数据

  // 对新的块分配存储空间
  m_CurrentChunk = new tChunk;

  // 继续读入块的内容直至本子块结束
  while (pPreviousChunk->bytesRead < pPreviousChunk->length)
  {
    // 读入下一个块
    ReadChunk(m_CurrentChunk);

    // 区别读入是哪种块
    switch (m_CurrentChunk->ID)
    {
    case OBJECT_MESH:          // 正读入的是一个新块
    
      // 使用递归函数调用,处理该新块
      ProcessNextObjectChunk(pModel, pObject, m_CurrentChunk);
      break;

    case OBJECT_VERTICES:        // 读入是对象顶点
      ReadVertices(pObject, m_CurrentChunk);
      break;

    case OBJECT_FACES:          // 读入的是对象的面
      ReadVertexIndices(pObject, m_CurrentChunk);
      break;

    case OBJECT_MATERIAL:        // 读入的是对象的材质名称
      
      // 该块保存了对象材质的名称,可能是一个颜色,也可能是一个纹理映射。同时在该块中也保存了
      // 纹理对象所赋予的面

      // 下面读入对象的材质名称
      ReadObjectMaterial(pModel, pObject, m_CurrentChunk);      
      break;

    case OBJECT_UV:            // 读入对象的UV纹理坐标

      // 读入对象的UV纹理坐标
      ReadUVCoordinates(pObject, m_CurrentChunk);
      break;

    default: 

      // 略过不需要读入的块
      m_CurrentChunk->bytesRead += fread(buffer, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
      break;
    }

    // 添加从最后块中读入的字节数到前面的读入的字节中
    pPreviousChunk->bytesRead += m_CurrentChunk->bytesRead;
  }

  // 释放当前块的内存空间,并把当前块设置为前面块
  delete m_CurrentChunk;
  m_CurrentChunk = pPreviousChunk;
}

// 下面的函数处理所有的材质信息
void CLoad3DS::ProcessNextMaterialChunk(t3DModel *pModel, tChunk *pPreviousChunk)
{
  int buffer[50000] = {0};          // 用于读入不需要的数据

  // 给当前块分配存储空间
  m_CurrentChunk = new tChunk;

  // 继续读入这些块,知道该子块结束
  while (pPreviousChunk->bytesRead < pPreviousChunk->length)
  {
    // 读入下一块
    ReadChunk(m_CurrentChunk);

    // 判断读入的是什么块
    switch (m_CurrentChunk->ID)
    {
    case MATNAME:              // 材质的名称
      
      // 读入材质的名称
      m_CurrentChunk->bytesRead += fread(pModel->pMaterials[pModel->numOfMaterials - 1].strName, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
      break;

    case MATDIFFUSE:            // 对象的R G B颜色
      ReadColorChunk(&(pModel->pMaterials[pModel->numOfMaterials - 1]), m_CurrentChunk);
      break;
    
    case MATMAP:              // 纹理信息的头部
      
      // 进入下一个材质块信息
      ProcessNextMaterialChunk(pModel, m_CurrentChunk);
      break;

    case MATMAPFILE:            // 材质文件的名称

      // 读入材质的文件名称
      m_CurrentChunk->bytesRead += fread(pModel->pMaterials[pModel->numOfMaterials - 1].strFile, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
      break;
    
    default: 

      // 掠过不需要读入的块
      m_CurrentChunk->bytesRead += fread(buffer, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);
      break;
    }

    // 添加从最后块中读入的字节数
    pPreviousChunk->bytesRead += m_CurrentChunk->bytesRead;
  }

  // 删除当前块,并将当前块设置为前面的块
  delete m_CurrentChunk;
  m_CurrentChunk = pPreviousChunk;
}

// 下面函数读入块的ID号和它的字节长度
void CLoad3DS::ReadChunk(tChunk *pChunk)
{
  // 读入块的ID号,占用了2个字节。块的ID号象OBJECT或MATERIAL一样,说明了在块中所包含的内容
  pChunk->bytesRead = fread(&pChunk->ID, 1, 2, m_FilePointer);

  // 然后读入块占用的长度,包含了四个字节
  pChunk->bytesRead += fread(&pChunk->length, 1, 4, m_FilePointer);
}

// 下面的函数读入一个字符串
int CLoad3DS::GetString(char *pBuffer)
{

⌨️ 快捷键说明

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