之前介绍过用SDK的常规方法来获取模型的网格信息。这里再介绍另外一种方法。
MaxSdk里面带了一个叫做IGame的包,里面包含有很多方便我们获取模型信息的方法。在sdk的自带例子里面,同样也有这个IGame的例子,不过我自己没有编译通过,存在一些错误。所以我自己看SDK的API,摸索出了使用的方法。

#include <IGame.h> 。

使用IGame之前需要先给他做一个初始化,以下是我的初始化的方法,直接在DoExport方法里面先调用就可以了:

void InitIGame(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options)
{
//保存路径
savePath = name;
//是否支持显示界面
showPrompts = suppressPrompts ? FALSE : TRUE;
//导出选中物体还是导出全部
exportSelected = (options & SCENE_EXPORT_SELECTED) ? true : false;
//获取IGame的版本,这个如果你用不到可以不要
igameVersion  = GetIGameVersion();
//IGameScene* pScene;这个东西就是代替了常规方法里面的场景树节点管理
pScene = GetIGameInterface();
//获取IGameConversionManager 是为了设置左右手坐标系,如果你不需要设置,可以不要。
//具体的SetUserCoordSystem数值可以去查maxSdk的api,有详细说明
IGameConversionManager * cm = GetConversionManager();
cm->SetUserCoordSystem(leftHandCoord);
//初始化场景
pScene->InitialiseIGame(exportSelected);
}这里和常规方法做一个对比,这个初始化的方法其实和常规方法差不多,不过方便的地方在于,我们可以直接的使用IGameScene类来管理场景,而不需要自己重新写一个树节点管理类,再自己写回调的方法了。然后可以设置左右手坐标系。常规方法如果你要转换坐标系,就要自己在导出的时间计算一下,调换一下坐标系的值了。最后,之前我们做是否导出选择的物体,需要自己在回调的方法里面判断exportSelected,但IGame却是在pScene->InitialiseIGame(exportSelected);这一步就已经把这件事完全的做好了。如果你是选择选中的物体导出,那么初始化的时候只会把选中的物体放进场景树节点里面,没有选择的东西是没有任何的信息的。这样做,好处是方便了操作,坏处是你想只导出选中的物体,又想遍历一些没有选中的物体做计算的时候,就不行了,但常规方法却可以。接下来再看看怎样获取物体节点的各种信息:void CollectObjects()
{
int num = pScene->GetTopLevelNodeCount();
IGameNode* pNode;
for(int i = 0; i < num; i++)
{pNode = pScene->GetTopLevelNode(i);if(pNode->IsTarget()){continue;}IGameObject* obj = pNode->GetIGameObject();char* oName = pNode->GetName();IGameObject::ObjectTypes type = obj->GetIGameType();switch (type){case IGameObject::IGAME_MESH:meshObjRoots.push_back(pNode);DebugLog(oName);DebugLog(" is a Mesh!!\n");break;case IGameObject::IGAME_BONE:boneObjRoots.push_back(pNode);DebugLog(oName);DebugLog(" is a Bone!!\n");break;default:break;}
}

}
以上的方法,就可以获取到场景里面的所有作为根节点的物体了。所谓的根节点,就是父物体为空(也就是父物体为场景Root)的物体,它有可能还有很多子物体,这里我们先不获取,然后我们下一步可以通过获取子物体的方法做递归,就可以获取全部的物体了。
在这里我们先来和常规方法对比一下:
常规方法我们要判断物体的类型,需要判断节点物体的ClassID(),而且ClassID()的类别繁多,骨骼还分为bone和biped需要分别作判断。而IGame却比较方便了,直接GetIGameType,然后就可以判断类型,而且不管是bone还是biped,它都是IGAME_BONE,比较方便。

获得了父物体之后,我们可以写一个方法来遍历他们的子物体,做一个递归,最后返回的数据就是当前父物体的所有子物体了,自己想办法存起来

vector<IGameNode*> getChildNode(IGameNode* pObj)
{
vector<IGameNode*> tempList;
tempList.push_back(pObj);
int childNum = pObj->GetChildCount();
if(childNum>0)
{for(int i = 0;i<childNum;i++){IGameNode* subNode = pObj->GetNodeChild(i);vector<IGameNode*> subVector = getChildNode(subNode);if(subVector.size()>0){for(int j = 0;j<subVector.size();j++){tempList.push_back(subVector[j]);}}}
}
return tempList;
}

