Пример #1
0
void FKSphylElem::DrawElemSolid(FPrimitiveDrawInterface* PDI, const FTransform& ElemTM, float Scale, const FMaterialRenderProxy* MaterialRenderProxy)
{
	const int32 NumSides = DrawCollisionSides;
	const int32 NumRings = (DrawCollisionSides/2) + 1;

	// The first/last arc are on top of each other.
	const int32 NumVerts = (NumSides+1) * (NumRings+1);
	FDynamicMeshVertex* Verts = (FDynamicMeshVertex*)FMemory::Malloc( NumVerts * sizeof(FDynamicMeshVertex) );

	// Calculate verts for one arc
	FDynamicMeshVertex* ArcVerts = (FDynamicMeshVertex*)FMemory::Malloc( (NumRings+1) * sizeof(FDynamicMeshVertex) );

	for(int32 RingIdx=0; RingIdx<NumRings+1; RingIdx++)
	{
		FDynamicMeshVertex* ArcVert = &ArcVerts[RingIdx];

		float Angle;
		float ZOffset;
		if( RingIdx <= DrawCollisionSides/4 )
		{
			Angle = ((float)RingIdx/(NumRings-1)) * PI;
			ZOffset = 0.5 * Scale * Length;
		}
		else
		{
			Angle = ((float)(RingIdx-1)/(NumRings-1)) * PI;
			ZOffset = -0.5 * Scale * Length;
		}

		// Note- unit sphere, so position always has mag of one. We can just use it for normal!		
		FVector SpherePos;
		SpherePos.X = 0.0f;
		SpherePos.Y = Scale * Radius * FMath::Sin(Angle);
		SpherePos.Z = Scale * Radius * FMath::Cos(Angle);

		ArcVert->Position = SpherePos + FVector(0,0,ZOffset);

		ArcVert->SetTangents(
			FVector(1,0,0),
			FVector(0.0f, -SpherePos.Z, SpherePos.Y),
			SpherePos
			);

		ArcVert->TextureCoordinate.X = 0.0f;
		ArcVert->TextureCoordinate.Y = ((float)RingIdx/NumRings);
	}

	// Then rotate this arc NumSides+1 times.
	for(int32 SideIdx=0; SideIdx<NumSides+1; SideIdx++)
	{
		const FRotator ArcRotator(0, 360.f * ((float)SideIdx/NumSides), 0);
		const FRotationMatrix ArcRot( ArcRotator );
		const float XTexCoord = ((float)SideIdx/NumSides);

		for(int32 VertIdx=0; VertIdx<NumRings+1; VertIdx++)
		{
			int32 VIx = (NumRings+1)*SideIdx + VertIdx;

			Verts[VIx].Position = ArcRot.TransformPosition( ArcVerts[VertIdx].Position );

			Verts[VIx].SetTangents(
				ArcRot.TransformVector( ArcVerts[VertIdx].TangentX ),
				ArcRot.TransformVector( ArcVerts[VertIdx].GetTangentY() ),
				ArcRot.TransformVector( ArcVerts[VertIdx].TangentZ )
				);

			Verts[VIx].TextureCoordinate.X = XTexCoord;
			Verts[VIx].TextureCoordinate.Y = ArcVerts[VertIdx].TextureCoordinate.Y;
		}
	}

	FDynamicMeshBuilder MeshBuilder;
	{
		// Add all of the vertices to the mesh.
		for(int32 VertIdx=0; VertIdx<NumVerts; VertIdx++)
		{
			MeshBuilder.AddVertex(Verts[VertIdx]);
		}

		// Add all of the triangles to the mesh.
		for(int32 SideIdx=0; SideIdx<NumSides; SideIdx++)
		{
			const int32 a0start = (SideIdx+0) * (NumRings+1);
			const int32 a1start = (SideIdx+1) * (NumRings+1);

			for(int32 RingIdx=0; RingIdx<NumRings; RingIdx++)
			{
				MeshBuilder.AddTriangle(a0start + RingIdx + 0, a1start + RingIdx + 0, a0start + RingIdx + 1);
				MeshBuilder.AddTriangle(a1start + RingIdx + 0, a1start + RingIdx + 1, a0start + RingIdx + 1);
			}
		}

	}
	MeshBuilder.Draw(PDI, ElemTM.ToMatrixWithScale(), MaterialRenderProxy, SDPG_World,0.f);


	FMemory::Free(Verts);
	FMemory::Free(ArcVerts);
}
void FSpriteGeometryEditingHelper::DrawGeometry(const FSceneView& View, FPrimitiveDrawInterface& PDI, const FLinearColor& GeometryVertexColor, const FLinearColor& NegativeGeometryVertexColor)
{
	if (GeometryBeingEdited == nullptr)
	{
		return;
	}

	FSpriteGeometryCollection& Geometry = GetGeometryChecked();
	const bool bIsHitTesting = PDI.IsHitTesting();
	const float UnitsPerPixel = EditorContext->SelectedItemGetUnitsPerPixel();

	// Run thru the geometry shapes and draw hit proxies for them
	for (int32 ShapeIndex = 0; ShapeIndex < Geometry.Shapes.Num(); ++ShapeIndex)
	{
		const FSpriteGeometryShape& Shape = Geometry.Shapes[ShapeIndex];

		const bool bIsShapeSelected = IsGeometrySelected(FShapeVertexPair(ShapeIndex, INDEX_NONE));
		const FLinearColor LineColorRaw = Shape.bNegativeWinding ? NegativeGeometryVertexColor : GeometryVertexColor;
		const FLinearColor VertexColor = Shape.bNegativeWinding ? NegativeGeometryVertexColor : GeometryVertexColor;

		const FLinearColor LineColor = Shape.IsShapeValid() ? LineColorRaw : FMath::Lerp(LineColorRaw, FLinearColor::Red, 0.8f);

		// Draw the interior (allowing selection of the whole shape)
		if (bIsHitTesting)
		{
			TSharedPtr<FSpriteSelectedShape> Data = MakeShareable(new FSpriteSelectedShape(EditorContext, Geometry, ShapeIndex, /*bIsBackground=*/ true));
			PDI.SetHitProxy(new HSpriteSelectableObjectHitProxy(Data));
		}

		FColor BackgroundColor(bIsShapeSelected ? SpriteEditingConstantsEX::GeometrySelectedColor : LineColor);
		BackgroundColor.A = 4;
		FMaterialRenderProxy* ShapeMaterialProxy = WidgetVertexColorMaterial->GetRenderProxy(bIsShapeSelected);

		if (Shape.ShapeType == ESpriteShapeType::Circle)
		{
			//@TODO: This is going to have issues if we ever support ellipses
			const FVector2D PixelSpaceRadius = Shape.BoxSize * 0.5f;
			const float WorldSpaceRadius = PixelSpaceRadius.X * UnitsPerPixel;

			const FVector CircleCenterWorldPos = EditorContext->TextureSpaceToWorldSpace(Shape.BoxPosition);

			DrawDisc(&PDI, CircleCenterWorldPos, PaperAxisX, PaperAxisY, BackgroundColor, WorldSpaceRadius, SpriteEditingConstantsEX::CircleShapeNumSides, ShapeMaterialProxy, SDPG_Foreground);
		}
		else
		{
			TArray<FVector2D> SourceTextureSpaceVertices;
			Shape.GetTextureSpaceVertices(/*out*/ SourceTextureSpaceVertices);

			TArray<FVector2D> TriangulatedPolygonVertices;
			PaperGeomTools::TriangulatePoly(/*out*/ TriangulatedPolygonVertices, SourceTextureSpaceVertices, /*bKeepColinearVertices=*/ true);

			if (((TriangulatedPolygonVertices.Num() % 3) == 0) && (TriangulatedPolygonVertices.Num() > 0))
			{
				FDynamicMeshBuilder MeshBuilder;

				FDynamicMeshVertex MeshVertex;
				MeshVertex.Color = BackgroundColor;
				MeshVertex.TextureCoordinate = FVector2D::ZeroVector;
				MeshVertex.SetTangents(PaperAxisX, PaperAxisY, PaperAxisZ);

				for (const FVector2D& SrcTriangleVertex : TriangulatedPolygonVertices)
				{
					MeshVertex.Position = EditorContext->TextureSpaceToWorldSpace(SrcTriangleVertex);
					MeshBuilder.AddVertex(MeshVertex);
				}

				for (int32 TriangleIndex = 0; TriangleIndex < TriangulatedPolygonVertices.Num(); TriangleIndex += 3)
				{
					MeshBuilder.AddTriangle(TriangleIndex, TriangleIndex + 1, TriangleIndex + 2);
				}

				MeshBuilder.Draw(&PDI, FMatrix::Identity, ShapeMaterialProxy, SDPG_Foreground);
			}
		}

		if (bIsHitTesting)
		{
			PDI.SetHitProxy(nullptr);
		}
	}
}