Announcement

Collapse
No announcement yet.

[Partly Solved]Canvas HUD - Deproject function

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

    [Partly Solved]Canvas HUD - Deproject function

    I basicly want to create a crosshair, on the center of the screen, that acts like a holographic dot. In other words, the crosshair should be projected from the middle of the HUD onto the envirronment, as shown by the image below (courtesy of UDN) .

    [shot]http://udn.epicgames.com/Three/rsrc/Three/CanvasTechnicalGuide/mouse_reticle.jpg[/shot]


    Excerpt of my HUD code:
    Code:
            Canvas.SetPos(X,Y);
    	Canvas.DrawTile(Texture2D'OC_HUD.crosshair', 48, 48, 0, 0, 64, 64);
    	Canvas.DeProject( ????? , ???? , ???? );
    so my question is, How do I do it, what exactly do I have to fill in? my crosshair texture is OC_crosshair, its dimensions are 64x64 and it needs to be rescaled to 48x48.
    (X and Y in canvas.SetPos are set to the center of the screen)

    thanks in advance.

    #2
    You need to use a trace to get the position.

    Comment


      #3
      If you are just doing it from the center of the screen, you shouldn't need to DeProject anything. You just do a trace from the camera location along the direction it is facing. Find where that trace hits something and use the HitLocation and HitNormal from the Trace to position and orient a movable decal to project your texture onto the surface in the world. The example in that pic does use DeProject, but it is slightly different as the reticule is following the mouse cursor which is not necessarily tied to the camera. It does use a movable decal to project the texture onto the environment like I described though.

      I believe this is the relevant code that was quickly thrown together to get the picture in that example (there maybe some errors in it as I tried to remove extraneous stuff and it is from an older version of UDK):

      ReticuleActor.uc
      Code:
      class ReticuleActor extends DecalActorMovable;
      
      defaultproperties
      {
      	bNoDelete=false
      }
      UDNHUD.uc
      Code:
      class UDNHUD extends MobileHUD;
      
      var CanvasIcon CursorIcon;
      
      var ReticuleActor Reticule;
      var MaterialInterface ReticuleMaterial;
      
      
      simulated function PostBeginPlay()
      {
      	local Vector MouseOrigin, MouseDir;
      	local vector HitLocation, HitNormal;
      
      	super.PostBeginPlay();
      
      	Canvas.DeProject(UDNPlayerController(PlayerOwner).MouseCoordinates, MouseOrigin, MouseDir);
      	PlayerOwner.Trace(HitLocation, HitNormal, MouseOrigin + (MouseDir * 100000), MouseOrigin, true);
      	Reticule = Spawn(class'UDNGame.ReticuleActor', , , HitLocation + (HitNormal * 48), Rotator(HitNormal * -1), , true);
      
      	if(Reticule != none)
      	{
      		Reticule.Decal.SetDecalMaterial(ReticuleMaterial);
      	}
      }
      
      function DrawHUD()
      {
      	local Vector MouseOrigin, MouseDir;
      	local vector HitLocation, HitNormal;
      
      	super.DrawHUD();
      
      	//Draw Mouse Cursor
      	Canvas.SetDrawColorStruct(WhiteColor);
      	Canvas.DrawIcon(CursorIcon, UDNPlayerController(PlayerOwner).MouseCoordinates.X, UDNPlayerController(PlayerOwner).MouseCoordinates.Y, 1.0);
      
      	//Draw Reticule
      	Canvas.DeProject(UDNPlayerController(PlayerOwner).MouseCoordinates, MouseOrigin, MouseDir);
      	if(PlayerOwner.Trace(HitLocation, HitNormal, MouseOrigin + (MouseDir * 100000), MouseOrigin, true) != none)
      	{
      		if(Reticule == none)
      		{
      			Reticule = Spawn(class'UDNGame.ReticuleActor', , , HitLocation + (HitNormal * 48), Rotator(HitNormal * -1), , true);
      
      			if(Reticule != none)
      			{
      				Reticule.Decal.SetDecalMaterial(ReticuleMaterial);
      			}
      		}
      
      		if(Reticule != none)
      		{
      			Reticule.SetLocation(HitLocation + (HitNormal * 48));
      			Reticule.SetRotation(Rotator(HitNormal * -1));
      		}
      	}
      }
      
      defaultproperties
      {
      	CursorIcon=(Texture=Texture2D'UDNHUDContent.UDN_HUDGraphics',U=8,V=136,UL=24,VL=24)
      	ReticuleMaterial=DecalMaterial'UDNHUDContent.DM_Reticle'
      }
      UDNPlayerController.uc
      Code:
      class UDNPlayerController extends UTPlayerController;
      
      var Vector2D MouseCoordinates;
      
      simulated function PostBeginplay()
      {
      	Super.PostBeginplay();
      
      	MouseCoordinates.X = MyHUD.CenterX;
      	MouseCoordinates.Y = MyHUD.CenterY;
      }
      
      state PlayerWalking
      {
      	function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
      	{
      		Super.ProcessMove(DeltaTime, NewAccel, DoubleClickMove, DeltaRot);
      
      		MouseCoordinates.X += (PlayerInput.aTurn * 0.1);
      		MouseCoordinates.Y -= (PlayerInput.aLookUp * 0.1);
      	
      		MouseCoordinates.X = FMin(MyHUD.SizeX, FMax(0, MouseCoordinates.X));
      		MouseCoordinates.Y = FMin(MyHUD.SizeY, FMax(0, MouseCoordinates.Y));
      	}
      }
      Attached Files

      Comment


        #4
        Alright, I'll try that code you provided me with, what are the mouseorigin and mousedirection vectors for? and are the files outside of the HUD file nescessary, or can you integrate everything into the HUD file?

        thanks for the quick reply , finding it hard to gather some documentation on all this.

        Comment


          #5
          Ah nvm, I see it now. So use trace to get hitlocation and hitnormal, then use a movable decal to project the crosshair. hmm. How exactly would that look in code?

          Comment


            #6
            Some stuff that might be helpful to you:
            Your trace should start from your view, so you can use Pawn.GetPawnViewLocation() to get a vector with that coordinates.
            And your trace should end in a certain distance (because the longer a trace gets, the more does it impact the performance) in the direction your are looking at.
            If it hits something before the maximum distance, you can use that as the location where you want to have the Deproject, otherwise you deproject at the end of the trace.
            This gets you a location in the distance you are looking at:
            vector(Pawn.GetViewRotation()) + Pawn.GetPawnViewLocation() * MaximumTraceDistance

            And to find out how you need to insert stuff into the Trace(), take a look here:
            http://wiki.beyondunreal.com/UE3:Act...28UDK%29#Trace

            Comment


              #7
              Originally posted by Beastenator View Post
              Ah nvm, I see it now. So use trace to get hitlocation and hitnormal, then use a movable decal to project the crosshair. hmm. How exactly would that look in code?
              The code is what I provided. A trace is performed in DrawHUD() and the HitLocation and HitNormal are used to position and orient the movable decal (the ReticuleActor).

              Comment


                #8
                Sorry for hijacking this thread.

                But I suppose it's better than starting another of the same topic?

                I am having a problem with this:

                Code:
                simulated function PostBeginPlay()
                {
                	local Vector MouseOrigin, MouseDir;
                	local vector HitLocation, HitNormal;
                
                	super.PostBeginPlay();
                
                	Canvas.DeProject(SRPlayerController(PlayerOwner).MouseCoordinates, MouseOrigin, MouseDir);
                	PlayerOwner.Trace(HitLocation, HitNormal, MouseOrigin + (MouseDir * 100000), MouseOrigin, true);
                	Reticule = Spawn(class'SR_Reticule', , , HitLocation + (HitNormal * 48), Rotator(HitNormal * -1), , true);
                
                	if(Reticule != none)
                	{
                		Reticule.Decal.SetDecalMaterial(ReticuleMaterial);
                	}
                
                	MouseCoordinates.X = CenterX;
                	MouseCoordinates.Y = CenterY;
                }
                MouseCoordinates at the bottom is giving me a "Bad Expression" error.

                Comment


                  #9
                  Originally posted by Graylord View Post
                  Sorry for hijacking this thread.

                  But I suppose it's better than starting another of the same topic?

                  I am having a problem with this:

                  Code:
                  simulated function PostBeginPlay()
                  {
                  	local Vector MouseOrigin, MouseDir;
                  	local vector HitLocation, HitNormal;
                  
                  	super.PostBeginPlay();
                  
                  	Canvas.DeProject(SRPlayerController(PlayerOwner).MouseCoordinates, MouseOrigin, MouseDir);
                  	PlayerOwner.Trace(HitLocation, HitNormal, MouseOrigin + (MouseDir * 100000), MouseOrigin, true);
                  	Reticule = Spawn(class'SR_Reticule', , , HitLocation + (HitNormal * 48), Rotator(HitNormal * -1), , true);
                  
                  	if(Reticule != none)
                  	{
                  		Reticule.Decal.SetDecalMaterial(ReticuleMaterial);
                  	}
                  
                  	MouseCoordinates.X = CenterX;
                  	MouseCoordinates.Y = CenterY;
                  }
                  MouseCoordinates at the bottom is giving me a "Bad Expression" error.
                  That's because those lines shouldn't be there. Like I said, I was trying to clean up the code before posting it and some things may have been missed. The code I have contained all of the code for about 6 different examples and I tried to remove all but what pertained to that one image.

                  Comment


                    #10
                    Ah, I see.

                    I also noticed a lot of stuff is done twice, like drawing and spawning the reticule.
                    It's done both in the PostBeginPlay and in the main draw loop.

                    I am not sure if it's an error, or if I have just missed why though.

                    Edit: It works though! Well, mostly.
                    It's quite offset, always hidden in the corner of the screen, and it's not showing the material. Does Canvas support SoftMasked materials?
                    Edit: It's telling me it has "invalid usage". I tried just using a plain diffuse material with the default settings, same thing. I'd try looking at the example material, but they seem to no longer be included, nor in the September version, which I am using for my project.

                    Comment


                      #11
                      Originally posted by Graylord View Post
                      Ah, I see.

                      I also noticed a lot of stuff is done twice, like drawing and spawning the reticule.
                      It's done both in the PostBeginPlay and in the main draw loop.

                      I am not sure if it's an error, or if I have just missed why though.
                      The reticule is never "drawn" in that code. It's a decal and all rendering is handled by the decal itself so I am not sure what you mean by that part. The reticule is spawned int he PostBeginPlay(), but I added a fail-safe in the DrawHUD() to respawn it in case it failed or gets detroyed elsewhere. That code only gets executed should the reticule not exist for some reason.

                      Originally posted by Graylord View Post
                      Edit: It works though! Well, mostly.
                      It's quite offset, always hidden in the corner of the screen, and it's not showing the material. Does Canvas support SoftMasked materials?
                      Edit: It's telling me it has "invalid usage". I tried just using a plain diffuse material with the default settings, same thing. I'd try looking at the example material, but they seem to no longer be included, nor in the September version, which I am using for my project.
                      The Canvas isn't drawing the reticule so I don't know why that would matter. I don't know if decals can handle soft-masked materials, but I also don't see any reason to use one. Just use a translucent, additive, or modulated material and it should be fine.

                      I'll take a few minutes at some point and test the code and make sure I didn't mangle it too badly when cleaning it up. I really just posted it as a pointer and not as code to be used verbatim, especially since it was quickly thrown together in the first place to get a screenshot.

                      Edit: I updated my original post with tested, working code and I attached a package with the mouse cursor and reticule in it so you can see how those were created.

                      When you said offset, if you meant that the cursor is not locked to the center of the screen, then that is correct. It was never meant to be since it was just a quick way to get a screenshot. Really the issue is I left in the mouse controlling the camera so I could get a little movement. Ideally, you would have either the mouse controlling the reticule or the mouse controlling the camera, not both.

                      Comment


                        #12
                        I see.

                        I left out the cursor, because I do not want to use it.

                        I'll let you in on the effect I was looking for.

                        Basically, when a player pushes the button, a decal appears in front of him, always where the center of the screen is pointing.
                        I already got the button working, so I only need to know how to make it always lock to the center of the screen.

                        But I don't understand how this is not already happening? I thought the trace origined from the camera in a straight line, then created the decal where it stops?

                        It should basically be the same as the OP is asking for.

                        Ideally, you would have either the mouse controlling the reticule or the mouse controlling the camera, not both.
                        When you say reticule, you're talking about the decal, right?
                        If so, that's exactly the functionality I need.
                        If I understand you correctly.

                        I could perhaps let the controller go into the state where it's controlling a cursor instead of the camera, but it's not ideal.

                        Edit: Wait, is there a camera trace rather than mouse trace?

                        Comment


                          #13
                          I recreated the material in the example using my own texture, and it's still giving me a "invalid usage" in the log when it tries to draw it by the way.

                          Comment


                            #14
                            Like I said previously, the example does not lock to the center of the screen. If that's the functionality you need, you will have to modify it to do the trace from the camera location along the direction it is facing. All I was providing is the original example code as a starting point. Making it fit your needs is up to you.

                            Comment


                              #15
                              Any lists in the documentation of the various types of trace and their syntax?

                              Comment

                              Working...
                              X