战魂小筑

讨论群:309800774 知乎关注:http://zhihu.com/people/sunicdavy 开源项目:https://github.com/davyxu

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  257 随笔 :: 0 文章 :: 506 评论 :: 0 Trackbacks

#

今天把原来写的max插件与新引擎整合下, MAXSDK又恶心了一次. 居然有core.lib这种第三方库导致与我的core.lib链接冲突, 真是霸道, 没办法, 只有我让步,我改名.

之后,发现每次即便每次完整编译完成,开始调试时,所有工程都会重复编译一次,Clean后,再编译,报了 一个vc90.pdb有关的C2859错误.

error C2859: x:\XXX\vc60.pdb is not the pdb file that was used when this precompiled header was created, recreate the precompiled header.
mschart.cpp

 

大概意思就是预编译头问题. 尝试着改名等,都不能完全解决, 干脆在Configuration Properties | C/C++  | Output Files里的Program Database File Name改为$(IntDir)\$(ProjectName).pdb, 也就是让 静态库pdb不是默认的vc90.pdb,而是跟随项目名称,瞬间, 问题解决,不会反复出现重编译问题.

写本文之前,Google了下其他人怎么解决这样的问题,结果居然看到有人说去掉预编译头. 这不是我做事的方法,为什么不动下脑筋解决这个问题呢?

posted @ 2010-05-21 17:17 战魂小筑 阅读(5928) | 评论 (0)编辑 收藏

CEGUI的字符串类设计的初衷是以32个字符为分界点, 低于32个字符使用固定buffer, 高于才使用栈分配内存存储字符串. 不过因为CEGUI使用utf32,兼容性虽然很好,但是在VC调试器里无法显示是个很大的问题.

这里参考了mybios博客中的文章,给CEGUI字符串做一个patch

然后需要找到vs2008的autoexp.dat文件

XP下位于:C:\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\autoexp.dat

用记事本等工具打开, 在AutoExpand段中像这样添加:

[AutoExpand]
; CEGUI String
CEGUI::String = str =<d_quickbuff,su> length =<d_cplength>

即可在VC调试器中看到CEGUI字符串内容, 不过中文还是暂时无法支持

posted @ 2010-05-14 12:01 战魂小筑 阅读(1833) | 评论 (0)编辑 收藏

要在游戏中用到强大而有扩展性的骨骼动画,有很多注意点.

首先,我们得弃用CPU蒙皮, 虽然兼容性好,但是面对现今多核但并不提高单核速率的情况下,GPU还是王道.而且GPU蒙皮代码可能更简单,不过也有一点小缺点, 对于小引擎来说,Shader必须给静态模型和骨骼动画模型写两套.

其次我们需要加强一个SubSkin的骨骼支持数量. 骨骼动画上的每个SubSkin都是一次Draw, 但是按照传统骨骼动画系统,每个骨头对应一个矩阵传入,那么SM2.0保守计算只能支持50根骨头. 不过在我前段时间的文章中有提到这个技术.并且已经在我的骨骼动画系统及OGRE中实现,效果很好.

美术也许很反感一个人物做1个SubSkin, 他们更新好多个SubSkin,也就是说身体每个部分都是一个SubSkin, 这样方便修改, 同时系统支持的骨骼数量还可以有一定量的上升.不过我们还需要做一个索引工作. 传统的GPU骨骼动画中总是在渲染SubSkin前传入所有这些SubSkin需要用到的骨骼矩阵. 但是每个SubSkin并不一定能用到所有的这些矩阵,这明显是一种浪费. 因此在OGRE中做过一次索引预处理,也就是将每个SubSkin用到的骨骼统计出来, 在渲染这次SubSkin时才重新传到GPU. 很明显,这是用速度还空间和兼容性. 如果在DX10以上,有ConstantBuffer还好. DX9实在太慢了

