青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

3d Game Walkman

3d圖形渲染,網絡引擎 — tonykee's Blog
隨筆 - 45, 文章 - 0, 評論 - 309, 引用 - 0
數據加載中……

最近在對骨骼導出插件進行重構,有了一些新的感悟

最近嘗試把3dmax的physique骨骼系統導出插件重構成了skin的方式,用了用skin感覺相比physique要強大的多,skin是max最老的蒙皮修改器,應該比physique還要早把,但后續版本升級做的很強大,據說和maya的方法差不多,physique修改器更新緩慢,而且用了一下確實是skin的修改器要好用一些,尤其對于蒙皮人物骨骼按部件進行拆分方面,skin方式要方便很多,實現換裝系統也不是問題,我最近正在實現一套比較好的部件裝配式的換裝系統,大體的方法是把人物拆分,按需要進行骨骼部件的組裝,比如手,腳,頭發,身體,裙擺,都可以是獨立的骨架部件,然后組裝在一起,很多游戲其實都有這樣的功能,實現方法大同小異吧,不過我這里有點心得可以分享一下,人物的骨骼導出的時候不要圖方便只導出每塊骨頭的世界矩陣,而應該導出這塊骨頭相對父骨節的矩陣,形成一顆顆子樹,這樣做在單副骨架上看似乎沒有什么大的優勢,還會帶來額外的計算量,但實際上要實現換裝,比如一個部件從一個形體直接配置到另外一個形體上的時候,優勢就體現出來了,真的必須這么干啊,我想以后做一些外界作用力的物理效果的時候,父骨架的偏移影響到子骨架的計算,或反向IK計算,應該也容易計算了(比如自由墜落的布娃系統)當然這是后話了,現在多做點這樣工作,以后擴展起來會容易很多

另外有個心得可以和大家分享一下,那就是關于骨骼矩陣的導出冗余數據的精簡方法、其實做過蒙皮的人應該會知道,一套完整的骨骼動畫的數據量最大的并不是頂點的數據,那個數量基本固定的,不會隨動作的增長而變大,真正龐大的是骨骼的關鍵幀導出數據
來個簡單的計算,如果一個蒙皮角色的總骨骼有100根,1000幀的動畫
那么占用的空間= 100 * 1000 * sizeof(D3DXMATRIX)  = 100 *1000 * 64Bytes  差不多占了6MB多的容量,一般一個角色的動畫多達幾千到上萬幀的,那么這個數量的增長是很龐大的,也許你會覺得這幾MB到10多MB的數據量不算什么,現在內存不都是幾個G了嗎?但你要想想,現在游戲卡的現象不在于你cpu多塊,內存多大,很大部分愿意是磁盤io讀取慢了,這才是瓶頸,這些年計算機的速度是提升了很多倍可就是硬盤的讀寫速度沒什么變化啊,同屏幾十個不同的角色,如果不預加載,用實時加載,那么一加載起來動不動就是幾十MB的數據,不管什么機器,再怎么多線程優化也一樣卡,即使單機都會卡
 
所以需要想辦法來壓縮精簡這些數據,其實壓縮的思路并不復雜,我們的骨骼矩陣一般都用的是線性差值計算的,max在打上關鍵幀的時候也基本上是線性差值的,這樣就好辦了,線性差值的數據過渡一般都有一個特點,那就是比較“平滑”,很多數據變化幅度不大的情況下前一幀和后一幀的矩陣平均值剛好等于當前幀的矩陣值,就利用這個特性我們就能過濾掉相當大數量級的矩陣了

以下的算法針對于連續線性變換的數據精簡壓縮都是有用的,不僅僅只針對于矩陣,我在下面的例子里面用的是整數,思路清楚以后換成矩陣就好了


#include "stdafx.h"
#include <WTypes.h>
#include <vector>
#include <map>
#include <assert.h>
using namespace std;

 

