Announcement

Collapse
No announcement yet.

Multiple active cameras for 1 player

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Multiple active cameras for 1 player

    I'm starting a project soon will require different views of the scene to be displayed by different physical monitors, sometimes with asymmetrical split screens per physical monitor (e.g. 3 camera views in one monitor).

    I've searched around and found some fragmented info regarding how to go about this (e.g. this thread here), which left me wondering if it is at all feasible with my current UE4 API knowledge (i.e. not great ).

    Though not shy of these type of challenges, I'd like to know if anyone already implemented that and could at least outline the steps/methods they've followed so confused me can avoid some pains.

    Thanks for your help!

    #2
    Hi guys, any more news about this? I am also interested to output multiple cameras to create an imersive environment using beamers in a room. If you found a solution to this, I would appreciate any update.

    cheers

    Comment


      #3
      Sorry guys, I never had the time to tackle this. It seems I'll go back to Unity to finish the project, unfortunately.

      Comment


        #4
        Anyone solved this?

        Comment


          #5
          Hey guys,
          these days i got an early solution for a seperate window, which acts as a launcher for different maps. It shows a mouse-interactive Widget-Blueprint. (I just have guesses how about showing the 3D world with different camera in it.)
          accordingly to the engine's solution, i looked at the Init() function of UGameEngine to make this. with a minimalistic thought, i got a lot of very different exceptions, so this quite stable version looks a bit overcoded/dirty(?).

          This functions are part of a UUserWidget derived class, so in the end, it adds itself to the new viewport. but in principle you can use the code in any uclass:
          Code:
          // MainUI.cpp
          bool UMainUI::CreateMainUI()
          {
          	bMainUICreated = false;
          
          	if( GIsClient )
          	{
          		//Initialize GameInstance of new viewport client
          		UPXGameInstance* PXGameInstance = NewObject<UPXGameInstance>( GEngine, UPXGameInstance::StaticClass() );
          		PXGameInstance->InitializeMainUIContext( GetWorld()->GetFirstPlayerController() );
          
          		//Initialize Viewport Client
          		// MainUI.h: UGameViewportClient* MainUIViewportClient;
          		MainUIViewportClient = NewObject<UGameViewportClient>( GEngine, UGameViewportClient::StaticClass() ); 
          		MainUIViewportClient->Init( *PXGameInstance->GetWorldContext(), PXGameInstance );
          
          		PXGameInstance->GetWorldContext()->GameViewport = MainUIViewportClient;
          
          		if( MainUIViewportClient )
          		{
          			//create and register a new Window
          			TSharedRef<SWindow> Window = SNew( SWindow )
          				.ScreenPosition( FVector2D( 100, 100 ) )
          				.ClientSize( FVector2D( 1024, 512 ) )
          				.SizingRule( ESizingRule::FixedSize )
          				.Title( FText::FromString( TEXT( "Launcher" ) ) )
          				.AutoCenter( EAutoCenter::None )
          				.FocusWhenFirstShown( true )
          				.UseOSWindowBorder( false )
          				.CreateTitleBar( true )
          				.SupportsTransparency( EWindowTransparency::PerWindow )
          				.InitialOpacity( 0.9f )
          				.SupportsMaximize( false );
          
          			TSharedPtr<SWindow> TopWindow = FSlateApplication::Get().GetActiveTopLevelWindow();
          			if( TopWindow.IsValid() )
          			{
          				FSlateApplication::Get().AddWindowAsNativeChild( Window, TopWindow.ToSharedRef(), true );
          			}
          			Window->SetWindowMode( EWindowMode::Windowed );
          			Window->SetCursor( EMouseCursor::Default );
          
          			// Attach the viewport client to a new viewport.
          			TSharedRef<SOverlay> ViewportOverlayWidgetRef = SNew( SOverlay );
          			ViewportOverlayWidgetRef->SetCursor( EMouseCursor::Default );
          
          			TSharedRef<SGameLayerManager> LayerManagerRef = SNew( SGameLayerManager )
          				.SceneViewport( MainUIViewportClient->GetGameViewport() )
          				.Visibility( EVisibility::Visible )
          				.UseScissor( false )
          				.Cursor( EMouseCursor::Default )
          				[
          					ViewportOverlayWidgetRef
          				];
          
          			TSharedPtr<class SViewport> Viewport = SNew( SViewport )
          				.RenderDirectlyToWindow( true )
          				.EnableGammaCorrection( false )
          				.EnableStereoRendering( true )
          				.Cursor( EMouseCursor::Default )
          				[
          					LayerManagerRef
          				];
          
          			MainUIViewportClient->SetViewportOverlayWidget( Window, ViewportOverlayWidgetRef );
          			MainUIViewportClient->SetGameLayerManager( LayerManagerRef );
          
          			Window->SetOnWindowClosed( FOnWindowClosed::CreateUObject( this, &UMainUI::OnMainUIWindowClosed ) );
          
          			// MainUI.h: TSharedPtr<FSceneViewport> MainUISceneViewport;
          			MainUISceneViewport = MakeShareable( new FSceneViewport( MainUIViewportClient, Viewport ) );
          			MainUIViewportClient->Viewport = MainUISceneViewport.Get();
          			Viewport->SetViewportInterface( MainUISceneViewport.ToSharedRef() );
          
          			FViewportFrame* ViewportFrame = MainUISceneViewport.Get();
          
          			MainUIViewportClient->SetViewportFrame( ViewportFrame );
          
          			Window->SetContent( Viewport.ToSharedRef() );
          			Window->ShowWindow();
          
          			this->Cursor = EMouseCursor::Default;
          			this->AddToScreen( MainUIViewportClient, 0 );
          
          			bMainUICreated = true;
          		}
          	}
          
          	return bMainUICreated;
          }
          
          void UMainUI::OnMainUIWindowClosed( const TSharedRef<SWindow>& WindowBeingClosed )
          {
          
          	MainUIViewportClient->CloseRequested( MainUISceneViewport->GetViewport() );
          	MainUISceneViewport.Reset();
          
          	MainUIViewportClient = NULL;
          	MainUISceneViewport = NULL;
          
          	UGameEngine* gameEngine = Cast<UGameEngine>( GEngine );
          	if( gameEngine )
          	{
          		if( gameEngine->GameViewportWindow.IsValid() )
          		{
          			gameEngine->OnGameWindowClosed( gameEngine->GameViewportWindow.Pin().ToSharedRef() );
          		}
          	}
          
          	bMainUICreated = false;
          }

          Because the WorldContext is inaccessable, the UGameInstance is inherited and this function overridden:
          Code:
          void UPXGameInstance::InitializeMainUIContext( AController* controller )
          {
          	WorldContext = &GetEngine()->CreateNewWorldContext( EWorldType::None );
          	WorldContext->OwningGameInstance = this;
          
          	// create a MainUI world
          	UWorld* MainUIWorld = UWorld::CreateWorld( EWorldType::None, false, "MainUI" );
          	MainUIWorld->SetGameInstance( this );
          	GEngine->DestroyWorldContext( MainUIWorld ); //the world context is not destroyed inside this function, it gets removed from the Engine's World List (to avoid references to this dummy world)
          	WorldContext->SetCurrentWorld( MainUIWorld );
          	
          	MainUIWorld->AddController( controller );
          
          	Init();
          }
          In this last function you can see, that a dummy world is created for the new ViewportClient. maybe you can play around with passing the actual game world with a different controller.
          Hope this helps.

          Comment


            #6
            Nice! Thank you for posting the code too. How do I go about adding this code to my project? Should I create a new class or add it to an existing class?

            Comment


              #7
              you should be able to add the first part to a UCLASS of your desire. these are the additional includes:
              #include "Engine/GameEngine.h"
              #include "SGameLayerManager.h"
              #include "Slate/SceneViewport.h"
              #include "PXGameInstance.h"
              #include "GameViewportClient.h"


              while the second part you inherit GameInstance (https://wiki.unrealengine.com/Game_I...t_Data_Storage)

              but problems can surely occure since i do not understand the complete engine code :/
              Meanwhile i investigate on the bottleneck that the complete game scene is rendered two times, which even is a desired behaviour if showing a 3D view from each window, but i didnt' tested this out.
              Play with it, i hope i can help

              Comment


                #8
                Hi,
                Is anybody can make this works?
                show another 3D view besides the main playing view?

                Comment


                  #9
                  Hi, I Recreate your code and when i Execute Nothing Show in New Window... New Window is Black...

                  Im My Map i Create a New Widget MainUI and Add to ViewPort....

                  How I Send Widget in New Screen ???

                  You have a Example ?


                  When I Build to Final Package in Windows I Receive Crash ...

                  LogStats:Warning: MetaData mismatch. Did you assign a stat to two groups? New //STATGROUP_Threads//FLauncherTask///Thread_2770_0///####STATCAT_Advanced#### old //STATGROUP_Threads//FLauncherTask///Thread_12c4_0///####STATCAT_Advanced####
                  LogPlayLevel: CosmicIllusion: LogModuleManager:Warning: ModuleManager: Module 'HTTPChunkInstaller' not found - its StaticallyLinkedModuleInitializers function is null.
                  LogPlayLevel: CosmicIllusion: LogInitisplay: RandInit(1707644882) SRandInit(1707644884).LogLinker:Warning: CreateImport: Failed to load Outer for resource 'WidgetTree': WidgetBlueprint /Script/UMGEditor.Default__WidgetBlueprint
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion: [2016.03.14-11.21.29:089][ 0]LogLinker:Warning: CreateImport: Failed to load Outer for resource 'WidgetTree': WidgetBlueprint /Script/UMGEditor.Default__WidgetBlueprintLogModuleManager:Warning: ModuleManager: Module 'GameplayDebugger' not found - its StaticallyLinkedModuleInitializers function is null.
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion: [2016.03.14-11.21.29:101][ 0]LogModuleManager:Warning: ModuleManager: Module 'GameplayDebugger' not found - its StaticallyLinkedModuleInitializers function is null.LogInitisplay: Game Engine Initialized.
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion: [2016.03.14-11.21.29:113][ 0]LogInitisplay: Game Engine Initialized.LogWindows:Error: Windows GetLastError: A opera��o foi conclu�da com �xito. (0)
                  LogPlayLevel: CosmicIllusion: LogWindows:Warning: CreateProc failed (2) ..\..\..\Engine\Binaries/Win64/CrashReportClient.exe -AppName=UE4-CosmicIllusion
                  LogPlayLevel: CosmicIllusion: LogThreadingWindows:Error: Runnable thread SlateLoadingThread crashed.
                  LogPlayLevel: CosmicIllusion: LogOutputDevice:Error:
                  LogPlayLevel: CosmicIllusion: begin: stack for UAT
                  LogPlayLevel: CosmicIllusion: LogWindows:Error: === Critical error: ===
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion: Assertion failed: CurrentThreadIfKnown == GetCurrentThread() [File:\BuildFarm\buildmachine_++depot+UE4-Releases+4.10\Engine\Source\Runtime\Core\Private\Async\TaskGraph.cpp] [Line: 1117]
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion: Crash in runnable thread SlateLoadingThread
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion:
                  LogPlayLevel: CosmicIllusion: LogOutputDevice:Error:
                  LogPlayLevel: CosmicIllusion: end: stack for UAT
                  LogPlayLevel: BuildCommand.Execute: ERROR: BUILD FAILED
                  LogPlayLevel: Program.Main: ERROR: AutomationTool terminated with exception:
                  LogPlayLevel: Program.Main: ERROR: Exception in AutomationScripts.Automation: Client exited with error code: 3
                  LogPlayLevel: Stacktrace: em Project.RunStandaloneClient(List`1 DeployContextList, String ClientLogFile, ERunOptions ClientRunFlags, String ClientApp, String ClientCmdLine, ProjectParams Params)
                  LogPlayLevel: em Project.RunInternal(ProjectParams Params, String ServerLogFile, String ClientLogFile)
                  LogPlayLevel: em Project.Run(ProjectParams Params)
                  LogPlayLevel: em BuildCookRun.DoBuildCookRun(ProjectParams Params)
                  LogPlayLevel: em BuildCommand.Execute()
                  LogPlayLevel: em AutomationTool.Automation.Execute(List`1 CommandsToExecute, CaselessDictionary`1 Commands)
                  LogPlayLevel: em AutomationTool.Automation.Process(String[] CommandLine)
                  LogPlayLevel: em AutomationTool.Program.MainProc(Object Param)
                  LogPlayLevel: em AutomationTool.InternalUtils.RunSingleInstance(Action`1 Main, Object Param)
                  LogPlayLevel: em AutomationTool.Program.Main()
                  LogPlayLevel: ProcessManager.KillAll: Trying to kill 0 spawned processes.
                  LogPlayLevel: Program.Main: AutomationTool exiting with ExitCode=Error_Unknown
                  LogPlayLevel: Domain_ProcessExit
                  LogPlayLevel: copying UAT log files...
                  LogPlayLevel: RunUAT.bat ERROR: AutomationTool was unable to run successfully.
                  LogPlayLevel: Completed Launch On Stage: Run Task, Time: 10.517573
                  LogPlayLevel: BUILD FAILED
                  PackagingResults:Error: Error Launch failed! Unknown Error
                  Last edited by CrashAngel; 03-14-2016, 07:24 AM.

                  Comment


                    #10
                    https://drive.google.com/open?id=0Bx...m9mVmRJS1FaTTA <-- MainUIWindow-Project

                    Originally posted by DennyD View Post
                    Hi,
                    Is anybody can make this works?
                    show another 3D view besides the main playing view?
                    hey, I managed a empty project supporting a separate window, showing a userwidget. you can start a level, control it via the widget and also get a rendertarget streaming to the separate window.
                    magic happens in the MainUI.cpp, which is managing the slate/window-stuff, and is also derived from userwidget to be the actual displayed widget.
                    GameManager.cpp is handling the maingame-window, while MainUIGameInstance.cpp is for interaction between the "game"- and "ui"-levels.
                    the level blueprint of Base_Level brings it all up.

                    the project works fine at 4.10.4 and also packages and launches quite well on windows at me. input stucks some times a bit. but be aware, until this is not a supported feature of the engine, the solution may get destroyed by the next engine-update.



                    Originally posted by CrashAngel View Post
                    Hi, I Recreate your code and when i Execute Nothing Show in New Window... New Window is Black...

                    Im My Map i Create a New Widget MainUI and Add to ViewPort....

                    How I Send Widget in New Screen ???

                    You have a Example ?


                    When I Build to Final Package in Windows I Receive Crash ...
                    I am very sorry, I don't have a clue about your packaging error. maybe you can check the code against the project I uploaded? upgrading from 4.9 to 4.10 required some code adaption. have you set the PrivateDependencyModuleNames in the .Build.cs -file?

                    the widget itself is set in MainUI.cpp, CreateMainUIWindow():

                    TSharedPtr<SWidget> UserSlateWidget = TakeWidget();
                    [...]
                    MainUIViewportClient->AddViewportWidgetContent( ViewportWidget, 10 );


                    you should be able to pass another widget into the function and replace the TakeWidget()


                    hope this helps, ask what you need!
                    greets

                    Comment


                      #11
                      Hi Schlabbermampf,

                      Hi Schlabbermampf,

                      I'm testing here and found that when I change the parameter values in the new window as the Mouse Click event is initiated the level window enters a state of Pause .. nothing happens while I do not finish to modify the parameter in the window HUD ... you would know what I can change that when the mouse event occurs in the HUD window the Level not please pause ???

                      Comment


                        #12
                        Originally posted by Schlabbermampf View Post
                        https://drive.google.com/open?id=0Bx...m9mVmRJS1FaTTA <-- MainUIWindow-Project



                        hey, I managed a empty project supporting a separate window, showing a userwidget. you can start a level, control it via the widget and also get a rendertarget streaming to the separate window.
                        magic happens in the MainUI.cpp, which is managing the slate/window-stuff, and is also derived from userwidget to be the actual displayed widget.
                        GameManager.cpp is handling the maingame-window, while MainUIGameInstance.cpp is for interaction between the "game"- and "ui"-levels.
                        the level blueprint of Base_Level brings it all up.

                        the project works fine at 4.10.4 and also packages and launches quite well on windows at me. input stucks some times a bit. but be aware, until this is not a supported feature of the engine, the solution may get destroyed by the next engine-update.





                        I am very sorry, I don't have a clue about your packaging error. maybe you can check the code against the project I uploaded? upgrading from 4.9 to 4.10 required some code adaption. have you set the PrivateDependencyModuleNames in the .Build.cs -file?

                        the widget itself is set in MainUI.cpp, CreateMainUIWindow():

                        TSharedPtr<SWidget> UserSlateWidget = TakeWidget();
                        [...]
                        MainUIViewportClient->AddViewportWidgetContent( ViewportWidget, 10 );


                        you should be able to pass another widget into the function and replace the TakeWidget()


                        hope this helps, ask what you need!
                        greets
                        Where I would have to change to instead put a widget inside the window I put a camera somewhere I Level?

                        I would like to change the parameter of the level object does not enter into a pause state ... I think if I put a viewport and then add a HUD interface in the viewport the game not enter into a pause state ...
                        Last edited by CrashAngel; 03-25-2016, 12:30 AM.

                        Comment


                          #13
                          Originally posted by CrashAngel View Post
                          you would know what I can change that when the mouse event occurs in the HUD window the Level not please pause ???
                          I'm sorry, since i this effect is even appearing in unreal editor (the game is paused during click/drag outside the PIE-viewport), this isn't fixed easily. referencing to this post, there is a workaround to at least simulate correctly: track the system time during mouse-drag and add it to the next frames delta time. however, this does not unpause the viewport :/
                          i assume it is some engine code, configurating the game windows


                          Originally posted by CrashAngel View Post
                          Where I would have to change to instead put a widget inside the window I put a camera somewhere I Level?

                          I would like to change the parameter of the level object does not enter into a pause state ... I think if I put a viewport and then add a HUD interface in the viewport the game not enter into a pause state ...
                          do you mean, setting up the second window, to show the actual view of a second camera, just like the game-windows does? not just a widget. at the moment, i have no solution for that, but i think it is doable.
                          the core code of the window creation is taken from UGameEngine::Init(IEngineLoop* InEngineLoop) and sub-functions. one will take a look here, where the engine is setting the viewport of the actual game-window, and do this accordingly for the new window. maybe another player-controller has do be spawned and passed.

                          Comment


                            #14
                            Originally posted by Schlabbermampf View Post
                            I'm sorry, since i this effect is even appearing in unreal editor (the game is paused during click/drag outside the PIE-viewport), this isn't fixed easily. referencing to this post, there is a workaround to at least simulate correctly: track the system time during mouse-drag and add it to the next frames delta time. however, this does not unpause the viewport :/
                            i assume it is some engine code, configurating the game windows




                            do you mean, setting up the second window, to show the actual view of a second camera, just like the game-windows does? not just a widget. at the moment, i have no solution for that, but i think it is doable.
                            the core code of the window creation is taken from UGameEngine::Init(IEngineLoop* InEngineLoop) and sub-functions. one will take a look here, where the engine is setting the viewport of the actual game-window, and do this accordingly for the new window. maybe another player-controller has do be spawned and passed.

                            I understood...

                            Schlabbermampf, actually I'm trying to create an application within the Unreal Engine ... and would need a new window to submit a interface where I could control all objects of Level being loaded .... So that part I've got making reflect the screen objects by C ++.
                            What is being harder it is to find a way to extend the windows ... I've done some tests in multiplayer mode and to work, more the problem is that in multiplayer mode I need to load into memory machine 2 Levels while every window and it would require a lot of processors ...

                            So you can understand, I am creating a software that will act as projection interactive video with synchronized audio ... A kind of Resolume http://www.resolume.com with Ableton Live http://www.ableton.com

                            Take a look at my development within the Unreal .. https://www.youtube.com/watch?v=dkF2...yIx65k&index=1

                            Now I wonder if you could or know someone who could make a Free-Lance just to assemble a window with HUD not to pause the game when a control is changed ... I'm in Brazil ... and could make payment PayPal .... I am a student and also would be willing to pay the amount of $ 115 ... what do you think?
                            Last edited by CrashAngel; 03-26-2016, 01:07 PM.

                            Comment


                              #15
                              A lot of work todo, but I will investigate in this from time to time and hope to find a clue. If I do, I let you know!
                              At best, Epic would add this as a common Engine feature

                              Comment

                              Working...
                              X