FVector2D FSingleTileEditorViewportClient::WorldSpaceToTextureSpace(const FVector& SourcePoint) const
{
	const FVector ProjectionX = SourcePoint.ProjectOnTo(PaperAxisX);
	const FVector ProjectionY = -SourcePoint.ProjectOnTo(PaperAxisY);

	const float XValue = FMath::Sign(ProjectionX | PaperAxisX) * ProjectionX.Size();
	const float YValue = FMath::Sign(ProjectionY | PaperAxisY) * ProjectionY.Size();

	return FVector2D(XValue, YValue);
}
float AGGJ16_Player::TakeDamage(float DamageAmount, struct FDamageEvent const &DamageEvent, class AController* EventInstigator, AActor* DamageCauser)
{
	if (!bDamaged)
	{
		health -= DamageAmount;
	}

	if (health <= 0)
	{
		playDeathAnim = true;
	}
	else
	{
		bDamaged = true;
	}

	if (DamageCauser)
	{
		FVector curForwardVector = DamageCauser->GetActorLocation() - this->GetActorLocation();
		curForwardVector.ProjectOnTo(FVector(1, 1, 0));
		curForwardVector.Normalize();
		LaunchCharacter(curForwardVector * KnockBackAlpha, true, true);
	}

	return 0.f;
	//do the pretty things
};
FVector2D FSingleTileEditorViewportClient::SelectedItemConvertWorldSpaceDeltaToLocalSpace(const FVector& WorldSpaceDelta) const
{
	const FVector ProjectionX = WorldSpaceDelta.ProjectOnTo(PaperAxisX);
	const FVector ProjectionY = WorldSpaceDelta.ProjectOnTo(PaperAxisY);

	const float XValue = FMath::Sign(ProjectionX | PaperAxisX) * ProjectionX.Size();
	const float YValue = FMath::Sign(ProjectionY | PaperAxisY) * ProjectionY.Size();

	return FVector2D(XValue, YValue);
}
Esempio n. 4
0
FVector UKismetMathLibrary::ProjectVectorOnToVector(FVector V, FVector Target)
{
	if (Target.SizeSquared() > SMALL_NUMBER)
	{
		return V.ProjectOnTo(Target);
	}
	else
	{
		FFrame::KismetExecutionMessage(TEXT("Divide by zero: ProjectVectorOnToVector with zero Target vector"), ELogVerbosity::Warning);
		return FVector::ZeroVector;
	}
}
Esempio n. 5
0
static FVector CombineAdjustments(FVector CurrentAdjustment, FVector AdjustmentToAdd)
{
	// remove the part of the new adjustment that's parallel to the current adjustment
	if (CurrentAdjustment.IsZero())
	{
		return AdjustmentToAdd;
	}

	FVector Projection = AdjustmentToAdd.ProjectOnTo(CurrentAdjustment);
	Projection = Projection.GetClampedToMaxSize(CurrentAdjustment.Size());

	FVector OrthogalAdjustmentToAdd = AdjustmentToAdd - Projection;
	return CurrentAdjustment + OrthogalAdjustmentToAdd;
}
FVector UKismetMathLibrary::ProjectOnTo(FVector X, FVector Y)
{
	return X.ProjectOnTo( Y );
}
void UPaperTileMapComponent::RebuildRenderData(FPaperTileMapRenderSceneProxy* Proxy)
{
	TArray<FSpriteDrawCallRecord> BatchedSprites;
	
	if (TileMap == nullptr)
	{
		return;
	}

	FVector CornerOffset;
	FVector OffsetYFactor;
	FVector StepPerTileX;
	FVector StepPerTileY;
	TileMap->GetTileToLocalParameters(/*out*/ CornerOffset, /*out*/ StepPerTileX, /*out*/ StepPerTileY, /*out*/ OffsetYFactor);
	
	UTexture2D* LastSourceTexture = nullptr;
	FVector TileSetOffset = FVector::ZeroVector;
	FVector2D InverseTextureSize(1.0f, 1.0f);
	FVector2D SourceDimensionsUV(1.0f, 1.0f);
	FVector2D TileSizeXY(0.0f, 0.0f);

	for (int32 Z = 0; Z < TileMap->TileLayers.Num(); ++Z)
	{
		UPaperTileLayer* Layer = TileMap->TileLayers[Z];

		if (Layer == nullptr)
		{
			continue;
		}

		FLinearColor DrawColor = FLinearColor::White;
#if WITH_EDITORONLY_DATA
		if (Layer->bHiddenInEditor)
		{
			continue;
		}

		DrawColor.A = Layer->LayerOpacity;
#endif

		FSpriteDrawCallRecord* CurrentBatch = nullptr;

		for (int32 Y = 0; Y < TileMap->MapHeight; ++Y)
		{
			// In pixels
			FVector EffectiveTopLeftCorner;

			switch (TileMap->ProjectionMode)
			{
			case ETileMapProjectionMode::Orthogonal:
			default:
				EffectiveTopLeftCorner = CornerOffset;
				break;
			case ETileMapProjectionMode::IsometricDiamond:
				EffectiveTopLeftCorner = CornerOffset - StepPerTileX;
				break;
			case ETileMapProjectionMode::IsometricStaggered:
			case ETileMapProjectionMode::HexagonalStaggered:
				EffectiveTopLeftCorner = CornerOffset + (Y & 1) * OffsetYFactor;
				break;
			}

			for (int32 X = 0; X < TileMap->MapWidth; ++X)
			{
				const FPaperTileInfo TileInfo = Layer->GetCell(X, Y);

				// do stuff
				const float TotalSeparation = (TileMap->SeparationPerLayer * Z) + (TileMap->SeparationPerTileX * X) + (TileMap->SeparationPerTileY * Y);
				FVector TopLeftCornerOfTile = (StepPerTileX * X) + (StepPerTileY * Y) + EffectiveTopLeftCorner;
				TopLeftCornerOfTile += TotalSeparation * PaperAxisZ;

				const int32 TileWidth = TileMap->TileWidth;
				const int32 TileHeight = TileMap->TileHeight;


				{
					UTexture2D* SourceTexture = nullptr;

					FVector2D SourceUV = FVector2D::ZeroVector;
					if (Layer->bCollisionLayer)
					{
						if (TileInfo.PackedTileIndex == 0)
						{
							continue;
						}
						SourceTexture = UCanvas::StaticClass()->GetDefaultObject<UCanvas>()->DefaultTexture;
					}
					else
					{
						if (TileInfo.TileSet == nullptr)
						{
							continue;
						}

						if (!TileInfo.TileSet->GetTileUV(TileInfo.PackedTileIndex, /*out*/ SourceUV))
						{
							continue;
						}

						SourceTexture = TileInfo.TileSet->TileSheet;
						if (SourceTexture == nullptr)
						{
							continue;
						}
					}

					if ((SourceTexture != LastSourceTexture) || (CurrentBatch == nullptr))
					{
						CurrentBatch = (new (BatchedSprites) FSpriteDrawCallRecord());
						CurrentBatch->Texture = SourceTexture;
						CurrentBatch->Color = DrawColor;
						CurrentBatch->Destination = TopLeftCornerOfTile.ProjectOnTo(PaperAxisZ);
					}

					if (SourceTexture != LastSourceTexture)
					{
						InverseTextureSize = FVector2D(1.0f / SourceTexture->GetSizeX(), 1.0f / SourceTexture->GetSizeY());

						if (TileInfo.TileSet != nullptr)
						{
							SourceDimensionsUV = FVector2D(TileInfo.TileSet->TileWidth * InverseTextureSize.X, TileInfo.TileSet->TileHeight * InverseTextureSize.Y);
							TileSizeXY = FVector2D(TileInfo.TileSet->TileWidth, TileInfo.TileSet->TileHeight);
							TileSetOffset = (TileInfo.TileSet->DrawingOffset.X * PaperAxisX) + (TileInfo.TileSet->DrawingOffset.Y * PaperAxisY);
						}
						else
						{
							SourceDimensionsUV = FVector2D(TileWidth * InverseTextureSize.X, TileHeight * InverseTextureSize.Y);
							TileSizeXY = FVector2D(TileWidth, TileHeight);
							TileSetOffset = FVector::ZeroVector;
						}
						LastSourceTexture = SourceTexture;
					}
					TopLeftCornerOfTile += TileSetOffset;

					SourceUV.X *= InverseTextureSize.X;
					SourceUV.Y *= InverseTextureSize.Y;

					FSpriteDrawCallRecord& NewTile = *CurrentBatch;

					const float WX0 = FVector::DotProduct(TopLeftCornerOfTile, PaperAxisX);
					const float WY0 = FVector::DotProduct(TopLeftCornerOfTile, PaperAxisY);

					const FVector4 BottomLeft(WX0, WY0 - TileSizeXY.Y, SourceUV.X, SourceUV.Y + SourceDimensionsUV.Y);
					const FVector4 BottomRight(WX0 + TileSizeXY.X, WY0 - TileSizeXY.Y, SourceUV.X + SourceDimensionsUV.X, SourceUV.Y + SourceDimensionsUV.Y);
					const FVector4 TopRight(WX0 + TileSizeXY.X, WY0, SourceUV.X + SourceDimensionsUV.X, SourceUV.Y);
					const FVector4 TopLeft(WX0, WY0, SourceUV.X, SourceUV.Y);

					new (NewTile.RenderVerts) FVector4(BottomLeft);
					new (NewTile.RenderVerts) FVector4(TopRight);
					new (NewTile.RenderVerts) FVector4(BottomRight);

					new (NewTile.RenderVerts) FVector4(BottomLeft);
					new (NewTile.RenderVerts) FVector4(TopLeft);
					new (NewTile.RenderVerts) FVector4(TopRight);
				}
			}
		}
	}

	Proxy->SetBatchesHack(BatchedSprites);
}
// Runs calculations on friction component, applies friction force to effected component and returns reaction forces(forces that can effect track or a wheel)
void UMMTFrictionComponent::ApplyFriction(const FVector& ContactPointLocation, const FVector& ContactPointNormal, const FVector& InducedVelocity, const FVector& PreNormalForceAtPoint,
        const EPhysicalSurface& PhysicalSurface, const float& NumberOfContactPoints, const float& DeltaTime, FVector& NormalizedReactionForce, FVector& RollingFrictionForce)
{
    // Gather stats
    SCOPE_CYCLE_COUNTER(STAT_MMTFrictionApply);

    float NormalForceAtContactPoint = PreNormalForceAtPoint.ProjectOnTo(ContactPointNormal).Size();

    // Check if Effected Component Mesh reference is valid and escape early otherwise
    if (!IsValid(EffectedComponentMesh))
    {
        GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, FString::Printf(TEXT("%s->%s component's EffectedComponentMesh reference is invalid!"), *GetOwner()->GetName(), *GetName()));
        UE_LOG(LogTemp, Warning, TEXT("%s->%s component's EffectedComponentMesh reference is invalid!"), *GetOwner()->GetName(), *GetName());
        NormalizedReactionForce = FVector::ZeroVector;
        RollingFrictionForce = FVector::ZeroVector;
        return;
    }

    //Find relative velocity of the friction surface and ground/another object at point
    FVector RelativeVelocityAtPoint = EffectedComponentMesh->GetPhysicsLinearVelocityAtPoint(ContactPointLocation) + InducedVelocity + FrictionSurfaceVelocity;
    RelativeVelocityAtPoint = RelativeVelocityAtPoint.VectorPlaneProject(RelativeVelocityAtPoint, ContactPointNormal);

    //filter out oscillations when vehicle is standing still but friction overshoots
    RelativeVelocityAtPoint = (PrevRelativeVelocityAtPoint + RelativeVelocityAtPoint) * 0.5;
    PrevRelativeVelocityAtPoint = RelativeVelocityAtPoint;

    // early exit if velocity is too low to consider as vehicle most likely standing still
    if (RelativeVelocityAtPoint.Size() < 1.0f)
    {
        NormalizedReactionForce = FVector::ZeroVector;
        RollingFrictionForce = FVector::ZeroVector;
        return;
    }

    //Calculate static and kinetic friction coefficients, taking into account velocity direction and friction ellipse
    float MuStatic;
    float MuKinetic;
    UMMTBPFunctionLibrary::GetMuFromFrictionElipse(RelativeVelocityAtPoint.GetSafeNormal(), ReferenceFrameTransform.TransformVector(FVector(1.0f, 1.0f, 1.0f)),
            MuXStatic, MuXKinetic, MuYStatic, MuYKinetic, MuStatic, MuKinetic);

    //Calculate "stopping force" which is amount of force necessary to completely remove velocity of the object
    FVector	StoppingForce = ((RelativeVelocityAtPoint * (-1.0f) * EffectedComponentMesh->GetMass()) / DeltaTime) / NumberOfContactPoints;

    //Static friction threshold
    float MuStaticByLoad = NormalForceAtContactPoint * MuStatic;

    //Friction Force that will be applied to effected mesh component
    FVector ApplicationForce;
    if (StoppingForce.Size() >= MuStaticByLoad)
    {
        ApplicationForce = StoppingForce.GetClampedToSize(0.0f, NormalForceAtContactPoint * MuKinetic);
        if (IsDebugMode)
        {
            DrawDebugString(GetWorld(), ContactPointLocation, FString("Kinetic Friction"), nullptr, FColor::Magenta, 0.0f, false);
        }
    }
    else
    {
        ApplicationForce = StoppingForce.GetClampedToSize(0.0f, MuStaticByLoad);
        if (IsDebugMode)
        {
            DrawDebugString(GetWorld(), ContactPointLocation, FString("Static Friction"), nullptr, FColor::Red, 0.0f, false);
        }
    }

    //Apply friction force
    UMMTBPFunctionLibrary::MMTAddForceAtLocationComponent(EffectedComponentMesh, ApplicationForce, ContactPointLocation);

    //Calculate Reaction force
    NormalizedReactionForce = (ApplicationForce * (-1.0f)) / EffectedComponentMesh->GetMass();


    //Calculate Rolling Friction
    float RollingFrictionCoefficient = FPhysicalSurfaceRollingFrictionCoefficient().RollingFrictionCoefficient;

    for (int32 i = 0; i < PhysicsSurfaceResponse.Num(); i++)
    {
        if (PhysicsSurfaceResponse[i].PhysicalSurface == PhysicalSurface)
        {
            RollingFrictionCoefficient = PhysicsSurfaceResponse[i].RollingFrictionCoefficient;
            break;
        }
    }

    RollingFrictionForce = RelativeVelocityAtPoint.GetSafeNormal() * NormalForceAtContactPoint * RollingFrictionCoefficient;

    if (IsDebugMode)
    {
        DrawDebugLine(GetWorld(), ContactPointLocation, ContactPointLocation + ApplicationForce * 0.005f, FColor::Yellow, false, 0.0f, 0, 3.0f);
        DrawDebugLine(GetWorld(), ContactPointLocation, ContactPointLocation + RollingFrictionForce * 0.005f, FColor::Green, false, 0.0f, 0, 3.0f);
        DrawDebugString(GetWorld(), ContactPointLocation+FVector(0.0f, 0.0f, 50.0f), (PhysicalSurfaceEnum ? PhysicalSurfaceEnum->GetEnumName(PhysicalSurface) : FString("<Invalid Enum>")), nullptr, FColor::Cyan, 0.0f, false);
        //DrawDebugString(GetWorld(), ContactPointLocation + FVector(0.0f, 0.0f, 25.0f), FString("Normal Force: ") + FString::SanitizeFloat(NormalForceAtContactPoint), nullptr, FColor::Turquoise, 0.0f, false);
    }
}