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

📄 3ds.h

📁 粒子效果演示(附代码) 利用C++所提供的一些标准容器很容易实现粒子效果. 简单的说就是,将粒子数据写在一个类里面,有一个粒子源,不停地生成粒子,然后放入一个stl::list中(push
💻 H
📖 第 1 页 / 共 3 页
字号:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fstream>
#include <vector>
#include <gl\gl.h>                    
#include <gl\glu.h>                    
#include <gl\glaux.h>
#include <crtdbg.h>

#include <olectl.h>              
#include <math.h>              

using namespace std;

#define MAX_TEXTURES 100                // 最大的纹理数目

// 定义3D点的类,用于保存模型中的顶点
class CVector3 
{
public:
  float x, y, z;
};

// 定义2D点类,用于保存模型的UV纹理坐标
class CVector2 
{
public:
  float x, y;
};

// 面的结构定义
struct tFace
{
  int vertIndex[3];      // 顶点索引
  int coordIndex[3];      // 纹理坐标索引
};

// 材质信息结构体
struct tMaterialInfo
{
  char strName[255];      // 纹理名称
  char strFile[255];      // 如果存在纹理映射,则表示纹理文件名称
  BYTE color[3];        // 对象的RGB颜色
  int texureId;        // 纹理ID
  float uTile;        // u 重复
  float vTile;        // v 重复
  float uOffset;       // u 纹理偏移
  float vOffset;        // v 纹理偏移
} ;

// 对象信息结构体
struct t3DObject 
{
  int numOfVerts;      // 模型中顶点的数目
  int numOfFaces;      // 模型中面的数目
  int numTexVertex;      // 模型中纹理坐标的数目
  int materialID;      // 纹理ID
  bool bHasTexture;      // 是否具有纹理映射
  char strName[255];      // 对象的名称
  CVector3 *pVerts;      // 对象的顶点
  CVector3 *pNormals;    // 对象的法向量
  CVector2 *pTexVerts;    // 纹理UV坐标
  tFace *pFaces;        // 对象的面信息
};

// 模型信息结构体
struct t3DModel 
{
  UINT texture[MAX_TEXTURES];
  int numOfObjects;          // 模型中对象的数目
  int numOfMaterials;          // 模型中材质的数目
  vector<tMaterialInfo> pMaterials;  // 材质链表信息
  vector<t3DObject> pObject;      // 模型中对象链表信息
};

#ifndef _3DS_H
#define _3DS_H

// 基本块(Primary Chunk),位于文件的开始
#define PRIMARY 0x4D4D

// 主块(Main Chunks)
#define OBJECTINFO 0x3D3D        // 网格对象的版本号
#define VERSION 0x0002        // .3ds文件的版本
#define EDITKEYFRAME 0xB000        // 所有关键帧信息的头部

// 对象的次级定义(包括对象的材质和对象)
#define MATERIAL   0xAFFF        // 保存纹理信息
#define OBJECT     0x4000        // 保存对象的面、顶点等信息

// 材质的次级定义
#define MATNAME 0xA000        // 保存材质名称
#define MATDIFFUSE 0xA020        // 对象/材质的颜色
#define MATMAP 0xA200        // 新材质的头部
#define MATMAPFILE 0xA300        // 保存纹理的文件名

#define OBJECT_MESH 0x4100        // 新的网格对象

// OBJECT_MESH的次级定义
#define OBJECT_VERTICES 0x4110      // 对象顶点
#define OBJECT_FACES    0x4120      // 对象的面
#define OBJECT_MATERIAL    0x4130      // 对象的材质
#define OBJECT_UV      0x4140      // 对象的UV纹理坐标

struct tIndices 
{              
  unsigned short a, b, c, bVisible;  
};

// 保存块信息的结构
struct tChunk
{
  unsigned short int ID;          // 块的ID    
  unsigned int length;          // 块的长度
  unsigned int bytesRead;          // 需要读的块数据的字节数
};

// CLoad3DS类处理所有的装入代码
class CLoad3DS
{
public:
  CLoad3DS();                // 初始化数据成员
  // 装入3ds文件到模型结构中
  bool Import3DS(t3DModel *pModel, char *strFileName);
  // 读入一个纹理
  int BuildTexture(char *szPathName, GLuint &texid);
  
private:
  // 读一个字符串
  int GetString(char *);
  // 读下一个块
  void ReadChunk(tChunk *);
  // 读下一个块
  void ProcessNextChunk(t3DModel *pModel, tChunk *);
  // 读下一个对象块
  void ProcessNextObjectChunk(t3DModel *pModel, t3DObject *pObject, tChunk *);
  // 读下一个材质块
  void ProcessNextMaterialChunk(t3DModel *pModel, tChunk *);
  // 读对象颜色的RGB值
  void ReadColorChunk(tMaterialInfo *pMaterial, tChunk *pChunk);
  // 读对象的顶点
  void ReadVertices(t3DObject *pObject, tChunk *);
  // 读对象的面信息
  void ReadVertexIndices(t3DObject *pObject, tChunk *);
  // 读对象的纹理坐标
  void ReadUVCoordinates(t3DObject *pObject, tChunk *);
  // 读赋予对象的材质名称
  void ReadObjectMaterial(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk);
  // 计算对象顶点的法向量
  void ComputeNormals(t3DModel *pModel);
  // 关闭文件,释放内存空间
  void CleanUp();
  // 文件指针
  FILE *m_FilePointer;

  tChunk *m_CurrentChunk;
  tChunk *m_TempChunk;
};

#endif

// 读入一个纹理
int CLoad3DS::BuildTexture(char *szPathName, GLuint &texid)
{
  HDC      hdcTemp;                        // The DC To Hold Our Bitmap
  HBITMAP    hbmpTemp;                        // Holds The Bitmap Temporarily
  IPicture  *pPicture;                        // IPicture Interface
  OLECHAR    wszPath[MAX_PATH+1];                  // Full Path To Picture (WCHAR)
  char    szPath[MAX_PATH+1];                    // Full Path To Picture
  long    lWidth;                          // Width In Logical Units
  long    lHeight;                        // Height In Logical Units
  long    lWidthPixels;                      // Width In Pixels
  long    lHeightPixels;                      // Height In Pixels
  GLint    glMaxTexDim ;                      // Holds Maximum Texture Size

  if (strstr(szPathName, "http://"))                  // If PathName Contains http:// Then...
  {
    strcpy(szPath, szPathName);                    // Append The PathName To szPath
  }
  else                                // Otherwise... We Are Loading From A File
  {
    GetCurrentDirectory(MAX_PATH, szPath);              // Get Our Working Directory
    strcat(szPath, "\\");                      // Append "\" After The Working Directory
    strcat(szPath, szPathName);                    // Append The PathName
  }

  MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH);    // Convert From ASCII To Unicode
  HRESULT hr = OleLoadPicturePath(wszPath, 0, 0, 0, IID_IPicture, (void**)&pPicture);

  if(FAILED(hr))                            // If Loading Failed
    return FALSE;                          // Return False

  hdcTemp = CreateCompatibleDC(GetDC(0));                // Create The Windows Compatible Device Context
  if(!hdcTemp)                            // Did Creation Fail?
  {
    pPicture->Release();                      // Decrements IPicture Reference Count
    return FALSE;                          // Return False (Failure)
  }

  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim);          // Get Maximum Texture Size Supported
  
  pPicture->get_Width(&lWidth);                    // Get IPicture Width (Convert To Pixels)
  lWidthPixels  = MulDiv(lWidth, GetDeviceCaps(hdcTemp, LOGPIXELSX), 2540);
  pPicture->get_Height(&lHeight);                    // Get IPicture Height (Convert To Pixels)
  lHeightPixels  = MulDiv(lHeight, GetDeviceCaps(hdcTemp, LOGPIXELSY), 2540);

  // Resize Image To Closest Power Of Two
  if (lWidthPixels <= glMaxTexDim) // Is Image Width Less Than Or Equal To Cards Limit
    lWidthPixels = 1 << (int)floor((log((double)lWidthPixels)/log(2.0f)) + 0.5f); 
  else // Otherwise Set Width To "Max Power Of Two" That The Card Can Handle
    lWidthPixels = glMaxTexDim;
 
  if (lHeightPixels <= glMaxTexDim) // Is Image Height Greater Than Cards Limit
    lHeightPixels = 1 << (int)floor((log((double)lHeightPixels)/log(2.0f)) + 0.5f);
  else // Otherwise Set Height To "Max Power Of Two" That The Card Can Handle
    lHeightPixels = glMaxTexDim;
  
  //  Create A Temporary Bitmap
  BITMAPINFO  bi = {0};                        // The Type Of Bitmap We Request
  DWORD    *pBits = 0;                        // Pointer To The Bitmap Bits

  bi.bmiHeader.biSize      = sizeof(BITMAPINFOHEADER);        // Set Structure Size
  bi.bmiHeader.biBitCount    = 32;                  // 32 Bit
  bi.bmiHeader.biWidth    = lWidthPixels;              // Power Of Two Width
  bi.bmiHeader.biHeight    = lHeightPixels;            // Make Image Top Up (Positive Y-Axis)
  bi.bmiHeader.biCompression  = BI_RGB;                // RGB Encoding
  bi.bmiHeader.biPlanes    = 1;                  // 1 Bitplane

  //  Creating A Bitmap This Way Allows Us To Specify Color Depth And Gives Us Imediate Access To The Bits
  hbmpTemp = CreateDIBSection(hdcTemp, &bi, DIB_RGB_COLORS, (void**)&pBits, 0, 0);
  
  if(!hbmpTemp)                            // Did Creation Fail?
  {
    DeleteDC(hdcTemp);                        // Delete The Device Context
    pPicture->Release();                      // Decrements IPicture Reference Count
    return FALSE;                          // Return False (Failure)
  }

  SelectObject(hdcTemp, hbmpTemp);                  // Select Handle To Our Temp DC And Our Temp Bitmap Object

  // Render The IPicture On To The Bitmap
  pPicture->Render(hdcTemp, 0, 0, lWidthPixels, lHeightPixels, 0, lHeight, lWidth, -lHeight, 0);

  // Convert From BGR To RGB Format And Add An Alpha Value Of 255
  for(long i = 0; i < lWidthPixels * lHeightPixels; i++)        // Loop Through All Of The Pixels
  {
    BYTE* pPixel  = (BYTE*)(&pBits[i]);              // Grab The Current Pixel
    BYTE temp    = pPixel[0];                  // Store 1st Color In Temp Variable (Blue)
    pPixel[0]    = pPixel[2];                  // Move Red Value To Correct Position (1st)
    pPixel[2]    = temp;                      // Move Temp Value To Correct Blue Position (3rd)

    // This Will Make Any Black Pixels, Completely Transparent    (You Can Hardcode The Value If You Wish)
    if ((pPixel[0]==0) && (pPixel[1]==0) && (pPixel[2]==0))      // Is Pixel Completely Black
      pPixel[3]  = 0;                      // Set The Alpha Value To 0
    else                              // Otherwise
      pPixel[3]  = 255;                      // Set The Alpha Value To 255
  }

  glGenTextures(1, &texid);                      // Create The Texture

  // Typical Texture Generation Using Data From The Bitmap
  glBindTexture(GL_TEXTURE_2D, texid);                // Bind To The Texture ID
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    // (Modify This For The Type Of Filtering You Want)
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // (Modify This For The Type Of Filtering You Want)
  gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, lWidthPixels, lHeightPixels, GL_RGBA, GL_UNSIGNED_BYTE, pBits);
  //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lWidthPixels, lHeightPixels, 0, GL_RGBA, GL_UNSIGNED_BYTE, pBits);  // (Modify This If You Want Mipmaps)
  
  DeleteObject(hbmpTemp);                        // Delete The Object
  DeleteDC(hdcTemp);                          // Delete The Device Context

  pPicture->Release();                        // Decrements IPicture Reference Count

  return TRUE;                            // Return True (All Good)

}


// 构造函数的功能是初始化tChunk数据
CLoad3DS::CLoad3DS()
{
  m_CurrentChunk = new tChunk;        // 初始化并为当前的块分配空间
  m_TempChunk = new tChunk;          // 初始化一个临时块并分配空间
}

⌨️ 快捷键说明

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