bool FD3D9MeshUtilities::LayoutUVs(
	struct FRawMesh& RawMesh,
	uint32 TextureResolution,
	uint32 TexCoordIndex,
	FText& OutError
	)
{
	OutError = FText();
	if(!IsValid() || !RawMesh.IsValid())
	{
		OutError = LOCTEXT("LayoutUVs_FailedInvalid", "LayoutUVs failed, mesh was invalid.");
		return false;
	}

	int32 NumTexCoords = 0;
	for (int32 i = 0; i < MAX_MESH_TEXTURE_COORDS; ++i)
	{
		if (RawMesh.WedgeTexCoords[i].Num() != RawMesh.WedgeIndices.Num())
		{
			break;
		}
		NumTexCoords++;
	}

	if (TexCoordIndex > (uint32)NumTexCoords)
	{
		OutError = LOCTEXT("LayoutUVs_FailedUVs", "LayoutUVs failed, incorrect number of texcoords.");
		return false;
	}

	// Sort the mesh's triangles by whether they need to be charted, or just to be packed into the atlas.
	FRawMesh MeshToAtlas = RawMesh;
	if (TexCoordIndex > 0)
	{
		MeshToAtlas.WedgeTexCoords[TexCoordIndex] = MeshToAtlas.WedgeTexCoords[0];
	}

	TRefCountPtr<ID3DXMesh> ChartMesh;
	TArray<uint32> AtlasAndChartAdjacency;
	TArray<int32> AtlasAndChartTriangleCharts;
	TRefCountPtr<ID3DXMesh> MergedMesh;
	TArray<uint32> MergedAdjacency;
	TArray<int32> MergedTriangleCharts;
	TRefCountPtr<ID3DXMesh> AtlasOnlyMesh;
	TArray<uint32> AtlasOnlyAdjacency;
	TArray<int32> AtlasOnlyTriangleCharts;

	{
		// Create a D3DXMesh for the triangles that only need to be atlassed.
		const bool bRemoveDegenerateTriangles = true;
		if (!ConvertRawMeshToD3DXMesh(Device,MeshToAtlas,bRemoveDegenerateTriangles,AtlasOnlyMesh))
		{
			OutError = LOCTEXT("LayoutUVs_FailedConvert", "LayoutUVs failed, couldn't convert to a D3DXMesh.");
			return false;
		}
		// generate mapping orientations info 
		FLayoutUVWindingInfo WindingInfo(AtlasOnlyMesh, TexCoordIndex);
		// Generate adjacency for the pre-charted triangles based on their input charts.
		GenerateAdjacency(AtlasOnlyMesh,AtlasOnlyAdjacency,FUVChartAdjacencyFilter(TexCoordIndex), &WindingInfo);


		////clean the mesh
		TRefCountPtr<ID3DXMesh> TempMesh;
		TArray<uint32> CleanedAdjacency;
		CleanedAdjacency.AddUninitialized(AtlasOnlyMesh->GetNumFaces() * 3);
		if( FAILED(D3DXCleanMesh( D3DXCLEAN_SIMPLIFICATION, 
			AtlasOnlyMesh, 
			(::DWORD *)AtlasOnlyAdjacency.GetTypedData(), 
			TempMesh.GetInitReference(), 
			(::DWORD *)CleanedAdjacency.GetTypedData(), 
			NULL ) ) )
		{
			OutError = LOCTEXT("LayoutUVs_FailedClean", "LayoutUVs failed, couldn't clean mesh.");
			return false;
		}

		// Group the pre-charted triangles into indexed charts based on their adjacency in the chart.
		AssignMinimalAdjacencyGroups(CleanedAdjacency,AtlasOnlyTriangleCharts);

		MergedMesh = TempMesh;
		MergedAdjacency = CleanedAdjacency;
		MergedTriangleCharts = AtlasOnlyTriangleCharts;
	}

	if(MergedMesh)
	{
		// Create a buffer to hold the triangle chart data.
		TRefCountPtr<ID3DXBuffer> MergedTriangleChartsBuffer;
		VERIFYD3D9RESULT(D3DXCreateBuffer(
			MergedTriangleCharts.Num() * sizeof(int32),
			MergedTriangleChartsBuffer.GetInitReference()
			));
		uint32* MergedTriangleChartsBufferPointer = (uint32*)MergedTriangleChartsBuffer->GetBufferPointer();
		for(int32 TriangleIndex = 0;TriangleIndex < MergedTriangleCharts.Num();TriangleIndex++)
		{
			*MergedTriangleChartsBufferPointer++ = MergedTriangleCharts[TriangleIndex];
		}
		const float GutterSize = 2.0f;
		// Pack the charts into a unified atlas.
		HRESULT Result = D3DXUVAtlasPack(
			MergedMesh,
			TextureResolution,
			TextureResolution,
			GutterSize,
			TexCoordIndex,
			(::DWORD *)MergedAdjacency.GetTypedData(),
			NULL,
			0,
			NULL,
			0,
			MergedTriangleChartsBuffer
			);
		if (FAILED(Result))
		{
			UE_LOG(LogD3D9MeshUtils, Warning, 
				TEXT("D3DXUVAtlasPack() returned %u."),
				Result
				);
			OutError = LOCTEXT("LayoutUVs_FailedPack", "LayoutUVs failed, D3DXUVAtlasPack failed.");
			return false;
		}

		int32 NewNumTexCoords = FMath::Max<int32>(NumTexCoords, TexCoordIndex + 1);
		FRawMesh FinalMesh;
		if (!ConvertD3DXMeshToRawMesh(MergedMesh, FinalMesh, NewNumTexCoords))
		{
			OutError = LOCTEXT("LayoutUVs_FailedSimple", "LayoutUVs failed, couldn't convert the simplified D3DXMesh back to a UStaticMesh.");
			return false;
		}
		RawMesh = FinalMesh;
	}
	return true;
}
Beispiel #2
0
static UBOOL D3D9CompileShaderWrapper(
	const TCHAR* ShaderFilename,
	const TCHAR* FunctionName,
	const TCHAR* ShaderProfile,
	DWORD CompileFlags,
	const FShaderCompilerEnvironment& InEnvironment,
	const vector<D3DXMACRO>& Macros,
	FShaderCompilerOutput& Output,
	vector<FD3D9ConstantDesc>& Constants,
	FString& DisassemblyString,
	FString& ErrorString
	)
{
	const FString& SourceFile = LoadShaderSourceFile(ShaderFilename);

	TRefCountPtr<ID3DXBuffer> Shader;
	TRefCountPtr<ID3DXBuffer> Errors;
	FD3DIncludeEnvironment Environment(InEnvironment);
	TRefCountPtr<ID3DXConstantTable> ConstantTable;
	FTCHARToANSI AnsiSourceFile(SourceFile.c_str());
	HRESULT Result = D3DXCompileShader(
						AnsiSourceFile, 
						SourceFile.size(), 
						&Macros[0], 
						&Environment, 
						TCHAR_TO_ANSI(FunctionName), 
						TCHAR_TO_ANSI(ShaderProfile),
						CompileFlags, 
						Shader.GetInitReference(),
						Errors.GetInitReference(), 
						ConstantTable.GetInitReference());

	if( FAILED(Result) )
	{
		ErrorString = TEXT("Compile Failed without warnings!");
		void* ErrorBuffer = Errors ? Errors->GetBufferPointer() : NULL;
		if( ErrorBuffer )
		{
			FANSIToTCHAR Convert((ANSICHAR*)ErrorBuffer);
			ErrorString = Convert;
		}
	}
	else
	{
		// get the ShaderCode
		INT NumShaderBytes = Shader->GetBufferSize();
		Output.ShaderCode.resize(NumShaderBytes);
		appMemcpy(&Output.ShaderCode[0], Shader->GetBufferPointer(), NumShaderBytes);

		// collect the constant table
		D3DXCONSTANTTABLE_DESC ConstantTableDesc;
		VERIFYD3DRESULT(ConstantTable->GetDesc(&ConstantTableDesc));
		for(UINT ConstantIndex = 0; ConstantIndex < ConstantTableDesc.Constants; ++ConstantIndex)
		{
			D3DXHANDLE ConstantHandle = ConstantTable->GetConstant(NULL, ConstantIndex);

			D3DXCONSTANT_DESC ConstantDesc;
			UINT NumConstants = 1;
			VERIFYD3DRESULT(ConstantTable->GetConstantDesc(ConstantHandle, &ConstantDesc, &NumConstants));

			FD3D9ConstantDesc NamedConstantDesc;
			appStrcpyANSI(NamedConstantDesc.Name, ConstantDesc.Name);
			NamedConstantDesc.bIsSampler = ConstantDesc.RegisterSet == D3DXRS_SAMPLER;
			NamedConstantDesc.RegisterIndex = ConstantDesc.RegisterIndex;
			NamedConstantDesc.RegisterCount = ConstantDesc.RegisterCount;
			Constants.push_back(NamedConstantDesc);
		}

		// disassemble a shader
		TRefCountPtr<ID3DXBuffer> DisassemblyBuffer;
		VERIFYD3DRESULT(D3DXDisassembleShader((const DWORD*)Shader->GetBufferPointer(), FALSE, NULL, DisassemblyBuffer.GetInitReference()));
		DisassemblyString = ANSI_TO_TCHAR((ANSICHAR*)DisassemblyBuffer->GetBufferPointer());
	}

	return TRUE;
}