获取到所有物体的节点之后,我们就可以来获取所有的网格信息了,在获取每一个节点的网格信息之前,有一个步骤是必须的:
IGameObject* iObj = node->GetIGameObject();
IGameMesh * iMesh = (IGameMesh*)iObj;
iMesh->InitializeData();//这个就是初始化数据
如果不先这样初始化一下IGameObject,那么你之后获取模型信息的时候,很可能会遇到顶点索引是空的,之类的问题。
获取顶点信息:

int vertSum = iMesh->GetNumberOfVerts();
for(i = 0;i<vertSum;i++)
{Vertex_t vInfo;Point3 pos = iMesh->GetVertex(i);//然后自己存起来
}

获取顶点索引的信息:

int faceSum = iMesh->GetNumberOfFaces();for(i = 0;i<faceSum;i++){FaceEx* face = iMesh->GetFace(i);vector<int> indexs;for(j = 0;j<3;j++){indexs.push_back(face->vert[j]);}//然后自己存起来}

获取UV信息:获取uv信息其实也是用上面的FaceEx方法的数据,不过由于3DsMax的贴图通道可能有很多个,我们习惯上就用第一个通道的,不过有些人会使用多套UV,可能会使用多个通道,所以我们先要获取一下所有的UV通道:

Tab<int> mapNums = iMesh->GetActiveMapChannelNum();

这样,这里面就存了可能用到的UV通道的序号。

int mapCount = mapNums.Count();
for(int i=0;i < mapCount;i++)
{for(j = 0;j<faceSum;j++){FaceEx* face = iMesh->GetFace(j);for(int k = 0;k<3;k++){int ind = face->vert[k];int induv = face->texCoord[k];Point3 tv;if(iMesh->GetMapVertex(mapNums[i],induv,tv)){if(ind<objList.vert.size()){//这里是注意重点,看下面解释objList.vert[ind].uv = tv;}}}}}

上面代码里面有一个非常重要的问题,很多人如果直接获取uv坐标,最终的模型很可能会出错的。我这里详细的说明一下。
之前用常规的SDK方法获取UV坐标,我们通过了一个TVFace来获取模型的实际uv点的坐标。这里我们使用了一个face->texCoord来获取UV坐标。其实他们的道理是一样的。
本来我们知道了顶点的总数,逐个去遍历他们的GetMapVertex,应该就可以获取到所有的顶点uv坐标,这是没错的。不过问题在于,顶点的位移坐标的排序,和uv坐标的排序是不一致的。有可能一个点在位移坐标时的排序index是10,但在uv坐标的排序index是20之类。所以如果你按照统一的一个顺序去遍历所有点再记录位移坐标和uv坐标,获取的数据是对的,但顺序很可能就错了,而导致之后你的模型的点和uv点对不上,导致了模型能显示出来,但uv贴图乱了。
这个uv坐标的排序index是怎样获得的呢?常规SDK是用TVFace和一般的Face相对应,然后获取Face对于的TVFace的顶点序号。而用IGame,它没有两种Face了,就只有一种FaceEx,里面的 face->vert是顶点位移的排序坐标,然后face->texCoord就是该位移顶点对应的uv坐标的排序了。

以上就是使用IGame获取模型网格信息的方法了。需要获取其他的数据,可以去查查api,里面都有说明。然后我们还是用C++提供的写文本方法,把数据保存起来就可以了。
接下来我将会再介绍一下骨骼动画的导出方法,

3DsMax导出插件编写(三)——使用IGame收集模型信息相关推荐

  1. 3DsMax导出插件编写(一)——vs2010和3dsmax2011(64位)的配置方法

    作为3D开发人员,特别是3D引擎开发人员,经常会接触到各种三维模型的数据.虽然说3dsmax已经可以导出很多格式的模型,不过总是不一定合适自己用.所以总有一种想自己写一个导出插件,让3dmax导出自己 ...

  2. 3D MAX导出插件编写

    文章版权归博客园 BigCoder所有,转载请于明显位置标明原文作者及出处,以示尊重!! 原文出处:http://www.cnblogs.com/csyisong/archive/2009/09/01 ...

  3. 3D MAX导出插件编写I

    3D MAX导出插件编写I 想想研究3D MAX 的SDK已经有了不短的时间,真正算起来也有两个月了吧,但是讲到收获,确实不大.作为一个3D MAX二次开发的学习者,我首先学习了导出插件的编写,网上有 ...

  4. 3ds max sdk导出插件编写的心得

    3ds max sdk导出插件编写的心得 作者:yhchinabest 来自:CG先生-3D图形插件开发网http://www.cgsir.com 写在前面 为什么要写这个心得?去年11月份的时候我写 ...

  5. VS2010插件编写学习总结

    VS2010 Addins 外接程序(插件)开发 http://www.cnblogs.com/Leo_wl/archive/2013/03/21/2973886.html 简单做了一个添加文件头注视 ...

  6. 3DMAX导出插件的编写

    原文链接: http://liweizhaolili.blog.163.com/blog/static/162307442013117731953/ 作为3D开发人员,特别是3D引擎开发人员,经常会接 ...

  7. 3dsmax导出html,3dsmax导出gltf格式插件

    [实例简介] 3dsmax导出gltf格式插件,里面包括插件,插件使用说明,插件功能介绍: [实例截图] [核心代码] 3dsmx_to_gltf格式插件 └── 3dsMax to gltf 2 ├ ...

  8. BurpSuite实战十六之BurpSuite插件编写

    Burp Suite的强大除了自身提供了丰富的可供测试人员使用的功能外,其提供的支持第三方拓展插件的功能也极大地方便使用者编写自己的自定义插件.从上一章节我们已经了解到, Burp Suite支持的插 ...

  9. 使用Python打造基本WEB漏洞扫描器(二) 爬虫插件系统的开发—E-Mail收集插件实列

    一.实验介绍 1.1 实验内容 基于上节的爬虫,在爬虫的基础上增加一个插件系统,通过爬虫爬取网页链接后调用这个插件系统中的插件进行各种操作,本节也会写个简单的email收集插件作为列子,后面也会讲到如 ...

最新文章

  1. 积极开展网络营销的AI换脸软件短短几日经历了从爆红到下架
  2. acdsee扫描没有图像_详解CT图像常见伪影成因及解决方法
  3. LWIP的数据包管理
  4. 免费好用的钉钉内网穿透
  5. mysql 身份证算年龄
  6. 微信公众号(头部GIF动图)制作方法
  7. 计算机桌面底部图标一直闪烁,win7系统桌面上的图标一直闪烁怎么办?图标一直闪烁的解决方法...
  8. 关于TikTok环境伪装度检测,whoer和上网大师app的对比
  9. Hadoop YARN架构设计要点
  10. 格拉姆--施密特(Gram-Schmidt)正交化方法笔记
  11. C++ Learning 3
  12. VMware虚拟机Host-Only(仅主机模式)
  13. 码农可能还不如俺村里人幸福...
  14. linux终端实现骇客帝国的字符雨动画
  15. Redis 从入门到弃坑
  16. 2022届应届生办理落户上海流程是怎样的?
  17. Modeling Personalized Item Frequency Information for Next-basket Recommendation SIGIR2020
  18. 蛋壳公寓信息/信息网爬取/小猪短租/豆瓣/拉钩/人民邮电报/百度电视剧/加载更多-获取字符串中间任意内容
  19. 无货源淘宝店怎么做运营?
  20. 周文洁 html5,清华大学出版社-图书详情-《JavaScript与jQuery网页前端开发与设计》...

热门文章

  1. 38款 流媒体服务器开源软件
  2. Linux 内核对浮点数的支持
  3. wagon-maven-plugin插件详解
  4. 郑州大学c语言考试系统,郑州大学c语言考试机真题.doc
  5. soc的核间通信机制-->mailbox
  6. 【专栏推荐】朱赟的技术管理课
  7. 全盘搜索器 能搜索整个磁盘所有目录
  8. 全盘镜像只还原c盘有影响么_系统全盘备份与还原
  9. C语言:有十个学生,每个学生的数据包括学号、姓名、3门课程的成绩,从键盘输入10个学生数据,要求输出3门课程的总平均成绩,以及最高分的学生的数据(包括学号、姓名、3门课程成绩、平均分数)
  10. 您的电脑遇到问题需要重启 我们只是收集(5步解决)