From bec76e00e74adf511eae4fc369621fb9336b986f Mon Sep 17 00:00:00 2001 From: monsterkodi Date: Fri, 12 Aug 2016 23:02:18 +0200 Subject: [PATCH] perspective --- coffee/lib/matrix.coffee | 103 ++++--- coffee/perspective.coffee | 598 +++++++------------------------------- coffee/player.coffee | 82 +++--- 3 files changed, 213 insertions(+), 570 deletions(-) diff --git a/coffee/lib/matrix.coffee b/coffee/lib/matrix.coffee index 47d814a..198dd38 100644 --- a/coffee/lib/matrix.coffee +++ b/coffee/lib/matrix.coffee @@ -8,56 +8,78 @@ class Matrix constructor: (o) -> @matrix = [] - @reset() if o instanceof Matrix - @matrix[0] =o.matrix[0]; matrix[1] =o.matrix[1]; matrix[2] =o.matrix[2]; matrix[3] =o.matrix[3]; - @matrix[4] =o.matrix[4]; matrix[5] =o.matrix[5]; matrix[6] =o.matrix[6]; matrix[7] =o.matrix[7]; - @matrix[8] =o.matrix[8]; matrix[9] =o.matrix[9]; matrix[10]=o.matrix[10];matrix[11]=o.matrix[11]; - @matrix[12] =o.matrix[12];matrix[13]=o.matrix[13];matrix[14]=o.matrix[14];matrix[15]=o.matrix[15]; + @copy o else if o instanceof Array - matrix[0] =o[0]; matrix[1] =o[1]; matrix[2] =o[2]; matrix[3] =o[3]; - matrix[4] =o[4]; matrix[5] =o[5]; matrix[6] =o[6]; matrix[7] =o[7]; - matrix[8] =o[8]; matrix[9] =o[9]; matrix[10]=o[10];matrix[11]=o[11]; - matrix[12]=o[12];matrix[13]=o[13];matrix[14]=o[14];matrix[15]=o[15]; + if o.length == 16 + for i in [0...16] + @matrix[i] = o[i] else if o?.x? and o?.y? and o?.z? - matrix[0] = x.x; matrix[4] = y.x; matrix[8] = z.x; matrix[12] = 0.0; - matrix[1] = x.y; matrix[5] = y.y; matrix[9] = z.y; matrix[13] = 0.0; - matrix[2] = x.z; matrix[6] = y.z; matrix[10] = z.z; matrix[14] = 0.0; - matrix[3] = x.w; matrix[7] = y.w; matrix[11] = z.w; matrix[15] = 1.0; + @initXYZ o.x, o.y, o.z else if o instanceof Quaternion - # calculate coefficients - x2 = o.x + o.x; y2 = o.y + o.y; - z2 = o.z + o.z; - xx = o.x * x2; xy = o.x * y2; xz = o.x * z2; - yy = o.y * y2; yz = o.y * z2; zz = o.z * z2; - wx = o.w * x2; wy = o.w * y2; wz = o.w * z2; - - matrix[0] = 1.0 - (yy + zz) - matrix[1] = xy + wz - matrix[2] = xz - wy - matrix[3] = 0.0 - matrix[4] = xy - wz - matrix[5] = 1.0 - (xx + zz) - matrix[6] = yz + wx - matrix[7] = 0.0 - matrix[8] = xz + wy - matrix[9] = yz - wx - matrix[10] = 1.0 - (xx + yy) - matrix[11] = 0.0 - matrix[12] = 0.0 - matrix[13] = 0.0 - matrix[14] = 0.0 - matrix[15] = 1.0 + @initQuat o + else + @reset() + initXYZ: (x,y,z) -> + @matrix[0] = x.x + @matrix[1] = x.y + @matrix[2] = x.z + @matrix[3] = x.w + @matrix[4] = y.x + @matrix[5] = y.y + @matrix[6] = y.z + @matrix[7] = y.w + @matrix[8] = z.x + @matrix[9] = z.y + @matrix[11] = z.w + @matrix[10] = z.z + @matrix[12] = 0.0 + @matrix[13] = 0.0 + @matrix[14] = 0.0 + @matrix[15] = 1.0 + @ + + initQuat: (o) -> + # calculate coefficients + x2 = o.x + o.x + y2 = o.y + o.y + z2 = o.z + o.z + xx = o.x * x2 + xy = o.x * y2 + xz = o.x * z2 + yy = o.y * y2 + yz = o.y * z2 + zz = o.z * z2 + wx = o.w * x2 + wy = o.w * y2 + wz = o.w * z2 + + @matrix[0] = 1.0 - (yy + zz) + @matrix[1] = xy + wz + @matrix[2] = xz - wy + @matrix[3] = 0.0 + @matrix[4] = xy - wz + @matrix[5] = 1.0 - (xx + zz) + @matrix[6] = yz + wx + @matrix[7] = 0.0 + @matrix[8] = xz + wy + @matrix[9] = yz - wx + @matrix[10] = 1.0 - (xx + yy) + @matrix[11] = 0.0 + @matrix[12] = 0.0 + @matrix[13] = 0.0 + @matrix[14] = 0.0 + @matrix[15] = 1.0 + @ + copy: (m) -> - @matrix[0] =m.matrix[0]; @matrix[1] =m.matrix[1]; @matrix[2] =m.matrix[2]; @matrix[3] =m.matrix[3] - @matrix[4] =m.matrix[4]; @matrix[5] =m.matrix[5]; @matrix[6] =m.matrix[6]; @matrix[7] =m.matrix[7] - @matrix[8] =m.matrix[8]; @matrix[9] =m.matrix[9]; @matrix[10]=m.matrix[10]; @matrix[11]=m.matrix[11] - @matrix[12]=m.matrix[12]; @matrix[13]=m.matrix[13]; @matrix[14]=m.matrix[14]; @matrix[15]=m.matrix[15] + for i in [0...16] + @matrix[i] = m.matrix[i] @ mul: (m) -> @@ -101,6 +123,7 @@ class Matrix @matrix[14] += @matrix[2]*v.x+@matrix[6]*v.y+@matrix[10]*v.z @matrix[15] += @matrix[3]*v.x+@matrix[7]*v.y+@matrix[11]*v.z + @rotation (x,y,z) -> new Matrix().rotate x,y,z rotate: (x,y,z) -> rx = Vector.DEG2RAD x diff --git a/coffee/perspective.coffee b/coffee/perspective.coffee index 291065d..57349bd 100644 --- a/coffee/perspective.coffee +++ b/coffee/perspective.coffee @@ -4,499 +4,119 @@ # 000 000 000 000 000 000 000 000 000 000 000 000 # 000 00000000 000 000 0000000 000 00000000 0000000 000 000 0 00000000 -class Perspective +Matrix = require './matrix' + +class Perspective extends Matrix - constructor: () -> + constructor: (fov,near,far) -> + @znear = near + @zfar = far + @fov = fov + @aspect_ratio = -1.0 + @eye_distance = 5.0 + @border = [0,0,0,0] + @setViewport 0.0, 0.0, 1.0, 1.0 + # WINDOW_SIZE_CHANGED -> updateViewport + super + + 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 = KMatrix.rotation x, 0.0, z + roty = KMatrix.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) - -/* - * KPerspectiveProjection.cpp - * kodisein - */ - -#include "KPerspectiveProjection.h" -#include "KConsole.h" -#include "KXMLTools.h" - -#define K_INCLUDE_GLU -#include "KIncludeTools.h" - -KDL_CLASS_INTROSPECTION_1 (KPerspectiveProjection, KProjection) - -// -------------------------------------------------------------------------------------------------------- -// -------------------------------------------------------------------------------------------------------- -KPerspectiveProjection::KPerspectiveProjection ( GLfloat f, GLfloat zn, GLfloat zf ) : KProjection ( zn, zf ) -{ - reset (); - fov = f; -} - -// -------------------------------------------------------------------------------------------------------- -KPerspectiveProjection::KPerspectiveProjection ( const KProjection & p ) : KProjection (p) -{ -} - -// -------------------------------------------------------------------------------------------------------- -KProjection * KPerspectiveProjection::copy() const -{ - return new KPerspectiveProjection(*this); -} - -// -------------------------------------------------------------------------------------------------------- -void KPerspectiveProjection::rotate ( const GLfloat x, const GLfloat y, const GLfloat z ) -{ - KVector savePos = getLookAtPosition(); - translate(-getPosition()); + # x & z-axis rotation + transmat = new Matrix up.cross(look), up, look - KVector up = getYVector(); - KVector look = getZVector(); - - KMatrix rotxz; rotxz.rotate (x, 0.0, z); - KMatrix roty; roty.rotate (0.0, y, 0.0); - - KVector yunit(0.0, 1.0, 0.0), zunit (0.0, 0.0, 1.0); - - KVector lookperp = look.perpendicular (yunit); // y-axis rotation - if (lookperp.length() > 0) - { - look = roty * lookperp + look.parallel(yunit); - up = roty * up.perpendicular(yunit) + up.parallel(yunit); - } + uprotxz = rotxz.transform yunit + lookrotxz = rotxz.transform zunit - // x & z-axis rotation - KMatrix transmat(up.cross(look), up, look); - - KVector uprotxz = rotxz * yunit; - KVector lookrotxz = rotxz * zunit; - - up = transmat * uprotxz; - look = transmat * lookrotxz; - - *((KMatrix*)this) = KMatrix(up.cross(look), up, look); - - setPosition( savePos + eye_distance * getZVector()); -} - -// -------------------------------------------------------------------------------------------------------- -void KPerspectiveProjection::apply () -{ - glViewport(vp[0], vp[1], vp[2], vp[3]); - - gluPerspective (fov, getCurrentAspectRatio(), znear, zfar); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - KVector lookAt = getLookAtPosition(); - - gluLookAt( matrix[TX], matrix[TY], matrix[TZ], - lookAt[X], lookAt[Y], lookAt[Z], - matrix[4], matrix[5], matrix[6]); - - KVector pos = getPosition() + light_offset; - light.setDirection(-getZVector()); - light.setPosition (KVector(pos[X], pos[Y], pos[Z], 1.0)); // positional light source - light.initialize (GL_LIGHT0); -} - - -// -------------------------------------------------------------------------------------------------------- -void KPerspectiveProjection::focusOn ( const KVector & pos ) -{ - setPosition (pos + eye_distance*getZVector()); -} - -// -------------------------------------------------------------------------------------------------------- -void KPerspectiveProjection::setEyeDistance ( GLfloat ed ) -{ - KVector lookAtPos = getLookAtPosition(); - eye_distance = kMin( kMax(znear, ed), 0.9 * zfar ); - setPosition(lookAtPos + eye_distance * getZVector()); -} - -// -------------------------------------------------------------------------------------------------------- -void KPerspectiveProjection::setLookAtPosition ( const KVector & lookAtPos ) -{ - KVector up = getYVector(); - KVector newLook = (lookAtPos - getPosition()).normal(); - KVector newRight = up.cross(newLook).normal(); - KVector newUp = newLook.cross(newRight).normal(); - - setXVector(newRight); setYVector(newUp); setZVector(newLook); - - eye_distance = (lookAtPos - getPosition()).length(); -} - -// -------------------------------------------------------------------------------------------------------- -KVector KPerspectiveProjection::getLookAtPosition () const -{ - return (-eye_distance * getZVector() + getPosition()); -} - -// -------------------------------------------------------------------------------------------------------- -void KPerspectiveProjection::reset () -{ - fov = 60.0; - eye_distance = znear; - KMatrix::reset(); - translate(0.0, 0.0, eye_distance); -} - -// -------------------------------------------------------------------------------------------------------- -KProjection::KProjection ( float zn, float zf ) : KMatrix () -{ - aspect_ratio = -1.0; - znear = zn; - zfar = zf; - fov = 0.0; - eye_distance = 5.0; - border[0] = border[1] = border[2] = border[3] = 0; - setViewport(0.0, 0.0, 1.0, 1.0); - - KEventHandler::notification_center.addReceiverCallback - (this, (KCallbackPtr)&KProjection::updateViewport, KDL_NOTIFICATION_TYPE_VIDEO_MODE_CHANGED); - KEventHandler::notification_center.addReceiverCallback - (this, (KCallbackPtr)&KProjection::updateViewport, KDL_NOTIFICATION_TYPE_WINDOW_SIZE_CHANGED); -} - -// -------------------------------------------------------------------------------------------------------- -KProjection::KProjection ( const KProjection & p ) : KMatrix ( p ) -{ - znear = p.znear; - zfar = p.zfar; - aspect_ratio = p.aspect_ratio; - border[0] = p.border[0]; - border[1] = p.border[1]; - border[2] = p.border[2]; - border[3] = p.border[3]; - - fov = p.fov; - eye_distance = p.eye_distance; - - setViewport(p.viewport[0], p.viewport[1], p.viewport[2], p.viewport[3]); -} - -// -------------------------------------------------------------------------------------------------------- -void KProjection::initProjection () -{ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - apply(); -} - -// -------------------------------------------------------------------------------------------------------- -void KProjection::updateViewport () -{ - KSize screenSize = KEventHandler::getScreenSize(); - - vp[0] = (int)(viewport[0] * (float)screenSize.w + (int)border[0]); - vp[1] = (int)(viewport[1] * (float)screenSize.h + (int)border[1]); - vp[2] = (int)(viewport[2] * (float)screenSize.w - (int)(border[0]+border[2])); - vp[3] = (int)(viewport[3] * (float)screenSize.h - (int)(border[1]+border[3])); -} - -// -------------------------------------------------------------------------------------------------------- -/* returns the position of the locator in "viewport coordinates" -*/ -KPosition KProjection::getLocatorViewportPos () const -{ - return (KEventHandler::getMousePos() - getViewportScreenPos()); -} - -// -------------------------------------------------------------------------------------------------------- -float KProjection::getCurrentAspectRatio () const -{ - KSize viewportSize = getViewportSize(); - return (aspect_ratio <= 0.0) ? ((float)viewportSize.w/viewportSize.h) : aspect_ratio; -} - -// -------------------------------------------------------------------------------------------------------- -void KProjection::getSaveMatrices (GLdouble * model, GLdouble * proj, GLint * view) -{ - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - initProjection(); - glGetDoublev(GL_PROJECTION_MATRIX, proj); - glGetDoublev(GL_MODELVIEW_MATRIX, model); - glGetIntegerv(GL_VIEWPORT, (GLint*)view); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); -} - -// -------------------------------------------------------------------------------------------------------- -void KProjection::getXYValuesForScreenDeltasAndMatrix - (float dx, float dy, const KMatrix & cm, float * x, float * y ) -{ - KMatrix m(cm); - GLdouble dxpox, dxpoy, dypox, dypoy, ox, oy, xpox, xpoy, ypox, ypoy, tz, model[16], proj[16]; - GLint view[4]; getSaveMatrices(model, proj, view); - - GLdouble screenUnits, xx, xy, yx, yy, zx, zy; - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &ox, &oy, &tz); - gluProject(m[TX] + 1.0, m[TY], m[TZ], model, proj, view, &xx, &xy, &tz); - gluProject(m[TX], m[TY] + 1.0, m[TZ], model, proj, view, &yx, &yy, &tz); - gluProject(m[TX], m[TY], m[TZ] + 1.0, model, proj, view, &zx, &zy, &tz); - screenUnits=(kMax(kMax(kAbs(xx-ox)+kAbs(xy-oy),kAbs(yx-ox)+kAbs(yy-oy)),kAbs(zx-ox)+kAbs(zy-oy))); - - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &ox, &oy, &tz); - KMatrix r(m); r.translate(1.0, 0.0, 0.0); - gluProject(r[TX], r[TY], r[TZ], model, proj, view, &xpox, &xpoy, &tz); - m.translate(0.0, 1.0, 0.0); - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &ypox, &ypoy, &tz); - dxpox = xpox - ox; dxpoy = xpoy - oy; dypox = ypox - ox; dypoy = ypoy - oy; - - if (kAbs(dxpox) >= kAbs(dypox)) // x-axis differnce in x-direction is bigger -> map x movement to x - { - if (dxpox >= 0) *x = dx/screenUnits; // positive movement in x direction - else *x = -dx/screenUnits; // negative movement in x direction - if (dypoy >= 0) *y = dy/screenUnits; // positive movement in y direction - else *y = -dy/screenUnits; // negative movement in y direction - } - else // x-axis differnce in y-direction is bigger -> map x movement to y - { - if (dypox >= 0) *y = dx/screenUnits; // positive movement in x direction - else *y = -dx/screenUnits; // negative movement in x direction - if (dxpoy >= 0) *x = dy/screenUnits; // positive movement in y direction - else *x = -dy/screenUnits; // negative movement in y direction - } -} - -// -------------------------------------------------------------------------------------------------------- -void KProjection::getXZValuesForScreenDeltasAndMatrix - ( float dx, float dy, const KMatrix & cm, float * x, float * z ) -{ - KMatrix m(cm); - GLdouble dxpox, dxpoy, dypox, dypoy, ox, oy, xpox, xpoy, ypox, ypoy, tz, model[16], proj[16]; - GLint view[4]; getSaveMatrices(model, proj, view); - - GLdouble screenUnits, xx, xy, yx, yy, zx, zy; - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &ox, &oy, &tz); - gluProject(m[TX] + 1.0, m[TY], m[TZ], model, proj, view, &xx, &xy, &tz); - gluProject(m[TX], m[TY] + 1.0, m[TZ], model, proj, view, &yx, &yy, &tz); - gluProject(m[TX], m[TY], m[TZ] + 1.0, model, proj, view, &zx, &zy, &tz); - screenUnits=(kMax(kMax(kAbs(xx-ox)+kAbs(xy-oy),kAbs(yx-ox)+kAbs(yy-oy)),kAbs(zx-ox)+kAbs(zy-oy))); - - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &ox, &oy, &tz); - KMatrix r(m); r.translate(1.0, 0.0, 0.0); - gluProject(r[TX], r[TY], r[TZ], model, proj, view, &xpox, &xpoy, &tz); - m.translate(0.0, 0.0, 1.0); - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &ypox, &ypoy, &tz); - dxpox = xpox - ox; dxpoy = xpoy - oy; dypox = ypox - ox; dypoy = ypoy - oy; - - if (kAbs(dxpox) >= kAbs(dypox)) // x-axis differnce in x-direction is bigger -> map x movement to x - { - if (dxpox >= 0) *x = dx/screenUnits; // positive movement in x direction - else *x = -dx/screenUnits; // negative movement in x direction - if (dypoy >= 0) *z = dy/screenUnits; // positive movement in y direction - else *z = -dy/screenUnits; // negative movement in y direction - } - else // x-axis differnce in y-direction is bigger -> map x movement to y - { - if (dypox >= 0) *z = dx/screenUnits; // positive movement in x direction - else *z = -dx/screenUnits; // negative movement in x direction - if (dxpoy >= 0) *x = dy/screenUnits; // positive movement in y direction - else *x = -dy/screenUnits; // negative movement in y direction - } -} - -// -------------------------------------------------------------------------------------------------------- -void KProjection::getYZValuesForScreenDeltasAndMatrix - ( float dx, const float dy, const KMatrix & cm, float * y, float * z ) -{ - KMatrix m(cm); - GLdouble dxpox, dxpoy, dypox, dypoy, ox, oy, xpox, xpoy, ypox, ypoy, tz, model[16], proj[16]; - GLint view[4]; getSaveMatrices(model, proj, view); - - GLdouble screenUnits, xx, xy, yx, yy, zx, zy; - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &ox, &oy, &tz); - gluProject(m[TX] + 1.0, m[TY], m[TZ], model, proj, view, &xx, &xy, &tz); - gluProject(m[TX], m[TY] + 1.0, m[TZ], model, proj, view, &yx, &yy, &tz); - gluProject(m[TX], m[TY], m[TZ] + 1.0, model, proj, view, &zx, &zy, &tz); - screenUnits=(kMax(kMax(kAbs(xx-ox)+kAbs(xy-oy),kAbs(yx-ox)+kAbs(yy-oy)),kAbs(zx-ox)+kAbs(zy-oy))); - - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &ox, &oy, &tz); - KMatrix r(m); r.translate(0.0, 1.0, 0.0); - gluProject(r[TX], r[TY], r[TZ], model, proj, view, &xpox, &xpoy, &tz); - m.translate(0.0, 0.0, 1.0); - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &ypox, &ypoy, &tz); - dxpox = xpox - ox; dxpoy = xpoy - oy; dypox = ypox - ox; dypoy = ypoy - oy; - - if (kAbs(dxpox) >= kAbs(dypox)) // x-axis differnce in x-direction is bigger -> map x movement to x - { - if (dxpox >= 0) *y = dx/screenUnits; // positive movement in x direction - else *y = -dx/screenUnits; // negative movement in x direction - if (dypoy >= 0) *z = dy/screenUnits; // positive movement in y direction - else *z = -dy/screenUnits; // negative movement in y direction - } - else // x-axis differnce in y-direction is bigger -> map x movement to y - { - if (dypox >= 0) *z = dx/screenUnits; // positive movement in x direction - else *z = -dx/screenUnits; // negative movement in x direction - if (dxpoy >= 0) *y = dy/screenUnits; // positive movement in y direction - else *y = -dy/screenUnits; // negative movement in y direction - } -} - -// -------------------------------------------------------------------------------------------------------- -float KProjection::getXValueForScreenDeltasAndMatrix (float dx, float dy, const KMatrix & cm) -{ - KMatrix m(cm); - GLdouble maxDelta, dox, doy, ox, oy, oxpo, oypo, z, model[16], proj[16]; - GLint view[4]; getSaveMatrices(model, proj, view); - - GLdouble screenUnits, xx, xy, yx, yy, zx, zy; - GLdouble mx = m[TX], my = m[TY], mz = m[TZ]; - gluProject(mx, my, mz, model, proj, view, &ox, &oy, &z); - gluProject(mx + 1.0, my, mz, model, proj, view, &xx, &xy, &z); - gluProject(mx, my + 1.0, mz, model, proj, view, &yx, &yy, &z); - gluProject(mx, my, mz + 1.0, model, proj, view, &zx, &zy, &z); - screenUnits=(kMax(kMax(kAbs(xx-ox)+kAbs(xy-oy),kAbs(yx-ox)+kAbs(yy-oy)),kAbs(zx-ox)+kAbs(zy-oy))); - - gluProject(mx, my, mz, model, proj, view, &ox, &oy, &z); - m.translate(1.0, 0.0, 0.0); - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &oxpo, &oypo, &z); - - dox = oxpo - ox; doy = oypo - oy; - - if (dox >= 0 && doy >= 0) maxDelta = kAbsMax(dx, dy); // upper right - keep directions - else if (dox <= 0 && doy <= 0) maxDelta = -kAbsMax(dx, dy); // lower left - invert both - else if (dox < 0) maxDelta = (kAbs(dx) > kAbs(dy)) ? -dx : dy; // upper left - invert x - else maxDelta = (kAbs(dx) > kAbs(dy)) ? dx : -dy; // lower right - invert y - - return (maxDelta/screenUnits); -} - -// -------------------------------------------------------------------------------------------------------- -float KProjection::getYValueForScreenDeltasAndMatrix ( float dx, float dy, const KMatrix & cm) -{ - KMatrix m(cm); - GLdouble maxDelta, dox, doy, ox, oy, oxpo, oypo, z, model[16], proj[16]; - GLint view[4]; getSaveMatrices(model, proj, view); - - GLdouble screenUnits, xx, xy, yx, yy, zx, zy; - GLdouble mx = m[TX], my = m[TY], mz = m[TZ]; - gluProject(mx, my, mz, model, proj, view, &ox, &oy, &z); - gluProject(mx + 1.0, my, mz, model, proj, view, &xx, &xy, &z); - gluProject(mx, my + 1.0, mz, model, proj, view, &yx, &yy, &z); - gluProject(mx, my, mz + 1.0, model, proj, view, &zx, &zy, &z); - screenUnits=(kMax(kMax(kAbs(xx-ox)+kAbs(xy-oy),kAbs(yx-ox)+kAbs(yy-oy)),kAbs(zx-ox)+kAbs(zy-oy))); - - gluProject(mx, my, mz, model, proj, view, &ox, &oy, &z); - m.translate(0.0, 1.0, 0.0); - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &oxpo, &oypo, &z); - - dox = oxpo - ox; doy = oypo - oy; - - if (dox >= 0 && doy >= 0) maxDelta = kAbsMax(dx, dy); // upper right - keep directions - else if (dox <= 0 && doy <= 0) maxDelta = -kAbsMax(dx, dy); // lower left - invert both - else if (dox < 0) maxDelta = (kAbs(dx) > kAbs(dy)) ? -dx : dy; // upper left - invert x - else maxDelta = (kAbs(dx) > kAbs(dy)) ? dx : -dy; // lower right - invert y - - return (maxDelta/screenUnits); -} - -// -------------------------------------------------------------------------------------------------------- -float KProjection::getZValueForScreenDeltasAndMatrix ( float dx, float dy, const KMatrix & cm) -{ - KMatrix m(cm); - GLdouble maxDelta, dox, doy, ox, oy, oxpo, oypo, z, model[16], proj[16]; - GLint view[4]; getSaveMatrices(model, proj, view); - - GLdouble screenUnits, xx, xy, yx, yy, zx, zy; - GLdouble mx = m[TX], my = m[TY], mz = m[TZ]; - gluProject(mx, my, mz, model, proj, view, &ox, &oy, &z); - gluProject(mx + 1.0, my, mz, model, proj, view, &xx, &xy, &z); - gluProject(mx, my + 1.0, mz, model, proj, view, &yx, &yy, &z); - gluProject(mx, my, mz + 1.0, model, proj, view, &zx, &zy, &z); - screenUnits=(kMax(kMax(kAbs(xx-ox)+kAbs(xy-oy),kAbs(yx-ox)+kAbs(yy-oy)),kAbs(zx-ox)+kAbs(zy-oy))); - - gluProject(mx, my, mz, model, proj, view, &ox, &oy, &z); - m.translate(0.0, 0.0, 1.0); - gluProject(m[TX], m[TY], m[TZ], model, proj, view, &oxpo, &oypo, &z); - - dox = oxpo - ox; doy = oypo - oy; - - if (dox >= 0 && doy >= 0) maxDelta = kAbsMax(dx, dy); // upper right - keep directions - else if (dox <= 0 && doy <= 0) maxDelta = -kAbsMax(dx, dy); // lower left - invert both - else if (dox < 0) maxDelta = (kAbs(dx) > kAbs(dy)) ? -dx : dy; // upper left - invert x - else maxDelta = (kAbs(dx) > kAbs(dy)) ? dx : -dy; // lower right - invert y - - return (maxDelta/screenUnits); -} - -// -------------------------------------------------------------------------------------------------------- -bool KProjection::getScreenCoordinates ( const KVector & pos, double * sx, double * sy) -{ - GLdouble sz, model[16], proj[16]; GLint view[4]; - getSaveMatrices (model, proj, view); - - if (gluProject(pos[X], pos[Y], pos[Z], model, proj, view, sx, sy, &sz)) - { - return true; - } - else - { - KConsole::printError("unable to calculate projection screen coordinates!"); - return false; - } -} - -// -------------------------------------------------------------------------------------------------------- -bool KProjection::moveObjectRelativeToWindow ( const KPosition & delta, KVector & pos ) -{ - GLdouble wx, wy, wz, model[16], proj[16]; GLint view[4]; - getSaveMatrices (model, proj, view); - - if (gluProject(pos[X], pos[Y], pos[Z], model, proj, view, &wx, &wy, &wz)) - { - GLdouble ox, oy, oz; + up = transmat.transform uprotxz + look = transmat.transform lookrotxz - if (gluUnProject(wx+delta.x, wy+delta.y, wz, model, proj, view, &ox, &oy, &oz) == false) - { - return false; - } - pos = KVector(ox, oy, oz); - } - else - { - return false; - } - - return true; -} - -// -------------------------------------------------------------------------------------------------------- -void KProjection::setViewportBorder ( unsigned int l, unsigned int b, unsigned int r, unsigned int t ) -{ - border[0] = l; border[1] = b; border[2] = r; border[3] = t; - updateViewport(); -} - -// -------------------------------------------------------------------------------------------------------- -void KProjection::setViewport ( float l, float b, float w, float h ) -{ - viewport[0] = l; viewport[1] = b; viewport[2] = w; viewport[3] = h; - updateViewport(); -} - -// -------------------------------------------------------------------------------------------------------- -void KProjection::setFov ( float f ) -{ - fov = kMax(2.0, kMin(f, 175.0)); -} - -// -------------------------------------------------------------------------------------------------------- -void KProjection::setEyeDistance ( float ed ) -{ - eye_distance = kMin( kMax(znear, ed), 0.9 * zfar ); -} - - - - + @.initXYZ up.cross(look), up, look + @setPosition savePos.plus @getZVector().mul @eye_distance + + initProjection: -> @apply() + + apply: -> + # glViewport(vp[0], vp[1], vp[2], vp[3]); + # gluPerspective (fov, getCurrentAspectRatio(), znear, zfar); + # glMatrixMode(GL_MODELVIEW); + # glLoadIdentity(); + # KVector lookAt = getLookAtPosition(); + # gluLookAt( matrix[TX], matrix[TY], matrix[TZ], + # lookAt[X], lookAt[Y], lookAt[Z], + # matrix[4], matrix[5], matrix[6]); + 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 + + focusOn: (pos) -> @setPosition pos.plus @getZVector().mul @eye_distance + + setEyeDistance: (distance) -> + lookAtPos = @getLookAtPosition() + @eye_distance = kMin( kMax(@znear, distance), 0.9 * @zfar ); + setPosition lookAtPos + @eye_distance * @getZVector() + + setLookAtPosition: (lookAtPos) -> + up = @getYVector() + newLook = (lookAtPos - @getPosition()).normal() + newRight = up.cross(newLook).normal() + newUp = newLook.cross(newRight).normal() + + @setXVector newRight + @setYVector newUp + @setZVector newLook + + @eye_distance = lookAtPos.minus(@getPosition()).length() + + getLookAtPosition: -> @getZVector().mul(-@eye_distance).plus @getPosition() + + updateViewport: -> + ss = @world.screenSize() + 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[0] = [l,b,w,h] + @updateViewport() + + setFov: (fov) -> @fov = Math.max(2.0, Math.min fov, 175.0) + + setEyeDistance: (distance) -> @eye_distance = Math.min( Math.max(@znear, distance), 0.9 * @zfar ); + module.exports = Perspective + \ No newline at end of file diff --git a/coffee/player.coffee b/coffee/player.coffee index d6c34dd..f674313 100644 --- a/coffee/player.coffee +++ b/coffee/player.coffee @@ -91,18 +91,18 @@ class Player extends Bot getEventWithName("keyset").triggerActions() updatePosition: () -> - if (move_action) - relTime = (Controller.getTime() - move_action.getStart()) / move_action.getDuration() + if @move_action + relTime = (Controller.getTime() - @move_action.getStart()) / @move_action.getDuration() if relTime <= 1.0 - switch move_action.id + switch @move_action.id when Action.FORWARD - current_position = position + relTime * getDir() + @current_position = @position + relTime * @getDir() when Action.FALL - current_position = position - relTime * getUp() + @current_position = @position - relTime * @getUp() when Action.JUMP_FORWARD - current_position = position + (1.0 - Math.cos(Math.PI/2 * relTime)) * getDir() + Math.cos(Math.PI/2 - Math.PI/2 * relTime) * getUp() + @current_position = @position + (1.0 - Math.cos(Math.PI/2 * relTime)) * @getDir() + Math.cos(Math.PI/2 - Math.PI/2 * relTime) * @getUp() when Action.FALL_FORWARD - current_position = position + Math.cos(Math.PI/2 - Math.PI/2 * relTime) * getDir() + (1.0 - Math.cos(Math.PI/2 * relTime)) * -getUp() + @current_position = @position + Math.cos(Math.PI/2 - Math.PI/2 * relTime) * @getDir() + (1.0 - Math.cos(Math.PI/2 * relTime)) * -@getUp() getProjection: () -> # smooth camera movement a little bit @@ -130,48 +130,48 @@ class Player extends Bot return projection getBehindProjection: () -> - updatePosition() + @updatePosition() - playerDir = getCurrentDir() - playerUp = current_orientation.rotate(KVector(0,1,0)).normal() + @playerDir = getCurrentDir() + @playerUp = current_orientation.rotate(KVector(0,1,0)).normal() # find a valid camera position botToCamera = (playerUp - 2 * playerDir) min_f = botToCamera.length() botToCamera.normalize() - min_f = Math.min world.getWallDistanceForRay(current_position, botToCamera), min_f - cameraPos = current_position + kMax(min_f, 0.72) * botToCamera + min_f = Math.min world.getWallDistanceForRay(@current_position, botToCamera), min_f + cameraPos = @current_position + kMax(min_f, 0.72) * botToCamera cameraPos = world.getInsideWallPosWithDelta cameraPos, 0.2 # smooth camera movement a little bit posDelta = 0.2 - projection.setPosition ((1.0 - posDelta) * projection.getPosition() + posDelta * cameraPos) + @projection.setPosition ((1.0 - posDelta) * @projection.getPosition() + posDelta * cameraPos) - if (@look_angle) - projection.setXVector(playerUp.cross(playerDir).normal()) - KQuaternion look_rot = KQuaternion.rotationAroundVector(@look_angle, projection.getXVector()) - projection.setYVector(look_rot.rotate(playerUp)) - projection.setZVector(look_rot.rotate(-playerDir)) + if @look_angle + @projection.setXVector(playerUp.cross(playerDir).normal()) + KQuaternion look_rot = KQuaternion.rotationAroundVector(@look_angle, @projection.getXVector()) + @projection.setYVector(look_rot.rotate(playerUp)) + @projection.setZVector(look_rot.rotate(-playerDir)) else # smooth camera rotation a little bit lookDelta = 0.3 - KVector newLookVector =(1.0 - lookDelta) * projection.getZVector() - lookDelta * playerDir + KVector newLookVector =(1.0 - lookDelta) * @projection.getZVector() - lookDelta * playerDir newLookVector.normalize() - projection.setZVector(newLookVector) - projection.setXVector(playerUp.cross(newLookVector).normal()) - projection.setYVector(newLookVector.cross(projection.getXVector()).normal()) + @projection.setZVector(newLookVector) + @projection.setXVector(playerUp.cross(newLookVector).normal()) + @projection.setYVector(newLookVector.cross(@projection.getXVector()).normal()) - return projection + @projection getFollowProjection: () -> - cameraPos = projection.getPosition() # current camera position + cameraPos = @projection.getPosition() # current camera position desiredDistance = 2.0 # desired distance from camera to bot updatePosition() - playerPos = current_position # desired look pos + playerPos = @current_position # desired look pos playerDir = getCurrentDir() playerUp = current_orientation.rotate(KVector(0,1,0)).normal() playerRight = playerDir.cross(playerUp).normal() @@ -233,29 +233,29 @@ class Player extends Bot # .................................................................. finally, set the position - projection.setPosition cameraPos + @projection.setPosition cameraPos # .................................................................. refining camera orientation # slowly adjust look direction by interpolating current and desired directions - lookDelta = 2.0 - projection.getZVector() * botToCameraNormal + lookDelta = 2.0 - @projection.getZVector() * botToCameraNormal lookDelta *= lookDelta / 30.0 - KVector newLookVector = (1.0 - lookDelta) * projection.getZVector() + lookDelta * botToCameraNormal + KVector newLookVector = (1.0 - lookDelta) * @projection.getZVector() + lookDelta * botToCameraNormal newLookVector.normalize() # slowly adjust up vector by interpolating current and desired up vectors - upDelta = 2.0 - projection.getYVector() * playerUp + upDelta = 2.0 - @projection.getYVector() * playerUp upDelta *= upDelta / 100.0 - KVector newRightVector = ((1.0 - upDelta) * projection.getYVector() + upDelta * playerUp).cross(newLookVector) + KVector newRightVector = ((1.0 - upDelta) * @projection.getYVector() + upDelta * playerUp).cross(newLookVector) newRightVector.normalize() KVector newUpVector = newLookVector.cross(newRightVector).normal() # finished interpolations, update camera matrix - projection.setZVector newLookVector - projection.setXVector newRightVector - projection.setYVector newUpVector + @projection.setZVector newLookVector + @projection.setXVector newRightVector + @projection.setYVector newUpVector - return projection + @projection initAction: (action) -> actionId = action.id @@ -297,7 +297,7 @@ class Player extends Bot @look_action = null @look_angle = 0.0 else - if action == move_action # move finished, update direction + if action == @move_action # move finished, update direction dir_sgn = new_dir_sgn if actionId != Action.LOOK_UP and actionId != Action.LOOK_DOWN @@ -351,7 +351,7 @@ class Player extends Bot if keyName == forward_key or keyName == backward_key move = true # try to move as long as the key is not released - if move_action == null # player is currently not performing a move action + if @move_action == null # player is currently not performing a move action # forward or backward direction new_dir_sgn = dir_sgn = (key.getUnmodifiedName() == backward_key) ? -1 : 1 @@ -417,11 +417,11 @@ class Player extends Bot if key.name == jump_key jump = false if jump_once - if move_action == null and world.isUnoccupiedPos position.plus getUp() + if @move_action == null and world.isUnoccupiedPos position.plus @getUp() jump_once = false - move_action = getActionWithId Action.JUMP + @move_action = getActionWithId Action.JUMP Controller.sound.playSound KikiSound.BOT_JUMP - Controller.timer_event.addAction (move_action) + Controller.timer_event.addAction @move_action return releaseHandled() if keyName == turn_left_key or keyName == turn_right_key @@ -452,7 +452,7 @@ class Player extends Bot if world.getCameraMode() == world.CAMERA_BEHIND # static bodyColor bodyColor = colors[KikiPlayer_base_color] - bodyColor.setAlpha(kMin(0.7, (projection.getPosition()-current_position).length()-0.4)) + bodyColor.setAlpha(kMin(0.7, (@projection.getPosition()-@current_position).length()-0.4)) return bodyColor return colors[KikiPlayer_base_color] @@ -461,7 +461,7 @@ class Player extends Bot if world.getCameraMode() == world.CAMERA_BEHIND # static tireColor tireColor = colors[KikiPlayer_tire_color] - tireColor.setAlpha(kMin(1.0, (projection.getPosition()-current_position).length()-0.4)) + tireColor.setAlpha(kMin(1.0, (@projection.getPosition()-@current_position).length()-0.4)) return tireColor return colors[KikiPlayer_tire_color]