现在的位置: 首页 > 综合 > 正文

加载并显示3ds文件

2013年09月09日 ⁄ 综合 ⁄ 共 20185字 ⁄ 字号 评论关闭

OpenGL ES可以自己绘制你所需要的图片,也可以直接加载一些3ds文件或者.x文件。将定点坐标、纹理坐标、法向量等转换成数组,并通过ES里的方法如:glDrawElements()、glDrawArray()等将模型显示。这里,我自己写了个类可以完成3ds文件的加载与显示,对于.x文件的显示则要简单点。在后面会给出方法。。。以下是代码:

如有失误,请更正。。。谢谢

/*
 * ThreeDS.h
 *
 *  Created on: 2009-10-30
 *      Author: yuyanya
 */

#ifndef _THREEDS_H
#define _THREEDS_H

#include <e32def.h>
#include <GLES/gl.h>
#include <e32cmn.h>
#include <e32Base.h>
#include <EIKDEF.H>
#include <f32file.h>
#include <EIKENV.H>
#include <coemain.h>
#include <e32std.h>
#include <math.h>
#include <fbs.h>
#include <d3ds_bmp.mbg>
#include <s32file.h>

 

#define PRIMARY       0x4D4D        //  基本块(Primary Chunk),位于文件的开始
//  主块(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 OBJ_MESH   0x4100  // 新的网格对象
#define MAX_TEXTURES  100   // 最大的纹理数目
//  OBJ_MESH的次级定义
#define OBJ_VERTICES  0x4110  // 对象顶点
#define OBJ_FACES   0x4120  // 对象的面
#define OBJ_MATERIAL  0x4130  // 对象的材质
#define OBJ_UV    0x4140  // 对象的UV纹理坐标

#define Mag(Normal) (sqrt(Normal.x*Normal.x + Normal.y*Normal.y + Normal.z*Normal.z))

class CVector3
 {
public:
 TReal32 x;
 TReal32 y;
 TReal32 z;
 };
class CVector2
 {
public:
 TReal32 x;
 TReal32 y;
 };

struct tFace
 {
 TInt vertIndex[3];
 TInt coordIndex[3];
 };

//材质信息
struct tMatInfo
 {
 TBuf8<255> strName;  //纹理名称
 TBuf8<255> strFile;  //如果存在纹理映射,则表示纹理文件名称
 TInt texureId;
 TBuf8<3> color;
 TReal uTile;
 TReal vTile;
 TReal uOffset;
 TReal vOffset;
 };
struct t3DObject
 {
 TInt numOfVerts;
 TInt numOfFaces;
 TInt numOfTexVertex;
 TInt materialId;
 TBool bHasTexture;   // 是否具有纹理映射
 TBuf8<255> strName;   // 对象的名称
 CVector3  *pVerts;   // 对象的顶点
 CVector3  *pNormals;  // 对象的法向量
 CVector2  *pTexVerts;  // 纹理UV坐标
 tFace *pFaces;    // 对象的面信息
 };
struct t3DModel //模型信息结构体
{ int numOfObjects;   // 模型中对象的数目
 int numOfMaterials;   // 模型中材质的数目
 RPointerArray<tMatInfo>pMaterials; // 材质链表信息
 RPointerArray<t3DObject> pObject; // 模型中对象链表信息
 
 
};
struct tChunk //保存块信息的结构
{ TUint16 ID;  // 块的ID  
 TUint length;  // 块的长度
 TUint bytesRead;  // 需要读的块数据的字节数
};
class CLoad3DS// CLoad3DS类处理所有的装入代码
{
public:
 RFs fs;
 //RFs mFs;
 static CLoad3DS* NewL();
 static CLoad3DS* NewLC();

private:
 CLoad3DS();        // 初始化数据成员
 void ConstructL();
 virtual ~CLoad3DS();
 
public: 
 void show3ds(int j0,float tx,float ty,float tz,float size);//显示3ds模型
 void Init(TFileName filename,int j);
 
 
private:
 TBool Import3DS(t3DModel *pModel, TFileName aFileName);// 装入3ds文件到模型结构中
 void CreateTextureL(TUint textureArray[], const TDesC& strFileName, TInt textureID);//  从文件中创建纹理
 int  GetString(TDes8& tBuf);        // 读一个字符串
 void ReadChunk(tChunk *);       // 读下一个块
 void ReadNextChunk(t3DModel *aModel, tChunk *);  // 读下一个块
 void ReadNextObjChunk(t3DModel *aModel,t3DObject *aObject,tChunk *);// 读下一个对象块
 void ReadNextMatChunk(t3DModel *aModel, tChunk *); // 读下一个材质块
 void ReadColor(tMatInfo *aMaterial, tChunk *aChunk);// 读对象颜色的RGB值
 void ReadVertices(t3DObject *aObject, tChunk *); // 读对象的顶点
 void ReadVertexIndices(t3DObject *aObject,tChunk *aPreChunk);// 读对象的面信息
 void ReadUVCoordinates(t3DObject *aObject,tChunk *);// 读对象的纹理坐标
 void ReadObjMat(t3DModel *aModel,t3DObject *aObject,tChunk *aPreChunk);// 读赋予对象的材质名称
 void ComputeNormals(t3DModel *aModel);    // 计算对象顶点的法向量
 void CleanUp();          // 关闭文件,释放内存空间
 //RFileReadStream mRs;
 RFile mFile;        // 文件指针
 tChunk *mCurrentChunk;
 tChunk *mTempChunk;
 
};
#endif

 

 

 

 

 

 

 

 

