我正在编写我自己的COLLADA进口商.我已经很远了,装载网格和材料等.但是我已经打动动画了,特别是联合旋转.

我用来剥皮我的网格的公式是直接的:

weighted;
for (i = 0; i < joint_influences; i++)
{
    weighted += 
        joint[joint_index[i]]->parent->local_matrix * 
        joint[joint_index[i]]->local_matrix * 
        skin->inverse_bind_pose[joint_index[i]] * 
        position * 
        skin->weight[j];
}
position = weighted;

就文献而言,这是正确的公式.现在,COLLADA指定了关节的两种旋转方式:局部和全局.您必须将旋转连接在一起以获得关节的局部变换.

COLLADA文档没有区别的是联合的本地轮换和联合的全局旋转.但是在我看到的大多数模型中,旋转可以具有rotate(全局)或jointOrient(local)的id.

当我忽略全局旋转,只使用本地旋转时,我得到模型的绑定姿势.但是,当我将全球轮转加入联合地方转型时,奇怪的事情开始发生.

这是没有使用全球轮换:

这是全球轮转:

在两个屏幕截图中,我使用线绘制骨架,但是在第一个视图中,它是不可见的,因为关节在网格内.在第二个屏幕截图中,顶点遍布当地!

为了比较,这是第二个截图应该是这样的:

很难看到,但是您可以看到关节在第二个截图中位于正确的位置.

但现在奇怪的是.如果我忽略由COLLADA指定的反向绑定姿势,而是采用联合的父局部变换的倒数乘以联合局部变换,我得到以下内容:

在这个截图中,我从每个顶点绘制一条线到有影响的关节.我得到绑定姿势的事实不是很奇怪,因为公式现在变成:

world_matrix * inverse_world_matrix * position * weight

但是它导致我怀疑COLLADA的反绑定姿势是错误的空间.

所以我的问题是:COLLADA在什么空间中指定了其反绑定姿势?而且如何将逆绑定姿势转换到我需要的空间?

解决方法

我开始比较我的值与我从Assimp(一个开源模型加载器)读取的值.在编写代码之后,我查看了它们构建绑定矩阵及其反向绑定矩阵的位置.

最终我最终在SceneAnimator :: GetBoneMatrices中包含以下内容:

// Bone matrices transform from mesh coordinates in bind pose to mesh coordinates in skinned pose
// Therefore the formula is offsetMatrix * currentGlobalTransform * inverseCurrentMeshTransform
for( size_t a = 0; a < mesh->mNumBones; ++a)
{
    const aiBone* bone = mesh->mBones[a];
    const aimatrix4x4& currentGlobalTransform
        = GetGlobalTransform( mBoneNodesByName[ bone->mName.data ]);
    mTransforms[a] = globalInverseMeshTransform * currentGlobalTransform * bone->mOffsetMatrix;
}

globalInverseMeshTransform始终是身份,因为网格不会转换任何东西. currentGlobalTransform是绑定矩阵,联合的父本的本地矩阵与联合的局部矩阵相连.而mOffsetMatrix是直接来自皮肤的反向绑定矩阵.

我检查了这些矩阵的值到我自己的(哦,是的,我在一个手表窗口比较它们),它们是完全一样的,可能是0.0001%,但这是微不足道的.那么为什么Assimp的版本工作和我的,即使公式是一样的?

这是我得到的:

当Assimp终于将矩阵上传到皮肤着色器时,它们执行以下操作:

helper->piEffect->SetMatrixTransposeArray( "gBoneMatrix",(D3DXMATRIX*)matrices,60);

Waaaaait一秒.他们上传他们转置?这不是那么容易.没门.

对.

还有一件事我做错了:在应用皮肤矩阵之前,我将坐标转换成正确的系统(厘米到米).这导致完全失真的模型,因为矩阵是为原始坐标系设计的.

未来GOOGLERS

>按您收到的顺序读取所有节点变换(旋转,转换,缩放等).
将它们连接到一个关节的局部矩阵.
采取联合的父母,并将其与本地矩阵相乘.
>将其存储为绑定矩阵.
>阅读皮肤信息.
>存储关节的逆绑定姿势矩阵.
>存储每个顶点的关节权重.
将具有反向绑定姿势矩阵的绑定矩阵相乘并将其转置,称之为剥皮矩阵.
>将占位矩阵乘以关节重量,并将其添加到加权位置.
>使用加权位置进行渲染.

完成!

