【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2346|回复: 0

[转帖]经典d3d mesh文件读取(帖子集)

[复制链接]
发表于 2005-8-6 00:20:02 | 显示全部楼层 |阅读模式
Posted by 俱真法师 on 2005-04-21 08:25 上午

本人是一名从事光学设计的老工程师,美术基础较差,但由于与工作中的三维设计的关系,忽然对游戏三维动画产生了兴趣,主要是做人,一年来的业余时间全投在Direct3D程序的代码编写中,深感做人难,做活人更难。今附上截图,虽然做的人丑,但完全是基于源代码所作,请各位大师主持指点。

Posted by AntSam on 2005-04-21 08:25 上午 "但完全是基于源代码所作" 是什么意思? 不是建模建好,然后用3ds max显示? Posted by KenChen on 2005-04-21 08:25 上午 楼主是不是指skeletalmesh 的render和shadow是d3d代码。 Posted by 俱真法师 on 2005-04-21 08:25 上午 我只接触过如SolidWorks等三维工业软件,既不会3ds max,也不会Maya,但直接以基于OpenGL或Direct3D的源代码开发来进行三维设计,可以随心所欲地创造自己想要的东西,虽然画面没有以上软件提供的现成模型那么精美。以上人物是通过多个网面(创建一个CMesh类)编辑而成,每个网面都象织毛衣一样,构筑一个个的三角形,调整各顶点的空间坐标和纹理坐标,每个关节由一个矩阵来控制,每个动作由控制所有关节的一套矩阵组成,将系列动作的多套矩阵保存后就可以重复地使用这套动作了,工作量虽然大了点,但比视频捕捉设备的成本低多了。要知道每秒至少要20帧的动作才能连续啊,还要保证不能过多地占用显卡、CPU和内存资源,所有这些都是通过VC程序来实现的。 Posted by Pointer on 2005-04-21 08:25 上午 [QUOTE=俱真法师]我只接触过如SolidWorks等三维工业软件,既不会3ds max,也不会Maya,但直接以基于OpenGL或Direct3D的源代码开发来进行三维设计,可以随心所欲地创造自己想要的东西,虽然画面没有以上软件提供的现成模型那么精美。以上人物是通过多个网面(创建一个CMesh类)编辑而成,每个网面都象织毛衣一样,构筑一个个的三角形,调整各顶点的空间坐标和纹理坐标,每个关节由一个矩阵来控制,每个动作由控制所有关节的一套矩阵组成,将系列动作的多套矩阵保存后就可以重复地使用这套动作了,工作量虽然大了点,但比视频捕捉设备的成本低多了。要知道每秒至少要20帧的动作才能连续啊,还要保证不能过多地占用显卡、CPU和内存资源,所有这些都是通过VC程序来实现的。[/QUOTE] 就是骨骼动画吧. ;) Posted by 千里马肝 on 2005-04-21 08:25 上午 [QUOTE=zhengtanggu265]俱真法师你好啊! 看到你的文章太高兴了,好久没能看到像这样令人兴奋的文章了,你做的人物模型很好,很有水准啊,我认为.在美术方面你是太自谦了. 如果不介意的话我想问几个问题不知你能不能回答我啊? 1.你说你的模型并不是在MAX或MAYA上做的,那是怎么做的呢?是在你说的那个工业3D软件上做出来的吗?我想这应当是可能的吧.如果如你所说是采用纯手工方式制作的话,对不起,这听起来似乎不大令人可信,你说呢? 2.关于模型数据的格式问题:我想询问一下,你采用哪一个三地体系来完成渲染的呢?是D3D呢?还是OPEN GL呢?如果你果真采用纯手工方式构造了那个"东北"美女且又将那些数据(我想这其中可能还包括了动画数据吧)写进数组(就OPEN GL言)或.X文件(就D3D言)的话,那我就不得不说:你肯定是天底下最能忍饥挨饿吃苦耐劳的人.我建议你应当去申请这方面的吉泥斯世界之最记录啊.你说呢,俱真大法师. 3.从你的图中我看到模型的关节处处理的很是光滑啊,但在你的叙述中并没有提及这一点,能否解释一下呢?对于这样一个重要技术你可能发明了更了不起的高招,请说明一下可以吗? 4. 对于你的源码本人是相当之感兴趣的,不知是不是能公开出来呢?或者略示一二出来呢? 另外,如果可以的话可与我联系,我手中有大量的实用代码和几种保密技术想与有识者交流,下面是我的E-MAIL ADDREE: e-mail: zhengtanggu265_c@sina.com[/QUOTE] 。。。。。。。。。。。。。。。。 Posted by AntSam on 2005-04-21 08:25 上午 [QUOTE=zhengtanggu265]俱真法师你好啊! 看到你的文章太高兴了,好久没能看到像这样令人兴奋的文章了,你做的人物模型很好,很有水准啊,我认为.在美术方面你是太自谦了. 如果不介意的话我想问几个问题不知你能不能回答我啊? 1.你说你的模型并不是在MAX或MAYA上做的,那是怎么做的呢?是在你说的那个工业3D软件上做出来的吗?我想这应当是可能的吧.如果如你所说是采用纯手工方式制作的话,对不起,这听起来似乎不大令人可信,你说呢? 2.关于模型数据的格式问题:我想询问一下,你采用哪一个三地体系来完成渲染的呢?是D3D呢?还是OPEN GL呢?如果你果真采用纯手工方式构造了那个"东北"美女且又将那些数据(我想这其中可能还包括了动画数据吧)写进数组(就OPEN GL言)或.X文件(就D3D言)的话,那我就不得不说:你肯定是天底下最能忍饥挨饿吃苦耐劳的人.我建议你应当去申请这方面的吉泥斯世界之最记录啊.你说呢,俱真大法师. 3.从你的图中我看到模型的关节处处理的很是光滑啊,但在你的叙述中并没有提及这一点,能否解释一下呢?对于这样一个重要技术你可能发明了更了不起的高招,请说明一下可以吗? 4. 对于你的源码本人是相当之感兴趣的,不知是不是能公开出来呢?或者略示一二出来呢? 另外,如果可以的话可与我联系,我手中有大量的实用代码和几种保密技术想与有识者交流,下面是我的E-MAIL ADDREE: e-mail: zhengtanggu265_c@sina.com[/QUOTE] ?????????????? :eek: Posted by 俱真法师 on 2005-04-21 08:25 上午 这一年来真的是没有八小时,没有周末过来的。但不知是我走火入魔,还是不懂真经,我在光学软件和工程计算上做得出神入化,怎么一个小小的人物一年了还只能做成这个模样呢?本来想作做的更完美来让各位大师检验的,然而这个工作量太大了,最近半年恐怕难以抽出大量时间继续做,只好匆匆献丑。 以上人物是用D3D做的,主要用了其中ID3DXMesh。但要对它的三角形构成、顶点位置和纹理坐标(法线可以通过计算得出)进行编辑,需要编写大量的代码,例如: // 选择多个顶点并沿法线或X, Y, Z轴改变顶点的坐标 void CMesh::SetPickedVertices(BYTE axis, float delta) { int i, iIndex, jIndex; MeshBackup(); // 备份现在的Mesh数据 for (i = 0; i < m_nVertices; i ++) { if (m_pPickedIndices[0] >= 0) // m_pPickedIndices对应D3DXMESH的顶点 { iIndex = m_pPickedIndices[0]; jIndex = m_pPickedIndices[1]; if (axis == 0) // 沿法线 m_pPos[iIndex*m_n+ jIndex] += delta*m_pNormals[iIndex*m_n+ jIndex]; else if (axis == 1) // 沿X轴 m_pPos[iIndex*m_n+ jIndex].x += delta; else if (axis == 2) m_pPos[iIndex*m_n+ jIndex].y += delta; else if (axis == 3) m_pPos[iIndex*m_n+ jIndex].z += delta; } else break; } CalculateNormals(); } 裁缝师不会去种棉花然后再纺线织布。我首先通过代码构建一个方阵Mesh, 再把要成型的不同方位的轮廓画出来保存,读取图形后插值计算各顶点的位置(当然也得编写代码),细节部分,如嘴鼻眼耳凸凹的部分就需要手工雕塑了。最后再象裁缝师一样,把冗余的顶点去掉并在空缺处补上三角形。 复杂的物体可由多个Mesh组成,但人体是活动的,运动时要保证关节处两个Mesh之间不能有裂缝或看到边界,这就要使关节处的两个Mesh的接口顶点数目相同,位置重合,法线相等,其中主要用了D3DXVec3TransformCoordArray,D3DXVec3TransformNormalArray和D3DXMatrixInverse函数,然后只要改变世界矩阵画肢体就行了,不需要对身体各部位所有顶点操作。 不知为何我们的服务器不能上传了,如果各位有兴趣,今后我整理一下再贴出。 虽然有计算D3DXMESH法线的函数,我似乎对自己的方法觉得更好用、更放心一些(如果您对ID3DXMESH比较了解,自然会看出各成员变量的意义): void CMesh::SetNormals() { D3DXVECTOR3* pFaceNormals = new D3DXVECTOR3[m_nFaces], edge[3]; float edgeLength[3], p; DWORD k; int i, n; for (k = 0; k < m_nFaces; k ++) { edge[0] = m_pD3DVtx[m_pTriIdx[3*k+1]].xyz - m_pD3DVtx[m_pTriIdx[3*k]].xyz; edge[1] = m_pD3DVtx[m_pTriIdx[3*k+2]].xyz - m_pD3DVtx[m_pTriIdx[3*k+1]].xyz; edge[2] = m_pD3DVtx[m_pTriIdx[3*k]].xyz - m_pD3DVtx[m_pTriIdx[3*k+2]].xyz; D3DXVec3Cross(pFaceNormals + k, edge, edge+1); D3DXVec3Normalize(pFaceNormals + k, pFaceNormals + k); p = 0.0f; for (i = 0; i < 3; i ++) { edgeLength = D3DXVec3Length(edge + i); p += edgeLength/2; } // 乘以面积因子 pFaceNormals[k] *= sqrtf(p * (p-edgeLength[0]) * (p-edgeLength[1]) * (p-edgeLength[2])); } for (n = 0; n < m_nVertices; n ++) m_pD3DVtx[n].normal = D3DXVECTOR3(0.0f, 0.0f, 0.0f); for (k = 0; k < m_nFaces; k ++) for (i = 0; i < 3; i ++) m_pD3DVtx[m_pTriIdx[3*k + i]].normal += pFaceNormals[k]; for (n = 0; n < m_nVertices; n ++) D3DXVec3Normalize(&m_pD3DVtx[n].normal, &m_pD3DVtx[n].normal); delete pFaceNormals; } 让各位见笑了。 Posted by 俱真法师 on 2005-04-21 08:25 上午 我知道典型的人物制作中采用了skin mesh和骨骼技术,但确实没有见到这方面的详细介绍,包括在D3D的辅导材料中,无法让读者从头到尾学会这项技术,但只要不是底层的东西,都可以用不同的方法实现。我只好土法上马。不知各位可以在这方面可否指教一二。在身体与头部的接口中设置了12个顶点,以下是脖子光滑的代码,其中m_pM[0], m_pM[1]分别是指向身体和头部的指针,m_pK0是对接口处顶点的索引 void CHuman::HeadLink(D3DXMATRIXA16 *pMtrx) // 头部与身体的连接, pMtrx是头部运动的矩阵 { int i; D3DXVECTOR3 jtVtx[12], jtNormals[12]; D3DXVec3TransformCoordArray(jtVtx, 12, m_jtVtx0, 12, pMtrx, 12); D3DXVec3TransformNormalArray(jtNormals, 12, m_jtNormals0, 12, pMtrx, 12); for (i = 0; i < 12; i ++) { // 接口处的顶点重合 jtVtx = m_pM[0]->m_pD3DVtx[m_pK0[0]].xyz = (m_pM[0]->m_pD3DVtx0[m_pK0[0]].xyz + jtVtx) / 2; // 接口处的法线相等 jtNormals = m_pM[0]->m_pD3DVtx[m_pK0[0]].normal = (m_pM[0]->m_pD3DVtx0[m_pK0[0]].normal + jtNormals) / 2; } D3DXMatrixInverse(&invM, NULL, pMtrx); D3DXVec3TransformCoordArray(jtVtx, 12, jtVtx, 12, &invM, 12); D3DXVec3TransformNormalArray(jtNormals, 12, jtNormals, 12, &invM, 12); for (i = 0; i < 12; i ++) { m_pM[1]->m_pD3DVtx[m_pKa0[0]].xyz = jtVtx; m_pM[1]->m_pD3DVtx[m_pKa0[0]].normal = jtNormals; } } 面部纹理的原型是从网上下载的一个西方人的脸改造而成,注意眼球和牙齿与头部并非一个Mesh,这样它们才能相对运动。所以一时兴起就画了个黑眼珠,颜色是很容易改的,不管白人黑人,会动就是活人。至于头发的纹理,从下载的画面中剪下一小块,通过photoshop给它长出来就行了,想要什么颜色还不容易吗?但头发丝的间隙是在纹理中加入了alpha通道并采用了alpha test来实现的,要想让它随风飘动,动态改变头发Mesh的顶点和纹理坐标就行了。不知为何我不能上传,只能在这瞎白惑了。

