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

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

Страницы: 1 2 3 4 5 6 7 Следующая »
#15
16:29, 21 июля 2009

heihachi
> pos = pos + mul(Input.Position, wmArray[IndexArray[0]]* (1.0f - LastWeight));
> norm = norm + mul(Input.Position, wmArray[IndexArray[0]]* (1.0f - LastWeight));
Привет, попробуй вместо wmArray[IndexArray[0]] последний индекс wmArray[IndexArray] - твоя ошибка в этом

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

Чувак
> твоя ошибка в этом
нет..  ошибка уж точно не в этом!  У меня передаётся остаточный вес на первую кость из ТЕХ которые действуют на эту вершину.. даже еслиб весь вес передавался то всеравно,хоть криво но выполнялась бы примерно таже анимация!  а тут по каждой оси в разные стороны кидает!  +  эта "фишка" в шейдере используется безтолку! т.к. веса полностью распределяются в программе!  и рапределяются правильно! (ну да, я убирал программно - одна фигня!)  дело НЕ в этом!

#17
22:01, 21 июля 2009

heihachi
А ты пробовал сменить последний вес? Просто у меня в свое время как раз дико глючило из за последнего веса.. А без анимации файл не глючит?

#18
22:11, 21 июля 2009

elephantman
> просто у меня в свое время как раз дико глючило из за последнего веса..
пробовал. Ни чего не выходит путёвого. Изза того веса модель должна тянуться или некоторые вершины оставаться в начальной позиции..  не это происходит


без анимации всё кулЪ, модель проверил во вьювере с анимацией - нормальна!  дайте ктонить свой загрузчег / отрисовщик
что было с чем сравнить а то вроде ну всё понятно!  но не работает.. это больше всего и напрягает : (

#19
22:17, 21 июля 2009

и да - есть ли гденить гид типа загрузка SMD моделей и отрисовка анимации на DirectX ??

#20
22:23, 21 июля 2009

По DirectX - в DirectX SDK для C# есть примеры со скелетной анимацией (SimpleAnimation) По smd - где то было, если найду - скину
Да и кстати, AnimationController ты двигаешь (AdvanceTime(elapsed))?

#21
22:27, 21 июля 2009

elephantman
> По smd - где то было, если найду - скину
Буду очень признателен.

elephantman
> По DirectX - в DirectX SDK для C# есть примеры со скелетной анимацией
> (SimpleAnimation)
тофигня! У меня она работала изначально как часы...  и я  то ведь вроде как и знаю как работает анимация, более того, как написать её лоадер/рендер. Что очень странно что не работает это всё!  Нету случайно экспортёра который сразу в LH координатную систему экспортирует? : )


п.с. чувак, обнови СДК!  Давно уже для C# ни чего не пихают в СДК к сожалению

#22
22:32, 21 июля 2009

А с какого формата экспортер надо, с smd? - тогда нету
Посмотри тут может что то найдешь

#23
22:57, 21 июля 2009

elephantman
> А с какого формата экспортер надо, с smd?
не, чтоб сразу правильно для DirectX из 3D Max экспортировал

#24
23:08, 21 июля 2009

Panda DirectX Exporter

#25
23:32, 21 июля 2009

elephantman
> Panda DirectX Exporter
аррр  нет : )  я проклял и изгнал Х формат!  он ЗЛО!  реквестирую экспортёр SMD из 3DMax который экспортирует правильную LeftHanded меш с анимацией  ^__^

#26
0:30, 22 июля 2009

хмм  странно это всё!  я остановил принудительно рендеринг на 30 кадре  (ессно не то, что должно быть отображается)