c – COLLADA:错误的空间中反绑定姿势?的更多相关文章

  1. ios – 如何将CGAffineTransform应用于CGPoint

    如果我有一个转换矩阵,作为CGAffineTransform,一个点,作为CGPoint,我怎样才能得到矩阵矢量乘积?

  2. 系统学习机器学习之正则化二

    监督机器学习问题无非就是“minimizeyourerrorwhileregularizingyourparameters”,也就是在规则化参数的同时最小化误差。对机器学习也是一样,如果被我们人稍微点拨一下,它肯定能更快的学习相应的任务。OK,到这里,如果你在机器学习浴血奋战多年,你会发现,哎哟哟,机器学习的大部分带参模型都和这个不但形似,而且神似。没错,这就是这节的题目把L0和L1放在一起的原因,因为他们有着某种不寻常的关系。

  3. 压缩感知重构算法之正则化正交匹配追踪(ROMP)

    本篇将在上一篇《压缩感知重构算法之正交匹配追踪》的基础上给出正则化正交匹配追踪算法的MATLAB函数代码,并且给出单次测试例程代码、测量数M与重构成功概率关系曲线绘制例程代码。

  4. 机器学习中的范数规则化之一L0、L1与L2范数

    机器学习中的范数规则化之(一)L0、L1与L2范数今天我们聊聊机器学习中出现的非常频繁的问题:过拟合与规则化。监督机器学习问题无非就是“minimizeyourerrorwhileregularizingyourparameters”,也就是在规则化参数的同时最小化误差。个人理解一是因为L0范数很难优化求解,二是L1范数是L0范数的最优凸近似,而且它比L0范数要容易优化求解。所以大家才把目光和万千宠爱转于L1范数。

  5. 机器学习中的范数规则化

    我们先简单的来理解下常用的L0、L1、L2和核范数规则化。监督机器学习问题无非就是“minimizeyourerrorwhileregularizingyourparameters”,也就是在规则化参数的同时最小化误差。对机器学习也是一样,如果被我们人稍微点拨一下,它肯定能更快的学习相应的任务。OK,到这里,如果你在机器学习浴血奋战多年,你会发现,哎哟哟,机器学习的大部分带参模型都和这个不但形似,而且神似。

  6. ios – OpenGL ES屏幕投影矩阵和相机投影矩阵

    我有一个投影矩阵,来自增强现实应用程序中的相机校准,只要屏幕宽高比与相机图像宽高比匹配,一切都很好.当相机图像与屏幕边缘不匹配时,您将在跟踪中出现失真.问题场景:>iPad上的1280×720视频>iPhone5S上的640×480视频.工作场景:>iPad上的640×480视频>iPhone5S上的1280×720视频.目标:我想以一般方式处理此屏幕/相机宽高比不匹配.出现此问题是因为视图在屏幕

  7. delphi – 使用世界坐标SVG图像中的屏幕坐标的Hittest

    我一直在寻找SVG代码,发现:http://development.mwcs.de/svgimage.html这是第一个实际上适用于SVG的Delphi组件,但我离题。该组件使用GDI显示圆,曲线等GDI使用矩阵将世界坐标,旋转和失真转换为屏幕坐标。在所有这些GDI对象中有很多矩阵可供选择。换一种说法从SVG图像中读取的形状是由矩阵变成屏幕坐标的原语。由于SVG图像的设置方式,每个形状都有一个id,我想使用它来查看我用鼠标命中的区域。在第一种情况下,平移存储在世界坐标中,在第二次平移中存储在屏幕坐标中。

  8. javascript – 获取一个div的translate3d值?

    说一个div适用于它:如何使用jQuery检索这些值?解决方法取决于是否设置了z值,该值将被存储为矩阵或matrix3d.假设没有其他变换,对于2D矩阵,X和Y是最后两个值.对于3D矩阵,X,Y,Z,1是最后四位数.您可以使用正则表达式获取值:

  9. c# – 关于继承和运算符重载的OOP设计问题

    如果是前者,请考虑在基类Matrix中实现运算符,并让该运算符实现策略模式,调用可以对每种类型组合执行实际操作的内部类.如果是后者,只需覆盖该类型矩阵的有效运算符的基类实现.

  10. c- AVX中的矩阵向​​量乘法不是比SSE中的比例快

    ,以了解如何进行循环平铺.在尝试SSE/AVX之前,我会尝试先将循环平铺放到第一位.我在矩阵乘法中获得的最大提升不是来自SIMD,也不是来自循环平铺的线程.我认为如果你获得了缓存使用权,你的AVX代码也会比SSE更加线性.

