zworld/engine/object/camera/camera.go

103 lines
2.2 KiB
Go
Raw Normal View History

2024-01-14 22:56:06 +08:00
package camera
import (
"zworld/engine/object"
"zworld/engine/renderapi"
"zworld/engine/renderapi/color"
"zworld/plugins/math/mat4"
"zworld/plugins/math/vec3"
)
// Camera Group
type Object struct {
object.Object
*Camera
}
// Camera Component
type Camera struct {
object.Component
Args
Viewport renderapi.Screen
Aspect float32
Proj mat4.T
View mat4.T
ViewInv mat4.T
ViewProj mat4.T
ViewProjInv mat4.T
Eye vec3.T
Forward vec3.T
}
type Args struct {
Fov float32
Near float32
Far float32
Clear color.T
}
// New creates a new camera component.
func New(args Args) *Camera {
return object.NewComponent(&Camera{
Args: args,
Aspect: 1,
})
}
func NewObject(args Args) *Object {
return object.New("Camera", &Object{
Camera: New(args),
})
}
func (cam *Object) Name() string { return "Camera" }
// Unproject screen space coordinates into world space
func (cam *Camera) Unproject(pos vec3.T) vec3.T {
// screen space -> clip space
pos.Y = 1 - pos.Y
pos = pos.Scaled(2).Sub(vec3.One)
// unproject to world space by multiplying inverse view-projection
return cam.ViewProjInv.TransformPoint(pos)
}
func (cam *Camera) RenderArgs(screen renderapi.Screen) renderapi.Args {
// todo: passing the global viewport allows the camera to modify the actual render viewport
// update view & view-projection matrices
cam.Viewport = screen
cam.Aspect = float32(cam.Viewport.Width) / float32(cam.Viewport.Height)
cam.Proj = mat4.Perspective(cam.Fov, cam.Aspect, cam.Near, cam.Far)
// calculate the view matrix.
// should be the inverse of the cameras transform matrix
tf := cam.Transform()
cam.Eye = tf.WorldPosition()
cam.Forward = tf.Forward()
cam.ViewInv = tf.Matrix()
cam.View = cam.ViewInv.Invert()
cam.ViewProj = cam.Proj.Mul(&cam.View)
cam.ViewProjInv = cam.ViewProj.Invert()
return renderapi.Args{
Viewport: cam.Viewport,
Near: cam.Near,
Far: cam.Far,
Fov: cam.Fov,
Projection: cam.Proj,
View: cam.View,
ViewInv: cam.ViewInv,
VP: cam.ViewProj,
VPInv: cam.ViewProjInv,
MVP: cam.ViewProj,
Clear: cam.Clear,
Position: cam.Transform().WorldPosition(),
Forward: cam.Transform().Forward(),
}
}