Beispiel #1
0
//--------------------------------------------------------------------------------------
CPUTBuffer *CPUTModel::GetBuffer( const cString &name, int meshIndex ) const
{
    if( meshIndex >= 0 )
    {
        CPUTMaterial *pMaterial = mpMaterial[meshIndex];
        if( pMaterial )
        {
            UINT bufferCount = pMaterial->GetBufferCount();
            for( UINT ii=0; ii<bufferCount; ii++ )
            {
                CPUTBuffer *pBuffer = pMaterial->GetBuffer(ii);
                if( 0 == _wcsicmp( pBuffer->GetName().data(), name.data() ) )
                {
                    pBuffer->AddRef();
                    return pBuffer;
                }
            }
        }
    }
    else
    {
        // No meshIndex specified, so check all materials
        for(UINT ii=0; ii<mMeshCount; ii++ )
        {
            CPUTBuffer *pBuffer = GetBuffer( name, ii );
            if( pBuffer )
            {
                return pBuffer;
            }
        }
    }
    return NULL;
}
//--------------------------------------------------------------------------------------
CPUTMaterial *CPUTMaterial::CreateMaterial(
    const    cString &absolutePathAndFilename,
    const    cString &modelSuffix,
    const    cString &meshSuffix,
    char   **pShaderMacros, // Note: this is honored only on first load.  Subsequent GetMaterial calls will return the material with shaders as compiled with original macros.
    int      numSystemMaterials,
    cString *pSystemMaterialNames
){
    // material was not in the library, so load it
#ifdef CPUT_FOR_DX11
    CPUTMaterial *pMaterial = new CPUTMaterialDX11();
#else    
    #error You must supply a target graphics API (ex: #define CPUT_FOR_DX11), or implement the target API for this file.
#endif
    CPUTResult result = pMaterial->LoadMaterial(absolutePathAndFilename, modelSuffix, meshSuffix, pShaderMacros, numSystemMaterials, pSystemMaterialNames );
    ASSERT( CPUTSUCCESS(result), _L("\nError - CPUTAssetLibrary::GetMaterial() - Error in material file: '")+absolutePathAndFilename+_L("'") );
    UNREFERENCED_PARAMETER(result);

    // add material to material library list
    // cString finalName = pMaterial->MaterialRequiresPerModelPayload() ? absolutePathAndFilename +  modelSuffix + meshSuffix : absolutePathAndFilename;
    // CPUTAssetLibrary::GetAssetLibrary()->AddMaterial( finalName, pMaterial );
    CPUTAssetLibrary::GetAssetLibrary()->AddMaterial( absolutePathAndFilename, pMaterial );

    return pMaterial;
}
// TODO: All of these Get() functions look very similar.
// Keep them all for their interface, but have them call a common function
//-----------------------------------------------------------------------------
CPUTMaterial *CPUTAssetLibrary::GetMaterial(const cString &name, bool nameIsFullPathAndFilename, const cString &modelSuffix, const cString &meshSuffix)
{
    // Resolve name to absolute path before searching
    CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
    cString absolutePathAndFilename;
    pServices->ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename? name : (mMaterialDirectoryName + name + _L(".mtl")), &absolutePathAndFilename);

    // If we already have one by this name, then return it
    CPUTMaterial *pMaterial = FindMaterial(absolutePathAndFilename, true);
    if(NULL==pMaterial)
    {
        // We don't already have it in the library, so create it.
        pMaterial = CPUTMaterial::CreateMaterial( absolutePathAndFilename, modelSuffix, meshSuffix );
        return pMaterial;
    }
    else if( (0==modelSuffix.length()) && !pMaterial->MaterialRequiresPerModelPayload() )
    {
        // This material doesn't have per-model elements, so we don't need to clone it.
        pMaterial->AddRef();
        return pMaterial;
    }

