5
\$\begingroup\$

I'm learning character animation with DirectX 9, and I'm new to 3D programming too.

I'm trying to use examples with my model that I'll be working with. They are from the book Character Animation with Direct3D, example 3.2 — hardware skinning.

Why loading of the Mesh and rendering works good: enter image description here

Skinned version of the example code produces horrible results. (The same code works fine with the sample model that's provided with the example). enter image description here

Please help me with ideas of where the mistake is. I don't have the intuition in 3D [yet].

...

Here is the render part of the hardware skinning:

void SkinnedMesh::Render(Bone *bone)
{
    if(bone == NULL)bone = (Bone*)m_pRootBone;

    //If there is a mesh to render...
    if(bone->pMeshContainer != NULL)
    {
        BoneMesh *boneMesh = (BoneMesh*)bone->pMeshContainer;

        if (boneMesh->pSkinInfo != NULL)
        {       
            // set up bone transforms
            int numBones = boneMesh->pSkinInfo->GetNumBones();
            for(int i=0;i < numBones;i++)
            {
                D3DXMatrixMultiply(&boneMesh->currentBoneMatrices[i],
                                   &boneMesh->boneOffsetMatrices[i], 
                                   boneMesh->boneMatrixPtrs[i]);
            }

            //Set HW matrix palette
            D3DXMATRIX view, proj;              
            g_pEffect->SetMatrixArray("MatrixPalette", boneMesh->currentBoneMatrices, boneMesh->pSkinInfo->GetNumBones());

            //Render the mesh
            for(int i=0;i < (int)boneMesh->NumAttributeGroups;i++)
            {
                int mtrlIndex = boneMesh->attributeTable[i].AttribId;
                if (mtrlIndex >= boneMesh->materials.size())
                    mtrlIndex = 0;
                g_pDevice->SetMaterial(&(boneMesh->materials[mtrlIndex]));
                g_pDevice->SetTexture(0, boneMesh->textures[mtrlIndex]);

                g_pEffect->SetTexture("texDiffuse", boneMesh->textures[mtrlIndex]);
                D3DXHANDLE hTech = g_pEffect->GetTechniqueByName("Skinning");
                g_pEffect->SetTechnique(hTech);
                g_pEffect->Begin(NULL, NULL);
                g_pEffect->BeginPass(0);

                boneMesh->MeshData.pMesh->DrawSubset(mtrlIndex);

                g_pEffect->EndPass();
                g_pEffect->End();
            }
        }
    }

    if(bone->pFrameSibling != NULL)Render((Bone*)bone->pFrameSibling);
    if(bone->pFrameFirstChild != NULL)Render((Bone*)bone->pFrameFirstChild);
}

where shaders are:

//////////////////////////////////////////////////////////////////////////
//                  Character Animation with Direct3D                   //
//                         Author: C. Granberg                          //
//                             2008 - 2009                              //
//////////////////////////////////////////////////////////////////////////

//Transformation Matrices
matrix matW;
matrix matVP;

//World Light Position
float3 lightPos;

//Texture
texture texDiffuse;

//Sampler
sampler DiffuseSampler = sampler_state
{
   Texture = (texDiffuse);
   MinFilter = Linear;   MagFilter = Linear;   MipFilter = Linear;
   AddressU  = Wrap;     AddressV  = Wrap;     AddressW  = Wrap;
   MaxAnisotropy = 16;
};

//Vertex Input
struct VS_INPUT
{
     float4 position : POSITION0;
     float3 normal   : NORMAL;
     float2 tex0     : TEXCOORD0;
};

//Vertex Output / Pixel Shader Input
struct VS_OUTPUT
{
     float4 position : POSITION0;
     float2 tex0     : TEXCOORD0;
     float  shade    : TEXCOORD1;
};

//Vertex Shader
VS_OUTPUT vs_lighting(VS_INPUT IN)
{
    VS_OUTPUT OUT = (VS_OUTPUT)0;

    //getting the position of the vertex in the world
    float4 posWorld = mul(IN.position, matW);
    float4 normal = normalize(mul(IN.normal, matW));

    //getting to position to object space
    OUT.position = mul(posWorld, matVP);

    OUT.shade = max(dot(normal, normalize(lightPos - posWorld)), 0.2f);

    OUT.tex0 = IN.tex0;

    return OUT;
}

//Pixel Shader
float4 ps_lighting(VS_OUTPUT IN) : COLOR0
{
    float4 color = tex2D(DiffuseSampler, IN.tex0);
    return color * IN.shade;
}

//Lighting Technique
technique Lighting
{
    pass P0
    {        
        Lighting = false;

        VertexShader = compile vs_2_0 vs_lighting();
        PixelShader  = compile ps_2_0 ps_lighting();
    }
}

//Pixel Shader
float4 ps_shadow(VS_OUTPUT IN) : COLOR0
{
    return float4(0.3f, 0.3f, 0.3f, 1.0f);
}

//Shadow Technique
technique Shadow
{
    pass P0
    {        
        Lighting = false;

        VertexShader = compile vs_2_0 vs_lighting();
        PixelShader  = compile ps_2_0 ps_shadow();
    }
}

////////////////////////////////////////////////////////////////////////////

extern float4x4 MatrixPalette[35]; 
extern int numBoneInfluences = 2;

//Vertex Input
struct VS_INPUT_SKIN
{
     float4 position : POSITION0;
     float3 normal   : NORMAL;
     float2 tex0     : TEXCOORD0;
     float4 weights  : BLENDWEIGHT0;
     int4   boneIndices : BLENDINDICES0;
};

VS_OUTPUT vs_Skinning(VS_INPUT_SKIN IN)
{
    VS_OUTPUT OUT = (VS_OUTPUT)0;

    float4 p = float4(0.0f, 0.0f, 0.0f, 1.0f);
    float3 norm = float3(0.0f, 0.0f, 0.0f);
    float lastWeight = 0.0f;
    int n = numBoneInfluences-1;
    IN.normal = normalize(IN.normal);

    //Blend vertex position & normal
    for(int i = 0; i < n; ++i)
    {
        lastWeight += IN.weights[i];
        p += IN.weights[i] * mul(IN.position, MatrixPalette[IN.boneIndices[i]]);
        norm += IN.weights[i] * mul(IN.normal, MatrixPalette[IN.boneIndices[i]]);
    }
    lastWeight = 1.0f - lastWeight;

    p += lastWeight * mul(IN.position, MatrixPalette[IN.boneIndices[n]]);
    norm += lastWeight * mul(IN.normal, MatrixPalette[IN.boneIndices[n]]);
    p.w = 1.0f;

    //Transform vertex to world space
    float4 posWorld = mul(p, matW);

    //... then to screen space
    OUT.position = mul(posWorld, matVP);

    //Copy UV coordinate
    OUT.tex0 = IN.tex0;

    //Calculate Lighting
    norm = normalize(norm);
    norm = mul(norm, matW);
    OUT.shade = max(dot(norm, normalize(lightPos - posWorld)), 0.2f);

    return OUT;
}

technique Skinning
{
    pass P0
    {
        Lighting = false;

        VertexShader = compile vs_2_0 vs_Skinning();
        PixelShader  = compile ps_2_0 ps_lighting();        
    }
}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ What kind of format are you using ( .x ?), what kind of modelling program are you using to export the model and what kind of exporter do you use? All of these can wreck havoc in skinned meshes :-) \$\endgroup\$
    – Valmond
    Commented Sep 14, 2011 at 16:08
  • 1
    \$\begingroup\$ You'll have to provide some code or at least a description of what you're doing when loading the model \$\endgroup\$
    – Tetrad
    Commented Sep 14, 2011 at 16:09
  • \$\begingroup\$ The model was exported from 3DS Max using Panda DirectX exporter. I'll add the code now. \$\endgroup\$ Commented Sep 14, 2011 at 16:41

2 Answers 2

1
\$\begingroup\$

If it works with one mesh but not the other then the code and the shader are okay, the model is not.

I did skinmesh with DirtectX a Loong time ago, there were this buggy exporter from microsoft you needed to fix and compile yourself. There seems to be an unpgraded version of that one (or a new one, I don't know but it seems it works), digging around I found it should be in the DirectX 9.0 SDK Extras

What you need to do is to COMPILE the plugin and for that you'll need a compiler like MSVC and the 3dsMax SDK (if you have a typical installation of 3dsMax you won't have it (the SDK ^^), relaunch the install and install the SDK too).

This will definitely work, it's a bit cumbersome though but who knows, there might be precompiled versions out there some where but it won't work if it isn't the same version of 3dsMax...

Good luck, skinmeshes are Hell (to be nice) to get up and running flawlessly but it's so nice when they do...

\$\endgroup\$
0
\$\begingroup\$

Take a look at this tutorial, it may give you a hint on what you are not doing, or doing wrong

Mesh Based Bone animation in XNA

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .