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)); }
FMatrix USkeletalMeshComponent::GetTransformMatrix() const { FTransform RootTransform = GetBoneTransform(0); FVector Translation; FQuat Rotation; // if in editor, it should always use localToWorld // if root motion is ignored, use root transform if( GetWorld()->IsGameWorld() || !SkeletalMesh ) { // add root translation info Translation = RootTransform.GetLocation(); } else { Translation = ComponentToWorld.TransformPosition(SkeletalMesh->RefSkeleton.GetRefBonePose()[0].GetTranslation()); } // if root rotation is ignored, use root transform rotation Rotation = RootTransform.GetRotation(); // now I need to get scale // only LocalToWorld will have scale FVector ScaleVector = ComponentToWorld.GetScale3D(); Rotation.Normalize(); return FScaleMatrix(ScaleVector)*FQuatRotationTranslationMatrix(Rotation, Translation); }
void DrawDebugCone(const UWorld* InWorld, FVector const& Origin, FVector const& Direction, float Length, float AngleWidth, float AngleHeight, int32 NumSides, FColor const& DrawColor, bool bPersistentLines, float LifeTime, uint8 DepthPriority) { // no debug line drawing on dedicated server if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer) { // Need at least 4 sides NumSides = FMath::Max(NumSides, 4); const float Angle1 = FMath::Clamp<float>(AngleHeight, (float)KINDA_SMALL_NUMBER, (float)(PI - KINDA_SMALL_NUMBER)); const float Angle2 = FMath::Clamp<float>(AngleWidth, (float)KINDA_SMALL_NUMBER, (float)(PI - KINDA_SMALL_NUMBER)); const float SinX_2 = FMath::Sin(0.5f * Angle1); const float SinY_2 = FMath::Sin(0.5f * Angle2); const float SinSqX_2 = SinX_2 * SinX_2; const float SinSqY_2 = SinY_2 * SinY_2; const float TanX_2 = FMath::Tan(0.5f * Angle1); const float TanY_2 = FMath::Tan(0.5f * Angle2); TArray<FVector> ConeVerts; ConeVerts.AddUninitialized(NumSides); for(int32 i = 0; i < NumSides; i++) { const float Fraction = (float)i/(float)(NumSides); const float Thi = 2.f * PI * Fraction; const float Phi = FMath::Atan2(FMath::Sin(Thi)*SinY_2, FMath::Cos(Thi)*SinX_2); const float SinPhi = FMath::Sin(Phi); const float CosPhi = FMath::Cos(Phi); const float SinSqPhi = SinPhi*SinPhi; const float CosSqPhi = CosPhi*CosPhi; const float RSq = SinSqX_2*SinSqY_2 / (SinSqX_2*SinSqPhi + SinSqY_2*CosSqPhi); const float R = FMath::Sqrt(RSq); const float Sqr = FMath::Sqrt(1-RSq); const float Alpha = R*CosPhi; const float Beta = R*SinPhi; ConeVerts[i].X = (1 - 2*RSq); ConeVerts[i].Y = 2 * Sqr * Alpha; ConeVerts[i].Z = 2 * Sqr * Beta; } // Calculate transform for cone. FVector YAxis, ZAxis; FVector DirectionNorm = Direction.SafeNormal(); DirectionNorm.FindBestAxisVectors(YAxis, ZAxis); const FMatrix ConeToWorld = FScaleMatrix(FVector(Length)) * FMatrix(DirectionNorm, YAxis, ZAxis, Origin); // this means foreground lines can't be persistent ULineBatchComponent* const LineBatcher = GetDebugLineBatcher( InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground) ); if(LineBatcher != NULL) { float const LineLifeTime = (LifeTime > 0.f) ? LifeTime : LineBatcher->DefaultLifeTime; TArray<FBatchedLine> Lines; Lines.Empty(NumSides); FVector CurrentPoint, PrevPoint, FirstPoint; for(int32 i = 0; i < NumSides; i++) { CurrentPoint = ConeToWorld.TransformPosition(ConeVerts[i]); Lines.Add(FBatchedLine(ConeToWorld.GetOrigin(), CurrentPoint, DrawColor, LineLifeTime, 0.0f, DepthPriority)); // PrevPoint must be defined to draw junctions if( i > 0 ) { Lines.Add(FBatchedLine(PrevPoint, CurrentPoint, DrawColor, LineLifeTime, 0.0f, DepthPriority)); } else { FirstPoint = CurrentPoint; } PrevPoint = CurrentPoint; } // Connect last junction to first Lines.Add(FBatchedLine(CurrentPoint, FirstPoint, DrawColor, LineLifeTime, 0.0f, DepthPriority)); LineBatcher->DrawLines(Lines); } } }
void FOculusRiftHMD::DrawDebug(UCanvas* Canvas) { #if !UE_BUILD_SHIPPING check(IsInGameThread()); const auto frame = GetFrame(); if (frame) { FSettings* FrameSettings = frame->GetSettings(); if (FrameSettings->Flags.bDrawGrid) { bool bStereo = Canvas->Canvas->IsStereoRendering(); Canvas->Canvas->SetStereoRendering(false); bool bPopTransform = false; if (FrameSettings->EyeRenderDesc[0].DistortedViewport.Size.w != FMath::CeilToInt(Canvas->ClipX) || FrameSettings->EyeRenderDesc[0].DistortedViewport.Size.h != Canvas->ClipY) { // scale if resolution of the Canvas does not match the viewport bPopTransform = true; Canvas->Canvas->PushAbsoluteTransform(FScaleMatrix( FVector((Canvas->ClipX) / float(FrameSettings->EyeRenderDesc[0].DistortedViewport.Size.w), Canvas->ClipY / float(FrameSettings->EyeRenderDesc[0].DistortedViewport.Size.h), 1.0f))); } const FColor cNormal(255, 0, 0); const FColor cSpacer(255, 255, 0); const FColor cMid(0, 128, 255); for (int eye = 0; eye < 2; ++eye) { int lineStep = 1; int midX = 0; int midY = 0; int limitX = 0; int limitY = 0; int renderViewportX = FrameSettings->EyeRenderDesc[eye].DistortedViewport.Pos.x; int renderViewportY = FrameSettings->EyeRenderDesc[eye].DistortedViewport.Pos.y; int renderViewportW = FrameSettings->EyeRenderDesc[eye].DistortedViewport.Size.w; int renderViewportH = FrameSettings->EyeRenderDesc[eye].DistortedViewport.Size.h; lineStep = 48; OVR::Vector2f rendertargetNDC = OVR::FovPort(FrameSettings->EyeRenderDesc[eye].Fov).TanAngleToRendertargetNDC(OVR::Vector2f(0.0f)); midX = (int)((rendertargetNDC.x * 0.5f + 0.5f) * (float)renderViewportW + 0.5f); midY = (int)((rendertargetNDC.y * 0.5f + 0.5f) * (float)renderViewportH + 0.5f); limitX = FMath::Max(renderViewportW - midX, midX); limitY = FMath::Max(renderViewportH - midY, midY); int spacerMask = (lineStep << 1) - 1; for (int xp = 0; xp < limitX; xp += lineStep) { float x[4]; float y[4]; x[0] = (float)(midX + xp) + renderViewportX; y[0] = (float)0 + renderViewportY; x[1] = (float)(midX + xp) + renderViewportX; y[1] = (float)renderViewportH + renderViewportY; x[2] = (float)(midX - xp) + renderViewportX; y[2] = (float)0 + renderViewportY; x[3] = (float)(midX - xp) + renderViewportX; y[3] = (float)renderViewportH + renderViewportY; if (xp == 0) { RenderLines(Canvas->Canvas, 1, cMid, x, y); } else if ((xp & spacerMask) == 0) { RenderLines(Canvas->Canvas, 2, cSpacer, x, y); } else { RenderLines(Canvas->Canvas, 2, cNormal, x, y); } } for (int yp = 0; yp < limitY; yp += lineStep) { float x[4]; float y[4]; x[0] = (float)0 + renderViewportX; y[0] = (float)(midY + yp) + renderViewportY; x[1] = (float)renderViewportW + renderViewportX; y[1] = (float)(midY + yp) + renderViewportY; x[2] = (float)0 + renderViewportX; y[2] = (float)(midY - yp) + renderViewportY; x[3] = (float)renderViewportW + renderViewportX; y[3] = (float)(midY - yp) + renderViewportY; if (yp == 0) { RenderLines(Canvas->Canvas, 1, cMid, x, y); } else if ((yp & spacerMask) == 0) { RenderLines(Canvas->Canvas, 2, cSpacer, x, y); } else { RenderLines(Canvas->Canvas, 2, cNormal, x, y); } } } if (bPopTransform) { Canvas->Canvas->PopTransform(); // optional scaling } Canvas->Canvas->SetStereoRendering(bStereo); } if (IsStereoEnabled() && FrameSettings->Flags.bShowStats) { static const FColor TextColor(0,255,0); // Pick a larger font on console. UFont* const Font = FPlatformProperties::SupportsWindowedMode() ? GEngine->GetSmallFont() : GEngine->GetMediumFont(); const int32 RowHeight = FMath::TruncToInt(Font->GetMaxCharHeight() * 1.1f); float ClipX = Canvas->ClipX; float ClipY = Canvas->ClipY; float LeftPos = 0; ClipX -= 100; //ClipY = ClipY * 0.60; LeftPos = ClipX * 0.3f; float TopPos = ClipY * 0.4f; int32 X = (int32)LeftPos; int32 Y = (int32)TopPos; FString Str, StatusStr; // First row // Str = FString::Printf(TEXT("TimeWarp: %s"), (FrameSettings->Flags.bTimeWarp) ? TEXT("ON") : TEXT("OFF")); // Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); // // Y += RowHeight; //Str = FString::Printf(TEXT("VSync: %s"), (FrameSettings->Flags.bVSync) ? TEXT("ON") : TEXT("OFF")); //Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); //Y += RowHeight; Str = FString::Printf(TEXT("Upd on GT/RT: %s / %s"), (!FrameSettings->Flags.bDoNotUpdateOnGT) ? TEXT("ON") : TEXT("OFF"), (FrameSettings->Flags.bUpdateOnRT) ? TEXT("ON") : TEXT("OFF")); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; // static IConsoleVariable* CFinishFrameVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.FinishCurrentFrame")); // int finFr = CFinishFrameVar->GetInt(); // Str = FString::Printf(TEXT("FinFr: %s"), (finFr || FrameSettings->Flags.bTimeWarp) ? TEXT("ON") : TEXT("OFF")); // Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); // // Y += RowHeight; Str = FString::Printf(TEXT("PD: %.2f"), FrameSettings->PixelDensity); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; Str = FString::Printf(TEXT("QueueAhead: %s"), (FrameSettings->bQueueAheadEnabled) ? TEXT("ON") : TEXT("OFF")); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; Str = FString::Printf(TEXT("FOV V/H: %.2f / %.2f deg"), FMath::RadiansToDegrees(FrameSettings->VFOVInRadians), FMath::RadiansToDegrees(FrameSettings->HFOVInRadians)); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; Str = FString::Printf(TEXT("W-to-m scale: %.2f uu/m"), frame->WorldToMetersScale); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); if ((FrameSettings->SupportedHmdCaps & ovrHmdCap_DynamicPrediction) != 0) { float latencies[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; const int numOfEntries = sizeof(latencies) / sizeof(latencies[0]); if (ovrHmd_GetFloatArray(Hmd, "DK2Latency", latencies, numOfEntries) == numOfEntries) { Y += RowHeight; char buf[numOfEntries][20]; char destStr[100]; FCStringAnsi::Snprintf(destStr, sizeof(destStr), "Latency, ren: %s tw: %s pp: %s err: %s %s", FormatLatencyReading(buf[0], sizeof(buf[0]), latencies[0]), FormatLatencyReading(buf[1], sizeof(buf[1]), latencies[1]), FormatLatencyReading(buf[2], sizeof(buf[2]), latencies[2]), FormatLatencyReading(buf[3], sizeof(buf[3]), latencies[3]), FormatLatencyReading(buf[4], sizeof(buf[4]), latencies[4])); Str = ANSI_TO_TCHAR(destStr); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); } } // Second row X = (int32)LeftPos + 200; Y = (int32)TopPos; StatusStr = ((FrameSettings->SupportedTrackingCaps & ovrTrackingCap_Position) != 0) ? ((FrameSettings->Flags.bHmdPosTracking) ? TEXT("ON") : TEXT("OFF")) : TEXT("UNSUP"); Str = FString::Printf(TEXT("PosTr: %s"), *StatusStr); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; Str = FString::Printf(TEXT("Vision: %s"), (frame->Flags.bHaveVisionTracking) ? TEXT("ACQ") : TEXT("LOST")); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; Str = FString::Printf(TEXT("IPD: %.2f mm"), FrameSettings->InterpupillaryDistance*1000.f); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; StatusStr = ((FrameSettings->SupportedHmdCaps & ovrHmdCap_LowPersistence) != 0) ? ((FrameSettings->Flags.bLowPersistenceMode) ? TEXT("ON") : TEXT("OFF")) : TEXT("UNSUP"); Str = FString::Printf(TEXT("LowPers: %s"), *StatusStr); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; // StatusStr = ((FrameSettings->SupportedDistortionCaps & ovrDistortionCap_Overdrive) != 0) ? // ((FrameSettings->Flags.bOverdrive) ? TEXT("ON") : TEXT("OFF")) : TEXT("UNSUP"); // Str = FString::Printf(TEXT("Overdrive: %s"), *StatusStr); // Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); // Y += RowHeight; } //TODO: Where can I get context!? UWorld* MyWorld = GWorld; if (FrameSettings->Flags.bDrawTrackingCameraFrustum) { DrawDebugTrackingCameraFrustum(MyWorld, Canvas->SceneView->ViewRotation, Canvas->SceneView->ViewLocation); } if (Canvas && Canvas->SceneView) { DrawSeaOfCubes(MyWorld, Canvas->SceneView->ViewLocation); } } #endif // #if !UE_BUILD_SHIPPING }