/*
 * ThreeDS.cpp
 *
 *  Created on: 2009-10-30
 *      Author: yuyanya
 */

#include "ThreeDS.h"
#include <AknUtils.h>

 

TUint g_Texture[MAX_TEXTURES] =
 {
 0
 };
t3DModel g_3DModel[10];

TBool g_bLighting = ETrue;

CLoad3DS* CLoad3DS::NewL()
 {
 CLoad3DS* self = CLoad3DS::NewLC();
 CleanupStack::Pop(self);
 return self;
 }

CLoad3DS* CLoad3DS::NewLC()
 {
 CLoad3DS* self = new (ELeave) CLoad3DS;
 CleanupStack::PushL(self);
 self->ConstructL();
 return self;
 }

CLoad3DS::CLoad3DS()
 {
 //
 }

void CLoad3DS::ConstructL()
 {
 fs = CCoeEnv::Static()->FsSession();
 //mFs = CCoeEnv::Static()->FsSession();
 mCurrentChunk = new (ELeave) tChunk; // 初始化并为当前的块分配空间
 mTempChunk = new (ELeave) tChunk; // 初始化一个临时块并分配空间
 }
CLoad3DS::~CLoad3DS()
 {
 fs.Close();
 //mFs.Close();
 delete mCurrentChunk; // 释放当前块
 delete mTempChunk; // 释放临时块
 }

TBool CLoad3DS::Import3DS(t3DModel *aModel, TFileName aFileName) // 装入3ds文件到模型结构中
 {

 User::LeaveIfError(mFile.Open(fs, aFileName, EFileStream));
 //User::LeaveIfError(mRs.Open(mFs,aFileName,EFileRead));
 ReadChunk(mCurrentChunk);
 if (mCurrentChunk->ID != PRIMARY)
  {
  RDebug::Print(_L("Unable to load PRIMARY chuck from file:%S/n"),aFileName);
  return false;
  }
 // 现在开始读入数据,ReadNextChunk()是一个递归函数
 // 通过调用下面的递归函数,将对象读出
 ReadNextChunk(aModel, mCurrentChunk);
 // 在读完整个3ds文件之后,计算顶点的法线
 ComputeNormals(aModel);
 return TRUE;
 }
void CLoad3DS::Init(TFileName filename, TInt j)
 {
 TBuf<255> temp;
 if (!Import3DS(&g_3DModel[j], filename))
  RDebug::Print(_L("Load file failed"));
 for (TInt i = 0; i < g_3DModel[j].numOfMaterials; i++)
  {
  if (g_3DModel[j].pMaterials[i]->strFile.Length() > 0)
   {
   temp.Copy(g_3DModel[j].pMaterials[j]->strFile);
   CreateTextureL(g_Texture, temp, i);
   }
  g_3DModel[j].pMaterials[i]->texureId = i;
  }
 }