struct  Idinfo
{
 int id;     //原數據索引
 int id0;   //等比區間索引上界索引
 int id1;   //等比區間索引下界索引
 BOOL GetValue(map<int,int> & imap, int& val)
 {
  if(id == id0 && id == id1)
  {
   map<int, int>::iterator it0 = imap.find(id0);
   assert(it0 != imap.end());
   val = it0->second;
   return TRUE;
  }
  else if(id > id0 && id < id1)
  {
   map<int, int>::iterator it0 = imap.find(id0);
   map<int, int>::iterator it1 = imap.find(id1);
   assert(it0 != imap.end());
   assert(it1 != imap.end());
   int v0 = it0->second;
   int v1 = it1->second;
   val = v0 + ((v1 - v0) / (id1 - id0)) * (id - id0);
   return TRUE;
  }
  return FALSE;
 }
};


int _tmain(int argc, _TCHAR* argv[])
{
 vector<int> arr; //假設這里面放的就是線性變換的數據
 arr.push_back(2);
 arr.push_back(4);
 arr.push_back(6);
 arr.push_back(8);
 arr.push_back(15);
 arr.push_back(16);
 arr.push_back(17);
 arr.push_back(18);
 arr.push_back(19);
 arr.push_back(20);

 map<int,int,less<int>> imap; //把非等比變化的數據導出(自動按原索引排序的)
 int sz = (int)arr.size();
 for(int i = 0; i < sz; ++i)
 {
  if(i == 0 || i == sz - 1)
  {
   imap.insert(pair<int, int>(i, arr[i])); //頭尾不過濾,一定要保留的
  }
  else
  {
   if(arr[i] != (arr[i - 1] + arr[i + 1]) / 2) //過濾掉前后等比的數據,
                                                            //提示一下,如果是浮點數建議不要這樣比較,浮點數有誤差的,建議有個0.0001的容差,視情況而定
   {
    imap.insert(pair<int, int>(i, arr[i]));
   }
  }
 }

 vector<Idinfo> vecIds;  //計算每個數據的索引描述

 for(int i = 0; i < sz; ++i)
 {
  map<int,int>::iterator it = imap.find(i);

  BOOL _lowBoundFind =  FALSE;
  BOOL _highBoneFind = FALSE;
  Idinfo idInfo;
  idInfo.id = i;
  for(it = imap.begin();it != imap.end(); ++it)
  {
   int id = it->first;
   if(i == id)
   {
    idInfo.id0 = id;
    idInfo.id1 = id;
    _lowBoundFind = TRUE;
    _highBoneFind = TRUE;
   }

   if(i > id)
   {
    idInfo.id0 = id;
    _lowBoundFind = TRUE;
   }

   if(i < id)
   {
    idInfo.id1 = id;
    _highBoneFind = TRUE;
   }

   if(_lowBoundFind && _highBoneFind)
   {
    vecIds.push_back(idInfo);
    break;
   }
  }
 }

 //檢驗一下能否把原線性隊列的數據完全還原出來
 for(vector<Idinfo>::iterator it = vecIds.begin(); it < vecIds.end(); ++it)
 {
  Idinfo & idInfo = *it;
  int id = 0;
  if(idInfo.GetValue(imap, id))
  {
   printf("%d \r\n", id);
  }
 }

 return 0;
}


//可以看到,我們實際導出的是imap就夠了,vecIds可以計算出來的,也就是說只需要imap就能確定arr集合的每一個元素了
上面的例子可以看到10個元素“壓縮”成了4個元素,數據變化越平滑,壓縮的數據量將會越大

posted on 2010-10-17 23:51 李侃 閱讀(3640) 評論(7)  編輯 收藏 引用 所屬分類: 設計思路

評論

# re: 最近在對骨骼導出插件進行重構,有了一些新的感悟[未登錄]  回復  更多評論   

"如果一個蒙皮角色的總骨骼有100根,1000幀的動畫那么占用的空間= 100 * 1000 * sizeof(D3DXMATRIX) = 100 *1000 * 64Bytes 差不多占了6MB多的容量,一般一個角色的動畫多達幾千到上萬幀的,....."
難道動畫沒關鍵幀插值?為啥每幀都有一個矩陣?
2010-10-18 13:50 | kaka

