skeletal animation + light = fubar, help?

Started by
22 comments, last by drdlord 19 years, 8 months ago
Can you post your rendering code (including where you build your matrix palette after AdvanceTime())?
[sub]My spoon is too big.[/sub]
Advertisement
render starts here:

//--------------------------------------------------------------------  //mesh  //--------------------------------------------------------------------    m_time = 0.01f;  //render mesh  if(m_pmesh != NULL)  {    D3DXMATRIX matRotation;    D3DXMATRIX matResult;    LPD3DXMATRIX matMeshLink = m_pmesh->getWorldMat();    D3DXMatrixRotationY(&matRotation, D3DX_PI/180);    D3DXMatrixMultiply(matMeshLink, matMeshLink, &matRotation);    m_pmesh->setTime(m_time);    m_pmesh->render();  }


m_pmesh->setTime is defined here:

/** * sets up the bones in the mesh to the appropriate position for the  * given time in the animation uses the world matrix setup in move * @param time the time in the animation */void Mesh::setTime(float time){  if(m_pAnimController != NULL)    m_pAnimController->AdvanceTime(time, NULL);  updateFrame((MY_D3DXFRAME*)m_pFrameRoot, m_worldMatrix);  }/** * traverses the bones in a mesh setting them relitave to each other * @param curFrame the current frame to work on * @param parentMatrix the matrix of the parent of the current frame */void Mesh::updateFrame( MY_D3DXFRAME *curFrame,                         LPD3DXMATRIX parentMatrix ){  if(curFrame->LinkedTransformationMatrix != NULL)  {    D3DXMatrixMultiply( &curFrame->CombinedTransformationMatrix,                         &curFrame->TransformationMatrix,                         curFrame->LinkedTransformationMatrix );  }  else  {    D3DXMatrixMultiply( &curFrame->CombinedTransformationMatrix,                         &curFrame->TransformationMatrix, parentMatrix );  }  if (curFrame->pFrameSibling != NULL)    updateFrame( (MY_D3DXFRAME*)curFrame->pFrameSibling,                  parentMatrix );  if (curFrame->pFrameFirstChild != NULL)    updateFrame( (MY_D3DXFRAME*)curFrame->pFrameFirstChild,                  &curFrame->CombinedTransformationMatrix );}



and m_pmesh->render(); does this

/** * renders the mesh, (setup world transform before calling) */void Mesh::render(){  renderFrame(m_pFrameRoot);}/** * renders a frame in the mesh */void Mesh::renderFrame(LPD3DXFRAME frame){  MeshInfo *info = (MeshInfo*)frame->pMeshContainer;  while(info != NULL)  {    info->render();    info = (MeshInfo*)info->pNextMeshContainer;  }  if (frame->pFrameSibling != NULL)    renderFrame(frame->pFrameSibling);  if (frame->pFrameFirstChild != NULL)    renderFrame(frame->pFrameFirstChild);}/** * renders the mesh container */void MeshInfo::render(){  D3DCOLORVALUE blendCol;  blendCol.r = 0.0;  blendCol.g = 0.0;  blendCol.b = 0.0;  blendCol.a = 0.0;  LPDIRECT3DDEVICE9 device;  MeshData.pMesh->GetDevice(&device);    //if skinned mesh  if(pSkinInfo != NULL)  {    if (maxFaceInfl == 1)      device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS);    else      device->SetRenderState(D3DRS_VERTEXBLEND, maxFaceInfl - 1);        if (maxFaceInfl)      device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);    D3DXMATRIX matTemp;    //loop through each combination of bones    for (UINT i = 0; i < numBoneCombo; i++)    {      //loop through all posible bones      for (UINT j = 0; j < pSkinInfo->GetNumBones(); j++)      {        UINT index = boneComb.BoneId[j];        //if index is UINT_MAX then the bone isn't used in this combo        if (index != UINT_MAX)        {          D3DXMatrixMultiply( &matTemp,                               pSkinInfo->GetBoneOffsetMatrix(j),                              bones[j] );            device->SetTransform(D3DTS_WORLDMATRIX(j), &matTemp);        }      }      D3DMATERIAL9 tempMat = pMaterials[boneComb.AttribId].MatD3D;      tempMat.Diffuse.r = (tempMat.Diffuse.r + blendCol.r)/2;      tempMat.Diffuse.g = (tempMat.Diffuse.g + blendCol.g)/2;      tempMat.Diffuse.b = (tempMat.Diffuse.b + blendCol.b)/2;      tempMat.Diffuse.a = (tempMat.Diffuse.a + blendCol.a)/2;            tempMat.Ambient = tempMat.Diffuse;      device->SetMaterial(&tempMat);      device->SetTexture(0,pTextures[boneComb.AttribId]);      MeshData.pMesh->DrawSubset(i);    }    // reset blending state    device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);    device->SetRenderState(D3DRS_VERTEXBLEND, 0);  }  else //standard mesh  {    device->SetTransform(D3DTS_WORLD, bones[0]);    for (DWORD i = 0; i < NumMaterials; i++)    {      D3DMATERIAL9 tempMat = pMaterials.MatD3D;      tempMat.Diffuse.r = (tempMat.Diffuse.r + blendCol.r)/2;      tempMat.Diffuse.g = (tempMat.Diffuse.g + blendCol.g)/2;      tempMat.Diffuse.b = (tempMat.Diffuse.b + blendCol.b)/2;      tempMat.Diffuse.a = (tempMat.Diffuse.a + blendCol.a)/2;//      tempMat.Diffuse = blendCol;      tempMat.Ambient = tempMat.Diffuse;      device->SetMaterial(&tempMat);      device->SetTexture(0, pTextures);      MeshData.pMesh->DrawSubset(i);    }  }}


does that help?
Well, just looking at it I'm seeing something that may or may not help. In MeshInfo::render(), the line

for (UINT j = 0; j < pSkinInfo->GetNumBones(); j++)

is not quite correct unless your entire bone array fits in your matrix palette (in which case you'd only have one bone combination). Should be

for (UINT j = 0; j < dwPaletteSize; j++)

where dwPaletteSize is the value you passed in for paletteSize in ConvertToIndexedBlendedMesh().

Though, I just had a thought. You're using fixed function indexed blending. Are you taking into account the palette size is halved if you're using normals (if lighting is on)? I bet that's the thing: When you convert to the blended mesh, halve the palette size if lighting is on. (It's buried deep in the docs somewhere, and easy to miss; it's so the runtime can use half the available palette for inverse transpose versions of matrices to transform normals behind the scenes.) It'll probably require more draw calls (more bone combinations) but it's a necessity if you're doing fixed-function indexed skinning.
[sub]My spoon is too big.[/sub]
YAY!!!! It works!!!! I was asuming the matrix pallet was big enough, (and aparently on some cards it was) stupid assumption though.

Thank you all for replying and helping me out

*does a happy dance*

This topic is closed to new replies.

Advertisement