103 lines
2.2 KiB
Go
103 lines
2.2 KiB
Go
|
|
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(),
|
||
|
|
}
|
||
|
|
}
|