void CLoad3DS::CreateTextureL(TUint textureArray[], const TDesC& strFileName,
  TInt textureID) //从文件中创建纹理
 {
 if (strFileName.Length() < 0)
  return;
 //CFbsBitmap* pBitmap = new (ELeave) CFbsBitmap;
 CFbsBitmap* pBitmap;
 
 _LIT(KFileName,"system//apps//graphics//d3ds_bmp.mbm");
 TFileName fileName(KFileName);
 //User::LeaveIfError(CompleteWithAppPath(fileName));
 //CleanupStack::PushL(pBitmap);
 //pBitmap = iEikonEnv->CreateBitmapL(strFileName,EMbmD3ds_bmpCar_dealers1);
 pBitmap = CEikonEnv::Static()->CreateBitmapL(fileName,EMbmD3ds_bmpFace);
 //User::LeaveIfError(pBitmap->Load(strFileName,EMbmD3ds_bmpCar_dealers1/*the resource ID*/,ETrue));         //TODO:  May be error
 glGenTextures(1, &textureArray[textureID]);
 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 glBindTexture(GL_TEXTURE_2D, textureArray[textureID]);
 glTexImage2D(GL_TEXTURE_2D, 0, 3, pBitmap->SizeInPixels().iWidth,
   pBitmap->SizeInPixels().iHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,
   pBitmap->DataAddress());
 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
   GL_LINEAR_MIPMAP_NEAREST);
 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,
   GL_LINEAR_MIPMAP_LINEAR);
 if (pBitmap)
  {
  delete pBitmap;
  }

 CleanupStack::PopAndDestroy(pBitmap);
 }

void CLoad3DS::show3ds(int j0, float tx, float ty, float tz, float size)
 {
 glPushMatrix();
 glDisable(GL_TEXTURE_2D);
 glTranslatef(tx, ty, tz);
 glScalef(size, size, size);
 glRotatef(90, 0, 1.0f, 0);
 for (TInt i = 0; i < g_3DModel[j0].numOfObjects; i++)
  {
  t3DObject* pObject = g_3DModel[j0].pObject[i];
  if (pObject->bHasTexture)
   {
   glEnable(GL_TEXTURE_2D);
   glBindTexture(GL_TEXTURE_2D,g_Texture[pObject->materialId]);
   }
  else
   glDisable(GL_TEXTURE_2D);
  glColor4f(255, 255, 255, 255);
  for (TInt j = 0; j < pObject->numOfFaces; j++)
   {
   for (TInt tex = 0; tex < 3; tex++)
    {
    TInt index = pObject->pFaces[j].vertIndex[tex];
    glNormal3f(pObject->pNormals[index].x,
      pObject->pNormals[index].y, pObject->pNormals[index].z); //设置法向量
    if (pObject->bHasTexture)
     {
     if (pObject->pTexVerts)
      {
      GLubyte texCoord[2];
      texCoord[0] = pObject->pTexVerts[index].x;
      texCoord[1] = pObject->pTexVerts[index].y;
      glTexCoordPointer(2, GL_FLOAT,0, texCoord); //创建纹理
      }
     }
    else
     {
     if (pObject->materialId >= 0)
      {
      GLubyte colors[4];
      colors[0]
        = g_3DModel[j0].pMaterials[pObject->materialId]->color[0];
      colors[1]
        = g_3DModel[j0].pMaterials[pObject->materialId]->color[1];
      colors[2]
        = g_3DModel[j0].pMaterials[pObject->materialId]->color[2];
      colors[3] = 255;
      glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
      }
     }
    GLubyte triangles[3];
    triangles[0] = pObject->pVerts[index].x;
    triangles[1] = pObject->pVerts[index].y;
    triangles[2] = pObject->pVerts[index].z;
    glDrawElements(GL_TRIANGLES, 1, GL_UNSIGNED_BYTE, triangles);
    }
   }
  }
 glEnable(GL_TEXTURE_2D);
 glPopMatrix();
 }

void CLoad3DS::CleanUp()
 {
 fs.Close();
 delete mCurrentChunk; // 释放当前块
 delete mTempChunk; // 释放临时块
 }