使用Marker点的换装系统很难处理例如贴身衣物这类物件换装. OGRE中有一种共享骨骼的技术, 可以支持, 不过从代码分析看来,这种技术对CPU端骨骼计算量实在是大的惊人. 因此我们决定将整个SubSkin(也就是SubEntity)换掉,这样由美术根据不同换装类型来将衣服在MAX中直接绑定好后直接替换原始模型中的SubSkin即可达到换装效果.可以说这是从动态计算到静态预处理的转变,效率提升很多.

posted @ 2010-05-11 10:21 战魂小筑 阅读(2351) | 评论 (1)编辑 收藏

在逛http://www.opengpu.org/index.php 时发现一个优秀的ARPG客户端引擎LingEngine

各位可以下载看下

 

image

从直观个人分析该引擎技术包括:

1. 基于SlimDX的.NET引擎

2. JavaScript脚本

3. 场景剔除效率还不错

4. 手感非常棒, 不亚于WOW

 

博客里还有几篇关于保留模式引擎的讨论. 个人觉得这大概是以后的趋势. 微软的WPF首先当了炮灰, 庆幸.

posted @ 2010-05-07 10:12 战魂小筑 阅读(2661) | 评论 (2)编辑 收藏

首先参考SDK里这个函数的定义:

HRESULT DrawIndexedPrimitiveUP(

D3DPRIMITIVETYPE PrimitiveType,

UINT MinVertexIndex,

UINT NumVertices,

UINT PrimitiveCount,

CONST void * pIndexData,

D3DFORMAT IndexDataFormat,

CONST void* pVertexStreamZeroData,

UINT VertexStreamZeroStride

);

 

这里假设我们要绘制一个由2个三角形组成的面,那么参数这样设置

MinVertexIndex = 0;

NumVertices = 4;

PrimitiveCount = 2;

pIndexData = { 0,1, 2, 0, 2, 3}

IndexDataFormat = D3DFMT_INDEX16

pVertexStreamZeroData = { 4个角的位置 }

VertexStreamZeroStride  = { 结构体的跨度 }

 

我们注意到, 没有任何一个参数用于描述CONST void * pIndexData的size 大小.

但其实你的图元是可以正确绘制的, 但是你并没有在indexdata后面加上例如字符串0的结尾副,那么D3D是怎么知道IndexCount呢?

我们先看下怎么根据VertexCount及 PrimitveType确定 PrimitiveCount

PrimitveType 公式
D3DPT_POINTLIST PrimitiveCount = VertexCount
D3DPT_LINELIST PrimitiveCount = VertexCount/2
D3DPT_LINESTRIP PrimitiveCount = VertexCount-1
D3DPT_TRIANGLELIST PrimitiveCount = VertexCount/3
D3DPT_TRIANGLESTRIP PrimitiveCount = VertexCount-2

注: D3DPT_TRIANGLEFAN在以后的驱动中已经不再使用,因此不再采用

当使用索引缓冲时, VertexCount = IndexCount

因此在上例中 PrimitiveCount = IndexCount/3

也就是说 IndexCount = PrimitiveCount * 3

代入PrimitiveCount = 2,因此 IndexCount = 6

 

因此稳定的API的函数参数设计是绝不会浪费任何一个参数的

posted @ 2010-05-05 17:07 战魂小筑 阅读(1554) | 评论 (1)编辑 收藏

#define MS_VC_EXCEPTION 0x406d1388
 
typedef struct tagTHREADNAME_INFO
{
    DWORD dwType;        // must be 0x1000
    LPCSTR szName;       // pointer to name (in same addr space)
    DWORD dwThreadID;    // thread ID (-1 caller thread)
    DWORD dwFlags;       // reserved for future use, most be zero
} THREADNAME_INFO;
 
void SetThreadName(DWORD dwThreadID, LPCTSTR szThreadName)
{
    THREADNAME_INFO info;
    info.dwType = 0x1000;
    info.szName = szThreadName;
    info.dwThreadID = dwThreadID;
    info.dwFlags = 0;
 
    __try
    {
        RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD),
(DWORD *)&info);
    }
    except (EXCEPTION_CONTINUE_EXECUTION)
    {
    }
}

 

