上個文章中我們已經操作了一遍Houdini & UE4的管線。但是應用到實際工作中時會發現其實還是有很多不方便的地方。
比如當你自己定義的layer導入houdini engine再導出後,會變成temp里的layerinfo文件。
再次input地形的話,自己定義的layer就沒有了。
再然後,如果修改了houdini engine導出的層,會發現修改的信息並不能正確的傳入houdini engine。
當然一些world compostion相關的易用性和區域更新也是很大的問題。但是這些會放在後面來講,歡迎關注哦!
在解決問題之前,我們還是應該先啃一下代碼,拋開其他流程不管,我們直接關注最後創建地形的地方。
UHoudiniAssetComponent::CreateAllLandscapes
------->
FHoudiniLandscapeUtils::CreateAllLandscapes
這裡就是最終創建地形的地方了,大致的流程是從houdini engine吧cook好的地形數據取出來,讀取一些屬性,從houdini的float數據轉化為UE4的uint8數據,然後創建新的地形或者是更新到輸入的地形當中。
具體的流程可以看下面的流程圖,了解清楚了houdini engine 導入地形到UE4中的流程後,我們就可以在其中想要修改流程的地方做自己的定製啦!
還有一個藏得比較深的代碼是,houdini engine在將layerinfo導入後,會把原來的的float數據保存在debugcolor中,用於導回houdini engine的時候保留一個較高的精度。
我們再看一下地形輸入houdini engine的流程,其實和導入一樣,主要還是一些數據的提取和float->uint8的轉化。
再反覆的踩坑和調試之後,發現流程中有一步恢復導入數據的代碼,後面居然夾帶了清除由houdini engine導入的層的功能。這就很奇怪了,上面明明還特意把信息存在debugcolor中用於導回,這裡居然反手就是一波清空(懵逼臉)。
在看完流程之後,這裡做兩處簡單的修改,是的真的很簡單啦。
講道理下面這兩部都是隱式的處理並不太有很好,有需要的話可以修改houdiniengine的slate部分,讓操作流程更加友好。
1、layername或者layerinfoname中帶有_custom的話,不傳入houdini的層。
bool FHoudiniLandscapeUtils::CreateHeightfieldFromLandscape( ALandscapeProxy* LandscapeProxy, HAPI_NodeId& CreatedHeightfieldNodeId ) { ...
// 1. Extract the uint8 values from the layer TArray<uint8> CurrentLayerIntData; FLinearColor LayerUsageDebugColor; FString LayerName; if ( !GetLandscapeLayerData( LandscapeInfo, n, CurrentLayerIntData, LayerUsageDebugColor, LayerName ) ) continue;
//////////////////////////////////////////////////// // Exclude the layers with "_custom" it indicate this layers is customized and only use in Unreal if (LayerName.Contains(TEXT("_custom")) || LandscapeInfo->Layers[n].LayerInfoObj->GetName().Contains(TEXT("_custom"))) { continue; } ////////////////////////////////////////////////////
// 2. Convert unreal uint8 values to floats // If the layer came from Houdini, additional info might have been stored in the DebugColor to convert the data back to float HAPI_VolumeInfo CurrentLayerVolumeInfo; TArray < float > CurrentLayerFloatData; if ( !ConvertLandscapeLayerDataToHeightfieldData( CurrentLayerIntData, XSize, YSize, LayerUsageDebugColor, CurrentLayerFloatData, CurrentLayerVolumeInfo ) ) continue;
... }
2、layername中帶有_remain的話,不會在輸入houdini engine的時候被清除
bool FHoudiniLandscapeUtils::RestoreLandscapeFromFile( ALandscapeProxy* LandscapeProxy ) { ... // Iterate on the landscape infos layer to remove any layer that could have been added by Houdini for (int LayerIndex = 0; LayerIndex < LandscapeInfo->Layers.Num(); LayerIndex++) { ULandscapeLayerInfoObject* CurrentLayerInfo = LandscapeInfo->Layers[LayerIndex].LayerInfoObj; if ( SourceLayers.Contains( CurrentLayerInfo ) ) continue;
//////////////////////////////////////////////////// // Exclude the layer with "_remain" so it wont be clear before upload to houdini FString CurLayerName = LandscapeInfo->Layers[LayerIndex].LayerName.ToString(); if (CurLayerName.Contains(TEXT("_remain"))) { continue; } ////////////////////////////////////////////////////
// Delete the added layer FName LayerName = LandscapeInfo->Layers[LayerIndex].LayerName; LandscapeInfo->DeleteLayer(CurrentLayerInfo, LayerName); } ... }
在我們看過一遍地形在UE4和houdini engine中導入和導出的代碼後,已經對整體流程有了一個基礎的了解,也是為後面的定製化開發打下了一個基礎。
這裡我們只是做了兩個簡單的修改,來修改layer導入導出的流程,為一些非houdini engine製作的layer加上保護,使得地形可以在UE4中編輯也可以在houdini中編輯。
下一篇會介紹如何定製化的把houdini engine中製作的地形導入UE4並拆散為關卡流,用於開啟了world composition的大世界場景製作,歡迎關注!
如果圖看不清,可以打開下面有道雲筆記的鏈接。