void CLoad3DS::ReadChunk(tChunk *aChunk)
 {
 TBuf8<20> tempID;
 tempID.Zero();
 TBuf8<20> tempLength;
 tempLength.Zero();
 User::LeaveIfError(mFile.Read(tempID, 2));
 aChunk->bytesRead = tempID.Size();
 aChunk->ID = tempID[1];
 aChunk->ID = aChunk->ID<<8;
 aChunk->ID = aChunk->ID + tempID[0];
// aChunk->ID = (tempID[1]&0xFFFF<<8) | tempID[0] & 0xFFFF; //Convert the TBuf8 to TUint16
 User::LeaveIfError(mFile.Read(tempLength, 4));
 aChunk->bytesRead += tempLength.Size();

 aChunk->length = tempLength[3] << 24 | tempLength[2] << 16 | tempLength[1]
   << 8 | tempLength[0] & 0xFFFFFFFF;
 }

void CLoad3DS::ReadNextChunk(t3DModel* aModel, tChunk* aPreChunk)
 {
 t3DObject* newObject = new (ELeave) t3DObject;
 tMatInfo* newTexture = new (ELeave) tMatInfo;

 TUint version = 0;
 HBufC8* buffer1 = HBufC8::NewL(1024);
 mCurrentChunk = new tChunk;
 TBuf8<10> tempVersion;

 while (aPreChunk->bytesRead < aPreChunk->length)
  {
  ReadChunk(mCurrentChunk);
  switch (mCurrentChunk->ID)
   {
   case VERSION:
    tempVersion.Zero();
    User::LeaveIfError(mFile.Read(tempVersion,
      mCurrentChunk->length - mCurrentChunk->bytesRead));
    mCurrentChunk->bytesRead += tempVersion.Size();
    version = tempVersion[3] << 24 | tempVersion[2] << 16
      | tempVersion[1] << 8 | tempVersion[0] & 0xFFFFFFFF;
    if (version > 0x03)
     RDebug::Print(
       _L("This 3DS file is over version 3 so it may load incorrectly"));
    break;
   case OBJECTINFO:
    tempVersion.Zero();
    ReadChunk(mTempChunk);
    User::LeaveIfError(mFile.Read(tempVersion, mTempChunk->length
      - mTempChunk->bytesRead));
    mTempChunk->bytesRead += tempVersion.Size();
    version = tempVersion[3] << 24 | tempVersion[2] << 16
      | tempVersion[1] << 8 | tempVersion[0] & 0xFFFFFFFF;
    mCurrentChunk->bytesRead += mTempChunk->bytesRead;
    ReadNextChunk(aModel, mCurrentChunk);
    break;
   case MATERIAL:
    aModel->numOfMaterials++;
    aModel->pMaterials.Append(newTexture);
    ReadNextMatChunk(aModel, mCurrentChunk);
    break;
   case OBJECT:
    aModel->numOfObjects++;
    aModel->pObject.Append(newObject);
    mCurrentChunk->bytesRead += GetString(
      aModel->pObject[aModel->numOfObjects - 1]->strName);
    ReadNextObjChunk(aModel, aModel->pObject[aModel->numOfObjects
      - 1], mCurrentChunk);
    break;
   case EDITKEYFRAME:
    TInt temp = mCurrentChunk->length - mCurrentChunk->bytesRead;
    TPtr8 temp1 = buffer1->Des();
    User::LeaveIfError(mFile.Read(temp1, temp));
    mCurrentChunk->bytesRead += temp;
    break;
   default:
    TInt tmplength = mCurrentChunk->length
      - mCurrentChunk->bytesRead;
    TPtr8 temp2 = buffer1->Des();
    User::LeaveIfError(mFile.Read(temp2, tmplength));
    mCurrentChunk->bytesRead += tmplength;
    break;
   }
  aPreChunk->bytesRead += mCurrentChunk->bytesRead;
  }
 delete mCurrentChunk;
 mCurrentChunk = aPreChunk;
 delete buffer1;
 buffer1 = NULL;
 }
int CLoad3DS::GetString(TDes8& tBuf)
 {
 TInt index;
 TBuf8<255> buf;
 TBuf8<1> buf1;
 buf1.Append('/0');
 do
  {
  buf.Zero();
  mFile.Read(buf, 1);
  tBuf.Append(buf);
  }
 while (buf[0] != '/0');

 index = tBuf.Find(buf1) + 1;

 return index;
 }

