新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 C/C++编程思想 』 → 网格模型高级技术(4) 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 16473 个阅读者浏览上一篇主题  刷新本主题   平板显示贴子 浏览下一篇主题
     * 贴子主题: 网格模型高级技术(4) 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 网格模型高级技术(4)

    索引顶点混合

    Direct3D通过索引顶点混合,扩展了使用多个混合矩阵对顶点进行混合的支持。在索引顶点混合中,混合矩阵被保存在矩阵调色板(可以看成一个矩阵数组)中,使用矩阵索引来引用特定的混合矩阵。矩阵索引使用8位无符号整数表示,由每个顶点提供,因为Direct3D中限定每个顶点最多受到4个混合矩阵的影响,所以每个顶点最多具有4个矩阵索引,每个顶点的矩阵索引被组合成一个DWORD类型的整数存储和表示。因为每个顶点最多受4个混合矩阵的影响,所以在渲染一个三角形时最多可能需要使用12个混合矩阵,在这种情况下,矩阵调色板中最少需要包含12个混合矩阵。

    下图演示了一个顶点使用矩阵索引引用4个混合矩阵,图中的顶点通过矩阵索引引用矩阵调色板中索引为0、2、5、6的混合矩阵:

    按此在新窗口浏览图片

    下图演示了渲染一个三角形时,如何通过矩阵索引引用矩阵调色板中的12个混合矩阵:

    按此在新窗口浏览图片

    在渲染图形时,要想启用索引顶点混合,需要将渲染状态D3DRS_INDEXEDVERTEXBLENDENABLE设置为TRUE,如果启用了索引顶点混合,则在顶点数据中就需要包含矩阵索引数据。如果将渲染状态D3DRS_INDEXEDVERTEXBLENDENABLE设置为FALSE则禁用索引顶点混合,但是又启用了图形混合功能,这时在顶点数据中就不需要包含矩阵索引数据,每个顶点的矩阵索引默认为0~3。

    D3DRS_INDEXEDVERTEXBLENDENABLE
    bool value that enables or disables indexed vertex blending. The default value is FALSE. When set to TRUE, indexed vertex blending is enabled. When set to FALSE, indexed vertex blending is disabled. If this render state is enabled, the user must pass matrix indices as a packed DWORDwith every vertex. When the render state is disabled and vertex blending is enabled through the D3DRS_VERTEXBLEND state, it is equivalent to having matrix indices 0, 1, 2, 3 in every vertex.
    D3DCAPS结构体的成员变量MaxVertexBlendMatrixIndex表示当前设备对索引顶点混合的支持,如果MaxVertexBlendMatrixIndex的值为0,表示当前硬件设备不支持索引顶点混合。如果MaxVertexBlendMatrixIndex的值不为0,表示混合矩阵的最大索引为MaxVertexBlendMatrixIndex,也就是当前硬件设备支持的矩阵调色板最大容量为MaxVertexBlendMatrixIndex+1,表示矩阵调色板最大可以容纳MaxVertexBlendMatrixIndex+1个混合矩阵。如果顶点中包含法线信息,则也需要对法线数据进行混合,这时矩阵调色板中矩阵的最大数量为(MaxVertexBlendMatrixIndex+1)/ 2。如果使用软件顶点处理模式,则矩阵调色板的最大容量为256,不管是否需要对法线向量进行混合。

    MaxVertexBlendMatrixIndex
    DWORD value that specifies the maximum matrix index that can be indexed into using the per-vertex indices. The number of matrices is MaxVertexBlendMatrixIndex + 1, which is the size of the matrix palette. If normals are present in the vertex data that needs to be blended for lighting, then the number of matrices is half the number specified by this capability flag. If MaxVertexBlendMatrixIndex is set to zero, the driver does not support indexed vertex blending. If this value is not zero then the valid range of indices is zero through MaxVertexBlendMatrixIndex.
    A zero value for MaxVertexBlendMatrixIndex indicates that the driver does not support indexed matrices.

    When software vertex processing is used, 256 matrices could be used for indexed vertex blending, with or without normal blending.

    For a given physical device, this capability may vary across Direct3D devices depending on the parameters supplied to IDirect3D9::CreateDevice.

    综合上面图形混合和索引顶点混合的内容,对顶点混合可以总结如下:

    (1)不管是否使用索引顶点混合,混合矩阵都是通过索引从矩阵调色板中引用。

    (2)如果不使用索引顶点混合,则混合矩阵索引最大为3,而且在顶点数据中不需要包含矩阵索引,矩阵索引默认为0~3。

    (3)如果使用索引顶点混合,矩阵索引最大为255,而且在顶点数据中需要指定影响该顶点混合矩阵的索引。

    (4)使用图形混合之前,首先需要检查当前设备支持的调色板容量是否满足要求,因为使用软件顶点处理模式时,最大混合矩阵索引为255,肯定能满足要求,所以如果硬件顶点处理模式下矩阵调色板容量不能满足要求,只需简单转换为使用软件顶点处理模式即可。

    蒙皮骨骼动画跟单纯的骨骼动画相比,只是使用了顶点混合技术,解决单纯的骨骼动画存在的问题。

    首先我们需要定义包含顶点混合权重和法线向量的结构体,还需要定义两个混合矩阵:

    struct sBlendVertex{ D3DXVECTOR3 pos; float  blend; D3DXVECTOR3 normal;};
    #define BLEND_VERTEX_FVF (D3DFVF_XYZB1 | D3DFVF_NORMAL)
    CDXUTMesh* g_dxut_mesh;D3DXMATRIX g_blend_matrix_1;D3DXMATRIX g_blend_matrix_2;
    因为顶点所有骨骼权重之和是1,所以如果1个顶点受到n块骨骼的影响,那么为顶点指定n-1个权重即可,最后一个权重可以通过1减去n-1个权重之和得到。这里每个顶点只受两个骨骼矩阵的影响,所以在上面的顶点结构中只需提供一个顶点权重即可。

    接着在回调函数ModifyDeviceSetttings()中用下列语句检查硬件是否支持索引顶点混合,如果当前硬件不支持索引顶点混合,则使用软件顶点处理模式:

    if(pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) pDeviceSettings->BehaviorFlags = D3DCREATE_MIXED_VERTEXPROCESSING;
    // if current device does not support vertex blending, use software device.if(pCaps->MaxVertexBlendMatrices < 1) pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    接下来在回调函数OnCreateDevice()中从.x文件中加载网格模型,因为该网格模型中并没有包含骨骼权重信息,所以首先调用CDXUTMesh:SetFVF()设置网格模型的顶点灵活格式,然后为该网格模型的每个顶点添加权重:

    g_dxut_mesh = new CDXUTMesh();V_RETURN(g_dxut_mesh->Create(pd3dDevice, L"mslogo.x"));
    // add vertex blending weight and normal informationg_dxut_mesh->SetFVF(pd3dDevice, BLEND_VERTEX_FVF);
    DWORD num_vertices = g_dxut_mesh->GetMesh()->GetNumVertices();
    IDirect3DVertexBuffer9* vertex_buffer;g_dxut_mesh->GetMesh()->GetVertexBuffer(&vertex_buffer);
    sBlendVertex* blend_vertices;vertex_buffer->Lock(0, 0, (void**)&blend_vertices, 0);
    // count min and max x coordinate of all vertices for calculating vertex blending weight
    float min_x =  1e10f;float max_x = -1e10f;
    for(DWORD i = 0; i < num_vertices; i++){ if(blend_vertices[i].pos.x < min_x)  min_x = blend_vertices[i].pos.x;
     if(blend_vertices[i].pos.x > max_x)  max_x = blend_vertices[i].pos.x;}
    // calculate for all vertices blending weightfor(DWORD i = 0; i < num_vertices; i++){ float scale = (blend_vertices[i].pos.x - min_x) / (max_x - min_x); blend_vertices[i].blend = 1.0f - sinf(scale * D3DX_PI);}
    vertex_buffer->Unlock();vertex_buffer->Release(); 
    接下来在回调函数中OnFrameMove()中实时构造并设置骨骼变换矩阵:

    float scale = (float) fTime;
    // calculate blend matrixD3DXVECTOR3 axis(2 + sinf(scale * 3.1f), 2 + sinf(scale * 3.3f), sinf(scale * 3.5f));D3DXMatrixIdentity(&g_blend_matrix_1);D3DXMatrixRotationAxis(&g_blend_matrix_2, &axis, sinf(3 * scale));
    // set vertex blend method and blend matrixpd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_1WEIGHTS);pd3dDevice->SetTransform(D3DTS_WORLDMATRIX(0), &g_blend_matrix_1);pd3dDevice->SetTransform(D3DTS_WORLDMATRIX(1), &g_blend_matrix_2);
    上面代码中的最后三行是相互对应的,缺一不可。首先将渲染状态D3DRS_VERTEXBLEND设置为D3DVBF_1WEIGHTS,渲染状态D3DRS_VERTEXBLEND用来指定进行顶点混合时所使用的矩阵的数目,这里将它设置为D3DVBF_1WEIGHTS,表示用宏D3DTS_WORLDMATRIX(index)设置两个骨骼矩阵进行顶点混合,而且这两个骨骼矩阵的索引号分别是0和1。

    因为要进行顶点混合,所以函数SetTransform()将要设置的不再是普通的世界坐标变换矩阵,而是骨骼变换矩阵,所以它的第一个参数应该采用宏D3DTS_WORLDMATRIX(index)的格式,而不像以前一样使用标识符D3DTS_WORLD。宏D3DTS_WORLDMATRIX(index)的定义如下:

    #define D3DTS_WORLDMATRIX(index) (D3DTRANSFORMSTATETYPE)(index + 256)

    该宏负责将索引号index映射到相应的变换状态下。

    在设置好各个骨骼矩阵之后,在回调函数OnFrameRender()中渲染网格模型:

    g_dxut_mesh->Render(pd3dDevice);

    运行截图:

    按此在新窗口浏览图片


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/1/5 13:42:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/7 2:58:38

    本主题贴数7,分页: [1]

     *树形目录 (最近20个回帖) 顶端 
    主题:  网格模型高级技术(4)(7681字) - 卷积内核,2009年1月5日
        回复:  主程序:#include "dxstdafx.h"#include "resource.h..(14856字) - 卷积内核,2009年1月5日
        回复:  一个网格模型中可以包含多个动画集,在渲染网格时通过动画控制器可以在各个动画集之间进行切换,从而可以..(3060字) - 卷积内核,2009年1月5日
        回复:  主程序:#include "dxstdafx.h"#include "resource.h..(13564字) - 卷积内核,2009年1月5日
        回复:  [B]cSkinMesh类的设计与实现[/B]cSkinMesh类的实现与cAnimMesh的..(7373字) - 卷积内核,2009年1月5日
        回复:  蒙皮骨骼动画网格模型接口是对上一节骨骼动画网格模型接口的扩展,添加了处理蒙皮信息的功能。 ..(8066字) - 卷积内核,2009年1月5日
        回复:  主程序:#include "dxstdafx.h"#include "resource.h..(16265字) - 卷积内核,2009年1月5日

    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    63.477ms