и попробовал вручную покрутить кости - нефиг делать! все кости чётко привязаны, веса правильно поставлены! все работает отлично! любой костью кручу как хочу .  значит в матрицах всё дело.  опишите точный полный процесс загрзки и создания матриц (со всеми шаманствами с обменом Y & Z координат и т.д.  пожалуйсто

#27
2:09, 22 июля 2009

А сколько всего костей?
Ты MAX_BONES используешь вообще не в том контексте. Она здесь не нужна.
> int IndexArray[MAX_BONES] = (int[MAX_BONES])(Input.BlendIndices);
> float WeightArray[MAX_BONES] = (float[MAX_BONES])(Input.BlendWeights);
В корне неверно, правильно будет:
int IndexArray[4] = (int[4])(Input.BlendIndices);
float WeightArray[4] = (float[4])(Input.BlendWeights);
А вообще попробуй вот это (если нормалсмэпинг не нужен, бинормали и тангенты можешь убрать) и сверь со своей вертекдекларацией:

struct SkinnedInfoNBT
{
    float4 Position;
    float3 Normal;
    float3 Tangent;
    float3 Binormal;
};

SkinnedInfoNBT SkinVertexNBT( float4 Position, float3 Normal, float3 Tangent, uint4 BlendIndices, float4 BlendWeight )
{
    SkinnedInfoNBT Output = (SkinnedInfoNBT)0;

    //Bone0
    uint iBone = BlendIndices.x;
    float fWeight = BlendWeight.x;
    matrix m = g_mBones[iBone];
    Output.Position += fWeight * mul( Position, m );
    Output.Normal += fWeight * mul( Normal, (float3x3)m );
    Output.Tangent += fWeight * mul( Tangent, (float3x3)m );

    //Bone1
    if(BlendWeight.y > 0.0f)
    {
        iBone = BlendIndices.y;
        fWeight = BlendWeight.y;
        m = g_mBones[iBone];
        Output.Position += fWeight * mul( Position, m );
        Output.Normal += fWeight * mul( Normal, (float3x3)m );
        Output.Tangent += fWeight * mul( Tangent, (float3x3)m );
    }

    //Bone2
    if(BlendWeight.z > 0.0f)
    {
        iBone = BlendIndices.z;
        fWeight = BlendWeight.z;
        m = g_mBones[iBone];
        Output.Position += fWeight * mul( Position, m );
        Output.Normal += fWeight * mul( Normal, (float3x3)m );
        Output.Tangent += fWeight * mul( Tangent, (float3x3)m );
    }

    //Bone3
    if(BlendWeight.w > 0.0f)
    {
        iBone = BlendIndices.w;
        fWeight = BlendWeight.w;
        m = g_mBones[iBone];
        Output.Position += fWeight * mul( Position, m );
        Output.Normal += fWeight * mul( Normal, (float3x3)m );
        Output.Tangent += fWeight * mul( Tangent, (float3x3)m );
    }

    Output.Binormal = cross(Normal, Tangent);

    return Output;
}

struct VS_INPUT
{
    float3  Position : POSITION;
    float4  Weights  : BLENDWEIGHT;
    uint4  Indices  : BLENDINDICES;
    float2  TexCoord : TEXCOORD;
    float3  Normal  : NORMAL;
    float3  Tangent  : TANGENT;
};

struct XCPSInput
{
    float4      Position    : SV_Position;
    float2      TexCoord    : TEXTURE0;
    float3      PositionWS  : TEXTURE1;
    float3      NormalWS    : TEXTURE2;
    float3      BinormalWS  : TEXTURE3;
    float3      TangentWS  : TEXTURE4;
};


XCPSInput VSSceneNBT( VS_INPUT input )
{
    SkinnedInfoNBT skinInfo = SkinVertexNBT( float4(input.Position, 1), input.Normal, input.Tangent, input.Indices, input.Weights );
    XCPSInput output = (XCPSInput)0;
    output.Position = mul(skinInfo.Position, g_mViewProjection);
    output.TexCoord = input.TexCoord;
    output.PositionWS = skinInfo.Position.xyz;
    output.NormalWS = skinInfo.Normal;
    output.TangentWS = skinInfo.Tangent;
    output.BinormalWS = skinInfo.Binormal;

    return output;
}

и еще, посмотри порядок умножения матриц анимации и костей. Порядок такой:
Child1*=Papent;
Child11*=Child1;
Child11*=Child12;
Bone1*=Child11;
Bone1*=Child12;
А вообше .SMD не самый лучшый выбор. Потеряй недельку и напиши собственный формат. Так глюки легче вылавливаются и модификация проще.

#28
12:48, 22 июля 2009

destrator
> Потеряй недельку и напиши собственный формат
у меня он есть только без анимации покачто.

destrator
> и еще, посмотри порядок умножения матриц анимации и костей. Порядок такой:
в любом порядке получается бред

шейдер у тебя немножко не универсален ты забыл про остаточный вес - если модель будет замоделена так что все кости в сумме не будут давать
1.0 вес то вершины будут "тянуться" к начальной позиции.

шейдер у меня 100% рабочий и декларация тоже! вот она:

VertexElement[] elements = new VertexElement[]
            {
                new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0),
                new VertexElement(0, 12, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Normal,0),
                new VertexElement(0, 24, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate,0),
                new VertexElement(0, 32, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.BlendIndices,0),
                new VertexElement(0, 48, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.BlendWeight,0),
                VertexElement.VertexDeclarationEnd
            };
            VertexDeclaration decl = new VertexDeclaration(CG.GraphicsDevice, elements);

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