void CLoad3DS::ReadNextObjChunk(t3DModel *aModel, t3DObject *aObject,
  tChunk *aPreChunk)
 {
 TInt i = 0;
 HBufC8* buf = HBufC8::NewL(102400);
 TPtr8 ptr = buf->Des();

 mCurrentChunk = new tChunk;
 while (aPreChunk->bytesRead < aPreChunk->length)
  {
  ReadChunk(mCurrentChunk);
  switch (mCurrentChunk->ID)
   {
   case OBJ_MESH:
    ReadNextObjChunk(aModel, aObject, mCurrentChunk);
    break;
   case OBJ_VERTICES:
    ReadVertices(aObject, mCurrentChunk);
    break;
   case OBJ_FACES:
    ReadVertexIndices(aObject, mCurrentChunk);
    break;
   case OBJ_MATERIAL:
    ReadObjMat(aModel, aObject, mCurrentChunk);
    break;
   case OBJ_UV:
    ReadUVCoordinates(aObject, mCurrentChunk);
    break;
   default:    
    User::LeaveIfError(mFile.Read(ptr, mCurrentChunk->length
      - mCurrentChunk->bytesRead));
    mCurrentChunk->bytesRead += mCurrentChunk->length - mCurrentChunk->bytesRead;
    ptr.Zero();
    break;
   }
  aPreChunk->bytesRead += mCurrentChunk->bytesRead;
  }
 delete mCurrentChunk;
 mCurrentChunk = aPreChunk;
 delete buf;
 buf = NULL;
 }

void CLoad3DS::ReadNextMatChunk(t3DModel *aModel, tChunk *aPreChunk)
 {
 TInt i = 0;
 HBufC8* buf = HBufC8::NewL(12000);
 TPtr8 ptr = buf->Des();

 mCurrentChunk = new tChunk;
 while (aPreChunk->bytesRead < aPreChunk->length)
  {
  ReadChunk(mCurrentChunk);
  switch (mCurrentChunk->ID)
   {
   case MATNAME: //如果是材质名称 
    User::LeaveIfError(
      mFile.Read(aModel->pMaterials[aModel->numOfMaterials
        - 1]->strName, mCurrentChunk->length
        - mCurrentChunk->bytesRead)); //读入材质名称
    mCurrentChunk->bytesRead
      += aModel->pMaterials[aModel->numOfMaterials - 1]->strName.Size();
    break;
   case MATDIFFUSE: //对象的RGB颜色
    ReadColor(aModel->pMaterials[aModel->numOfMaterials - 1],
      mCurrentChunk);
    break;
   case MATMAP: //纹理信息的头部
    ReadNextMatChunk(aModel, mCurrentChunk); //进入下一个材质块信息
    break;
   case MATMAPFILE: // 读入材质的文件名称       
    User::LeaveIfError(
      mFile.Read(aModel->pMaterials[aModel->numOfMaterials
        - 1]->strFile, mCurrentChunk->length
        - mCurrentChunk->bytesRead));
    mCurrentChunk->bytesRead
      += aModel->pMaterials[aModel->numOfMaterials - 1]->strFile.Size();
    break;
   default:
    User::LeaveIfError(mFile.Read(ptr, mCurrentChunk->length - mCurrentChunk->bytesRead)); // 掠过不需要读入的块
    mCurrentChunk->bytesRead += mCurrentChunk->length - mCurrentChunk->bytesRead;
    break;
   }
  aPreChunk->bytesRead += mCurrentChunk->bytesRead;
  }
 delete mCurrentChunk;
 mCurrentChunk = aPreChunk; // 删除当前块,并将当前块设置为前面的块
 delete buf;
 buf = NULL;
 }

void CLoad3DS::ReadColor(tMatInfo *aMaterial, tChunk *aChunk) //读入RGB颜色
 {
 ReadChunk(mTempChunk);
 User::LeaveIfError(mFile.Read(aMaterial->color, mTempChunk->length
   - mTempChunk->bytesRead));
 mTempChunk->bytesRead += aMaterial->color.Size();
 aChunk->bytesRead += mTempChunk->bytesRead;
 }

