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

📄 lesson2.cpp

📁 一个简单的导入3ds文件格式的例子
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// 下面的函数读入对象的材质名称
void CLoad3DS::ReadObjectMaterial(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk)
{
  char strMaterial[255] = {0};      // 用来保存对象的材质名称
  int buffer[50000] = {0};        // 用来读入不需要的数据

  // 材质或者是颜色,或者是对象的纹理,也可能保存了象明亮度、发光度等信息。

  // 下面读入赋予当前对象的材质名称
  pPreviousChunk->bytesRead += GetString(strMaterial);

  // 遍历所有的纹理
  for(int i = 0; i < pModel->numOfMaterials; i++)
  {
    //如果读入的纹理与当前的纹理名称匹配
    if(strcmp(strMaterial, pModel->pMaterials[i].strName) == 0)
    {
      // 设置材质ID
      pObject->materialID = i;

      // 判断是否是纹理映射,如果strFile是一个长度大于1的字符串,则是纹理
      if(strlen(pModel->pMaterials[i].strFile) > 0) {
        //载入纹理
        BuildTexture(pModel->pMaterials[i].strFile, pModel->texture[pObject->materialID]);
		// 设置对象的纹理映射标志
        pObject->bHasTexture = true;
      }  
      break;
    }
    else
    {
      // 如果该对象没有材质,则设置ID为-1
      pObject->materialID = -1;
    }
  }

  pPreviousChunk->bytesRead += fread(buffer, 1, pPreviousChunk->length - pPreviousChunk->bytesRead, m_FilePointer);
}      

// 下面的这些函数主要用来计算顶点的法向量,顶点的法向量主要用来计算光照
// 下面的宏定义计算一个矢量的长度
#define Mag(Normal) (sqrt(Normal.x*Normal.x + Normal.y*Normal.y + Normal.z*Normal.z))

// 下面的函数求两点决定的矢量
CVector3 Vector(CVector3 vPoint1, CVector3 vPoint2)
{
  CVector3 vVector;              

  vVector.x = vPoint1.x - vPoint2.x;      
  vVector.y = vPoint1.y - vPoint2.y;      
  vVector.z = vPoint1.z - vPoint2.z;      

  return vVector;                
}

// 下面的函数两个矢量相加
CVector3 AddVector(CVector3 vVector1, CVector3 vVector2)
{
  CVector3 vResult;              
  
  vResult.x = vVector2.x + vVector1.x;    
  vResult.y = vVector2.y + vVector1.y;    
  vResult.z = vVector2.z + vVector1.z;    

  return vResult;                
}

// 下面的函数处理矢量的缩放
CVector3 DivideVectorByScaler(CVector3 vVector1, float Scaler)
{
  CVector3 vResult;              
  
  vResult.x = vVector1.x / Scaler;      
  vResult.y = vVector1.y / Scaler;      
  vResult.z = vVector1.z / Scaler;      

  return vResult;                
}

// 下面的函数返回两个矢量的叉积
CVector3 Cross(CVector3 vVector1, CVector3 vVector2)
{
  CVector3 vCross;                
                        
  vCross.x = ((vVector1.y * vVector2.z) - (vVector1.z * vVector2.y));
                        
  vCross.y = ((vVector1.z * vVector2.x) - (vVector1.x * vVector2.z));
                        
  vCross.z = ((vVector1.x * vVector2.y) - (vVector1.y * vVector2.x));

  return vCross;                
}

// 下面的函数规范化矢量
CVector3 Normalize(CVector3 vNormal)
{
  double Magnitude;              

  Magnitude = Mag(vNormal);          // 获得矢量的长度

  vNormal.x /= (float)Magnitude;        
  vNormal.y /= (float)Magnitude;        
  vNormal.z /= (float)Magnitude;        

  return vNormal;                
}

// 下面的函数用于计算对象的法向量
void CLoad3DS::ComputeNormals(t3DModel *pModel)
{
  CVector3 vVector1, vVector2, vNormal, vPoly[3];

  // 如果模型中没有对象,则返回
  if(pModel->numOfObjects <= 0)
    return;

  // 遍历模型中所有的对象
  for(int index = 0; index < pModel->numOfObjects; index++)
  {
    // 获得当前的对象
    t3DObject *pObject = &(pModel->pObject[index]);

    // 分配需要的存储空间
    CVector3 *pNormals    = new CVector3 [pObject->numOfFaces];
    CVector3 *pTempNormals  = new CVector3 [pObject->numOfFaces];
    pObject->pNormals    = new CVector3 [pObject->numOfVerts];

    // 遍历对象的所有面
    for(int i=0; i < pObject->numOfFaces; i++)
    {                        
      vPoly[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]];
      vPoly[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]];
      vPoly[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]];

      // 计算面的法向量

      vVector1 = Vector(vPoly[0], vPoly[2]);    // 获得多边形的矢量
      vVector2 = Vector(vPoly[2], vPoly[1]);    // 获得多边形的第二个矢量

      vNormal = Cross(vVector1, vVector2);    // 获得两个矢量的叉积
      pTempNormals[i] = vNormal;          // 保存非规范化法向量
      vNormal = Normalize(vNormal);        // 规范化获得的叉积

      pNormals[i] = vNormal;            // 将法向量添加到法向量列表中
    }

    // 下面求顶点法向量
    CVector3 vSum = {0.0, 0.0, 0.0};
    CVector3 vZero = vSum;
    int shared=0;
    // 遍历所有的顶点
    for (i = 0; i < pObject->numOfVerts; i++)      
    {
      for (int j = 0; j < pObject->numOfFaces; j++)  // 遍历所有的三角形面
      {                        // 判断该点是否与其它的面共享
        if (pObject->pFaces[j].vertIndex[0] == i || 
          pObject->pFaces[j].vertIndex[1] == i || 
          pObject->pFaces[j].vertIndex[2] == i)
        {
          vSum = AddVector(vSum, pTempNormals[j]);
          shared++;                
        }
      } 
      
      pObject->pNormals[i] = DivideVectorByScaler(vSum, float(-shared));

      // 规范化最后的顶点法向
      pObject->pNormals[i] = Normalize(pObject->pNormals[i]);  

      vSum = vZero;                
      shared = 0;                    
    }
  
    // 释放存储空间,开始下一个对象
    delete [] pTempNormals;
    delete [] pNormals;
  }
}




