ПрограммированиеФорумГрафика

SMD анимация : ( Ни как не получается. (Решено - осталось несколько вопросов))

Страницы: 1 2 3 4 5 6 7 Следующая »
#0
11:05, 11 июля 2009

Привет.

Блин, прогаю C# + SlimDX

Сделал загрузчик моделей и анимации SMD. Модель рисуется отлично (ну кроме багов с нормалями но то не суть важно).
Первый кадр как и в редакторе но вот с анимацией траблы : (  Я быстро накидал AnimationController и попробовал проиграть анимацию.. о жесть! Модель всю корячит  так шо ппц. Уже 3 день не могу понять в чём причина. Сейчас наглядно покажу:

это первый кадр  (3D Max):
Mesh reference pose | SMD анимация : (  Ни как не получается. (Решено - осталось несколько вопросов))

вот кадр анимации #30  (3DMAX)
Mesh 30 frame | SMD анимация : (  Ни как не получается. (Решено - осталось несколько вопросов))

а это кадр анимации #30 в моём "движке"
Mesh 30 frame my engine | SMD анимация : (  Ни как не получается. (Решено - осталось несколько вопросов))

Как видите, анимация в моём движке не особо похожа на ту, что нужна.
В чём может быть причина?

вся анимация рисуется через шейдер (не кидайтесь помидорами, я его на скорую руку написал, лишь бы работал)

#define MAX_MATRICES 50
#define MAX_BONES 4
float4x4 matWVP : WORLDVIEWPROJECTION;
float4x4 matVP : VIEWPROJECTION;
float4x4 matWV : WORLDVIEW;
float3 sunPosition : SUN;
float4x4 matW : WORLD;
float4 ambient : AMBIENT, diffuse : DIFFUSE, specular : SPECULAR, emissive : EMISSIVE;
Texture baseTexture : TEXTURE_BASE;
float4x4 wmArray[MAX_MATRICES];
sampler baseSampler = sampler_state 
{ texture = <baseTexture>;  
minfilter = anisotropic;
magfilter = anisotropic;
};

struct VS_INPUT 
{
   float4 Position : POSITION0;
   float2 Texcoord : TEXCOORD0;
   float3 Normal : NORMAL;
    float4  BlendWeights    : BLENDWEIGHT;
    float4  BlendIndices    : BLENDINDICES;
};

struct VS_OUTPUT 
{
   float4 Position : POSITION0;
   float2 Texcoord : TEXCOORD0;
   float3 Normal : TEXCOORD1;
   float3 Light: TEXCOORD2;
};

VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;
 
 
   Output.Texcoord = Input.Texcoord;

   int IndexArray[MAX_BONES] = (int[MAX_BONES])(Input.BlendIndices);
   float WeightArray[MAX_BONES] = (float[MAX_BONES])(Input.BlendWeights);

   float LastWeight = 0;
   float4 pos = 0;
float4 norm = 0;

for(int i = 0; i<MAX_BONES;i++)
{
LastWeight  = LastWeight + WeightArray[i];
pos = pos + mul(Input.Position, wmArray[IndexArray[i]]*WeightArray[i]);
norm = norm + mul(Input.Position, wmArray[IndexArray[i]]*WeightArray[i]);
}
pos = pos + mul(Input.Position, wmArray[IndexArray[0]]* (1.0f - LastWeight));
norm = norm + mul(Input.Position, wmArray[IndexArray[0]]* (1.0f - LastWeight));
 Output.Position  = mul(pos,matVP);
  Output.Normal = norm.xyz;
Output.Light = sunPosition.xyz -  Output.Position.xyz;
   return( Output );

}
 
struct PS_INPUT 
{
   float2 Texcoord : TEXCOORD0;
   float3 Normal : TEXCOORD1;
   float3 Light: TEXCOORD2;
};

float4 ps_main( PS_INPUT Input ) : COLOR0
{  

   return float4(float3(1,1,1) * dot(normalize(Input.Normal), normalize(Input.Light)),1);
}

technique Default_Skin
{

   pass Pass_0
   {
    //  cullmode = none;
      VertexShader = compile vs_3_0 vs_main();
      PixelShader = compile ps_3_0 ps_main();
   }

}


Позиции вершин и анимация (положение, поворот кости) грузятся так:  XZY  (Y и Z меняем местами)

Иерархия костей 100% верная - проверял каждую кость вручную.

Как считаюабсолютную трансформацию кости:
для каждой кости выполняется её функция:  (псевдокод)

AbsoluteMatrix = ParentMatrix * (BaseMatrix * FrameMatrix);

где ParentMatrix - абсолютная матрица родительской кости, BaseMatrix - инвертированная матрица первого кадра,
FrameMatrix - матрица нынешнего кадра.

Нужна ваша помощь ибо у самого скоро мосх разорвёт на куски : (  заранее спасибо!

#1
11:17, 11 июля 2009

На всякий случай:
сама модель (SMD):
Model SMD

её анимация:
Анимация SMD

#2
11:40, 11 июля 2009

Чтото гдето не так с матрицами костей делаешь... Сложно сказать конкретно, может гдето на бинд позу не помножил, может наоборот помножил, да зря... :) Смотря как там всё хранится...

#3
12:21, 11 июля 2009

ок, довайте разбираться...

как всё хранится:

(немного у меня не оптимизированно но мне главное сейчас результат а потом оптимизирую ^^)

Есть класс Skeleton

в нём массив костей. У каждой кости есть Имя, ID, ссылки на родительскую кость и на дочерние кости.  У Root кости ссылка на родителя = null

итак:

1. RootBone - кость с ID  = -1.  на неё ни что в меше не забиндено. Она просто root-ом является и всё. Все её матрицы = Identity.