void CLoad3DS::ReadVertexIndices(t3DObject *aObject, tChunk *aPreChunk) //读入顶点索引
 {
 TUint16 index = 0; // 用于读入当前面的索引
 TBuf8<255> bufIndex;
 TBuf8<10> num;
 User::LeaveIfError(mFile.Read(num, 2)); // 读入该对象中面的数目
 
 aPreChunk->bytesRead += num.Size();
 
 aObject->numOfFaces = ((num[1] & 0xFFFFFF) << 8) | num[0]& 0xFFFFFFFF;

 aObject->pFaces = new tFace[aObject->numOfFaces];
 memset(aObject->pFaces, 0, sizeof(tFace) * aObject->numOfFaces); // 分配所有面的存储空间,并初始化结构
 for (TInt i = 0; i < aObject->numOfFaces; i++)
  {
  for (TInt j = 0; j < 4; j++) // 遍历对象中所有的面
   {
   User::LeaveIfError(mFile.Read(bufIndex, sizeof(index))); // 读入当前面的第一个点
   aPreChunk->bytesRead += bufIndex.Size();
//   index = ((bufIndex[3] & 0xFFFFFFFF) << 24)
//   | ((bufIndex[2] & 0xFFFFFFFF) << 16) | ((bufIndex[1]
//   & 0xFFFFFFFF) << 8) | (bufIndex[0] & 0xFFFFFFFF);
   index = bufIndex[1]&0xFFFF<<8|bufIndex[0]&0xFFFF;

   if (j < 3)
    {
    aObject->pFaces[i].vertIndex[j] = index;
    }
   }
  }
 }

void CLoad3DS::ReadUVCoordinates(t3DObject *aObject, tChunk *aPreChunk) // 读对象的纹理坐标
 {
 TBuf8<10> texNum;
 TBuf8<255> texVert;
 HBufC8* buf = HBufC8::NewL(30000);
 TPtr8 ptr = buf->Des();
 TInt preValue;
 TInt tempNum;
 TInt structNum;
 User::LeaveIfError(mFile.Read(texNum, 2)); //读UV坐标的数量
 aPreChunk->bytesRead += texNum.Size();
 aObject->numOfTexVertex = ((texNum[1] & 0xFFFFFF) << 8) | texNum[0]& 0xFFFFFFFF;

 aObject->pTexVerts = new CVector2[aObject->numOfTexVertex]; //分配保存UV坐标的空间
 User::LeaveIfError(mFile.Read(ptr, aPreChunk->length
   - aPreChunk->bytesRead));                   //读入纹理坐标
 
 preValue = aPreChunk->length - aPreChunk->bytesRead - 1;
 tempNum = (aPreChunk->length - aPreChunk->bytesRead) / 4;             //记录有多少个值
 structNum = tempNum / 3;                                 //记录有多少组顶点
 for (TInt i = 1; i < structNum; i++)   //对顶点赋值
  {
  aObject->pTexVerts[i].y = ((ptr[preValue--] & 0xFFFFFFFF) << 24)
  | ((ptr[preValue--] & 0xFFFFFFFF) << 16) | ((ptr[preValue--]
  & 0xFFFFFFFF) << 8) | (ptr[preValue--] & 0xFFFFFFFF);
  
  aObject->pTexVerts[i].x = ((ptr[preValue--] & 0xFFFFFFFF) << 24)
  | ((ptr[preValue--] & 0xFFFFFFFF) << 16) | ((ptr[preValue--]
  & 0xFFFFFFFF) << 8) | (ptr[preValue--] & 0xFFFFFFFF);
  }
 aPreChunk->bytesRead += ptr.Size();
 delete buf;
 buf = NULL;
 }