线程名称限制在9个ANSI字符内,调用这个函数后,将触发一个调试器异常,VC调试器将会把字符串设置为线程名称,并在调试器中显示

posted @ 2010-05-04 15:28 战魂小筑 阅读(1861) | 评论 (0)编辑 收藏

CSDN上有这么一篇文章, 说的是VC/MFC用WPF, 当我翻到回帖第20楼时,我囧了,还没见过有那么执着的童鞋

 

回复于:2010-05-03 09:14:20

请问楼主是用VC.net吗? 中文版

如果在VC6下怎么做呢?能否给个vc6的工程实例,毕竟大多数人还是用VC6。

现在都是VS2010( VC10 ) 时代了, WPF已经不是VC6能兼容的了

看着某些童鞋,每天无止境的将标准C++代码不断翻译成VC6only代码, 为什么不把精力放在代码设计上呢?

万恶的VC6中文版, XX公司汉化的这个版本不知道害了多少人

我曾经回复无数人的博客,解释VC6的BUG. 这些童鞋居然一致坚持说VC6简单.

也许他们总是认为: VC的代码与二进制在调试时不匹配, 数组越界等等问题,都是自己掌握语言不足而引起的.

人与动物最大的区别就是使用工具, 高效优质的工具提高工作效率

posted @ 2010-05-03 18:01 战魂小筑 阅读(3790) | 评论 (23)编辑 收藏

     摘要:   阅读全文
posted @ 2010-04-26 19:47 战魂小筑 阅读(15601) | 评论 (0)编辑 收藏

传统的蒙皮骨骼动画混合方法易于理解,但是在SM 2.0的256常量限制下,骨骼数保守计算最多50根骨头,因此对美术的工作流程以及模型渲染方法造成了很大的障碍

float4x4 matBoneArray[40]; //  这是传输的瓶颈
 
VS_OUTPUT vs_main( SkinnedVS_INPUT In )
{
 
    VS_OUTPUT Out = (VS_OUTPUT)0;
 
    float4x4 skinTransform = 0;
 
    skinTransform += matBoneArray[In.BoneIndices.x] * In.BoneWeights.x;
    skinTransform += matBoneArray[In.BoneIndices.y] * In.BoneWeights.y;
    skinTransform += matBoneArray[In.BoneIndices.z] * In.BoneWeights.z;
    skinTransform += matBoneArray[In.BoneIndices.w] * In.BoneWeights.w;
    float4 localpos = mul(In.Position, skinTransform);
    
    Out.Position = mul( localpos, matViewProj ); 
    Out.TexCoord = In.TexCoord;
  
    return Out;
}

matBoneArray这个数组是骨骼的LocalRot和LocalTranslation 通过以下函数build出来

    Matrix4& Matrix4::FromTranslationRotation( const Vector3& translation, const Quaternion& rotation )
    {
        float xx = rotation.x * rotation.x * 2.0f, yy = rotation.y * rotation.y * 2.0f, zz = rotation.z * rotation.z * 2.0f;
        float xy = rotation.x * rotation.y * 2.0f, zw = rotation.z * rotation.w * 2.0f, xz = rotation.x * rotation.z * 2.0f;
        float yw = rotation.y * rotation.w * 2.0f, yz = rotation.y * rotation.z * 2.0f, xw = rotation.x * rotation.w * 2.0f;
 
        m[0][0] = 1.0f - yy - zz; m[0][1] =        xy + zw; m[0][2] =        xz - yw; m[0][3] = 0.0f;
        m[1][0] =        xy - zw; m[1][1] = 1.0f - xx - zz; m[1][2] =        yz + xw; m[1][3] = 0.0f;
        m[2][0] =        xz + yw; m[2][1] =        yz - xw; m[2][2] = 1.0f - xx - yy; m[2][3] = 0.0f;
        m[3][0] =  translation.x; m[3][1] =  translation.y; m[3][2] =  translation.z; m[3][3] = 1.0f;
 
        return *this;
    }