-- ФУНКЦИЯ ЗАГРУЗКИ АНИМАЦИИ

   public static LifeAnimationTrack LoadSMDAnimation(string fileName, Skeleton skelet)
        {
            LifeAnimationTrack animationTrack = new LifeAnimationTrack();
   
            float sampleRate = 30.0f;
            //get full animation path
            string filePath = LifeFileSystem.AnimationsPath + fileName;


            //++++++++++++++++++++++++++++LOAD SMD ANIMATION+++++++++++++++++++++++++++++
            FileStream stream = new FileStream(filePath, FileMode.Open);
            StreamReader reader = new StreamReader(stream, true);
            string tmp = reader.ReadLine();
            //Read header and check file version
            Debug.Assert(tmp.Split(' ')[1] == "1", "Wrong file version!");

            SortedList<int, LifeFrame> frames = new SortedList<int, LifeFrame>();
            //Skip everything up to "skeleton" token
            do tmp = reader.ReadLine(); while (tmp != "skeleton");
            //move to the first bone
            string[] frameData;
            string[] tmpData;
            int frameKey = 0;
            int maxFrameNumber = 0;
            do
            {
                tmp = reader.ReadLine();
                tmpData = tmp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                //if new frame, add it to the buffer
                if (tmpData[0] == "time")
                {
                    LifeFrame frame = new LifeFrame((float)Convert.ToInt32(tmpData[1])/sampleRate);
                    frame.FrameName = Convert.ToInt32(tmpData[1]);
                    frames.Add(Convert.ToInt32(tmpData[1]), frame);
                    frameKey = Convert.ToInt32(tmpData[1]);

                    maxFrameNumber = Convert.ToInt32(tmpData[1]);
                }
                else if(tmp!="end") //if not new frame, read transformation matrix for bone
                {
                    tmp = tmp.Replace('.', ',');
                    frameData = tmp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    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])));
                  
                    int bn = Convert.ToInt32(frameData[0]);
                    frames[frameKey].g_bonesTransformations.Add(bn,  boneMatrix);
                }
            }
            while (tmp != "end");
            //EOF, close any streams

            stream.Close();
            reader.Dispose();
            stream.Dispose();
            animationTrack.FramesCount = maxFrameNumber + 1;
            animationTrack.TrackTime = maxFrameNumber / sampleRate;
            animationTrack.Frames = new LifeFrame[maxFrameNumber + 1];
            frames.Values.CopyTo(animationTrack.Frames, 0);
            return animationTrack;
        }
#29
12:51, 22 июля 2009