void CLoad3DS::ReadVertices(t3DObject *aObject, tChunk *aPreChunk) //读对象的顶点
 {
 TBuf8<10> vertNum;
 HBufC8 *vert = HBufC8::NewL(30000);
 TPtr8 ptr = vert->Des();
 TInt structNum;
 TInt preValue = 0;
 TInt tempNum;
 User::LeaveIfError(mFile.Read(vertNum, 2)); //读入顶点的数目
 aPreChunk->bytesRead += vertNum.Size();
 aObject->numOfVerts = ((vertNum[1] & 0xFFFFFF) << 8) | vertNum[0]
   & 0xFFFFFFFF;
 aObject->pVerts = new (ELeave) CVector3[aObject->numOfVerts];
 memset(aObject->pVerts, 0, sizeof(CVector3) * aObject->numOfVerts); //为存储顶点分配空间并初始化
 User::LeaveIfError(
   mFile.Read(ptr, aPreChunk->length - aPreChunk->bytesRead));
 tempNum = (aPreChunk->length - aPreChunk->bytesRead) / 4; //记录有多少个值
 TInt temp = aPreChunk->length - aPreChunk->bytesRead - 1;
 structNum = tempNum / 3; //记录有多少组顶点
 aPreChunk->bytesRead += ptr.Size();
 
 for (TInt i = 0; i < structNum; i++) //对顶点赋值
  {
  aObject->pVerts[i].z = ((ptr[temp--] & 0xFFFFFFFF) << 24)
    | ((ptr[temp--] & 0xFFFFFFFF) << 16) | ((ptr[temp--]
    & 0xFFFFFFFF) << 8) | (ptr[temp--] & 0xFFFFFFFF);

  aObject->pVerts[i].y = ((ptr[temp--] & 0xFFFFFFFF) << 24)
    | ((ptr[temp--] & 0xFFFFFFFF) << 16) | ((ptr[temp--]
    & 0xFFFFFFFF) << 8) | (ptr[temp--] & 0xFFFFFFFF);
  aObject->pVerts[i].x = ((ptr[temp--] & 0xFFFFFFFF) << 24)
    | ((ptr[temp--] & 0xFFFFFFFF) << 16) | ((ptr[temp--]
    & 0xFFFFFFFF) << 8) | (ptr[temp--] & 0xFFFFFFFF);

  }

 for (TInt i = 0; i < aObject->numOfVerts; i++) //将y轴和z轴交换并对z轴反向
  {
  TReal fTempY = aObject->pVerts[i].z;
  aObject->pVerts[i].y = aObject->pVerts[i].z;
  aObject->pVerts[i].z = -fTempY;
  }
 delete vert;
 vert = NULL;
 }

void CLoad3DS::ReadObjMat(t3DModel *aModel, t3DObject *aObject,
  tChunk *aPreChunk) //读入对象的材质名称
 {
 TBuf8<255> strMaterial; //保存对象的材质名称
 HBufC8* buf = HBufC8::NewL(12000);
 TPtr8 ptr = buf->Des();        //读入不需要的错误
 
 aPreChunk->bytesRead += GetString(strMaterial); // 材质或者是颜色,或者是对象的纹理,也可能保存了象明亮度、发光度等信息。
 // 下面读入赋予当前对象的材质名称
 for (TInt i = 0; i < aModel->numOfMaterials; i++)
  {
  if (strMaterial==(aModel->pMaterials[i]->strName)) //如果读入的纹理与当前的纹理名称匹配
   {
   aObject->materialId = i;
   if (aModel->pMaterials[i]->strFile.Length() > 0) // 判断是否是纹理映射,如果strFile是一个长度大于1的字符串,则是纹理
    {
    aObject->bHasTexture = ETrue;
    }
   break;
   }
  else
   {
   aObject->materialId = -1; //如果该对象没有材质,则设置materialId为-1
   }
  }
 User::LeaveIfError(
   mFile.Read(ptr, aPreChunk->length - aPreChunk->bytesRead));
 aPreChunk->bytesRead += aPreChunk->length - aPreChunk->bytesRead;
 delete buf;
 buf = NULL;
 }

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, TReal 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 *aModel) //计算对象的法向量
 {
 CVector3 vVector1, vVector2, vNormal, vPloy[3];
 if (aModel->numOfObjects <= 0) //模型中没有对象就返回
  return;
 for (TInt index = 0; index < aModel->numOfObjects; index++)
  {
  t3DObject *pObject = aModel->pObject[index]; //获得当前的对象
  CVector3 *pNormals = new CVector3[pObject->numOfFaces]; //分配存储空间      
  CVector3 *pTempNormals = new CVector3[pObject->numOfFaces];
  pObject->pNormals = new CVector3[pObject->numOfVerts];
  for (TInt i = 0; i < pObject->numOfFaces; i++)
   {
   vPloy[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]];
   vPloy[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]];
   vPloy[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]];

   vVector1 = Vector(vPloy[0], vPloy[2]); //获得多边形的矢量
   vVector2 = Vector(vPloy[2], vPloy[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;
  TInt shared = 0;
  for (TInt i = 0; i < pObject->numOfVerts; i++)
   {
   for (TInt 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, TReal(-shared));
   pObject->pNormals[i] = Normalize(pObject->pNormals[i]);
   vSum = vZero;
   shared = 0;
   }
  delete pTempNormals;
  delete pNormals;
  }
 }

 

抱歉!评论已关闭.