从这里你可以发现, 本来每根骨头只需要2个float4 传递变换信息的,现在却需要4个float4,也就是一个矩阵来传递,矩阵中还有很多不使用的变量也被传输到GPU中,这里就是优化的点.

重新调整后的Shader代码:

float4x4 BuildFromTransRot( float4 translation, float4 rot )
{
    float4 rotation = rot;
    
    float xx = rotation.x * rotation.x * 2.0f, yy = rotation.y * rotation.y * 2.0f, zz = rotation.z * rotation.z * 2.0f;
    float xy = rotation.x * rotation.y * 2.0f, zw = rotation.z * rotation.w * 2.0f, xz = rotation.x * rotation.z * 2.0f;
    float yw = rotation.y * rotation.w * 2.0f, yz = rotation.y * rotation.z * 2.0f, xw = rotation.x * rotation.w * 2.0f;
    float4x4 m = { 
    {1.0f - yy - zz,             xy + zw,             xz - yw,         0},
    {xy - zw,              1.0f - xx - zz,             yz + xw,         0},
    {xz + yw,                      yz - xw,     1.0f - xx - yy,         0},
    {translation.x,       translation.y,       translation.z,         1}
    
    };
    
    return m;
}
 
float4x4 GetBoneElement( float index )
{
    return BuildFromTransRot( vecBoneLocalTrans[index], vecBoneLocalRot[index] );
}

VS_OUTPUT vs_main( SkinnedVS_INPUT In )
{
 
    VS_OUTPUT Out = (VS_OUTPUT)0;
 
    float4x4 skinTransform = 0;
 
    skinTransform += GetBoneElement(In.BoneIndices.x) * In.BoneWeights.x;
    skinTransform += GetBoneElement(In.BoneIndices.y) * In.BoneWeights.y;
    skinTransform += GetBoneElement(In.BoneIndices.z) * In.BoneWeights.z;
    skinTransform += GetBoneElement(In.BoneIndices.w) * In.BoneWeights.w;
    float4 localpos = mul(In.Position, skinTransform);
    
    Out.Position = mul( localpos, matViewProj ); 
    Out.TexCoord = In.TexCoord;
  
    return Out;
}

我们将骨头的local旋转及偏移传递至GPU,然后在GPU内重组,虽然对GPU性能计算有部分损耗,但是骨骼数量就能保守提高到100个.

posted @ 2010-04-26 13:31 战魂小筑 阅读(3604) | 评论 (7)编辑 收藏

引擎中的每个工程均以静态库方式链接到最后的exe. 代码中包含有静态类成员,第一次运行正常,后面不知什么原因, 这些静态类成员不会被初始化, 在 crtexec.c 的CRT 初始化全局类成员函数

static void __cdecl _initterm (
#endif  /* CRTDLL */
        _PVFV * pfbegin,
        _PVFV * pfend
        )
{
        /*
         * walk the table of function pointers from the bottom up, until
         * the end is encountered.  Do not skip the first entry.  The initial
         * value of pfbegin points to the first valid entry.  Do not try to
         * execute what pfend points to.  Only entries before pfend are valid.
         */
        while ( pfbegin < pfend )
        {
            /*
             * if current table entry is non-NULL, call thru it.
             */
            if ( *pfbegin != NULL )
                (**pfbegin)();
            ++pfbegin;
        }
}

 

 

这个函数会初始化所有链接到exe中的全局函数构造, 跟踪这个地方, 发现,只有1个lib中的能被正确调用,但是出问题的那个lib中所有构造都不能被调用. 尝试调整编译顺序无果

唯一的方法只有修改架构为在winmain内进行构造

如果有这方面调试经验的同学可以回帖,谢谢

posted @ 2010-04-23 17:47 战魂小筑 阅读(1500) | 评论 (6)编辑 收藏

仅列出标题
共26页: First 13 14 15 16 17 18 19 20 21 Last