# re: 最近在對骨骼導出插件進行重構,有了一些新的感悟  回復  更多評論   

樓主的骨骼動畫數據可能是通過采集獲得的,沒有做成關鍵幀。
2010-10-18 20:49 | wimdys

# re: 最近在對骨骼導出插件進行重構,有了一些新的感悟  回復  更多評論   

今天看了一下max的api,關鍵幀運動插值計算有TCB, BEZIER,和LINEAR三種方式,還要根據IKeyControl來獲取旋轉、平移、和縮放的x,y,z三個分量的關鍵幀控制器,可以說相當于有9組控制器,通過這些控制器來得到運動軌跡曲線上標注的關鍵幀,三種插值得到的運動軌跡的變化是不一樣的,前兩個是曲線,最后一個是直線,這里面基本意思是看明白了,我決定把這通過IKeyControl得到的關鍵幀,和前面提到的幀壓縮算法結合起來再來試驗一下效果,但不打算使用TCB和BEZIER兩種計算方法,這兩種差值算法還要折騰曲線方程,過于復雜了,還是打算使用LINEAR線性差值的方式,我想缺點就是動作也許會沒那么平滑吧,就好像行車轉彎的時候按直線轉和按弧線轉,肯定是弧線自然一些,但代價似乎也不小吧,主要是計算插值的曲線方程不太容易搞
2010-10-19 20:14 | 李侃

# re: 最近在對骨骼導出插件進行重構,有了一些新的感悟  回復  更多評論   

@李侃
建議樓主如果是導出關鍵幀數據的話還是用IGAME吧!!用IGame導出關鍵幀非常方便的哦!!!
2010-10-23 01:29 | G++

# re: 最近在對骨骼導出插件進行重構,有了一些新的感悟  回復  更多評論   

已經搞定了,還真是不容易,拋棄矩陣,那玩意根本就不能直接拿來做線性插值,因為旋轉的產生是有弧度的,直接這個矩陣來做差值一定會結果變成直線位移而嚴重失真,應該用每個骨骼原點自身的四元素旋轉和自身位移和骨骼的世界原點這三個數據來做,回頭我會寫一篇具體實現方法的文章,現在任意時間的任意頂點的位置經過我的關鍵幀插值計算,已經和3dmax完全能對應上無誤差了
2010-10-24 12:30 | 李侃

# re: 最近在對骨骼導出插件進行重構,有了一些新的感悟  回復  更多評論   

對動作進行采樣,然后用一定的算法從采樣數據中提出關鍵幀。

因為Max中的關鍵幀插值算法比較復雜(看曲線編輯器)。

一種幀壓縮算法:
《Ogre的skeleton數據的壓縮》Azure Product
http://www.azure.com.cn/?id=430
2010-10-27 20:25 | funcman

# re: 最近在對骨骼導出插件進行重構,有了一些新的感悟  回復  更多評論   

Max中的關鍵幀插值算法的確是比較復雜,可吃透它意義非同凡響啊

之前看過這篇文章,那個幀壓縮算法我已經不需要了,我已經成功模擬實現了max的關鍵幀的差值算法,通過這個把星期的分析把曲線上的數據統統解出來而且吃透了,通過我的計算,目前是LINEAR這種方式,任意時間得到的各頂點的位置和max的一模一樣,這樣下來根本不用去做什么幀壓縮了,max的動畫曲線上有多少個節點我就導出多少個數據(導出的數據超乎想象的少,打個比方兩點是一條直線,這條直線多長,我不用關心,因為直線上的任意一點我能計算出來,我只需要這兩個關鍵點就好了,這才是真正的“關鍵幀”數據插值計算啊),而且這其中的意義不光在幀數據的剔除(過去的認識很膚淺,骨骼動畫不能光是“播放”的),不同動畫集動作之間的自動融合的問題用固定的幀數據去播放是無法解決的,想象一下一個動作沒播完,而打斷去播放下一個動作,這兩個動作怎么去自動連貫起來呢?如果要做到自動連貫起來,那么過渡幀的數據是要用通過關鍵幀插值來融合計算的,這能大大豐富動作的連貫和動作組合的復雜度,通過研究和實現max的插值算法以后正好能很好的解決這個問題