#ifdef _DEBUG
    // We need to clone the material.  Do that by loading it again, but with a different name.
    // Add the model's suffix (address as string, plus model's material array index as string)
    CPUTMaterial *pUniqueMaterial = FindMaterial(absolutePathAndFilename + modelSuffix + meshSuffix, true);
    ASSERT( NULL == pUniqueMaterial, _L("Unique material already not unique: ") + absolutePathAndFilename + modelSuffix + meshSuffix );
#endif

    CPUTMaterial *pClonedMaterial = pMaterial->CloneMaterial( absolutePathAndFilename, modelSuffix, meshSuffix );
    AddMaterial( absolutePathAndFilename + modelSuffix + meshSuffix, pClonedMaterial );

    return pClonedMaterial;
}
//--------------------------------------------------------------------------------------
CPUTMaterial *CPUTMaterial::CreateMaterial(
    const cString   &absolutePathAndFilename,
    const CPUTModel *pModel,
    int        meshIndex,
    const char     **pShaderMacros, // Note: this is honored only on first load.  Subsequent GetMaterial calls will return the material with shaders as compiled with original macros.
    int        numSystemMaterials,
    cString   *pSystemMaterialNames,
    int        externalCount,
    cString   *pExternalName,
    float4    *pExternals,
    int       *pExternalOffset,
    int       *pExternalSize
    ){
        // Create the material and load it from file.
        //#ifdef CPUT_FOR_DX11
        //    CPUTMaterial *pMaterial = new CPUTMaterialDX11();
        //#elif (defined(CPUT_FOR_OGL) || defined(CPUT_FOR_OGLES))
        //    CPUTMaterial *pMaterial = new CPUTMaterialOGL();
        //#else    
        //    #error You must supply a target graphics API (ex: #define CPUT_FOR_DX11), or implement the target API for this file.
        //#endif

        //    pMaterial->mpSubMaterials = NULL;
        CPUTMaterial* pMaterial = new CPUTMaterial();

        CPUTResult result = pMaterial->LoadMaterial( absolutePathAndFilename, pModel, meshIndex, pShaderMacros, numSystemMaterials, pSystemMaterialNames, externalCount, pExternalName, pExternals, pExternalOffset, pExternalSize );
        ASSERT( CPUTSUCCESS(result), _L("\nError - CPUTAssetLibrary::GetMaterial() - Error in material file: '")+absolutePathAndFilename+_L("'") );
        UNREFERENCED_PARAMETER(result);

        // Add the material to the asset library.
        CPUTAssetLibrary::GetAssetLibrary()->AddMaterial( absolutePathAndFilename, _L(""), _L(""), pMaterial, pShaderMacros );

        return pMaterial;
}
CPUTMaterial *CPUTAssetLibrary::GetMaterialByName(const cString &name)
{
    CPUTMaterial *pMaterial = (CPUTMaterial *) FindAssetByName(name, mpMaterialList);
    if (pMaterial != NULL)
    {
        pMaterial->AddRef();
        return pMaterial;
    }

    return NULL;
}
//-----------------------------------------------------------------------------
void CPUTAssetSet::RenderRecursive(CPUTRenderParameters &renderParams, int materialIndex)
{
	if (!IsEnabled)
		return;
    CPUTMaterial* pCurrentMaterial = NULL;
    CPUTRenderStateBlock* pCurrentRenderState = NULL;
    CPUTRenderNode* pCurrent = mpRootNode;
    CPUTInputLayoutCache* pInputLayoutCache = CPUTInputLayoutCache::GetInputLayoutCache();
    while (pCurrent)
    {
        if (pCurrent->GetNodeType() == CPUTRenderNode::CPUT_NODE_MODEL)
        {
            CPUTModel* pModel = (CPUTModel*)pCurrent;
            pModel->UpdateShaderConstants(renderParams);
            int meshCount = pModel->GetMeshCount();
            for (int mesh = 0; mesh < meshCount; mesh++)
            {
                CPUTMaterial* pMaterial = pModel->GetMaterial(mesh, materialIndex);
                if (pMaterial != NULL)
                {
                    CPUTRenderStateBlock* pRenderStateBlock = pMaterial->GetRenderStateBlock();
                    CPUTMesh* pMesh = pModel->GetMesh(mesh);
                    SetMaterialStates(pMaterial, pCurrentMaterial);
                    SetRenderStateBlock(pRenderStateBlock, pCurrentRenderState);
                    pInputLayoutCache->Apply(pMesh, pMaterial);
                    pMesh->Draw();
                    SAFE_RELEASE(pCurrentMaterial);
                    pCurrentMaterial = pMaterial;
                    SAFE_RELEASE(pCurrentRenderState)
                    pCurrentRenderState = pRenderStateBlock;
                }
            }
        }
        CPUTRenderNode* pNext = pCurrent->GetChild();
        if (pNext == NULL)
        {
            pNext = pCurrent->GetSibling();

            if (pNext == NULL)
            {
                pNext = pCurrent->GetParent();
                if (pNext != NULL)
                {
                    pNext = pNext->GetSibling();
                }
            }
        }
        pCurrent = pNext;
    }
    SAFE_RELEASE(pCurrentMaterial);
    SAFE_RELEASE(pCurrentRenderState);
}
//-----------------------------------------
void CPUTSprite::DrawSprite(
    CPUTRenderParameters &renderParams,
    CPUTMaterial         &material
)
{
    // TODO: Should we warn here?
    // If it doesn't draw, make sure you created it with createDebugSprite == true
    if( mpVertexBuffer )
    {
        ID3D11DeviceContext *pContext = ((CPUTRenderParametersDX*)&renderParams)->mpContext;

        material.SetRenderStates(renderParams);

        UINT stride = sizeof( SpriteVertex );
        UINT offset = 0;
        pContext->IASetVertexBuffers( 0, 1, &mpVertexBuffer, &stride, &offset );

        // Set the input layout
        pContext->IASetInputLayout( mpInputLayout );

        // Set primitive topology
        pContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

        pContext->Draw( 6, 0 );
    }
} // CPUTSprite::DrawSprite()
void Menu_FaceMapping::LoadFace(const std::string &filename)
{
	mObjFilename = filename;
	mFaceModel.LoadObjFilename(filename);

	CPUTTexture *texture;
	mFaceCPUTModel = mFaceModel.LoadCPUTModel(&texture);

	CPUTAssetLibrary *pAssetLibrary = CPUTAssetLibrary::GetAssetLibrary();
	pAssetLibrary->SetRootRelativeMediaDirectory("MyAssets");
	std::string matName = pAssetLibrary->GetMaterialDirectoryName();
	CPUTFileSystem::CombinePath(matName, "displace_map_render.mtl", &matName);

	CPUTMaterial *material = CPUTMaterial::Create(matName);
	material->OverridePSTexture(0, texture);
	mFaceCPUTModel->SetMaterial(0, &material, 1);
}
CPUTMaterial *CPUTMaterial::CreateMaterial( const cString &absolutePathAndFilename, const CPUTModel *pModel, int meshIndex )
{
    // material was not in the library, so load it
#ifdef CPUT_FOR_DX11
    CPUTMaterial *pMaterial = new CPUTMaterialDX11();
#else    
    #error You must supply a target graphics API (ex: #define CPUT_FOR_DX11), or implement the target API for this file.
#endif
    CPUTResult result = pMaterial->LoadMaterial(absolutePathAndFilename, pModel, meshIndex);
    ASSERT( CPUTSUCCESS(result), _L("\nError - CPUTAssetLibrary::GetMaterial() - Error in material file: '")+absolutePathAndFilename+_L("'") );

    // add material to material library list
    if( pModel && pMaterial->MaterialRequiresPerModelPayload() )
    {
        CPUTAssetLibrary::GetAssetLibrary()->AddMaterial( absolutePathAndFilename, pMaterial, pModel, meshIndex );
    } else
    {
        CPUTAssetLibrary::GetAssetLibrary()->AddMaterial( absolutePathAndFilename, pMaterial );
    }

    return pMaterial;
}
// TODO: All of these Get() functions look very similar.
// Keep them all for their interface, but have them call a common function
//-----------------------------------------------------------------------------
CPUTMaterial *CPUTAssetLibrary::GetMaterial(
    const std::string   &name,
    bool                 nameIsFullPathAndFilename
){
    // Resolve name to absolute path before searching
    std::string absolutePathAndFilename;
    if (name[0] == '%')
    {
        absolutePathAndFilename = mSystemDirectoryName + "Material/" + name.substr(1) + ".mtl";  // TODO: Instead of having the Material/directory hardcoded here it could be set like the normal material directory. But then there would need to be a bunch new variables like SetSystemMaterialDirectory
        CPUTFileSystem::ResolveAbsolutePathAndFilename(absolutePathAndFilename, &absolutePathAndFilename);
    } else if( !nameIsFullPathAndFilename )
    {
        CPUTFileSystem::ResolveAbsolutePathAndFilename( mMaterialDirectoryName + name + ".mtl", &absolutePathAndFilename);
    } else
    {
        absolutePathAndFilename = name;
    }

    CPUTMaterial *pMaterial = NULL;

    pMaterial = FindMaterial(absolutePathAndFilename, true);

    if( pMaterial )
    {
        pMaterial->AddRef();
    }
    else
    {
        pMaterial = CPUTMaterial::Create(absolutePathAndFilename);
        LIBRARY_ASSERT(pMaterial, "Failed creating material Effect.");
        if (pMaterial != NULL)
        {
            AddMaterial(absolutePathAndFilename, "", "", pMaterial);
        }
    }
    return pMaterial;
}
// Load the set file definition of this object
// 1. Parse the block of name/parent/transform info for model block
// 2. Load the model's binary payload (i.e., the meshes)
// 3. Assert the # of meshes matches # of materials
// 4. Load each mesh's material
//-----------------------------------------------------------------------------
CPUTResult CPUTModelOGL::LoadModel(CPUTConfigBlock *pBlock, int *pParentID, CPUTModel *pMasterModel, int numSystemMaterials, cString *pSystemMaterialNames)
{
    CPUTResult result = CPUT_SUCCESS;
    CPUTAssetLibraryOGL *pAssetLibrary = (CPUTAssetLibraryOGL*)CPUTAssetLibrary::GetAssetLibrary();

    cString modelSuffix = ptoc(this);

    // set the model's name
    mName = pBlock->GetValueByName(_L("name"))->ValueAsString();
    mName = mName + _L(".mdl");

    // resolve the full path name
    cString modelLocation;
    cString resolvedPathAndFile;
    modelLocation = ((CPUTAssetLibraryOGL*)CPUTAssetLibrary::GetAssetLibrary())->GetModelDirectoryName();
    modelLocation = modelLocation+mName;

    CPUTFileSystem::ResolveAbsolutePathAndFilename(modelLocation, &resolvedPathAndFile);

    // Get the parent ID.  Note: the caller will use this to set the parent.
    *pParentID = pBlock->GetValueByName(_L("parent"))->ValueAsInt();

    LoadParentMatrixFromParameterBlock( pBlock );

    // Get the bounding box information
    float3 center(0.0f), half(0.0f);
    pBlock->GetValueByName(_L("BoundingBoxCenter"))->ValueAsFloatArray(center.f, 3);
    pBlock->GetValueByName(_L("BoundingBoxHalf"))->ValueAsFloatArray(half.f, 3);
    mBoundingBoxCenterObjectSpace = center;
    mBoundingBoxHalfObjectSpace   = half;

    mMeshCount = pBlock->GetValueByName(_L("meshcount"))->ValueAsInt();
    mpMesh     = new CPUTMesh*[mMeshCount];
    mpLayoutCount = new UINT[mMeshCount];
    mpRootMaterial = new CPUTMaterial*[mMeshCount];
    memset( mpRootMaterial, 0, mMeshCount * sizeof(CPUTMaterial*) );
    mpMaterialEffect = new CPUTMaterialEffect**[mMeshCount];
    memset( mpMaterialEffect, 0, mMeshCount * sizeof(CPUTMaterialEffect*) );
       
    // get the material names, load them, and match them up with each mesh
    cString materialName,shadowMaterialName;
    char pNumber[4];
    cString materialValueName;

    CPUTModelOGL *pMasterModelDX = (CPUTModelOGL*)pMasterModel;

    for(UINT ii=0; ii<mMeshCount; ii++)
    {
        if(pMasterModelDX)
        {
            // Reference the master model's mesh.  Don't create a new one.
            mpMesh[ii] = pMasterModelDX->mpMesh[ii];
            mpMesh[ii]->AddRef();
        }
        else
        {
            mpMesh[ii] = new CPUTMeshOGL();
        }
    }
    if( !pMasterModelDX )
    {
        // Not a clone/instance.  So, load the model's binary payload (i.e., vertex and index buffers)
        // TODO: Change to use GetModel()
        result = LoadModelPayload(resolvedPathAndFile);
        ASSERT( CPUTSUCCESS(result), _L("Failed loading model") );
    }

    for(UINT ii=0; ii<mMeshCount; ii++)
    {
        // get the right material number ('material0', 'material1', 'material2', etc)
        materialValueName = _L("material");
        snprintf(pNumber, 4, "%d", ii);
//        _itoa(ii, pNumber, 4, 10);
        materialValueName.append(s2ws(pNumber));
        materialName = pBlock->GetValueByName(materialValueName)->ValueAsString();
        shadowMaterialName = pBlock->GetValueByName(_L("shadowCast") + materialValueName)->ValueAsString();
        bool isSkinned = pBlock->GetValueByName(_L("skeleton")) != &CPUTConfigEntry::sNullConfigValue;
        if( shadowMaterialName.length() == 0 )
        {
            if(!isSkinned)
            {
                shadowMaterialName = _L("%shadowCast");
            }
            else
            {
                shadowMaterialName = _L("%shadowCastSkinned");
            }
        }

        // Get/load material for this mesh
        UINT totalNameCount = numSystemMaterials + NUM_GLOBAL_SYSTEM_MATERIALS;
        cString *pFinalSystemNames = new cString[totalNameCount];

        // Copy "global" system materials to caller-supplied list
        for( int jj=0; jj<numSystemMaterials; jj++ )
        {
            pFinalSystemNames[jj] = pSystemMaterialNames[jj];
        }
        pFinalSystemNames[totalNameCount + CPUT_MATERIAL_INDEX_SHADOW_CAST]                =  shadowMaterialName;
//        pFinalSystemNames[totalNameCount + CPUT_MATERIAL_INDEX_BOUNDING_BOX]                = _L("%BoundingBox");
        int finalNumSystemMaterials = numSystemMaterials + NUM_GLOBAL_SYSTEM_MATERIALS;
        CPUTMaterial *pMaterial = pAssetLibrary->GetMaterial(materialName, false, this, ii, NULL, finalNumSystemMaterials, pFinalSystemNames);
        ASSERT( pMaterial, _L("Couldn't find material.") );

        delete []pFinalSystemNames;

        mpLayoutCount[ii] = pMaterial->GetMaterialEffectCount();
        SetMaterial(ii, pMaterial);

        // Release the extra refcount we're holding from the GetMaterial operation earlier
        // now the asset library, and this model have the only refcounts on that material
        pMaterial->Release();

        // Create two ID3D11InputLayout objects, one for each material.
     //   mpMesh[ii]->BindVertexShaderLayout( mpMaterial[ii], mpShadowCastMaterial);
        // mpShadowCastMaterial->Release()
    }


    return result;
}