//----------------------------------------------------------------------------- bool CPUTShaderDX11::ShaderRequiresPerModelPayload( CPUTConfigBlock &properties ) { ID3D11ShaderReflection *pReflector = NULL; D3DReflect( mpBlob->GetBufferPointer(), mpBlob->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&pReflector); // Walk through the shader input bind descriptors. // If any of them begin with '@', then we need a unique material per model (i.e., we need to clone the material). int ii=0; D3D11_SHADER_INPUT_BIND_DESC desc; HRESULT hr = pReflector->GetResourceBindingDesc( ii++, &desc ); while( SUCCEEDED(hr) ) { cString tagName = s2ws(desc.Name); CPUTConfigEntry *pValue = properties.GetValueByName(tagName); if( !pValue->IsValid() ) { // We didn't find our property in the file. Is it in the global config block? pValue = CPUTMaterial::mGlobalProperties.GetValueByName(tagName); } cString boundName = pValue->ValueAsString(); if( (boundName.length() > 0) && ((boundName[0] == '@') || (boundName[0] == '#')) ) { return true; } hr = pReflector->GetResourceBindingDesc( ii++, &desc ); } return false; }
//----------------------------------------------------------------------------- CPUTResult CPUTAssetSetDX11::LoadAssetSet(cString name) { CPUTResult result = CPUT_SUCCESS; // if not found, load the set file CPUTConfigFile ConfigFile; result = ConfigFile.LoadFile(name); #if 1 if( !CPUTSUCCESS(result) ) { return result; } // ASSERT( CPUTSUCCESS(result), _L("Failed loading set file '") + name + _L("'.") ); mAssetCount = ConfigFile.BlockCount() + 1; // Add one for the implied root node // mAssetCount = min(2, mAssetCount); // Add one for the implied root node mppAssetList = new CPUTRenderNode*[mAssetCount]; mppAssetList[0] = mpRootNode; mpRootNode->AddRef(); CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); for(UINT ii=0; ii<mAssetCount-1; ii++) // Note: -1 because we added one for the root node (we don't load it) { CPUTConfigBlock *pBlock = ConfigFile.GetBlock(ii); int assetIndex = pBlock->GetNameValue(); cString nodeType = pBlock->GetValueByName(_L("type"))->ValueAsString(); CPUTRenderNode *pParentNode = NULL; // TODO: use Get*() instead of Load*() ? cString name = pBlock->GetValueByName(_L("name"))->ValueAsString(); int parentIndex; CPUTRenderNode *pNode; if(0==nodeType.compare(_L("null"))) { pNode = pNode = new CPUTNullNode(); result = ((CPUTNullNode*)pNode)->LoadNullNode(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; cString &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix + _L(".") + name ); pAssetLibrary->AddNullNode(parentPrefix + name, (CPUTNullNode*)pNode); // Add this null's name to our prefix // Append this null's name to our parent's prefix pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); } else if(0==nodeType.compare(_L("model"))) { CPUTConfigEntry *pValue = pBlock->GetValueByName( _L("instance") ); CPUTModelDX11 *pModel = new CPUTModelDX11(); if( pValue == &CPUTConfigEntry::sNullConfigValue ) { // Not found. So, not an instance. pModel->LoadModel(pBlock, &parentIndex, NULL); } else { int instance = pValue->ValueAsInt(); pModel->LoadModel(pBlock, &parentIndex, (CPUTModel*)mppAssetList[instance+1]); } pParentNode = mppAssetList[parentIndex+1]; pModel->SetParent( pParentNode ); pParentNode->AddChild( pModel ); cString &parentPrefix = pParentNode->GetPrefix(); pModel->SetPrefix( parentPrefix ); pAssetLibrary->AddModel(parentPrefix + name, pModel); pModel->UpdateBoundsWorldSpace(); #ifdef SUPPORT_DRAWING_BOUNDING_BOXES // Create a mesh for rendering the bounding box // TODO: There is definitely a better way to do this. But, want to see the bounding boxes! pModel->CreateBoundingBoxMesh(); #endif pNode = pModel; } else if(0==nodeType.compare(_L("light"))) { pNode = new CPUTLight(); ((CPUTLight*)pNode)->LoadLight(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; // +1 because we added a root node to the start pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); cString &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix ); pAssetLibrary->AddLight(parentPrefix + name, (CPUTLight*)pNode); } else if(0==nodeType.compare(_L("camera"))) { pNode = new CPUTCamera(); ((CPUTCamera*)pNode)->LoadCamera(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; // +1 because we added a root node to the start pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); cString &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix ); pAssetLibrary->AddCamera(parentPrefix + name, (CPUTCamera*)pNode); if( !mpFirstCamera ) { mpFirstCamera = (CPUTCamera*)pNode; mpFirstCamera->AddRef();} ++mCameraCount; } else { ASSERT(0,_L("Unsupported node type '") + nodeType + _L("'.")); } // Add the node to our asset list (i.e., the linear list, not the hierarchical) mppAssetList[ii+1] = pNode; // Don't AddRef.Creating it set the refcount to 1. We add it to the list, and then we're done with it. // Net effect is 0 (+1 to add to list, and -1 because we're done with it) // pNode->AddRef(); } #endif HEAPCHECK return result; }
//----------------------------------------------------------------------------- CPUTResult CPUTAssetSet::LoadAssetSet(std::string name, int numSystemMaterials, std::string *pSystemMaterialNames) { CPUTResult result = CPUT_SUCCESS; // if not found, load the set file CPUTConfigFile ConfigFile; result = ConfigFile.LoadFile(name); if( !CPUTSUCCESS(result) ) { return result; } // ASSERT( CPUTSUCCESS(result), "Failed loading set file '" + name + "'." ); mAssetCount = ConfigFile.BlockCount() + 1; // Add one for the implied root node mppAssetList = new CPUTRenderNode*[mAssetCount]; mppAssetList[0] = mpRootNode; mpRootNode->AddRef(); CPUTAssetLibrary *pAssetLibrary = (CPUTAssetLibrary*)CPUTAssetLibrary::GetAssetLibrary(); CPUTAnimation *pDefaultAnimation = NULL; for(UINT ii=0; ii<mAssetCount-1; ii++) // Note: -1 because we added one for the root node (we don't load it) { CPUTConfigBlock *pBlock = ConfigFile.GetBlock(ii); ASSERT(pBlock != NULL, "Cannot find block"); if( !pBlock ) { return CPUT_ERROR_PARAMETER_BLOCK_NOT_FOUND; } std::string nodeType = pBlock->GetValueByName("type")->ValueAsString(); CPUTRenderNode *pParentNode = NULL; // TODO: use Get*() instead of Load*() ? std::string name = pBlock->GetValueByName("name")->ValueAsString(); int parentIndex; CPUTRenderNode *pNode = NULL; if(0==nodeType.compare("null")) { pNode = pNode = CPUTNullNode::Create(); result = ((CPUTNullNode*)pNode)->LoadNullNode(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; std::string &parentPrefix = pParentNode->GetPrefix(); std::string prefix = parentPrefix; prefix.append("."); prefix.append(name); pNode->SetPrefix(prefix); // pNode->SetPrefix( parentPrefix + "." + name ); pAssetLibrary->AddNullNode("", parentPrefix + name, "", (CPUTNullNode*)pNode); // Add this null's name to our prefix // Append this null's name to our parent's prefix pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); } else if(0==nodeType.compare("model")) { CPUTConfigEntry *pValue = pBlock->GetValueByName( "instance" ); CPUTModel *pModel = CPUTModel::Create(); if( pValue == &CPUTConfigEntry::sNullConfigValue ) { // Not found. So, not an instance. pModel->LoadModel(pBlock, &parentIndex, NULL, numSystemMaterials, pSystemMaterialNames); } else { int instance = pValue->ValueAsInt(); // If the current node is an instance of itself then it has no "master" model if(ii == instance) { // TODO: create instance model object pModel->LoadModel(pBlock, &parentIndex, NULL, numSystemMaterials, pSystemMaterialNames); } else { pModel->LoadModel(pBlock, &parentIndex, (CPUTModel*)mppAssetList[instance+1], numSystemMaterials, pSystemMaterialNames); } } pParentNode = mppAssetList[parentIndex+1]; pModel->SetParent( pParentNode ); pParentNode->AddChild( pModel ); std::string &parentPrefix = pParentNode->GetPrefix(); pModel->SetPrefix( parentPrefix ); pAssetLibrary->AddModel(name, parentPrefix, "", pModel); pModel->UpdateBoundsWorldSpace(); #ifdef SUPPORT_DRAWING_BOUNDING_BOXES // Create a mesh for rendering the bounding box // TODO: There is definitely a better way to do this. But, want to see the bounding boxes! pModel->CreateBoundingBoxMesh(); #endif pNode = pModel; } else if(0==nodeType.compare("light")) { pNode = CPUTLight::Create(); ((CPUTLight*)pNode)->LoadLight(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; // +1 because we added a root node to the start pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); std::string &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix ); pAssetLibrary->AddLight(name, parentPrefix, "", (CPUTLight*)pNode); } else if(0==nodeType.compare("camera")) { pNode = CPUTCamera::Create(CPUT_PERSPECTIVE); ((CPUTCamera*)pNode)->LoadCamera(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; // +1 because we added a root node to the start pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); std::string &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix ); pAssetLibrary->AddCamera(name, parentPrefix, "", (CPUTCamera*)pNode); if( !mpFirstCamera ) { mpFirstCamera = (CPUTCamera*)pNode; mpFirstCamera->AddRef();} ++mCameraCount; } else { ASSERT(0,"Unsupported node type '" + nodeType + "'."); } CPUTConfigEntry *pAnimValue = pBlock->GetValueByName( "Animation0" ); //int autoPlayAnimationIndex = pBlock->GetValueByName( "DefaultAnimation" ); for(int i = 1; pAnimValue != &CPUTConfigEntry::sNullConfigValue; ++i ) { CPUTAnimation *pCurrentAnimation = pAssetLibrary->GetAnimation(pAnimValue->ValueAsString()); //First Animation will be default for now if(pCurrentAnimation != NULL && i == 1 /*autoPlayAnimationIndex*/) { pDefaultAnimation = pCurrentAnimation ; pCurrentAnimation->AddRef(); } std::stringstream animName; animName << "Animation" << i; pAnimValue = pBlock->GetValueByName(animName.str()); pNode->mAnimationList.push_back(pCurrentAnimation); } // Add the node to our asset list (i.e., the linear list, not the hierarchical) mppAssetList[ii+1] = pNode; // Don't AddRef.Creating it set the refcount to 1. We add it to the list, and then we're done with it. // Net effect is 0 (+1 to add to list, and -1 because we're done with it) // pNode->AddRef(); } //Set the default animation to the current Asset Set if(pDefaultAnimation != NULL && mAssetCount > 1) { //Apply Animation to root of the setfile mppAssetList[1]->SetAnimation(pDefaultAnimation); } SAFE_RELEASE(pDefaultAnimation); return result; }