Jump to content

Positioning 3D plane using 2D coordinates


Rick
 Share

Recommended Posts

I have a plane model that I'm using for a gui widget. I want to have options to anchor these to top, bottom, left, right edges of the screen. I'm just testing top left (0,0) atm so I have the following code:

 

local pos = self.camera:UnProject(Vec3(0, 0, 1))

-- always face the camera
self.entity:SetPosition(self.camera:GetPosition())
self.entity:SetRotation(self.camera:GetRotation())
self.entity:Move((pos.x / 2), (pos.y / 2), 1, false)
self.entity:Turn(270, 0, 0)

 

However this doesn't align the plane exactly to the top left edge. For a screen resolution of 1024x768 if I change the Move() code to self.entity:Move((pos.x / 2) + .018, (pos.y / 2) - .15, 1) it lines up perfectly, but for other resolutions that doesn't line up.

 

I'm using the plane model that comes with LE Models/Primitives/plane.mdl

 

Why is self.camera:UnProject(Vec3(0, 0, 1)) not producing a point that would be exactly in the center of the plane at the 2D space 0,0? How can I do this to be more consistent with any resolution?

Link to comment
Share on other sites

i don't know what you exactly try to achieve but if you wan't to have the plane center at the top left position of the screen

 

local pos = self.camera:UnProject(Vec3(0, 0, 1))
-- always face the camera
self.entity:SetPosition(pos)
self.entity:SetRotation(self.camera:GetRotation())
self.entity:Turn(270, 0, 0)

 

this works for me.

Link to comment
Share on other sites

That does work thanks. I'm a little confused though. If I unproject (800, 600, 1) then the center of the plane is in the bottom right. I guess I would expect then (0,0,1) would have the center of the plane in the top/left (since I'm guessing that's the center of the plane model), but it's not the center of the plane it's actually the top/left of the plane.

 

Basically, I'm looking to anchor the plane to any edge of the 2D screen.

 

Trying to do this against the right edges seems like I'll need to convert the scale of the plane to pixels on the screen so I can subtract that difference by what I send to UnProject? Not really sure how I'd do this. Man I wish I was better at math :/

Link to comment
Share on other sites

uhm. UnProject converts a pixel position on your screen from the camera to a global 3d position.

 

So to attach it to the top right side you would only need to get the width of your context.

 

local context=Context:GetCurrent()
local pos = self.camera:UnProject(Vec3(context:GetWidth(), 0, 1))

Link to comment
Share on other sites

That doesn't work for me. The center of the plane ends up in the top right corner. I would want the top right of the plane to be in the top right corner of the window. This is why I'm confused some why 0, 0 puts the top left corner of the plane at the top left corner of the window instead of the center of the plane at the top left corner of the window as I assume the local 0,0 of the plane would be it's center.

 

If this was 2D you'd have to subtract the width of the image from the right edge to "anchor" it on the right side. However because it's a 3D plane I'm not sure how you'd do this. I think you'd have to convert width of the plane from 3D space to 2D space and then subtract that number by the context width before sending it to UnProject(). Not sure how to do that 3D to 2D conversion of a size.

 

[edit]

Actually I was incorrect. (0,0,1) does put the plane at the center point of the plane in the top/left instead of the top/left corner of the plane. So on all edges I'll have to account for 1/2 the plane width/height and adjust somehow. The texture I was using didn't make this obvious but I switched textures and now I can see that.

 

Thinking out loud. Let's say we have a plane, 2 units in width, total, and 1 unit away from the camera. Would need to see how wide in pixels that is given the current screen resolution.

 

Maybe I could get the scale and subtract 1/2 the scale from the position and unproject that value, then add 1/2 the scale to the position and unproject that value, then find the difference between those 2 values to get the size in pixels and then add that to the screen space I want to unproject. hmm will give it a go.

Link to comment
Share on other sites

hmm. i don't know how we could get the actual screen pixels of the entity since it is also depending of the distance etc.

 

The easiest would be to change the base of the entity. I think that would be possible in a 3d model editor.

 

 

Another way could be to set a pivot at the position and parent your entity to it.

 

Just like this:

function Script:Start()
 self.pivot = Pivot:Create()
 local entityscale = self.entity:GetScale()
 local entityPos = self.entity:GetPosition()
 entityPos.x = entityPos.x + (entityscale.x/2)
 entityPos.z = entityPos.z + (entityscale.z/2)
 self.pivot:SetPosition(entityPos)
 self.entity:SetParent(self.pivot)
end
function Script:UpdateWorld()
 local context=Context:GetCurrent()
 local pos = self.camera:UnProject(Vec3(context:GetWidth(), 0, 1))
 -- always face the camera
 self.pivot:SetPosition(pos)
 self.pivot:SetRotation(self.camera:GetRotation())
 self.pivot:Turn(270, 0, 0)
end

Link to comment
Share on other sites

The easiest would be to change the base of the entity. I think that would be possible in a 3d model editor.

 

I don't think this would work as I want to be able to anchor to any side the same plane so setting the base at the top/left would work for the top/left screen but not the bottom/right is I want to anchor a widget plane there. I'd be in the same boat. Maybe there is a way to change this dynamically in LE though. Will check that out as that might be the easiest.

 

I put in that code but got a funky result.

Link to comment
Share on other sites

i tried my code and it works for me. Now i have the plane top right corner at the top left right of the screen.

And you can change the pivot position if you wan't to attach the plane at another corner.

Edited by beo6
Link to comment
Share on other sites

Got it to work. My plane was rotated in the editor to start with which screwed it up. I got all of the edges anchorable now. I have a hard time thinking in 3D though.

 

So anchoring on some other edges requires different combinations of positioning the pivot and what point is unprojected? Like I can unproject (0,0) or (contextWidth, 0) or (0, contextHeight) or (contextWidth, contextHeight), or even 1/2 contextWidth and height, etc?

 

Thanks for the help and good idea of the pivot!

Link to comment
Share on other sites

Nice that you got it to work. It was just a quick idea since I had no better idea.

You can unproject any position on the screen. and the pivot is only the Anchor position of the entity. if you want to change the pivot on the fly it becomes a bit more complicated since you move your entity with the pivot because it is parented.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...