diff --git a/coffee/lib/matrix.coffee b/coffee/lib/matrix.coffee new file mode 100644 index 0000000..47d814a --- /dev/null +++ b/coffee/lib/matrix.coffee @@ -0,0 +1,308 @@ +# 00 00 0000000 000000000 00000000 000 000 000 +# 000 000 000 000 000 000 000 000 000 000 +# 000000000 000000000 000 0000000 000 00000 +# 000 0 000 000 000 000 000 000 000 000 000 +# 000 000 000 000 000 000 000 000 000 000 + +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]; + + 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]; + + 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; + + 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 + + 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] + @ + + mul: (m) -> + if m instanceof Matrix + mm = new Matrix + mm.matrix[0] = @matrix[0]*m.matrix[0] + @matrix[4]*m.matrix[1] + @matrix[8] *m.matrix[2] + @matrix[12]*m.matrix[3] + mm.matrix[1] = @matrix[1]*m.matrix[0] + @matrix[5]*m.matrix[1] + @matrix[9] *m.matrix[2] + @matrix[13]*m.matrix[3] + mm.matrix[2] = @matrix[2]*m.matrix[0] + @matrix[6]*m.matrix[1] + @matrix[10]*m.matrix[2] + @matrix[14]*m.matrix[3] + mm.matrix[3] = @matrix[3]*m.matrix[0] + @matrix[7]*m.matrix[1] + @matrix[11]*m.matrix[2] + @matrix[15]*m.matrix[3] + mm.matrix[4] = @matrix[0]*m.matrix[4] + @matrix[4]*m.matrix[5] + @matrix[8] *m.matrix[6] + @matrix[12]*m.matrix[7] + mm.matrix[5] = @matrix[1]*m.matrix[4] + @matrix[5]*m.matrix[5] + @matrix[9] *m.matrix[6] + @matrix[13]*m.matrix[7] + mm.matrix[6] = @matrix[2]*m.matrix[4] + @matrix[6]*m.matrix[5] + @matrix[10]*m.matrix[6] + @matrix[14]*m.matrix[7] + mm.matrix[7] = @matrix[3]*m.matrix[4] + @matrix[7]*m.matrix[5] + @matrix[11]*m.matrix[6] + @matrix[15]*m.matrix[7] + mm.matrix[8] = @matrix[0]*m.matrix[8] + @matrix[4]*m.matrix[9] + @matrix[8] *m.matrix[10] + @matrix[12]*m.matrix[11] + mm.matrix[9] = @matrix[1]*m.matrix[8] + @matrix[5]*m.matrix[9] + @matrix[9] *m.matrix[10] + @matrix[13]*m.matrix[11] + mm.matrix[11]= @matrix[3]*m.matrix[8] + @matrix[7]*m.matrix[9] + @matrix[11]*m.matrix[10] + @matrix[15]*m.matrix[11] + mm.matrix[10]= @matrix[2]*m.matrix[8] + @matrix[6]*m.matrix[9] + @matrix[10]*m.matrix[10] + @matrix[14]*m.matrix[11] + mm.matrix[12]= @matrix[0]*m.matrix[12] + @matrix[4]*m.matrix[13] + @matrix[8] *m.matrix[14] + @matrix[12]*m.matrix[15] + mm.matrix[13]= @matrix[1]*m.matrix[12] + @matrix[5]*m.matrix[13] + @matrix[9] *m.matrix[14] + @matrix[13]*m.matrix[15] + mm.matrix[14]= @matrix[2]*m.matrix[12] + @matrix[6]*m.matrix[13] + @matrix[10]*m.matrix[14] + @matrix[14]*m.matrix[15] + mm.matrix[15]= @matrix[3]*m.matrix[12] + @matrix[7]*m.matrix[13] + @matrix[11]*m.matrix[14] + @matrix[15]*m.matrix[15] + mm + else + new Vector @matrix[0] * v.x + @matrix[4]*v.y + @matrix[8] *v.z + @matrix[12]*v.w, + @matrix[1] * v.x + @matrix[5]*v.y + @matrix[9] *v.z + @matrix[13]*v.w, + @matrix[2] * v.x + @matrix[6]*v.y + @matrix[10]*v.z + @matrix[14]*v.w, + @matrix[3] * v.x + @matrix[7]*v.y + @matrix[11]*v.z + @matrix[15]*v.w + + reset: -> + @matrix[0] = @matrix[5] = @matrix[10] = @matrix[15] = 1.0 + @matrix[1] = @matrix[4] = @matrix[8] = @matrix[12] = 0.0 + @matrix[2] = @matrix[6] = @matrix[9] = @matrix[13] = 0.0 + @matrix[3] = @matrix[7] = @matrix[11] = @matrix[14] = 0.0 + + transform: (m) -> @copy @.mul m + + translate: (x,y,z) -> + v = new Vector x,y,z + @matrix[12] += @matrix[0]*v.x+@matrix[4]*v.y+@matrix[8] *v.z + @matrix[13] += @matrix[1]*v.x+@matrix[5]*v.y+@matrix[9] *v.z + @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 + + rotate: (x,y,z) -> + + rx = Vector.DEG2RAD x + ry = Vector.DEG2RAD y + rz = Vector.DEG2RAD z + + cx = Math.cos rx + sx = Math.sin rx + cy = Math.cos ry + sy = Math.sin ry + cz = Math.cos rz + sz = Math.sin rz + + b0 = cy*cz + b1 = sx*sy*cz+cx*sz + b2 = -cx*sy*cz+sx*sz + b4 = -cy*sz + b5 = -sx*sy*sz+cx*cz + b6 = cx*sy*sz+sx*cz + b8 = sy + b9 = -sx*cy + b10 = cx*cy + + a0 = @matrix[0] + a1 = @matrix[1] + a2 = @matrix[2] + a3 = @matrix[3] + a4 = @matrix[4] + a5 = @matrix[5] + a6 = @matrix[6] + a7 = @matrix[7] + a8 = @matrix[8] + a9 = @matrix[9] + a10 = @matrix[10] + a11 = @matrix[11] + + @matrix[0] = a0*b0+a4*b1+a8*b2 + @matrix[1] = a1*b0+a5*b1+a9*b2 + @matrix[2] = a2*b0+a6*b1+a10*b2 + @matrix[3] = a3*b0+a7*b1+a11*b2 + @matrix[4] = a0*b4+a4*b5+a8*b6 + @matrix[5] = a1*b4+a5*b5+a9*b6 + @matrix[6] = a2*b4+a6*b5+a10*b6 + @matrix[7] = a3*b4+a7*b5+a11*b6 + @matrix[8] = a0*b8+a4*b9+a8*b10 + @matrix[9] = a1*b8+a5*b9+a9*b10 + @matrix[10] = a2*b8+a6*b9+a10*b10 + @matrix[11] = a3*b8+a7*b9+a11*b10 + + scale: (x,y,z) -> + @matrix[0] *= x + @matrix[1] *= x + @matrix[2] *= x + @matrix[3] *= x + @matrix[4] *= y + @matrix[5] *= y + @matrix[6] *= y + @matrix[7] *= y + @matrix[8] *= z + @matrix[9] *= z + @matrix[10] *= z + @matrix[11] *= z + + @COFACTOR_4X4_IJ: (fac,m,i,j) -> + + ii = [0,0,0,0] + jj = [0,0,0,0] + + for k in [0...i] # compute which row, columnt to skip + ii[k] = k + for k in [i...3] + ii[k] = k+1 + for k in [0...j] + jj[k] = k + for k in [0...3] + jj[k] = k+1 + + fac = m[ii[0]][jj[0]] * (m[ii[1]][jj[1]]*m[ii[2]][jj[2]] + - m[ii[1]][jj[2]]*m[ii[2]][jj[1]]) + fac -= m[ii[0]][jj[1]] * (m[ii[1]][jj[0]]*m[ii[2]][jj[2]] + - m[ii[1]][jj[2]]*m[ii[2]][jj[0]]) + fac += m[ii[0]][jj[2]] * (m[ii[1]][jj[0]]*m[ii[2]][jj[1]] + - m[ii[1]][jj[1]]*m[ii[2]][jj[0]]) + + k = i+j + if k != (k/2)*2 # compute sign + fac = -fac + fac + + @DETERMINANT_4X4: (m) -> + d = m[0][0] * @COFACTOR_4X4_IJ m, 0, 0 + d += m[0][1] * @COFACTOR_4X4_IJ m, 0, 1 + d += m[0][2] * @COFACTOR_4X4_IJ m, 0, 2 + d += m[0][3] * @COFACTOR_4X4_IJ m, 0, 3 + d + + @SCALE_ADJOINT_4X4: (a,s,m) -> + for i in [0...4] + for j in [0...4] + a[j][i] = @COFACTOR_4X4_IJ m, i, j + a[j][i] *= s + + @INVERT_4X4: (b,a) -> + det = @DETERMINANT_4X4 a + @SCALE_ADJOINT_4X4 b, 1.0 / det, a + + invert: () -> + + t = [[],[],[],[]] + inv = [[],[],[],[]] + t[0][0] = @matrix[0] + t[0][1] = @matrix[1] + t[0][2] = @matrix[2] + t[0][3] = @matrix[3] + t[1][0] = @matrix[4] + t[1][1] = @matrix[5] + t[1][2] = @matrix[6] + t[1][3] = @matrix[7] + t[2][0] = @matrix[8] + t[2][1] = @matrix[9] + t[2][2] = @matrix[10] + t[2][3] = @matrix[11] + t[3][0] = @matrix[12] + t[3][1] = @matrix[13] + t[3][2] = @matrix[14] + t[3][3] = @matrix[15] + + Matrix.INVERT_4X4 inv, t + + @matrix[0] = inv[0][0] + @matrix[1] = inv[0][1] + @matrix[2] = inv[0][2] + @matrix[3] = inv[0][3] + @matrix[4] = inv[1][0] + @matrix[5] = inv[1][1] + @matrix[6] = inv[1][2] + @matrix[7] = inv[1][3] + @matrix[8] = inv[2][0] + @matrix[9] = inv[2][1] + @matrix[10] = inv[2][2] + @matrix[11] = inv[2][3] + @matrix[12] = inv[3][0] + @matrix[13] = inv[3][1] + @matrix[14] = inv[3][2] + @matrix[15] = inv[3][3] + @ + + getQuaternion: () -> + + tr = @matrix[0] + @matrix[5] + @matrix[10] + + if tr > 0.0 # check the diagonal + s = Math.sqrt tr + 1.0 + ss = 0.5 / s + new Quaternion s/2.0, (@matrix[6]-@matrix[9])*ss, + (@matrix[8]-@matrix[2])*ss, + (@matrix[1]-@matrix[4])*ss + else # diagonal is negative + i = 0 + nxt = [1, 2, 0] + q = [0,0,0,0] + + i = 1 if @matrix[5] > @matrix[0] + i = 2 if @matrix[10] > @matrix[i*4+i] + j = nxt[i] + k = nxt[j] + + s = Math.sqrt (@matrix[i*4+i] - (@matrix[j*4+j] + @matrix[k*4+k])) + 1.0 + q[i] = s * 0.5 + + s = 0.5 / s if s != 0.0 + + q[3] = (@matrix[j*4+k] - @matrix[k*4+j]) * s + q[j] = (@matrix[i*4+j] + @matrix[j*4+i]) * s + q[k] = (@matrix[i*4+k] + @matrix[k*4+i]) * s + + new Quaternion q[3], q[0], q[1], q[2] + + setPosition: (x,y,z) -> + v = new Vector x,y,z + @matrix[12] = v.x + @matrix[13] = v.y + @matrix[14] = v.z + + setXVector: (v) -> + @matrix[0] = v[0] + @matrix[1] = v[1] + @matrix[2] = v[2] + + setYVector: (v) -> + @matrix[4] = v[0] + @matrix[5] = v[1] + @matrix[6] = v[2] + + setZVector: (v) -> + @matrix[8] = v[0] + @matrix[9] = v[1] + @matrix[10] = v[2] + + getXVector: () -> new Vector @matrix[0], @matrix[1], @matrix[2] + getYVector: () -> new Vector @matrix[4], @matrix[5], @matrix[6] + getZVector: () -> new Vector @matrix[8], @matrix[9], @matrix[10] + getPosition: () -> new Vector @matrix[12], @matrix[13], @matrix[14] + +module.exports = Matrix diff --git a/coffee/perspective.coffee b/coffee/perspective.coffee new file mode 100644 index 0000000..291065d --- /dev/null +++ b/coffee/perspective.coffee @@ -0,0 +1,502 @@ +# 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 + +class Perspective + + constructor: () -> + + +/* + * 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()); + + 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); + } + + // 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; + + 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 ); +} + + + + + +module.exports = Perspective diff --git a/coffee/player.coffee b/coffee/player.coffee index 00abce4..d6c34dd 100644 --- a/coffee/player.coffee +++ b/coffee/player.coffee @@ -106,21 +106,21 @@ class Player extends Bot getProjection: () -> # smooth camera movement a little bit - posDelta = Controller.getSpeed() / 10.0 - projection.setPosition ((1.0 - posDelta) * projection.getPosition() + posDelta * current_position) + posDelta = world.getSpeed() / 10.0 + @projection.setPosition ((1.0 - posDelta) * @projection.getPosition() + posDelta * @current_position) - KVector playerDir = getCurrentDir() - KVector playerUp = current_orientation.rotate (KVector(0,1,0)).normal() + playerDir = @getCurrentDir() + playerUp = @current_orientation.rotate(new KVector(0,1,0)).normal() - if (@look_angle) # player is looking up or down - projection.setXVector playerUp.cross (playerDir).normal() - look_rot = KQuaternion.rotationAroundVector @look_angle, projection.getXVector() - projection.setYVector look_rot.rotate (playerUp) - projection.setZVector look_rot.rotate (-playerDir) + if @look_angle # player is looking up or down + projection.setXVector playerUp.cross(@playerDir).normal() + @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 = (2.0 - projection.getZVector() * playerDir) * Controller.getSpeed() / 50.0 - KVector newLookVector = (1.0 - lookDelta) * projection.getZVector() - lookDelta * playerDir + lookDelta = (2.0 - projection.getZVector() * @playerDir) * world.getSpeed() / 50.0 + newLookVector = (1.0 - lookDelta) * projection.getZVector() - lookDelta * @playerDir newLookVector.normalize() projection.setXVector playerUp.cross(newLookVector).normal() @@ -310,19 +310,19 @@ class Player extends Bot Controller.timer_event.addAction rotate_action die: () -> - Controller.removeKeyHandler (this) - KikiBot.die() - Controller.displayText("game over") - Controller.sound.playSound (KikiSound.BOT_DEATH) - world.setCameraMode (world.CAMERA_FOLLOW) + # Controller.removeKeyHandler @ + super + # Controller.displayText "game over" + # Controller.sound.playSound KikiSound.BOT_DEATH + world.setCameraMode world.CAMERA_FOLLOW reborn: () -> - Controller.addKeyHandler (this) + Controller.addKeyHandler @ died = false reset: () -> KikiBot.reset() - Controller.timer_event.removeActionsOfObject * + Controller.timer_event.removeActionsOfObject @ @look_action = null @look_angle = 0.0 diff --git a/coffee/world.coffee b/coffee/world.coffee index 6589bdf..1aa2bf3 100644 --- a/coffee/world.coffee +++ b/coffee/world.coffee @@ -6,21 +6,20 @@ # 00 00 0000000 000 000 0000000 0000000 { first, -last -} = require "/Users/kodi/s/ko/js/tools/tools" +last} = require "/Users/kodi/s/ko/js/tools/tools" log = require "/Users/kodi/s/ko/js/tools/log" Pos = require './lib/pos' -KikiCell = require './cell' -KikiLight = require './light' +Cell = require './cell' +Light = require './light' Player = require './player' -KQuaternion = require './lib/quaternion' -KVector = require './lib/vector' +Quaternion = require './lib/quaternion' +Vector = require './lib/vector' Pos = require './lib/pos' _ = require 'lodash' world = null -class KikiWorld +class World @CAMERA_INSIDE = 0 @CAMERA_BEHIND = 1 @@ -85,26 +84,26 @@ class KikiWorld @cells = [] @size = new Pos() @depth = -Number.MAX_SAFE_INTEGER - @camera_mode = KikiWorld.CAMERA_BEHIND + @camera_mode = World.CAMERA_BEHIND @edit_projection = null @edit_mode = false @debug_camera = false @debug_cells = false - @raster_size = 0.1 + @raster_size = 0.1 @init: (view) -> return if world? - global.rot0 = new KQuaternion() - global.rotz180 = KQuaternion.rotationAroundVector(180, KVector(0,0,1)) - global.rotz90 = KQuaternion.rotationAroundVector(90, KVector(0,0,1)) - global.roty270 = KQuaternion.rotationAroundVector(270, KVector(0,1,0)) - global.roty180 = KQuaternion.rotationAroundVector(180, KVector(0,1,0)) - global.roty90 = KQuaternion.rotationAroundVector(90, KVector(0,1,0)) - global.roty0 = KQuaternion.rotationAroundVector(0, KVector(0,1,0)) - global.rotx180 = KQuaternion.rotationAroundVector(180, KVector(1,0,0)) - global.rotx90 = KQuaternion.rotationAroundVector(90, KVector(1,0,0)) + global.rot0 = new Quaternion() + global.rotz180 = Quaternion.rotationAroundVector(180, Vector(0,0,1)) + global.rotz90 = Quaternion.rotationAroundVector(90, Vector(0,0,1)) + global.roty270 = Quaternion.rotationAroundVector(270, Vector(0,1,0)) + global.roty180 = Quaternion.rotationAroundVector(180, Vector(0,1,0)) + global.roty90 = Quaternion.rotationAroundVector(90, Vector(0,1,0)) + global.roty0 = Quaternion.rotationAroundVector(0, Vector(0,1,0)) + global.rotx180 = Quaternion.rotationAroundVector(180, Vector(1,0,0)) + global.rotx90 = Quaternion.rotationAroundVector(90, Vector(1,0,0)) # 000 00000000 000 000 00000000 000 0000000 # 000 000 000 000 000 000 000 @@ -145,7 +144,6 @@ class KikiWorld "mutants", ] - @levelDict = {} # import the levels for levelName in @levelList @@ -153,7 +151,7 @@ class KikiWorld # log 'levelDict', @levelDict log "create world in view:", view - world = new KikiWorld view + world = new World view global.world = world world.create first @levelList world @@ -170,9 +168,9 @@ class KikiWorld if worldDict if _.isString worldDict - @level_index = KikiWorld.levelList.indexOf worldDict + @level_index = World.levelList.indexOf worldDict @level_name = worldDict - @dict = KikiWorld.levelDict[worldDict] + @dict = World.levelDict[worldDict] else @dict = worldDict @@ -316,12 +314,12 @@ class KikiWorld @player.status.setMoves 0 if "world" in @dict["exits"][parseInt name.slice 5] w = @dict["exits"][parseInt name.slice 5]["world"] - if w instanceof KikiWorld + if w instanceof World w.create() else if _.isFunction w w() else - exec "KikiWorld().create(" + world + ")" + exec "World().create(" + world + ")" else KikiPyWorld().create (levelList[world.level_index+1]) @@ -503,7 +501,7 @@ class KikiWorld setObjectAtPos: (object, pos) -> if @isInvalidPos pos - log "KikiWorld.setObjectAtPos invalid pos:", pos + log "World.setObjectAtPos invalid pos:", pos return cell = @getCellAtPos pos @@ -513,7 +511,7 @@ class KikiWorld objectAtNewPos = cell.getOccupant() if objectAtNewPos instanceof KikiTmpObject if objectAtNewPos.time > 0 - log "WARNING KikiWorld.setObject already occupied pos:", pos + log "WARNING World.setObject already occupied pos:", pos # "already occupied by %s with time %d!", # object.getClassName(), pos.x, pos.y, pos.z, # cell.getOccupant().getClassName(), @@ -522,7 +520,7 @@ class KikiWorld cell = @getCellAtPos pos if not cell? - cell = new KikiCell() + cell = new Cell() @cells[@posToIndex(pos)] = cell log "world.setObjectAtPos new cell", cell @@ -546,7 +544,7 @@ class KikiWorld addObject: (object) -> object = @newObject object - if object instanceof KikiLight + if object instanceof Light @lights.push object # if lights.indexOf(object) < 0 else @objects.push object # if objects.indexOf(object) < 0 @@ -575,7 +573,7 @@ class KikiWorld deleteObject: (object) -> if not object? - log "WARNING: KikiWorld.deleteObject null" + log "WARNING: World.deleteObject null" return @removeObject object object.del() @@ -595,14 +593,14 @@ class KikiWorld oldSize = @lights.length last(@lights).del() # destructor will call remove object if oldSize == @lights.length - log "WARNING KikiWorld.deleteAllObjects light no auto remove" + log "WARNING World.deleteAllObjects light no auto remove" @lights.pop() while @objects.length oldSize = @objects.length last(@objects).del() # destructor will call remove object if oldSize == @objects.length - log "WARNING KikiWorld.deleteAllObjects object no auto remove" + log "WARNING World.deleteAllObjects object no auto remove" @objects.pop() deleteObjectsWithClassName: (className) -> @@ -614,7 +612,7 @@ class KikiWorld for o in @objects if objectName == o.getName() return o - log "KikiWorld.getObjectWithName :: no object found with name #{objectName}" + log "World.getObjectWithName :: no object found with name #{objectName}" null setCameraMode: (mode) -> @camera_mode = clamp CAMERA_INSIDE, CAMERA_FOLLOW, mode @@ -633,10 +631,10 @@ class KikiWorld cell = @getCellAtPos pos if @isInvalidPos pos - log "KikiWorld::objectWillMoveToPos invalid pos:", pos + log "objectWillMoveToPos invalid pos:", pos if object.getPos() == pos - log "WARNING KikiWorld::objectWillMoveToPos equal pos:", pos + log "WARNING objectWillMoveToPos equal pos:", pos return if cell @@ -648,9 +646,9 @@ class KikiWorld # temporary object at new pos will vanish before object will arrive . delete it objectAtNewPos.del() else - log "KikiWorld.objectWillMoveToPos timing conflict at pos:", pos + log "World.objectWillMoveToPos timing conflict at pos:", pos else - log "KikiWorld.objectWillMoveToPos already occupied:", pos + log "World.objectWillMoveToPos already occupied:", pos @unsetObject object # remove object from cell grid @@ -671,16 +669,16 @@ class KikiWorld pos = new Pos movedObject.position if @isInvalidPos pos - log "KikiWorld.updateStatus invalid new pos" + log "World.updateStatus invalid new pos" return if tmpObject = @getObjectOfTypeAtPos KikiTmpObject, pos if tmpObject.object == movedObject tmpObject.del() else - log "KikiWorld.updateStatus wrong tmp object at pos:", pos + log "World.updateStatus wrong tmp object at pos:", pos else if @isOccupiedPos pos - log "KikiWorld.updateStatus object moved to occupied pos:", pos + log "World.updateStatus object moved to occupied pos:", pos @setObjectAtPos movedObject, pos @moved_objects.pop() @@ -731,10 +729,157 @@ class KikiWorld mode: Action.ONCE resized: (w,h) -> - # log "world.resized w:#{w} h:#{h}" @aspect = w/h @camera?.aspect = @aspect @camera?.updateProjectionMatrix() @renderer?.setSize w,h -module.exports = KikiWorld + getNearestValidPos: (pos) -> + new KikiPos Math.min(size.x-1, Math.max(pos.x, 0)), + Math.min(size.y-1, Math.max(pos.y, 0)), + Math.min(size.z-1, Math.max(pos.z, 0)) + + isUnoccupiedPos: (pos) -> + return false if @isInvalidPos pos + not @getOccupantAtPos pos + + isOccupiedPos: (pos) -> not @isUnoccupiedPos pos + + # returns true, if a pushable object is at pos and may be pushed + mayObjectPushToPos: (object, pos, duration) -> + return false if @isInvalidPos pos + + direction = pos.minus object.getPos() # direction from object to pushable object + + return false if @isInvalidPos pos.plus @direction + + objectAtNewPos = @getOccupantAtPos pos.plus direction + if objectAtNewPos + if objectAtNewPos instanceof TmpObject + tmpObject = objectAtNewPos + + if tmpObject.time < 0 and -tmpObject.time <= duration + # temporary object at new pos will vanish before object will arrive -> delete it + tmpObject.del() + else return false + else return false + + pushableObject = @getOccupantAtPos pos + + if pushableObject? and pushableObject instanceof Pushable and + pushableObject instanceof MotorGear # bad + pushableObject.pushedByObjectInDirection object, direction, duration + return true + + false + + reinit: () -> + for o in @objects + if o instanceof Light + o.initialize() + + # Spikes::initialize() + # Text::reinit() + + getInsideWallPosWithDelta: (pos, delta) -> + insidePos = new Vector pos + for w in [0..5] + planePos = new Vector -0.5, -0.5, -0.5 + if w >= 3 then planePos.add size + + f = kRayPlaneIntersectionFactor pos, -@normals[w], planePos, @normals[w] + + if f < delta + insidePos.add new Vector (delta-f)*@normals[w] + + insidePos + + # returns the distance to the next wall (positive or negative) + getWallDistanceForPos: (pos) -> + + min_f = 10000 + for w in [0..5] + planePos = new Vector -0.5, -0.5, -0.5 + if w >= 3 then planePos.add size + + f = kRayPlaneIntersectionFactor pos, -@normals[w], planePos, @normals[w] + + min_f = kAbsMin min_f, f + min_f + + # returns the distace to the next wall in direction rayDirection from rayPos (positive values only) + getWallDistanceForRay: (rayPos, rayDirection) -> + + min_f = 10000 + for w in [0..5] + planePos -0.5, -0.5, -0.5 + if w >= 3 then planePos.add size + + f = kRayPlaneIntersectionFactor rayPos, rayDirection, planePos, @normals[w] + + min_f = f if f >= 0.0 and f < min_f + min_f + + displayLights: () -> + for light in @lights + lignt.display() + + displayWall: (width, height) -> + l = @raster_size/2.0 + t = 1.0 - l + + # if flags[DISPLAY_RASTER] == false + # l = 0.0; t = 1.0 + + glNormal3f 0.0, 0.0, 1.0 + for w in [0..width] + for h in [0..height] + glRectf w+l, h+l, w+t, h+t + + getProjection: () -> + if @projection == NULL + switch @camera_mode + when CAMERA_INSIDE then @projection = @player.getProjection() + when CAMERA_BEHIND then @projection = @player.getBehindProjection() + when CAMERA_FOLLOW then @projection = @player.getFollowProjection() + @projection + + display: (mode) -> + switch @camera_mode + when CAMERA_INSIDE then @projection = @player.getProjection() + when CAMERA_BEHIND then @projection = @player.getBehindProjection() + when CAMERA_FOLLOW then @projection = @player.getFollowProjection() + + @player_projection = @projection + + @projection.initProjection() + + # glDisable(GL_BLEND); + # glDisable(GL_DEPTH_TEST); + # glDisable(GL_ALPHA_TEST); + # glDisable(GL_NORMALIZE); +# + # # colors[World_plate_color].glColor(); +# + # glTranslatef(-0.5, -0.5, -0.5); +# + # displayWall(size.x, size.y); # xy+z + # glRotatef(180.0, 0.0, 1.0, 0.0); + # glTranslatef(-size.x, 0.0, -size.z); + # displayWall(size.x, size.y); # xy-z +# + # glRotatef(90.0, 1.0, 0.0, 0.0); # xz-y + # glTranslatef(0.0, 0.0, -size.y); + # displayWall(size.x, size.z); + # glRotatef(180.0, 0.0, 1.0, 0.0); # xz+y + # glTranslatef(-size.x, 0.0, -size.y); + # displayWall(size.x, size.z); +# + # glRotatef(-90.0, 0.0, 1.0, 0.0); # yz+x + # glTranslatef(0.0, 0.0, -size.x); + # displayWall(size.y, size.z); + # glRotatef(180.0, 1.0, 0.0, 0.0); # yz-x + # glTranslatef(0.0, -size.z, -size.x); + # displayWall(size.y, size.z); + +module.exports = World