//-------------------------------------------------------------------------------------- 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; }