Пример #1
0
// Erm, I think this fudge works
FProcMeshTangent FZoneGeneratorWorker::GetTangentFromNormal(const FVector aNormal)
{
	FVector tangentVec, bitangentVec;
	FVector c1, c2;

	c1 = FVector::CrossProduct(aNormal, FVector(0.0f, 0.0f, 1.0f));
	c2 = FVector::CrossProduct(aNormal, FVector(0.0f, 1.0f, 0.0f));

	if (c1.Size() > c2.Size())
	{
		tangentVec = c1;
	}
	else
	{
		tangentVec = c2;
	}

	tangentVec = tangentVec.GetSafeNormal();
	bitangentVec = FVector::CrossProduct(aNormal, tangentVec);

	return FProcMeshTangent(bitangentVec, false );
}
Пример #2
0
// Sets default values
AMyObjPawn::AMyObjPawn()
{
    // Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

    // Set this pawn to be controlled by the lowest-numbered player (このポーンが最小値のプレイヤーで制御されるように設定)
    AutoPossessPlayer = EAutoReceiveInput::Player0;

    // ダミーキャラクターを置く
    RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
    // Create a dummy root component we can attach things to.(親子付け可能なダミーのルートコンポーネントを作成)
    UCameraComponent* OurCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("OurCamera"));

    // Attach our camera and visible object to our root component. (カメラと可視オブジェクトをルートコンポーネントに親子付け。カメラをオフセットして回転)
    OurCamera->AttachTo(RootComponent);
    OurCamera->SetRelativeLocation(FVector(-350.0f, 0.0f, 100.0f));
    OurCamera->SetRelativeRotation(FRotator(0.0f, 0.0f, 0.0f));

    /**
    *	Create/replace a section for this procedural mesh component.
    *	@param	SectionIndex		Index of the section to create or replace.
    *	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
    *	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
    *	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
    *	@param	UV0					Optional array of texture co-ordinates for each vertex. If supplied, must be same length as Vertices array.
    *	@param	VertexColors		Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
    *	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
    *	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
    */

    // 動的オブジェクトを置く
    mProceduralMeshComponent = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("GeneratedMesh"));

    TArray<FVector> positions;
    TArray<FVector> normals;
    TArray<FVector2D> uvs;
    TArray<FColor> colors;
    TArray<FProcMeshTangent> tangents;
    TArray<int32> indices;

    ObjectParser(positions, normals, uvs, indices);

    for (size_t i = 0; i < positions.Num(); i++)
    {
        colors.Add(FColor(255, 255, 255, 255));
        tangents.Add(FProcMeshTangent(1, 1, 1));
    }

    ConstructorHelpers::FObjectFinder<UMaterial>* pMaterialAsset = new ConstructorHelpers::FObjectFinder<UMaterial>(
        _T("/Game/InfinityBladeAdversaries/Enemy/Enemy_Bear/Materials/M_Bear_Master.M_Bear_Master")
        );
    if (pMaterialAsset->Succeeded())
    {
        mMaterial = pMaterialAsset->Object;
        UE_LOG(LogTemp, Warning, TEXT("output : %s"), L"マテリアルロードに成功しました");
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("output : %s"), L"マテリアルロードに失敗しました");
    }

    mProceduralMeshComponent->CreateMeshSection(0, positions, indices, normals, uvs, colors, tangents, false);
    mProceduralMeshComponent->SetMaterial(0, mMaterial);
    mProceduralMeshComponent->AttachTo(RootComponent);
}
int32 FProceduralTerrainWorker::PolygonizeToTriangles(
	UTerrainGrid *TerrainGrid,
	float p_fSurfaceCrossValue,
	FIntVector ChunkStartSize,
	FIntVector ChunkEndSize,
	FVector &ChunkLocation,
	FVector &ChunkScale,
	FTransform &TerrainTransform,

	TArray<FVector> &Vertices,
	TArray<int32> &Indices,
	TArray<FVector> &Normals,
	TArray<FVector2D> &UVs,
	TArray<FColor> &VertexColors,
	TArray<FProcMeshTangent> &Tangents
	)
{
	// TODO?
	float PosX = ChunkLocation.X;
	float PosY = ChunkLocation.Y;
	float PosZ = ChunkLocation.Z;
	TArray<FVector> Positions;

	int NumTriangles = 0;
	for (int32 x = ChunkStartSize.X; x < ChunkEndSize.X; ++x)
	{
		for (int32 y = ChunkStartSize.Y; y < ChunkEndSize.Y; ++y)
		{
			for (int32 z = ChunkStartSize.Z; z < ChunkEndSize.Z; ++z)
			{

				// Get each points of a cube.
				float p0 = TerrainGrid->GetVoxel(x, y, z);
				float p1 = TerrainGrid->GetVoxel(x + 1, y, z);
				float p2 = TerrainGrid->GetVoxel(x, y + 1, z);
				float p3 = TerrainGrid->GetVoxel(x + 1, y + 1, z);
				float p4 = TerrainGrid->GetVoxel(x, y, z + 1);
				float p5 = TerrainGrid->GetVoxel(x + 1, y, z + 1);
				float p6 = TerrainGrid->GetVoxel(x, y + 1, z + 1);
				float p7 = TerrainGrid->GetVoxel(x + 1, y + 1, z + 1);

				/*
				Determine the index into the edge table which
				tells us which vertices are inside of the surface
				*/
				int crossBitMap = 0;

				if (p0 < p_fSurfaceCrossValue) crossBitMap |= 1;
				if (p1 < p_fSurfaceCrossValue) crossBitMap |= 2;

				if (p2 < p_fSurfaceCrossValue) crossBitMap |= 8;
				if (p3 < p_fSurfaceCrossValue) crossBitMap |= 4;

				if (p4 < p_fSurfaceCrossValue) crossBitMap |= 16;
				if (p5 < p_fSurfaceCrossValue) crossBitMap |= 32;

				if (p6 < p_fSurfaceCrossValue) crossBitMap |= 128;
				if (p7 < p_fSurfaceCrossValue) crossBitMap |= 64;


				/* Cube is entirely in/out of the surface */
				int edgeBits = edgeTable[crossBitMap];
				if (edgeBits == 0)
					continue;

				float interpolatedCrossingPoint = 0.0f;
				FVector interpolatedValues[12];

				if ((edgeBits & 1) > 0)
				{

					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p0) / (p1 - p0);
					interpolatedValues[0] = FMath::Lerp(FVector(PosX + x, PosY + y, PosZ + z), FVector(PosX + x + 1, PosY + y, PosZ + z), interpolatedCrossingPoint);
				}
				if ((edgeBits & 2) > 0)
				{
					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p1) / (p3 - p1);
					interpolatedValues[1] = FMath::Lerp(FVector(PosX + x + 1, PosY + y, PosZ + z), FVector(PosX + x + 1, PosY + y + 1, PosZ + z), interpolatedCrossingPoint);
				}
				if ((edgeBits & 4) > 0)
				{
					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p2) / (p3 - p2);
					interpolatedValues[2] = FMath::Lerp(FVector(PosX + x, PosY + y + 1, PosZ + z), FVector(PosX + x + 1, PosY + y + 1, PosZ + z), interpolatedCrossingPoint);
				}
				if ((edgeBits & 8) > 0)
				{
					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p0) / (p2 - p0);
					interpolatedValues[3] = FMath::Lerp(FVector(PosX + x, PosY + y, PosZ + z), FVector(PosX + x, PosY + y + 1, PosZ + z), interpolatedCrossingPoint);
				}

				//Top four edges
				if ((edgeBits & 16) > 0)
				{
					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p4) / (p5 - p4);
					interpolatedValues[4] = FMath::Lerp(FVector(PosX + x, PosY + y, PosZ + z + 1), FVector(PosX + x + 1, PosY + y, PosZ + z + 1), interpolatedCrossingPoint);
				}
				if ((edgeBits & 32) > 0)
				{
					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p5) / (p7 - p5);
					interpolatedValues[5] = FMath::Lerp(FVector(PosX + x + 1, PosY + y, PosZ + z + 1), FVector(PosX + x + 1, PosY + y + 1, PosZ + z + 1), interpolatedCrossingPoint);
				}
				if ((edgeBits & 64) > 0)
				{
					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p6) / (p7 - p6);
					interpolatedValues[6] = FMath::Lerp(FVector(PosX + x, PosY + y + 1, PosZ + z + 1), FVector(PosX + x + 1, PosY + y + 1, PosZ + z + 1), interpolatedCrossingPoint);
				}
				if ((edgeBits & 128) > 0)
				{
					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p4) / (p6 - p4);
					interpolatedValues[7] = FMath::Lerp(FVector(PosX + x, PosY + y, PosZ + z + 1), FVector(PosX + x, PosY + y + 1, PosZ + z + 1), interpolatedCrossingPoint);
				}

				//Side four edges
				if ((edgeBits & 256) > 0)
				{
					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p0) / (p4 - p0);
					interpolatedValues[8] = FMath::Lerp(FVector(PosX + x, PosY + y, PosZ + z), FVector(PosX + x, PosY + y, PosZ + z + 1), interpolatedCrossingPoint);
				}
				if ((edgeBits & 512) > 0)
				{
					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p1) / (p5 - p1);
					interpolatedValues[9] = FMath::Lerp(FVector(PosX + x + 1, PosY + y, PosZ + z), FVector(PosX + x + 1, PosY + y, PosZ + z + 1), interpolatedCrossingPoint);
				}
				if ((edgeBits & 1024) > 0)
				{
					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p3) / (p7 - p3);
					interpolatedValues[10] = FMath::Lerp(FVector(PosX + x + 1, PosY + y + 1, PosZ + z), FVector(PosX + x + 1, PosY + y + 1, PosZ + z + 1), interpolatedCrossingPoint);
				}
				if ((edgeBits & 2048) > 0)
				{
					interpolatedCrossingPoint = (p_fSurfaceCrossValue - p2) / (p6 - p2);
					interpolatedValues[11] = FMath::Lerp(FVector(PosX + x, PosY + y + 1, PosZ + z), FVector(PosX + x, PosY + y + 1, PosZ + z + 1), interpolatedCrossingPoint);
				}

				crossBitMap <<= 4;

				int triangleIndex = 0;
				while (triTable[crossBitMap + triangleIndex] != -1)
				{
					// For each triangle in the look up table, create a triangle and add it to the list.
					int index1 = triTable[crossBitMap + triangleIndex];
					int index2 = triTable[crossBitMap + triangleIndex + 1];
					int index3 = triTable[crossBitMap + triangleIndex + 2];

					FDynamicMeshVertex Vertex0;
					Vertex0.Position = TerrainTransform.TransformVector(ChunkScale * interpolatedValues[index1]);
					FDynamicMeshVertex Vertex1;
					Vertex1.Position = TerrainTransform.TransformVector(ChunkScale * interpolatedValues[index2]);
					FDynamicMeshVertex Vertex2;
					Vertex2.Position = TerrainTransform.TransformVector(ChunkScale * interpolatedValues[index3]);

					Vertex0.TextureCoordinate.X = Vertex0.Position.X / 100.0f;
					Vertex0.TextureCoordinate.Y = Vertex0.Position.Y / 100.0f;
					
					Vertex1.TextureCoordinate.X = Vertex1.Position.X / 100.0f;
					Vertex1.TextureCoordinate.Y = Vertex1.Position.Y / 100.0f;

					Vertex2.TextureCoordinate.X = Vertex2.Position.X / 100.0f;
					Vertex2.TextureCoordinate.Y = Vertex2.Position.Y / 100.0f;

					// Fill Index buffer And Vertex buffer with the generated vertices.
					int32 VIndex0 = Positions.Find(Vertex0.Position);
					if (VIndex0 < 0)
					{
						VIndex0 = Positions.Add(Vertex0.Position);
						Indices.Add(VIndex0);
						Vertices.Add(Vertex0.Position);
						UVs.Add(FVector2D(Vertex0.TextureCoordinate));
					}
					else {
						Indices.Add(VIndex0);
					}

					int32 VIndex1 = Positions.Find(Vertex1.Position);
					if (VIndex1 < 0)
					{
						VIndex1 = Positions.Add(Vertex1.Position);
						Indices.Add(VIndex1);
						Vertices.Add(Vertex1.Position);
						UVs.Add(FVector2D(Vertex1.TextureCoordinate));
					}
					else {
						Indices.Add(VIndex1);
					}

					int32 VIndex2 = Positions.Find(Vertex2.Position);
					if (VIndex2 < 0)
					{
						VIndex2 = Positions.Add(Vertex2.Position);
						Indices.Add(VIndex2);
						Vertices.Add(Vertex2.Position);
						UVs.Add(FVector2D(Vertex2.TextureCoordinate));
					}
					else {
						Indices.Add(VIndex2);
					}

					++NumTriangles;
					triangleIndex += 3;

				}



			}
		}
	}



	VertexColors.SetNum(Vertices.Num(), false);
	Normals.SetNum(Vertices.Num(), false);
	Tangents.SetNum(Vertices.Num(), false);

	for (int32 Index = 0; Index < Indices.Num(); Index += 3)
	{
		const FVector Edge21 = Vertices[Indices[Index + 1]] - Vertices[Indices[Index + 2]];
		const FVector Edge20 = Vertices[Indices[Index + 0]] - Vertices[Indices[Index + 2]];
		FVector TriNormal = (Edge21 ^ Edge20).GetSafeNormal();

		FVector FaceTangentX = Edge20.GetSafeNormal();
		FVector FaceTangentY = (FaceTangentX ^ TriNormal).GetSafeNormal();
		FVector FaceTangentZ = TriNormal;

		// Use Gram-Schmidt orthogonalization to make sure X is orth with Z
		FaceTangentX -= FaceTangentZ * (FaceTangentZ | FaceTangentX);
		FaceTangentX.Normalize();

		// See if we need to flip TangentY when generating from cross product
		const bool bFlipBitangent = ((FaceTangentZ ^ FaceTangentX) | FaceTangentY) < 0.f;
		TriNormal.Normalize();
		FaceTangentX.Normalize();
		FProcMeshTangent tangent = FProcMeshTangent(FaceTangentX, bFlipBitangent);
		for (int32 i = 0; i < 3; i++)
		{
			Normals[Indices[Index + i]] = TriNormal;
			Tangents[Indices[Index + i]] = tangent;
			VertexColors[Indices[Index + i]] = FColor(1, 1, 1, 1);
		}
	}
	//UE_LOG(LogTemp, Warning, TEXT("NumTriangles: %d => %d,%d -> %d,%d"), NumTriangles, ChunkStartSize.X, ChunkStartSize.Y, ChunkEndSize.X, ChunkEndSize.Y);
	return NumTriangles;
}
void ASimpleCubeActor::GenerateCube(FProceduralMeshData& MeshData, float Depth, float Width, float Height)
{
	// NOTE: Unreal uses an upper-left origin UV
	// NOTE: This sample uses a simple UV mapping scheme where each face is the same
	// NOTE: For a normal facing towards us, be build the polygon CCW in the order 0-1-2 then 0-2-3 to complete the quad.
	// Remember in Unreal, X is forwards, Y is to your right and Z is up.

	// Calculate a half offset so we get correct center of object
	float DepthOffset = Depth / 2.0f; // X
	float WidthOffset = Width / 2.0f; // Y
	float HeightOffset = Height / 2.0f; // Z

	// Define the 8 corners of the cube
	FVector p0 = FVector(DepthOffset,  WidthOffset, -HeightOffset);
	FVector p1 = FVector(DepthOffset, -WidthOffset, -HeightOffset);
	FVector p2 = FVector(DepthOffset, -WidthOffset,  HeightOffset);
	FVector p3 = FVector(DepthOffset,  WidthOffset,  HeightOffset);
	FVector p4 = FVector(-DepthOffset, WidthOffset, -HeightOffset);
	FVector p5 = FVector(-DepthOffset, -WidthOffset, -HeightOffset);
	FVector p6 = FVector(-DepthOffset, -WidthOffset, HeightOffset);
	FVector p7 = FVector(-DepthOffset, WidthOffset, HeightOffset);

	// Now we create 6x faces, 4 vertices each
	int32 VertexCount = 6 * 4;
	MeshData.Vertices.AddUninitialized(VertexCount);
	MeshData.UVs.AddUninitialized(VertexCount);
	MeshData.Normals.AddUninitialized(VertexCount);
	MeshData.Tangents.AddUninitialized(VertexCount);

	int32 VertexOffset = 0;
	FVector Normal = FVector::ZeroVector;
	FProcMeshTangent Tangent = FProcMeshTangent();

 	// Front (+X) face: 0-1-2-3
	Normal = FVector(1, 0, 0);
	Tangent = FProcMeshTangent(0, 1, 0);
	VertexOffset = BuildQuad(MeshData, p0, p1, p2, p3, VertexOffset, Normal, Tangent);

 	// Back (-X) face: 5-4-7-6
	Normal = FVector(-1, 0, 0);
	Tangent = FProcMeshTangent(0, -1, 0);
	VertexOffset = BuildQuad(MeshData, p5, p4, p7, p6, VertexOffset, Normal, Tangent);

 	// Left (-Y) face: 1-5-6-2
	Normal = FVector(0, -1, 0);
	Tangent = FProcMeshTangent(1, 0, 0);
	VertexOffset = BuildQuad(MeshData, p1, p5, p6, p2, VertexOffset, Normal, Tangent);

 	// Right (+Y) face: 4-0-3-7
	Normal = FVector(0, 1, 0);
	Tangent = FProcMeshTangent(-1, 0, 0);
	VertexOffset = BuildQuad(MeshData, p4, p0, p3, p7, VertexOffset, Normal, Tangent);

 	// Top (+Z) face: 6-7-3-2
	Normal = FVector(0, 0, 1);
	Tangent = FProcMeshTangent(0, 1, 0);
	VertexOffset = BuildQuad(MeshData, p6, p7, p3, p2, VertexOffset, Normal, Tangent);

 	// Bottom (-Z) face: 1-0-4-5
	Normal = FVector(0, 0, -1);
	Tangent = FProcMeshTangent(0, -1, 0);
	VertexOffset = BuildQuad(MeshData, p1, p0, p4, p5, VertexOffset, Normal, Tangent);
}