我導出的數據僅僅只有各骨骼關鍵幀的旋轉四元數(連位移都不需要,我發現骨骼的移動全部是上層旋轉帶動的,如果不考慮縮放,那么也骨骼根本沒有自身的位移量,看曲線一目了然的),另外還有蒙皮姿勢的各骨骼初始位置,和蒙皮姿勢的Mesh各頂點,另外還有材質等數據,這些數據足以

目前在這個基礎之上還實現了換裝,也就是更換蒙皮骨骼部件的功能,主蒙皮的骨架計算影響到次級副部件的子骨架這樣的功能,很快我差不多能實現蒙皮部件換裝,批量繪制,物件綁定插槽編輯,動作標簽編輯,動作融合設置,等等...一個復雜的蒙皮配置系統了,應該會比OGRE那套復雜的多
2010-10-27 21:44 | 李侃
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久国产综合精品| 亚洲在线不卡| 亚洲一区免费在线观看| 在线观看成人av电影| 亚洲女女女同性video| 夜夜嗨av色综合久久久综合网| 欧美一区亚洲| 一本色道久久综合亚洲精品不卡| 久久久青草婷婷精品综合日韩 | 国内精品国产成人| 国产婷婷成人久久av免费高清| 99在线|亚洲一区二区| 亚洲免费观看高清完整版在线观看| 久久一区精品| 性做久久久久久久久| 欧美日韩三级视频| 亚洲精品五月天| 国内伊人久久久久久网站视频| 亚洲女女女同性video| 99热免费精品| 国产一区二区三区视频在线观看| 国产精品你懂的| 欧美在线网站| 欧美成人精品福利| 香蕉久久国产| 嫩草成人www欧美| 午夜久久tv| 欧美sm重口味系列视频在线观看| 亚洲一区精品在线| 免费欧美日韩| 欧美在线视频免费观看| 欧美啪啪成人vr| 另类图片综合电影| 国产精品国产三级国产aⅴ入口 | 伊甸园精品99久久久久久| 91久久精品美女高潮| 国产精品欧美久久| 亚洲国产精品一区| 黄色成人小视频| 亚洲中午字幕| 亚洲一区二区动漫| 欧美国产国产综合| 久久一区欧美| 国产亚洲欧美中文| 亚洲一区免费网站| 亚洲神马久久| 欧美福利视频一区| 欧美成人资源网| 国产一区二区成人| 亚洲一区二区在线观看视频| 亚洲美女免费精品视频在线观看| 久久久久久噜噜噜久久久精品| 先锋影音一区二区三区| 欧美日韩亚洲视频| 亚洲日本va午夜在线影院| 亚洲国产精品国自产拍av秋霞| 久久精品亚洲一区| 久久精品国产第一区二区三区最新章节 | 亚洲美女精品久久| 亚洲精品看片| 欧美激情亚洲国产| 亚洲欧洲在线播放| 亚洲免费av观看| 欧美电影资源| 亚洲日本aⅴ片在线观看香蕉| 亚洲区第一页| 欧美久久视频| 一区二区三区国产在线| 亚洲一区在线免费| 国产精品亚洲一区| 久久精品一区中文字幕| 久久综合狠狠综合久久激情| 黄色一区三区| 欧美成人综合在线| 亚洲精品在线观看视频| 亚洲精品欧美激情| 欧美日韩午夜| 亚洲欧美国产不卡| 久久一区中文字幕| 最新国产の精品合集bt伙计| 欧美大片91| 亚洲天堂av综合网| 噜噜噜91成人网| 国产一区二区三区久久悠悠色av | 亚洲国产三级在线| 一区二区毛片| 国产精品久久久久久户外露出| 亚洲一区二区三区四区在线观看| 欧美在线www| 亚洲国产精品va在线看黑人动漫| 欧美国产三区| 亚洲欧美韩国| 欧美激情精品久久久久| 亚洲一区二区伦理| 国外成人免费视频| 欧美精品日韩| 欧美亚洲尤物久久| 欧美国产第二页| 亚洲综合三区| 亚洲国产日韩欧美在线动漫| 国产精品v欧美精品v日本精品动漫| 性感少妇一区| 亚洲国产三级| 久久免费视频网| 洋洋av久久久久久久一区| 国产热re99久久6国产精品| 久久综合给合| 国产精品99久久久久久有的能看| 久久狠狠婷婷| 亚洲免费电影在线观看| 国产一区二区中文| 欧美二区在线观看| 午夜精品av| 日韩视频―中文字幕| 噜噜噜躁狠狠躁狠狠精品视频| 一本色道88久久加勒比精品| 国内久久精品视频| 欧美性猛交99久久久久99按摩| 久久精品1区| 亚洲天堂免费观看| 亚洲人成网站在线观看播放| 久久久97精品| 中文精品视频| 亚洲精品美女免费| 在线观看中文字幕亚洲| 国产一区视频在线观看免费| 国产精品网站一区| 欧美视频一区在线| 欧美精品一区二区三区很污很色的 | 免播放器亚洲| 久久国产综合精品| 亚洲欧美日韩精品| 国产精品99久久99久久久二8 | 久久精品夜色噜噜亚洲a∨| 亚洲综合色在线| 亚洲一区二区三区四区五区黄| 亚洲欧洲精品一区| 亚洲黄网站黄| 亚洲精品偷拍| 亚洲美女av电影| 亚洲免费观看高清完整版在线观看熊 | 韩国三级电影久久久久久| 日韩亚洲欧美中文三级| 激情婷婷久久| 国模大胆一区二区三区| 国产一区二区三区观看| 国产亚洲女人久久久久毛片| 国产亚洲综合精品| 伊甸园精品99久久久久久| 在线看片第一页欧美| 在线电影欧美日韩一区二区私密| 精品动漫3d一区二区三区免费| 国内精品美女在线观看| 国内精品久久久久久久影视蜜臀| 国产精品一区二区久久精品| 国产精品一卡| 精品不卡视频| 最新成人av网站| 亚洲一二三区视频在线观看| 亚洲欧美日韩成人| 久久精品中文字幕一区| 美日韩精品视频| 亚洲精品国产欧美| 亚洲欧美另类久久久精品2019| 欧美一区二区高清| 另类综合日韩欧美亚洲| 欧美偷拍一区二区| 国产日韩欧美在线一区| 亚洲国内欧美| 午夜视频久久久| 久久综合色天天久久综合图片| 欧美激情第9页| 一本色道精品久久一区二区三区| 午夜日韩在线| 欧美黄色精品| 国产在线日韩| aaa亚洲精品一二三区| 欧美在线黄色| 亚洲国产精品免费| 午夜精品久久久| 欧美激情视频一区二区三区免费 | 伊人成人在线| 亚洲一区二区三区高清不卡| 美女在线一区二区| 一区二区不卡在线视频 午夜欧美不卡在 | 亚洲看片免费| 久久精品国产综合| 亚洲欧洲精品成人久久奇米网| 亚洲自拍16p| 欧美日韩日日骚| 亚洲国产精品久久久久婷婷884| 亚洲欧美中文另类| 亚洲高清免费视频| 欧美一区二区三区的| 欧美日韩视频专区在线播放 | 亚洲午夜久久久久久久久电影院 | 久久精品国产亚洲a| 国产精品99久久久久久宅男 | 欧美亚洲在线观看| 国产精品麻豆成人av电影艾秋|