--ФУНКЦИЯ ЗАГРУЗКИ МОДЕЛИ  (в ней внутри используется предыдущая функция)

  public static Geometric LoadModelSMD(string fileName)
        {
            //get full model path
            string filePath = LifeFileSystem.ObjectsPath + fileName;

           
            //++++++++++++++++++++++++++++LOAD SMD+++++++++++++++++++++++++++++
            SkinInforamtion skinInfo = new SkinInforamtion();
            List<TRIANGLE> triCache = new List<TRIANGLE>();
            Skeleton ObjSkeleton = new Skeleton();
            FileStream stream = new FileStream(filePath, FileMode.Open);
            StreamReader reader = new StreamReader(stream, true);
            string tmp = reader.ReadLine();

            //Read header and check file version
            Debug.Assert(tmp.Split(' ')[1] == "1", "Wrong file version!");

            //skip everything to move to "nodes" block
            do tmp = reader.ReadLine(); while (tmp != "nodes");
            tmp = reader.ReadLine();//advance position to the first node  
            string[] nodeData;
            //Read nodes
            int boneCnt = 0;
            do
            {
                boneCnt++;
                nodeData = tmp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                //Add a bone to the skeleton
                BONE b = ObjSkeleton.AddBone(
                    new BONE(Convert.ToInt32(nodeData[0]),
                    nodeData[1], ObjSkeleton.GetBone(Convert.ToInt32(nodeData[2]))));
                //If current bone is not root, we'll add current node as a child to the parent bone
                    ObjSkeleton.GetBone(Convert.ToInt32(nodeData[2])).AddChild(b);
                ObjSkeleton.maxBoneID = b.ID;
                tmp = reader.ReadLine();
            }
            while (tmp != "end");
            skinInfo.BonesCount = boneCnt;
            //Skip everything up to "skeleton" token
            do tmp = reader.ReadLine(); while (tmp != "skeleton");
            //move to the first bone
            string[] frameData;
            tmp = reader.ReadLine();
            tmp = reader.ReadLine();
            do
            {
                tmp = tmp.Replace('.', ',');
                frameData = tmp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                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])));
             

              
                ObjSkeleton.GetBone(Convert.ToInt32(frameData[0])).BaseMatrix = boneMatrix;
                ObjSkeleton.GetBone(Convert.ToInt32(frameData[0])).LocalMatrix = Matrix.Identity;

                tmp = reader.ReadLine();
            }
            while (tmp != "end");

            LifeAnimationController cntrl = new LifeAnimationController();
      
          
            cntrl.g_skeleton = ObjSkeleton;

            LifeAnimationTrack track = LoadSMDAnimation(fileName, ObjSkeleton);
            cntrl.AddTrack(track);
            skinInfo.Controller = cntrl;
            skinInfo.Skeleton = ObjSkeleton;
            //check, if we need to load this geometry.  maybe we have it in our cache already.
            if (g_geometryCache.Count > 0)
                for (int i = 0; i < g_geometryCache.Count; i++)
                    if (g_geometryCache.Values[i].ResourceDataName == filePath)
                    {
                       
                        return g_geometryCache[i];
                    }


            //Skip everything up to "triangles" token

            do tmp = reader.ReadLine(); while (tmp != "triangles");
            //move to the first triangle
            tmp = reader.ReadLine();
            //reading triangles
            string[] triData;
            CustomVertex.Skinned v1, v2, v3;
            int parentBone;
            do
            {
                TRIANGLE tri = new TRIANGLE();
                //read texture name
                triData = tmp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                tri.TextureName = triData[0];

                //------------------1'st vertex---------------------
                tmp = reader.ReadLine();
                tmp = tmp.Replace('.', ',');
                //read first vertex
                triData = tmp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                parentBone = Convert.ToInt32(triData[0]);
                v1 = new CustomVertex.Skinned();
                v1.Position = new Vector3(
                    Convert.ToSingle(triData[1]),
                    Convert.ToSingle(triData[3]),
                    Convert.ToSingle(triData[2]));
                v1.Normal = new Vector3(
                   Convert.ToSingle(triData[4]),
                   Convert.ToSingle(triData[6]),
                   Convert.ToSingle(triData[5]));
                v1.Texture = new Vector2(
                   Convert.ToSingle(triData[7]),
                   Convert.ToSingle(triData[8]));
                //reading bones count, which affecting on current vertex
                v1.Bones = new Vector4(0, 0, 0, 0);
                v1.Weights = new Vector4(0, 0, 0, 0);
                float totalWeight = 0;
                int offset = 9;
                int numBones = 0;
                if (triData.Length > 9)
                {
                    numBones = Convert.ToInt32(triData[9]);

                    if (numBones > 4)
                        Debug.Fail("Bones limit overflow!", "Maximum allowed count of bones per vertex: 4\nbut current bones count per vertex is: " + numBones.ToString());

             
                    for (int i = 0; i < numBones; i++)
                    {
                        if (i == 0)
                        {
                            v1.Bones.X = (float)Convert.ToInt32(triData[++offset]);
                            v1.Weights.X = Convert.ToSingle(triData[++offset]);
                            totalWeight += v1.Weights.X;
                        }
                        else if (i == 1)
                        {
                            v1.Bones.Y = (float)Convert.ToInt32(triData[++offset]);
                            v1.Weights.Y = Convert.ToSingle(triData[++offset]);
                            totalWeight += v1.Weights.Y;
                        }
                        else if (i == 2)
                        {
                            v1.Bones.Z = (float)Convert.ToInt32(triData[++offset]);
                            v1.Weights.Z = Convert.ToSingle(triData[++offset]);
                            totalWeight += v1.Weights.Z;
                        }
                        else if (i == 3)
                        {
                            v1.Bones.W = (float)Convert.ToInt32(triData[++offset]);
                            v1.Weights.W = Convert.ToSingle(triData[++offset]);
                            totalWeight += v1.Weights.W;
                        }
                    }
                }
                float addWeight = 1.0f - totalWeight;
                if (addWeight > 0)
                    if ((int)v1.Bones.X == parentBone)
                        v1.Weights.X += addWeight;
                    else if ((int)v1.Bones.Y == parentBone)
                        v1.Weights.Y += addWeight;
                    else if ((int)v1.Bones.Z == parentBone)
                        v1.Weights.Z += addWeight;
                    else if ((int)v1.Bones.W == parentBone)
                        v1.Weights.W += addWeight;


----------продолжение далее

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

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