随机推荐

  1. 从C到C#的zlib(如何将byte []转换为流并将流转换为byte [])

    我的任务是使用zlib解压缩数据包(已接收),然后使用算法从数据中生成图片好消息是我在C中有代码,但任务是在C#中完成C我正在尝试使用zlib.NET,但所有演示都有该代码进行解压缩(C#)我的问题:我不想在解压缩后保存文件,因为我必须使用C代码中显示的算法.如何将byte[]数组转换为类似于C#zlib代码中的流来解压缩数据然后如何将流转换回字节数组?

  2. 为什么C标准使用不确定的变量未定义?

    垃圾价值存储在哪里,为什么目的?解决方法由于效率原因,C选择不将变量初始化为某些自动值.为了初始化这些数据,必须添加指令.以下是一个例子:产生:虽然这段代码:产生:你可以看到,一个完整的额外的指令用来移动1到x.这对于嵌入式系统来说至关重要.

  3. 如何使用命名管道从c调用WCF方法?

    更新:通过协议here,我无法弄清楚未知的信封记录.我在网上找不到任何例子.原版的:我有以下WCF服务我输出添加5行,所以我知道服务器是否处理了请求与否.我有一个.NET客户端,我曾经测试这一切,一切正常工作预期.现在我想为这个做一个非托管的C客户端.我想出了如何得到管道的名称,并写信给它.我从here下载了协议我可以写信给管道,但我看不懂.每当我尝试读取它,我得到一个ERROR_broKEN_P

  4. “这”是否保证指向C中的对象的开始?

    我想使用fwrite将一个对象写入顺序文件.班级就像当我将一个对象写入文件时.我正在游荡,我可以使用fwrite(this,sizeof(int),2,fo)写入前两个整数.问题是:这是否保证指向对象数据的开始,即使对象的最开始可能存在虚拟表.所以上面的操作是安全的.解决方法这提供了对象的地址,这不一定是第一个成员的地址.唯一的例外是所谓的标准布局类型.从C11标准:(9.2/20)Apointe

  5. c – 编译单元之间共享的全局const对象

    当我声明并初始化一个const对象时.两个cpp文件包含此标头.和当我构建解决方案时,没有链接错误,你会得到什么如果g_Const是一个非const基本类型!PrintInUnit1()和PrintInUnit2()表明在两个编译单元中有两个独立的“g_Const”具有不同的地址,为什么?

  6. 什么是C名称查找在这里? (&amp;GCC对吗?)

    为什么在第三个变体找到func,但是在实例化的时候,原始变体中不合格查找找不到func?解决方法一般规则是,任何不在模板定义上下文中的内容只能通过ADL来获取.换句话说,正常的不合格查找仅在模板定义上下文中执行.因为在定义中间语句时没有声明func,并且func不在与ns::type相关联的命名空间中,所以代码形式不正确.

  7. c – 在输出参数中使用auto

    有没有办法在这种情况下使用auto关键字:当然,不可能知道什么类型的.因此,解决方案应该是以某种方式将它们合并为一个句子.这可用吗?解决方法看起来您希望默认初始化给定函数期望作为参数的类型的对象.您无法使用auto执行此操作,但您可以编写一个特征来提取函数所需的类型,然后使用它来声明您的变量:然后你就像这样使用它:当然,只要你重载函数,这一切都会失败.

  8. 在C中说“推动一切浮动”的确定性方式

    鉴于我更喜欢将程序中的数字保留为int或任何内容,那么使用这些数字的浮点数等效的任意算术最方便的方法是什么?说,我有我想写通过将转换放在解析的运算符树叶中,无需将表达式转化为混乱是否可以使用C风格的宏?应该用新的类和重载操作符完成吗?解决方法这是一个非常复杂的表达.更好地给它一个名字:现在当您使用整数参数调用它时,由于参数的类型为double,因此使用常规的算术转换将参数转换为double用C11lambda……

  9. objective-c – 如何获取未知大小的NSArray的第一个X元素?

    在objectiveC中,我有一个NSArray,我们称之为NSArray*largeArray,我想要获得一个新的NSArray*smallArray,只有第一个x对象…

  10. c – Setprecision是混乱

    我只是想问一下setprecision,因为我有点困惑.这里是代码:其中x=以下:方程的左边是x的值.1.105=1.10应为1.111.115=1.11应为1.121.125=1.12应为1.131.135=1.14是正确的1.145=1.15也正确但如果x是:2.115=2.12是正确的2.125=2.12应为2.13所以为什么在一定的价值是正确的,但有时是错误的?请启发我谢谢解决方法没有理由期望使用浮点系统可以正确地表示您的帖子中的任何常量.因此,一旦将它们存储在一个双变量中,那么你所拥有的确切的一

返回
顶部