About Monkey 2 › Forums › Monkey 2 Programming Help › Projecting vectors
Tagged: camera projection, mojo3d
This topic contains 6 replies, has 3 voices, and was last updated by
Mark Sibly
1 year, 7 months ago.
-
AuthorPosts
-
September 11, 2017 at 7:54 pm #10404
How do I take a Vec3 coordinate and “project” it onto the 2D camera plane?
I’m trying to draw HUD elements on top of a 3D scene that stay locked to their 3D counterparts. Going through the modules I see that the camera has a Matrix and I can multiply the point by that, but I don’t know how to proceed from there and get the actual projected point as Vec2.
Thanks!
September 11, 2017 at 8:04 pm #10405Dividing a 3d point by it’s ‘z’ component will give you a 2d point at z=1.
September 11, 2017 at 9:40 pm #10412Ok, almost working…
The line translates across the screen as the camera rotates, but at a different rate. I imagine this is because I’m using the camera’s Matrix but not the ProjectionMatrix, so the FOV is ignored. But a ProjectionMatrix is Mat4, and I don’t see any method there that could help me in this case. Or is there?
Monkey12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970#Import "<mojo3d>"Using std..Using mojo..Using mojo3d..Function Main()New AppInstanceNew TestWindowApp.Run()EndClass TestWindow Extends WindowField refBall:ModelField camera:CameraField light:LightMethod New()Super.New( "Test", 1280, 720, WindowFlags.Resizable )ClearColor = Color.BlackLayout = "fill"refBall = Model.CreateSphere( 1, 30,30, New PbrMaterial( Color.Orange, 0, 0.5 ) )camera = New Cameracamera.Move( 0, 2, -5 )camera.Near = 0.1camera.Far = 10.0camera.PointAt( New Vec3f )light = New Lightlight.Rotation = New Vec3f( 30, 60, 0 )EndMethod OnRender( canvas:Canvas ) OverrideApp.RequestRender()If Keyboard.KeyDown( Key.Right )camera.Ry -= 1.0Else If Keyboard.KeyDown( Key.Left )camera.Ry += 1.0EndIf Keyboard.KeyDown( Key.Up )camera.Rx -= 1.0Else If Keyboard.KeyDown( Key.Down )camera.Rx += 1.0EndScene.GetCurrent().Render( canvas, camera )Draw3DLine( canvas, camera, Width, Height, New Vec3f(0,-1,0), New Vec3f(0,1,0) )EndFunction Draw3DLine( canvas:Canvas, camera:Camera, width:Float, height:Float, v0:Vec3f, v1:Vec3f )Local c0 := ( -camera.Matrix*v0 )Local c1 := ( -camera.Matrix*v1 )Local offsetX := width/2.0Local offsetY := height/2.0Local s0 := New Vec2f( ((c0.x/c0.z)*width)+offsetX, ((c0.y/-c0.z)*height)+offsetY )Local s1 := New Vec2f( ((c1.x/c1.z)*width)+offsetX, ((c1.y/-c1.z)*height)+offsetY )canvas.DrawLine( s0, s1 )EndEndSeptember 11, 2017 at 11:30 pm #10414Ok, I think these camera methods are basically what you’re after? Adding to repos soon…
Monkey1234567891011121314151617181920212223242526#rem monkeydoc Converts a point from world coordinates to viewport coordinates.#endMethod ProjectToViewport:Vec2f( worldVertex:Vec3f )Local clip_coords:=ProjectionMatrix * InverseMatrix * New Vec4f( worldVertex,1.0 )Local ndc_coords:=clip_coords.XY/clip_coords.wLocal vp_coords:=Cast<Vec2f>( Viewport.Size ) * (ndc_coords * 0.5 + 0.5)Return vp_coordsEnd#rem monkeydoc Converts a point from viewport coordinates to world coordinates.#endMethod UnprojectFromViewport:Vec3f( viewportCoords:Vec2f )Local vp_coords:=viewportCoords / Cast<Vec2f>( Viewport.Size ) * 2.0 - 1.0Local clip_coords:=New Mat4f( Matrix ) * -ProjectionMatrix * New Vec4f( vp_coords,-1.0,1.0 )Local world_coords:=clip_coords.XYZ/clip_coords.wReturn world_coordsEndYou can added these as extensoin methods if you want, or butcher them for your own evil purposes.
September 12, 2017 at 1:51 am #10419Is there a plan to add switcher for camera orthographic / perspective mode?
September 12, 2017 at 2:30 am #10420Sweet! Thanks!
Is there a plan to add switcher for camera orthographic / perspective mode?
That would be great. I tried doing it by butchering the existing classes and failed miserably!
Here’s the working version of the 3D lines example, if anyone is interested…
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778#Import "<mojo3d>"Using std..Using mojo..Using mojo3d..Function Main()New AppInstanceNew TestWindowApp.Run()EndClass TestWindow Extends WindowField refBall:ModelField camera:CameraField light:LightMethod New()Super.New( "Test", 1280, 720, WindowFlags.Resizable )ClearColor = Color.BlackLayout = "fill"refBall = Model.CreateSphere( 1, 30,30, New PbrMaterial( Color.Orange, 0, 0.5 ) )camera = New Cameracamera.Move( 0, 0, -5 )camera.Near = 0.1camera.Far = 10.0camera.FOV = 60camera.PointAt( New Vec3f )light = New Lightlight.Rotation = New Vec3f( 30, 60, 0 )EndMethod OnRender( canvas:Canvas ) OverrideApp.RequestRender()If Keyboard.KeyDown( Key.Right )camera.Ry -= 1.0Else If Keyboard.KeyDown( Key.Left )camera.Ry += 1.0EndIf Keyboard.KeyDown( Key.Up )camera.Rx -= 1.0Else If Keyboard.KeyDown( Key.Down )camera.Rx += 1.0EndScene.GetCurrent().Render( canvas, camera )canvas.DrawText( "Use cursor keys to rotate camera", 10, 10 )Draw3DLine( canvas, camera, New Vec3f(-1,-1,0), New Vec3f(1,-1,0) )Draw3DLine( canvas, camera, New Vec3f(1,-1,0), New Vec3f(1,1,0) )Draw3DLine( canvas, camera, New Vec3f(1,1,0), New Vec3f(-1,1,0) )Draw3DLine( canvas, camera, New Vec3f(-1,1,0), New Vec3f(-1,-1,0) )EndMethod Draw3DLine( canvas:Canvas, camera:Camera, v0:Vec3f, v1:Vec3f )Local s0 := camera.ProjectToView( v0 )Local s1 := camera.ProjectToView( v1 )canvas.DrawLine( s0.X, -s0.Y+Height, s1.X, -s1.Y+Height )EndEndClass Camera ExtensionMethod ProjectToView:Vec2f( worldVertex:Vec3f )Local clip_coords:=ProjectionMatrix * InverseMatrix * New Vec4f( worldVertex,1.0 )Local ndc_coords:=clip_coords.XY/clip_coords.wLocal vp_coords:=Cast<Vec2f>( Viewport.Size ) * (ndc_coords * 0.5 + 0.5)Return vp_coordsEndEndSeptember 12, 2017 at 9:12 am #10427Yes, camera’ll eventually support orthographic, and hopefully stero one day!
This is the nice thing about the 4×4 projection matrix – it supports both perspective and orthographic projections so the project/unproject code wont have to change.
-
AuthorPosts
You must be logged in to reply to this topic.