package render import ( "edgaru089.ink/go/gl01/internal/util/itype" "github.com/go-gl/mathgl/mgl32" ) // View represents a viewport in the 3-d world. // It is essentialy a projection and a view matrix. type View struct { EyePos itype.Vec3f // position of the eye rotY, rotZ, fovY itype.Angle aspect float32 near, far float32 clipSet bool } // View returns the View matrix from parameters set with LookAt(). func (r *View) View() mgl32.Mat4 { delta := mgl32.Rotate3DY(r.rotY.Radians()).Mul3(mgl32.Rotate3DZ(r.rotZ.Radians())).Mul3x1(mgl32.Vec3{1, 0, 0}) return mgl32.LookAt( r.EyePos[0], r.EyePos[1], r.EyePos[2], r.EyePos[0]+delta[0], r.EyePos[1]+delta[1], r.EyePos[2]+delta[2], 0, 1, 0, ) } // Perspective returns the Perspective matrix with parameters set with Aspect(), FovY() and Clip(). func (r *View) Perspective() mgl32.Mat4 { if r.clipSet { return mgl32.Perspective(r.fovY.Radians(), r.aspect, r.near, r.far) } else { return mgl32.Perspective(r.fovY.Radians(), r.aspect, 0.1, 200) } } // LookAt resets the View matrix with a camera looking from Eye. // The camera points to +RotY from X+ axis rotating around Y axis (right-handed); // +/-RotZ form X+ axis rotating up/down around Z axis. // ( RotZ should be in the (-90,90) degrees range ) // // It also returns itself so that operations can be chained. func (r *View) LookAt(eye itype.Vec3f, rotY, rotZ itype.Angle) *View { r.EyePos = eye r.rotY = rotY r.rotZ = rotZ return r } // Aspect sets the aspect (width / height) of the viewport. // // It also returns itself so that operations can be chained. func (r *View) Aspect(aspectRatio float32) *View { r.aspect = aspectRatio return r } // FovY sets the Field of View (an angle) on the Y axis. // FovX = FovY * aspect. // // With FovX, call SetFovY(FovX / aspect). // // It also returns itself so that operations can be chained. func (r *View) FovY(fovy itype.Angle) *View { r.fovY = fovy return r } // Clip sets the near/far clipping distance of the Perspective. // It defaults to 0.1 / 200. // // It also returns itself so that operations can be chained. func (r *View) Clip(near, far float32) *View { r.near, r.far = near, far r.clipSet = true return r }