HDC			hDC=NULL;		// Private GDI Device Context
HGLRC		hRC=NULL;		// Permanent Rendering Context
HWND		hWnd=NULL;		// Holds Our Window Handle
HINSTANCE	hInstance;		// Holds The Instance Of The Application

bool	keys[256];			// Array Used For The Keyboard Routine
bool	active=TRUE;		// Window Active Flag Set To TRUE By Default
bool	fullscreen=TRUE;	// Fullscreen Flag Set To Fullscreen Mode By Default

t3DModel CarModel;


void DrawModel(t3DModel& Model)
{
  // 遍历模型中所有的对象
  for(int i = 0; i < Model.numOfObjects; i++)
  {
    // 如果对象的大小小于0,则退出
    if(Model.pObject.size() <= 0) break;

    // 获得当前显示的对象
    t3DObject *pObject = &Model.pObject[i];
      
    // 判断该对象是否有纹理映射
    if(pObject->bHasTexture) {

      // 打开纹理映射
      glEnable(GL_TEXTURE_2D);
      glColor3ub(255, 255, 255);
      
	  glBindTexture(GL_TEXTURE_2D, Model.texture[pObject->materialID]);
    } else {

      // 关闭纹理映射
      glDisable(GL_TEXTURE_2D);
      glColor3ub(255, 255, 255);
    }
    // 开始以g_ViewMode模式绘制
    glBegin(GL_TRIANGLES);          
      // 遍历所有的面
      for(int j = 0; j < pObject->numOfFaces; j++)
      {
        // 遍历三角形的所有点
        for(int whichVertex = 0; whichVertex < 3; whichVertex++)
        {
          // 获得面对每个点的索引
          int index = pObject->pFaces[j].vertIndex[whichVertex];
      
          // 给出法向量
          glNormal3f(pObject->pNormals[ index ].x, pObject->pNormals[ index ].y, pObject->pNormals[ index ].z);
        
          // 如果对象具有纹理
          if(pObject->bHasTexture) {

            // 确定是否有UVW纹理坐标
            if(pObject->pTexVerts) {
              glTexCoord2f(pObject->pTexVerts[ index ].x, pObject->pTexVerts[ index ].y);
            }
          } else {

            if(Model.pMaterials.size() && pObject->materialID >= 0) 
            {
              BYTE *pColor = Model.pMaterials[pObject->materialID].color;
              glColor3ub(pColor[0], pColor[1], pColor[2]);
            }
          }
          glVertex3f(pObject->pVerts[ index ].x, pObject->pVerts[ index ].y, pObject->pVerts[ index ].z);
        }
      }

    glEnd();                // 绘制结束
  }
}











LRESULT	CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);	// Declaration For WndProc

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)		// Resize And Initialize The GL Window
{
	if (height==0)										// Prevent A Divide By Zero By
	{
		height=1;										// Making Height Equal One
	}

	glViewport(0,0,width,height);						// Reset The Current Viewport

	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
	glLoadIdentity();									// Reset The Projection Matrix

	// Calculate The Aspect Ratio Of The Window
	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,6000.0f);

	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
	glLoadIdentity();									// Reset The Modelview Matrix
}

int InitGL(GLvoid)										// All Setup For OpenGL Goes Here
{
	glShadeModel(GL_SMOOTH);							// Enable Smooth Shading
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);				// Black Background
	glClearDepth(1.0f);									// Depth Buffer Setup
	glEnable(GL_DEPTH_TEST);							// Enables Depth Testing
	glDepthFunc(GL_LEQUAL);								// The Type Of Depth Testing To Do
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculations
	
    CLoad3DS *loader=NULL;
    loader=new(CLoad3DS);
  
    loader->Import3DS(&CarModel, "Bf109G6.3DS");
    
    GLfloat LightAmbient[]= { 0.8f, 0.8f, 0.8f, 1.0f }; 
    GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
	GLfloat LightPosition[]= { 0.0f, 0.0f, -500.0f, 1.0f };

	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
	glEnable(GL_LIGHT1);	
    glEnable(GL_LIGHTING);
delete loader;
	
	
	
	
	
	
	
	
	return TRUE;										// Initialization Went OK
}

int DrawGLScene(GLvoid)									// Here's Where We Do All The Drawing
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer
	glLoadIdentity();									// Reset The Current Modelview Matrix
	gluLookAt(0, 0, -10, 0, 0, 0, 0, 1, 0);
	static float ax=0.0f;
	static float ay=0.0f;
	static float az=0.0f;

	glPushMatrix();
	glRotatef(ax, 1.0f, 0.0f, 0.0f);
	glRotatef(ay, 0.0f, 1.0f, 0.0f);
	glRotatef(az, 0.0f, 0.0f, 1.0f);
	DrawModel(CarModel);
	glPopMatrix();
	
	ax+=1.0f;
	ay+=0.50f;
	az+=1.10f;
	return TRUE;										// Keep Going
}

⌨️ 快捷键说明

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