void AGraph::initializeEdgeMesh(UStaticMeshComponent* edgeMesh, const AGVertex* v1, const AGVertex* v2) { auto pos1 = v1->GetActorLocation(); auto pos2 = v2->GetActorLocation(); auto ray = pos2 - pos1; auto n_p1p2 = ray; n_p1p2.Z = 0; n_p1p2 = n_p1p2.GetSafeNormal(); //tile is 40*40*1. The distance needs to substract half of the tile size auto totalOffsetDistance = 40.0f; //change start & end positions from the center of the vertex mesh //to the edges of the mesh to the right direction auto p1_offset = n_p1p2 * totalOffsetDistance; pos1 += p1_offset; pos2 += -p1_offset; auto newRay = pos2 - pos1; auto rotation = FRotationMatrix::MakeFromX(newRay); auto scaleX = FVector::Dist(pos1, pos2) * .5f ; auto scaleY = 40.0f; auto scaleZ = 1.0f; FMatrix transformMatrix = FScaleMatrix(FVector(scaleX, scaleY, scaleZ)) * rotation * FTranslationMatrix(pos1); edgeMesh->SetWorldTransform(FTransform(transformMatrix)); edgeMesh->AddLocalOffset(FVector(scaleX, 0.0f, 0.0f)); }
//!< FPrimitiveSceneProxy virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, class FMeshElementCollector& Collector) const override { FDynamicMeshBuilder MeshBuilder; const auto Num = 20; const auto DeltaUV = 1.0f / (Num - 1); TArray<FDynamicMeshVertex> Vertices; Vertices.Reserve(Num * Num); for (auto i = 0; i < Num; ++i) { for (auto j = 0; j < Num; ++j) { const auto UV = FVector2D(DeltaUV * j, DeltaUV * i); FDynamicMeshVertex Vertex; Vertex.Position = GetPosition(UV); Vertex.TextureCoordinate = GetUV(UV); const auto Edge01 = GetPosition(UV + FVector2D(0.01f, 0.0f)) - Vertex.Position; const auto Edge02 = GetPosition(UV - FVector2D(0.0f, 0.01f)) - Vertex.Position; Vertex.TangentX = Edge01.GetSafeNormal(); Vertex.TangentZ = (Edge02 ^ Edge01).GetSafeNormal(); Vertex.Color = FColor::Green; Vertices.Add(Vertex); } } MeshBuilder.AddVertices(Vertices); TArray<int32> Indices; Indices.Reserve((Num - 1) * (Num - 1) * 6); for (auto i = 0; i < Num - 1; ++i) { for (auto j = 0; j < Num - 1; ++j) { const auto Index = j + i * Num; Indices.Add(Index); Indices.Add(Index + Num); Indices.Add(Index + 1); Indices.Add(Index + 1); Indices.Add(Index + Num); Indices.Add(Index + Num + 1); } } MeshBuilder.AddTriangles(Indices); auto MaterialRenderProxy = UMaterial::GetDefaultMaterial(MD_Surface)->GetRenderProxy(IsSelected()); if (nullptr != MaterialInterface) { MaterialRenderProxy = MaterialInterface->GetRenderProxy(false); } if (Views[0]->Family->EngineShowFlags.Wireframe) { MaterialRenderProxy = GEngine->WireframeMaterial->GetRenderProxy(IsSelected()); } MeshBuilder.GetMesh(GetLocalToWorld(), MaterialRenderProxy, 0, false, false, 0, Collector); }
void UTankMovementComponent::RequestDirectMove(const FVector& MoveVelocity, bool bForceMaxSpeed) { auto TankForward = GetOwner()->GetActorForwardVector().GetSafeNormal(); auto AIForwardIntention = MoveVelocity.GetSafeNormal(); auto ForwardThrow = FVector::DotProduct(TankForward, AIForwardIntention); auto RightThrow = FVector::CrossProduct(AIForwardIntention, TankForward); IntendMoveForward(ForwardThrow); IntendTurnRight(RightThrow.GetSafeNormal().Z); }
void ALaser::checkLaserCollisions(float dt) { FHitResult hit; FCollisionQueryParams queryParam; queryParam.bFindInitialOverlaps = false; queryParam.bReturnFaceIndex = true; FCollisionObjectQueryParams objectParam = objectParam.DefaultObjectQueryParam; if ( !canHitBall ) queryParam.AddIgnoredActor( GetWorld()->GetGameState<AProjectTapGameState>()->GetPlayer() ); auto pos = GetActorLocation(); auto rayStart = pos + dir * 5.0f; auto laserVector = dir * length; auto laserEmitter = laserParticle->EmitterInstances[0]; //ray cast to see if laser hits anything GetWorld()->LineTraceSingleByObjectType(hit,rayStart, pos + laserVector, objectParam,queryParam); auto hitActor = hit.Actor.Get(); if (hitActor != nullptr) { currHitPoint = hit.ImpactPoint; if(!laserSparkParticle->bIsActive) laserSparkParticle->ActivateSystem(); //kills ball if laser hits it auto ball = Cast<ABallPawn>(hitActor); if (ball != nullptr) { ball->Kill(); laserEmitter->SetBeamTargetPoint(hit.ImpactPoint, 0); KillSubLaser(); } else { //if not set laser end point laserEmitter->SetBeamTargetPoint(hit.ImpactPoint, 0); bool typeFound = false; //if hits deflective tile then spawn a new laser object auto tile = Cast<ADeflectiveTile>(hitActor); bool isFrame = false; if (tile != nullptr) { typeFound = true; TArray<USceneComponent*> Children; tile->frameCollisionsComponent->GetChildrenComponents(true, Children); for(int i = 0; i < Children.Num() && typeFound ; ++i) { // printonscreen(hit.Component.Get()->GetName()); // printonscreen(Children[i]->GetName()); if(hit.Component.Get() == Children[i]) { typeFound = false; isFrame = true; } } //cut the laser length to make sure new sub laser start doesn't hit the same object if (typeFound && CanSpawnSubLaser()) SpawnSubLaser(hit.ImpactPoint + hit.ImpactNormal * 10.0f, hit.ImpactNormal); } //if sub laser already exists then keep updating its rotation and position auto subLaserExistsHitDeflectiveTile = currentDepth < MAX_DEPTH && nextLaser != nullptr && tile != nullptr; if (subLaserExistsHitDeflectiveTile) { auto incomingVector = hit.ImpactPoint - GetActorLocation(); //if the incoming vector's angle is too small then kill sublasers to avoid laser flickering auto dot = FVector::DotProduct(-incomingVector.GetSafeNormal(), hit.ImpactNormal); auto angle = FMath::RadiansToDegrees(FMath::Acos(dot)); if (angle < 70.0f) { auto newDir = FMath::GetReflectionVector(incomingVector, hit.ImpactNormal); auto start = hit.ImpactPoint + newDir * 2.0f; nextLaser->SetActorLocation(hit.ImpactPoint); nextLaser->dir = newDir.IsNormalized() ? newDir : newDir.GetSafeNormal(); nextLaser->laserParticle->EmitterInstances[0]->SetBeamSourcePoint(hit.ImpactPoint, 0); nextLaser->laserParticle->EmitterInstances[0]->SetBeamTargetPoint(start + newDir * length, 0); } else { KillSubLaser(); } } //if the laser hits turret then kills it if (!typeFound) { auto turret = Cast<ATurretPawn>(hitActor); if (turret != nullptr) { typeFound = true; turret->Damage(2.0f); } } APortalTile* portal = nullptr; if (!typeFound) { portal = Cast<APortalTile>(hitActor); if (CanSpawnSubLaser() && portal != nullptr) { typeFound = true; auto relativePos = hit.ImpactPoint - hit.GetComponent()->GetComponentLocation(); currHitPoint = relativePos + portal->GetActorLocation(); SpawnSubLaser(currHitPoint, hit.ImpactNormal); } } auto subLaserExistsHitPortalTile = currentDepth < MAX_DEPTH && nextLaser != nullptr && portal != nullptr; if (subLaserExistsHitPortalTile) { FVector newSourcePos; portal->GetLaserPortalTransportedLocation(hit.GetComponent(), nextLaser->dir, newSourcePos); nextLaser->SetActorLocation(newSourcePos); nextLaser->laserParticle->EmitterInstances[0]->SetBeamSourcePoint(newSourcePos, 0); nextLaser->laserParticle->EmitterInstances[0]->SetBeamTargetPoint(newSourcePos + nextLaser->dir * length, 0); } bool notHitDeflectiveTile = tile == nullptr || isFrame; bool notHitPortal = portal == nullptr; if (notHitDeflectiveTile && notHitPortal) { KillSubLaser(); } } laserSparkParticle->SetWorldLocation(currHitPoint); laserSparkParticle->SetWorldRotation(FVector(currHitPoint - GetActorLocation()).GetSafeNormal().Rotation().Quaternion()); } else { currHitPoint = laserVector; laserEmitter->SetBeamTargetPoint(pos + currHitPoint, 0); laserSparkParticle->SetWorldLocation( pos + currHitPoint ); laserSparkParticle->SetWorldRotation( FVector( (pos + currHitPoint) - GetActorLocation() ).GetSafeNormal().Rotation().Quaternion() ); KillSubLaser(); } //only root laser can have an emitter mesh if (currentDepth != 0) { //update laser emitter rotation mesh->SetVisibility(false); } else { mesh->SetWorldRotation(dir.Rotation()); } }