Re: C2259 : cannot instantiate abstract class
"John Carson" <jcarson_n_o_sp_am_@netspace.net.au> ???g???l???s?D:%23NaSbY9MHHA.4384@TK2MSFTNGP03.phx.gbl...
"Jacky" <jl@knight.com> wrote in message
news:uy%231QV9MHHA.1280@TK2MSFTNGP04.phx.gbl
In the inherited class, I have four methods declared as PURE on the
end of the declarations.
I derive this class to say class B
In class B, I am sure I have implemented all 4 methods mentioned
above. How come C2259 is still there? Could anybody help?
Thanks
Post the code. We aren't mind readers.
--
John Carson
Ok.. Let's start it from there
========================================================
DECLARE_INTERFACE(ID3DXAllocateHierarchy)
{
// ID3DXAllocateHierarchy
//------------------------------------------------------------------------
// CreateFrame:
// ------------
// Requests allocation of a frame object.
//
// Parameters:
// Name
// Name of the frame to be created
// ppNewFrame
// Returns the created frame object
//
//------------------------------------------------------------------------
STDMETHOD(CreateFrame)(THIS_ LPCSTR Name,
LPD3DXFRAME *ppNewFrame) PURE;
//------------------------------------------------------------------------
// CreateMeshContainer:
// --------------------
// Requests allocation of a mesh container object.
//
// Parameters:
// Name
// Name of the mesh
// pMesh
// Pointer to the mesh object if basic polygon data found
// pPMesh
// Pointer to the progressive mesh object if progressive mesh data found
// pPatchMesh
// Pointer to the patch mesh object if patch data found
// pMaterials
// Array of materials used in the mesh
// pEffectInstances
// Array of effect instances used in the mesh
// NumMaterials
// Num elements in the pMaterials array
// pAdjacency
// Adjacency array for the mesh
// pSkinInfo
// Pointer to the skininfo object if the mesh is skinned
// pBoneNames
// Array of names, one for each bone in the skinned mesh.
// The numberof bones can be found from the pSkinMesh object
// pBoneOffsetMatrices
// Array of matrices, one for each bone in the skinned mesh.
//
//------------------------------------------------------------------------
STDMETHOD(CreateMeshContainer)(THIS_
LPCSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer) PURE;
//------------------------------------------------------------------------
// DestroyFrame:
// -------------
// Requests de-allocation of a frame object.
//
// Parameters:
// pFrameToFree
// Pointer to the frame to be de-allocated
//
//------------------------------------------------------------------------
STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree) PURE;
//------------------------------------------------------------------------
// DestroyMeshContainer:
// ---------------------
// Requests de-allocation of a mesh container object.
//
// Parameters:
// pMeshContainerToFree
// Pointer to the mesh container object to be de-allocated
//
//------------------------------------------------------------------------
STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER
pMeshContainerToFree) PURE;
};
======================================================
Derived class: hope it won't be too overkilled :)
class CAllocateHierarchy : public ID3DXAllocateHierarchy
{
public:
// ID3DXInterpolator
STDMETHOD(CreateFrame)(THIS_ LPCSTR Name,
LPD3DXFRAME *ppNewFrame)
{
HRESULT hr = S_OK;
SFrame *pFrame;
*ppNewFrame = NULL;
pFrame = new SFrame;
if (pFrame == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
hr = AllocateName(Name, &pFrame->szName);
if (FAILED(hr))
goto e_Exit;
*ppNewFrame = (LPD3DXFRAME)pFrame;
pFrame = NULL;
e_Exit:
delete pFrame;
return hr;
}
STDMETHOD(CreateMeshContainer)(THIS_ LPCSTR Name, LPD3DXMESHDATA
pMeshData,
LPD3DXMATERIAL pMaterials, LPD3DXEFFECTINSTANCE
pEffects, DWORD NumMaterials,
DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
HRESULT hr;
SMeshContainer *pMeshContainer = NULL;
UINT iBone, cBones;
UINT NumFaces;
UINT iMaterial;
LPDIRECT3DDEVICE9 pd3dDevice = NULL;
LPDIRECT3DTEXTURE9 ptex;
LPD3DXEFFECT pEffect;
D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE];
CD3DXCrackDecl1 cd;
DWORD dwSkinningSupport;
LPD3DXBUFFER pbufErrors;
D3DXVECTOR3 vMeshCenter;
FLOAT fMeshRadius;
BOOL bUsesTangents = FALSE;
LPD3DXMESH pMesh = NULL;
LPD3DXPMESH pPMesh = NULL;
LPD3DXPATCHMESH pPatchMesh = NULL;
if (pMeshData->Type == D3DXMESHTYPE_PATCHMESH)
pPatchMesh = pMeshData->pPatchMesh;
else if (pMeshData->Type == D3DXMESHTYPE_PMESH)
pPMesh = pMeshData->pPMesh;
else
pMesh = pMeshData->pMesh;
*ppNewMeshContainer = NULL;
pMeshContainer = new SMeshContainer;
if (pMeshContainer == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
pMeshContainer->m_Method = g_pData->m_method;
pMeshContainer->m_iPaletteSize = g_pData->m_iPaletteSize;
hr = AllocateName(Name, &pMeshContainer->Name);
if (FAILED(hr))
goto e_Exit;
// if a patch mesh is found, enable tesselate mode for this node and
then generate a mesh via tesselation
if (pPatchMesh != NULL)
{
pPatchMesh->GetDevice(&pd3dDevice);
pMeshContainer->pPatchMesh = pPatchMesh;
pPatchMesh->AddRef();
hr = g_pData->Tesselate(pMeshContainer, FALSE);
if(FAILED(hr))
goto e_Exit;
pPatchMesh->GetDeclaration(pDecl);
pMeshContainer->bTesselateMode = TRUE;
}
// if a pmesh is found, setup this node to enable pmeshes and
allocate an adjacency array large enough for the max LOD
else if (pPMesh != NULL)
{
pPMesh->GetDevice(&pd3dDevice);
pMeshContainer->bPMMeshMode = true;
pMeshContainer->m_cNumVertices = pPMesh->GetNumVertices();
pMeshContainer->m_cMaxVerticesSoft = pPMesh->GetMaxVertices();
pMeshContainer->m_cMinVerticesSoft = pPMesh->GetMinVertices();
pMeshContainer->pPMMesh = pPMesh;
pMeshContainer->pPMMesh->AddRef();
NumFaces = pMeshContainer->pPMMesh->GetMaxFaces();
pMeshContainer->rgdwAdjacency = new DWORD[NumFaces*3];
if (pMeshContainer->rgdwAdjacency == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
// get the adjacency from the pmesh rather than the input
pMeshContainer->pPMMesh->GetAdjacency(pMeshContainer->rgdwAdjacency);
pMeshContainer->pPMMesh->GetDeclaration(pDecl);
}
// standard mesh found, allocate an adjacency buffer of the same
size
else
{
pMesh->GetDevice(&pd3dDevice);
pMeshContainer->pMesh = pMesh;
pMeshContainer->pMesh->AddRef();
NumFaces = pMeshContainer->pMesh->GetNumFaces();
pMeshContainer->rgdwAdjacency = new DWORD[NumFaces*3];
if (pMeshContainer->rgdwAdjacency == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
memcpy(pMeshContainer->rgdwAdjacency, pAdjacency, sizeof(DWORD)
* NumFaces*3);
pMeshContainer->pMesh->GetDeclaration(pDecl);
}
//.now that we have data for the vertex layout, create a crack decl
cd.SetDeclaration(pDecl);
// if no materials are found, then generate a "default" material of
gray
if ((pMaterials == NULL) || (NumMaterials == 0))
{
pMeshContainer->NumMaterials = 1;
pMeshContainer->m_cAttributeGroups = 1;
pMeshContainer->m_rgpfxAttributes = new
LPD3DXEFFECT[pMeshContainer->NumMaterials];
pMeshContainer->m_rgEffectInfo = new
SEffectInfo[pMeshContainer->NumMaterials];
pMeshContainer->rgMaterials = new
D3DXMATERIAL[pMeshContainer->NumMaterials];
if ((pMeshContainer->rgMaterials == NULL) ||
(pMeshContainer->m_rgEffectInfo == NULL) ||
(pMeshContainer->m_rgpfxAttributes == NULL))
{
pMeshContainer->NumMaterials = 0;
hr = E_OUTOFMEMORY;
goto e_Exit;
}
memset(pMeshContainer->rgMaterials, 0, sizeof(D3DXMATERIAL) *
pMeshContainer->NumMaterials);
memset(pMeshContainer->m_rgpfxAttributes, 0,
sizeof(LPD3DXEFFECT) * pMeshContainer->NumMaterials);
D3DMATERIAL9 mat;
memset(&mat, 0, sizeof(D3DMATERIAL9));
mat.Diffuse.r = 0.5f;
mat.Diffuse.g = 0.5f;
mat.Diffuse.b = 0.5f;
mat.Specular = mat.Diffuse;
pMeshContainer->rgMaterials[0].MatD3D = mat;
pMeshContainer->rgMaterials[0].pTextureFilename = NULL;
D3DXEFFECTINSTANCE EffectInstance;
memset(&EffectInstance, 0, sizeof(D3DXEFFECTINSTANCE));
// create effect instance will create a "default" effect when
pEffectFilename is NULL
hr = D3DXCreateEffectInstance(&EffectInstance, pd3dDevice,
&pMeshContainer->m_rgpfxAttributes[0], NULL);
if (FAILED(hr))
goto e_Exit;
//hr = GenerateEffectInfo(pMeshContainer->m_rgpfxAttributes[0],
&pMeshContainer->m_rgEffectInfo[0]);
//if (FAILED(hr))
//goto e_Exit;
// set our "default" material colors
pMeshContainer->m_rgpfxAttributes[0]->SetVector("Ambient",
(LPD3DXVECTOR4)&mat.Ambient);
pMeshContainer->m_rgpfxAttributes[0]->SetVector("Diffuse",
(LPD3DXVECTOR4)&mat.Diffuse);
pMeshContainer->m_rgpfxAttributes[0]->SetVector("Specular",
(LPD3DXVECTOR4)&mat.Specular);
}
// materials found, so save them off
else
{
pMeshContainer->m_rgpfxAttributes = new
LPD3DXEFFECT[NumMaterials];
pMeshContainer->m_rgEffectInfo = new SEffectInfo[NumMaterials];
pMeshContainer->rgMaterials = new D3DXMATERIAL[NumMaterials];
pMeshContainer->pEffects = new D3DXEFFECTINSTANCE[NumMaterials];
pMeshContainer->NumMaterials = NumMaterials;
pMeshContainer->m_cAttributeGroups = NumMaterials;
if ((pMeshContainer->rgMaterials == NULL) ||
(pMeshContainer->m_rgEffectInfo == NULL) ||
(pMeshContainer->m_rgpfxAttributes == NULL))
{
pMeshContainer->NumMaterials = 0;
hr = E_OUTOFMEMORY;
goto e_Exit;
}
memset(pMeshContainer->rgMaterials, 0, sizeof(D3DXMATERIAL) *
NumMaterials);
memset(pMeshContainer->m_rgpfxAttributes, 0,
sizeof(LPD3DXEFFECT) * NumMaterials);
memset(pMeshContainer->pEffects, 0, sizeof(D3DXEFFECTINSTANCE) *
NumMaterials);
for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
{
hr = CopyEffectInstance(&pEffects[iMaterial],
&pMeshContainer->pEffects[iMaterial]);
if (FAILED(hr))
goto e_Exit;
pMeshContainer->rgMaterials[iMaterial].MatD3D =
pMaterials[iMaterial].MatD3D;
ptex = NULL;
if (pMaterials[iMaterial].pTextureFilename != NULL)
{
DWORD cchFilename =
strlen(pMaterials[iMaterial].pTextureFilename) + 1;
pMeshContainer->rgMaterials[iMaterial].pTextureFilename
= new char[cchFilename];
if
(pMeshContainer->rgMaterials[iMaterial].pTextureFilename == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
memcpy(pMeshContainer->rgMaterials[iMaterial].pTextureFilename,
pMaterials[iMaterial].pTextureFilename,
sizeof(char) * cchFilename);
}
hr = D3DXCreateEffectInstance(&pEffects[iMaterial],
pd3dDevice, &pMeshContainer->m_rgpfxAttributes[iMaterial], &pbufErrors);
if (pbufErrors)
{
MessageBox(NULL, (LPSTR)pbufErrors->GetBufferPointer(),
"Effect file errors", MB_OK);
GXRELEASE(pbufErrors);
}
if (FAILED(hr))
goto e_Exit;
//pMeshContainer->m_rgpfxAttributes[iMaterial]->SetTechnique((LPCSTR)1);
//hr =
GenerateEffectInfo(pMeshContainer->m_rgpfxAttributes[iMaterial],
&pMeshContainer->m_rgEffectInfo[iMaterial]);
//if (FAILED(hr))
// goto e_Exit;
}
}
// if skinning info is found, then we need to setup all info for
skinning this mesh container
if (pSkinInfo != NULL)
{
pMeshContainer->pSkinInfo = pSkinInfo;
pSkinInfo->AddRef();
pMeshContainer->m_pOrigMesh = pMesh;
pMesh->AddRef();
cBones = pSkinInfo->GetNumBones();
pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
pMeshContainer->m_pBoneMatrix = new D3DXMATRIX*[cBones];
if ((pMeshContainer->m_pBoneMatrix == NULL) ||
(pMeshContainer->pBoneOffsetMatrices == NULL))
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
for (iBone = 0; iBone < cBones; iBone++)
{
pMeshContainer->pBoneOffsetMatrices[iBone] =
*(pSkinInfo->GetBoneOffsetMatrix(iBone));
}
hr = GenerateMesh(pMeshContainer);
if (FAILED(hr))
goto e_Exit;
dwSkinningSupport = D3DXST_3WEIGHT;
}
else // non-skinned case, unskinned required
{
dwSkinningSupport = D3DXST_UNSKINNED;
}
pd3dDevice->SetSoftwareVertexProcessing(TRUE);
pMeshContainer->m_dwSkinningType = dwSkinningSupport;
pd3dDevice->SetFVF(D3DFVF_XYZ);
// now that the skinning mode has been selected, select the first
technique to match it and validate
for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials;
iMaterial++)
{
hr =
SelectTechnique(pMeshContainer->m_rgpfxAttributes[iMaterial],
dwSkinningSupport);
if (FAILED(hr))
{
DPF(0, "CreateMeshContainer: No technique found that will
validate");
goto e_Exit;
}
hr =
GenerateEffectInfo(pMeshContainer->m_rgpfxAttributes[iMaterial],
&pMeshContainer->m_rgEffectInfo[iMaterial]);
if (FAILED(hr))
goto e_Exit;
D3DXTECHNIQUE_DESC TechniqueDesc;
D3DXPASS_DESC PassDesc;
D3DXHANDLE hPass;
D3DXHANDLE hTechnique;
hTechnique =
pMeshContainer->m_rgpfxAttributes[iMaterial]->GetCurrentTechnique();
pMeshContainer->m_rgpfxAttributes[iMaterial]->GetTechniqueDesc(hTechnique,
&TechniqueDesc);
for( UINT iPass = 0; iPass < TechniqueDesc.Passes; iPass++ )
{
hPass =
pMeshContainer->m_rgpfxAttributes[iMaterial]->GetPass( hTechnique, iPass );
pMeshContainer->m_rgpfxAttributes[iMaterial]->GetPassDesc(
hPass, &PassDesc );
// for( UINT iSem = 0; iSem < PassDesc.Annotations; iSem++ )
// {
// if( PassDesc.VSSemantics[iSem].Usage ==
D3DDECLUSAGE_TANGENT )
// {
// bUsesTangents = TRUE;
// break;
// }
// }
}
}
pd3dDevice->SetSoftwareVertexProcessing(FALSE);
// handle the case where there is a mesh without normals
if (pMeshContainer->pMesh != NULL)
{
/* if no normals in the mesh, then clone the mesh to add the
normals and then compute them */
if (cd.GetSemanticElement(D3DDECLUSAGE_NORMAL, 0) == NULL)
{
LPD3DXMESH pMeshTemp = pMeshContainer->pMesh;
AddNormal(cd, pDecl);
pMeshContainer->pMesh = NULL;
// clone in the space for the new normal
hr = pMeshTemp->CloneMesh(pMeshTemp->GetOptions(), pDecl,
pd3dDevice, &pMeshContainer->pMesh);
GXRELEASE(pMeshTemp);
if (FAILED(hr))
goto e_Exit;
hr = D3DXComputeNormals(pMeshContainer->pMesh, NULL);
if (FAILED(hr))
goto e_Exit;
}
if (bUsesTangents && (NULL ==
cd.GetSemanticElement(D3DDECLUSAGE_TANGENT, 0)))
{
LPD3DXMESH pMeshTemp = pMeshContainer->pMesh;
AddTangent(cd, pDecl);
pMeshContainer->pMesh = NULL;
// clone in the space for the new normal
hr = pMeshTemp->CloneMesh(pMeshTemp->GetOptions(), pDecl,
pd3dDevice, &pMeshContainer->pMesh);
GXRELEASE(pMeshTemp);
if (FAILED(hr))
goto e_Exit;
hr = D3DXComputeTangent( pMeshContainer->pMesh, 0, 0,
D3DX_DEFAULT, TRUE, NULL );
if (FAILED(hr))
goto e_Exit;
}
// down cast to the base mesh type (could also QI for it)
GXRELEASE(pMeshContainer->ptmDrawMesh);
pMeshContainer->ptmDrawMesh = pMeshContainer->pMesh;
pMeshContainer->ptmDrawMesh->AddRef();
}
// handle the case where there is a pmesh without normals
else if (pMeshContainer->pPMMesh != NULL)
{
/* if no normals in the mesh, then clone the mesh to add the
normals and then compute them */
if (cd.GetSemanticElement(D3DDECLUSAGE_NORMAL, 0) == NULL)
{
LPD3DXPMESH pPMeshTemp = pMeshContainer->pPMMesh;
pMeshContainer->pPMMesh = NULL;
AddNormal(cd, pDecl);
hr = pPMeshTemp->ClonePMesh(pPMeshTemp->GetOptions(), pDecl,
pd3dDevice, &pMeshContainer->pPMMesh);
GXRELEASE(pPMeshTemp);
if (FAILED(hr))
goto e_Exit;
hr = D3DXComputeNormals(pMeshContainer->pPMMesh, NULL);
if (FAILED(hr))
goto e_Exit;
}
// need compute tangent to take a base mesh
if (bUsesTangents && (NULL ==
cd.GetSemanticElement(D3DDECLUSAGE_TANGENT, 0)))
{
LPD3DXMESH pMeshTemp;
LPD3DXPMESH pPMeshTemp = pMeshContainer->pPMMesh;
pMeshContainer->pPMMesh = NULL;
AddTangent(cd, pDecl);
hr = pPMeshTemp->ClonePMesh(pPMeshTemp->GetOptions(), pDecl,
pd3dDevice, &pMeshContainer->pPMMesh);
GXRELEASE(pPMeshTemp);
if (FAILED(hr))
goto e_Exit;
// normal mesh required for compute tangent, so clone one that
uses the same VB and do the work there
// set to Max LOD so that all vertices will be touched
pMeshContainer->pPMMesh->SetNumVertices(0xffffffff);
// clone the mesh NOTE: SHARING the VB
hr =
pMeshContainer->pPMMesh->CloneMesh(pMeshContainer->pPMMesh->GetOptions() |
D3DXMESH_VB_SHARE, NULL, pd3dDevice, &pMeshTemp);
if (FAILED(hr))
goto e_Exit;
// compute the tangents on the mesh with the shared VB
hr = D3DXComputeTangent( pMeshTemp, 0, 0, D3DX_DEFAULT,
TRUE, NULL );
GXRELEASE (pMeshTemp);
if (FAILED(hr))
goto e_Exit;
}
// down cast to the base mesh type (could also QI for it)
GXRELEASE(pMeshContainer->ptmDrawMesh);
pMeshContainer->ptmDrawMesh = pMeshContainer->pPMMesh;
pMeshContainer->ptmDrawMesh->AddRef();
}
// setup attribute table
pMeshContainer->ptmDrawMesh->GetAttributeTable(NULL,
&pMeshContainer->m_caeAttributeTable);
// The load function will attribute sort the mesh, just make sure
that there is one
GXASSERT(pMeshContainer->m_caeAttributeTable > 0);
// allocate an attribute table for convenience purposes
delete []pMeshContainer->m_rgaeAttributeTable;
pMeshContainer->m_rgaeAttributeTable = new
D3DXATTRIBUTERANGE[pMeshContainer->m_caeAttributeTable];
if (pMeshContainer->m_rgaeAttributeTable == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
pMeshContainer->ptmDrawMesh->GetAttributeTable(pMeshContainer->m_rgaeAttributeTable,
&pMeshContainer->m_caeAttributeTable);
hr = CalculateBoundingSphereMC(pMeshContainer, &vMeshCenter,
&fMeshRadius);
if (FAILED(hr))
goto e_Exit;
// set the mesh radius/center into the effect
for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials;
iMaterial++)
{
SetEffectMeshInfo(pMeshContainer->m_rgpfxAttributes[iMaterial],
&vMeshCenter, fMeshRadius);
}
*ppNewMeshContainer = (LPD3DXMESHCONTAINER)pMeshContainer;
pMeshContainer = NULL;
e_Exit:
GXRELEASE(pd3dDevice);
// call Destroy function to properly clean up the memory allocated
if (pMeshContainer != NULL)
{
DestroyMeshContainer((LPD3DXMESHCONTAINER)pMeshContainer);
}
return hr;
}
STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree)
{
SFrame *pFrame = (SFrame*)pFrameToFree;
pFrame->pframeSibling = NULL;
pFrame->pframeFirstChild = NULL;
pFrame->pmcMesh = NULL;
delete pFrame;
return S_OK;
}
STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER
pMeshContainerBase)
{
SMeshContainer *pMeshContainer =
(SMeshContainer*)pMeshContainerBase;
// DON"T traverse the list of mesh containers to free them in the
destructor
pMeshContainer->pNextMeshContainer = NULL;
delete pMeshContainer;
return S_OK;
}
};
HRESULT
InitViews
(
SFrame *pframe,
SDrawElement *pde
)
{
HRESULT hr = S_OK;
SMeshContainer *pmcCur = pframe->pmcMesh;
SFrame *pframeCur;
while (pmcCur != NULL)
{
hr = pmcCur->UpdateViews(pde);
if (FAILED(hr))
goto e_Exit;
pmcCur = (SMeshContainer*)pmcCur->pNextMeshContainer;
}
pframeCur = pframe->pframeFirstChild;
while (pframeCur != NULL)
{
hr = InitViews(pframeCur, pde);
if (FAILED(hr))
goto e_Exit;
pframeCur = pframeCur->pframeSibling;
}
e_Exit:
return hr;
}