Posted by 俱真法师 on 2005-04-21 08:25 上午 以上代码完全可以把两个Mesh吻合得天衣无缝,不信可以自己试试。在运行以上的人物动画中,我的C400DELL笔记本(1.2G)的CPU占用比只有3~4%左右(25帧/秒),说明用这种人物制作方法和动画在系统资源的消耗上还是比较便宜的,至少比D3D辅导例程中的人物动画便宜。 最后我再把我认为很有用的一段代码贴出,人物在崎岖的山坡上跑动时需要顺着地形而改变身体位置,在动画文件制作过程中,为了保证一个动作组合的重复可用,肯定不能把人随地形的高低的位置变化固定死,否则你的人只能沿固定的路线运动,或要求地形必须是水平的。那么在任何一个位置都要保证人在地面上走动,而不变成飞人或穿山甲,可以如下实现: void CHuman::FeetOnLand(ANIMATION *pAni, CMesh *pGround) // ANIMATION是自定义一个动作的结构,包含矩阵组和一些辅助参数 { BOOL isCollide; float h[2], hmin; int i; D3DXVECTOR3 ray, vct, vctm; for (i = 4; i <= 5; i ++) // 4,5代表左右脚 { ray = D3DXVECTOR3(0.0f, -1.0f, 0.0f); // m_pM->m_Matrices[2]为脚的运动矩阵,对脚尖和脚跟顶点操作 D3DXVec3TransformCoord(&vct, &m_pM->m_pD3DVtx[m_toeIndex].xyz, m_pM->m_Matrices+2); D3DXVec3TransformCoord(&vctm, &m_pM->m_pD3DVtx[m_heelIndex].xyz, m_pM->m_Matrices+2); vct = (vctm.y < vct.y) ? vctm : vct; D3DXIntersect(pGround->m_pD3DMesh, &vct, &ray, &isCollide, NULL, NULL, NULL, h+i-4, NULL, NULL); if (!isCollide) // 如果不在地面以上 { ray.y = 1.0f; D3DXIntersect(pGround->m_pD3DMesh, &vct, &ray, &isCollide, NULL, NULL, NULL, h+i-4, NULL, NULL); } h[i-4] *= -ray.y; } hmin = min(h[0], h[1]); // 得出校正身体位置到地面的矩阵m_Mat[1], jumpAt为ANIMATION中定义的跳跃高度,如果为0则在地面上行走。 D3DXMatrixTranslation(m_Mat+1, 0.0f, pAni->jumpAt - hmin, 0.0f); } 无论是车辆还是其它动物,在不是水平的地面上运动时都可以用近似的方法进行与地面的碰撞检测。 以上都是我面壁300多天悟出的一部分内容,缺乏交流,所以在此贴出。由于要到地球另一边去谋生,迫于生计,最近再无暇面壁了,只好匆匆地跟各位施主说声再见。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2024-5-19 00:10

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表