У RootBone 2 дочерних кости:  кость с ID = 0  - сам меш.  У меня от неё ни чего не наследуется.  И вторая кость с ID = 1 - первая "реальная" кость в скелете.  И далее у этой кости есть дети, у детей другие дети и т.д. - обычное дерево.

Как происходит у меня анимация:

1. Блендю матрицы анимации, полученные матрицы выставляю костям!  (у кости она называется LocalMatrix)

у RootBone вызываем функцию

 public void UpdateMatrices()
        {
            if(Parent !=null)
                WorldMatrix = Parent.WorldMatrix *(g_baseMat *  LocalMatrix);
            if (Childs != null && Childs.Length > 0)
                for (int i = 0; i < Childs.Length; i++)
                    Childs[i].UpdateMatrices();
                   
        }

тут g_baseMat  это инвертированная матрица первого кадра.

Вот так у меня хранится

#4
14:42, 11 июля 2009

Если для геометрии нужно Y и  Z координаты вершин поменять местами, нужно ли их менять местами для поворотов?

#5
14:49, 11 июля 2009

и ещё, вот как я строю (читаю) матрицу кости..это верно?

                    Matrix boneMatrix = Matrix.RotationX(Convert.ToSingle(frameData[4])) *
                        Matrix.RotationY(Convert.ToSingle(frameData[6])) *
                        Matrix.RotationZ(Convert.ToSingle(frameData[5])) *
                        Matrix.Translation(new Vector3(
                            Convert.ToSingle(frameData[1]),
                             Convert.ToSingle(frameData[3]),
                              Convert.ToSingle(frameData[2])));
#6
16:06, 11 июля 2009

up ^

#7
21:53, 11 июля 2009

^

#8
22:33, 11 июля 2009

Если уж ни кто помочь не может, может поделитесь загрузчиком/отрисовщиком SMD?  Желательно только это без лишнего кода - чтоб только загружалась и отображалась модель.  C++  или C# - не важно.  Ессно на DirectX. Спасибо.

#9
14:38, 21 июля 2009

блин... типа ни у кого SMD не грузится???  > : (

#10
16:05, 21 июля 2009

Не понятно что происходит с поворотами костей о_О

вот сначала как я всё гружу и рисую (псевдокодом)

1. ЗАГРУЗКА МОДЕЛИ
а. грузим скелет - строим иерархию согласно nodes блоку. (Класс Skeleton - в нём хранится rootBone (класс Bone) в котором ссылки надочерние кости, у каждой кости также есть ссылка на родительскую кость)
б. каждой ноде загружаем трансформации первого кадра из блока skeleton
как именно: 
>6 1.909899 -0.000000 0.000000 0.000000 0.000000 -0.007202
7 сегментов - сегмент #1 =  ID кости, беру эту кость
читаю позиции в  float px,py,pz; МЕНЯЯ местами Y и Z координаты  (переводим в координатную систему DirectX)
читаю повороты  в  float rx,ry,rz; МЕНЯЯ местами Y и Z координаты  (переводим в координатную систему DirectX)

теперь создаю из полученных данных матрицу:  BaseMatrix = MatrixRotationX(rx) * MatrixRotationY(ry) *
MatrixRotationZ(rz) * MatrixTranslation(tx,ty,tz);

итого получил скелет со связанными в правильную иерархию костями и их матрицами из первого кадра

в. читаю треугольники - у каждой вершины меняю также местами Y и  Z координаты.

2. ЧИТАЮ ФАЙЛ С АНИМАЦИЕЙ
там всё просто  есть класс AnimationTrack в него загружаются все кадры.. в каждом кадре для каждой кости загружается матрица трансформации. (матрица грузится также как и при загрузке модели в п.1)

3. ОТРИСОВКА
интерполирую кадры (тут всё чётко)  получаю матрицы трансформаций для каждой кости.

 
WorldMatrix  = ParentMatrix * (Matrix.Invert(BaseMatrix) * LocalMatrix);
где:
WorldMatrix = абсолютная матрица кости,
ParentMatrix = абсолютная матрица родительской кости,
(Matrix.Invert(BaseMatrix)) - инверсия базовой матрицы - матрицы нулевого кадра.
LocalMatrix кости = текущая интерполированная матрица.

полученные абсолютные матрицы передаю в шейдер (см. выше)

позиция  норме но повороты ужасны - по совсем другим осям крутятся кости)

#11
16:05, 21 июля 2009

Такое ощущение, что для каждой точки трансформаций, система координат установлена по разному и движутся они поэтому не туда, куда надо. Проверь в максе точки трансформаций, попробуй какой нибудь ResetXForm применить к модели.

Может дело не в бобине?

#12
16:08, 21 июля 2009

JR-44
> Такое ощущение, что для каждой точки трансформаций, система координат
> установлена по разному и движутся они поэтому не туда, куда над
вот вот так и есть!  те кости, что лежат вдоль оси Х, они НОРМАЛЬНО движутся! Остальные кости также и с такой скоростью поворачиваются как в максе но по другим осям! Не понятно почему : ( 

ResetXForm я попробую но AFAIK это устраняет только проблемму с инвертированными нормалями!

Просьба затестить прикреплённые к посту #1 модель и анимацию! Может действительно в НИХ проблема а не в  моём коде?
ОЧЕНЬ нужно! Риальне!  Мегареспект за любую помощь!

#13
16:21, 21 июля 2009

У меня тока х файлы грузит. Попробуй ее куда нибудь импортни - какую нибудь прогу, которая анимацию показывает и увидишь. Или попробовать импортнуть последний кадр анимации в DeepEploration например, тока надо в максе экспортнуть последний кадр.

#14
16:23, 21 июля 2009

В максе посмотри куда направлены оси координат этих центров. Они должны совпадать.

Страницы: 1 2 3 4 5 6 7 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.