kiki/coffee/perspective.coffee
monsterkodi b9be62273f camera
2016-08-14 17:28:20 +02:00

119 lines
4.2 KiB
CoffeeScript

# 00000000 00000000 00000000 0000000 00000000 00000000 0000000 000000000 000 000 000 00000000
# 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
# 00000000 0000000 0000000 0000000 00000000 0000000 000 000 000 000 000 0000000
# 000 000 000 000 000 000 000 000 000 000 000 000
# 000 00000000 000 000 0000000 000 00000000 0000000 000 000 0 00000000
{
clamp
} = require '/Users/kodi/s/ko/js/tools/tools'
log = require '/Users/kodi/s/ko/js/tools/log'
Matrix = require './lib/matrix'
class Perspective extends Matrix
constructor: (fov,near=0.01,far=1000) ->
@znear = near
@zfar = far
@fov = fov
@aspect_ratio = -1.0
@eye_distance = @znear
# @eye_distance = 5.0
@border = [0,0,0,0]
@setViewport 0.0, 0.0, 1.0, 1.0
super
# log "Perspective #{@fov} #{@znear} #{@zfar}"
reset: ->
@fov = 60.0
@eye_distance = @znear
super
@translate 0, 0, @eye_distance
# rotate: (x,y,z) ->
# savePos = @getLookAtPosition()
# @translate -@getPosition()
#
# up = @getYVector()
# look = @getZVector()
#
# rotxz = Matrix.rotation x, 0.0, z
# roty = Matrix.rotation 0.0, y, 0.0
#
# yunit = new Vector 0.0, 1.0, 0.0
# zunit = new Vector 0.0, 0.0, 1.0
#
# lookperp = @look.perpendicular yunit # y-axis rotation
# if lookperp.length() > 0
# look = roty.transform lookperp.plus look.parallel(yunit)
# up = roty.transform up.perpendicular(yunit).plus up.parallel(yunit)
#
# # x & z-axis rotation
# transmat = new Matrix up.cross(look), up, look
#
# uprotxz = rotxz.transform yunit
# lookrotxz = rotxz.transform zunit
#
# up = transmat.transform uprotxz
# look = transmat.transform lookrotxz
#
# @.initXYZ up.cross(look), up, look
#
# @setPosition savePos.plus @getZVector().mul @eye_distance
apply: (camera) ->
camPos = @getPosition()
camera.position.copy camPos
camera.up.copy @getYVector()
camera.lookAt camPos.plus @getZVector()
if @light?
pos = @getPosition().plus @light_offset
@light.setDirection -@getZVector()
@light.setPosition new Vector pos[X], pos[Y], pos[Z], 1.0 # positional light source
# setEyeDistance: (distance) ->
# log 'setEyeDistance', distance
# lookAtPos = @getLookAtPosition()
# @eye_distance = Math.min Math.max(@znear, distance), 0.9*@zfar
# @setPosition lookAtPos.plus @getZVector().mul @eye_distance
# setLookAtPosition: (lookAtPos) ->
# up = @getYVector()
# newLook = lookAtPos.minus(@getPosition()).normal()
# newRight = up.cross(newLook).normal()
# newUp = newLook.cross(newRight).normal()
#
# @setXVector newRight
# @setYVector newUp
# @setZVector newLook
# # log 'setLookAtPosition', @matrix
# @eye_distance = lookAtPos.minus(@getPosition()).length()
getLookAtPosition: -> @getZVector().mul(-@eye_distance).plus @getPosition()
updateViewport: ->
ss = world.screenSize
vp = []
vp[0] = @viewport[0] * ss.w + @border[0]
vp[1] = @viewport[1] * ss.h + @border[1]
vp[2] = @viewport[2] * ss.w - @border[0] - @border[2]
vp[3] = @viewport[3] * ss.h - @border[1] - @border[3]
getCurrentAspectRatio: ->
vps = @getViewportSize()
@aspect_ratio <= 0.0 and vps.w/vps.h or @aspect_ratio
getScreenCoordinates: (pos, sx, sy) ->
setViewportBorder: (l, b, r, t) ->
@border = [l,b,r,t]
@updateViewport()
setViewport: (l, b, w, h) ->
@viewport = [l,b,w,h]
@updateViewport()
setFov: (fov) -> @fov = Math.max(2.0, Math.min fov, 175.0)
module.exports = Perspective