diff --git a/coffee/levels/plate.coffee b/coffee/levels/plate.coffee index c1e230d..3ff5b8a 100644 --- a/coffee/levels/plate.coffee +++ b/coffee/levels/plate.coffee @@ -1,5 +1,8 @@ # level design by Michael Abel +KQuaternion = require '../lib/quaternion' +KVector = require '../lib/vector' + module.exports = name: "plate" scheme: "blue_scheme" @@ -13,7 +16,7 @@ module.exports = player: coordinates: [3,2,1] nostatus: 0 - orientation: KQuaternion.rotationAroundVector(270, KVector(1,0,0)) + orientation: KQuaternion.rotationAroundVector(270, KVector(1,0,0)) exits: [ name: "exit" active: 1 diff --git a/coffee/lib/KQuaternion.h b/coffee/lib/KQuaternion.h new file mode 100755 index 0000000..51f4506 --- /dev/null +++ b/coffee/lib/KQuaternion.h @@ -0,0 +1,148 @@ +/* + * KQuaternion.h + * kodisein + */ + +#ifndef __KQuaternion +#define __KQuaternion + +#include "KVector.h" +#include "KMatrix.h" + +#include + +// -------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------- +class KQuaternion +{ + public: + + float w, x, y, z; + + KQuaternion ( float _w = 1.0, float _x = 0.0, float _y = 0.0, float _z = 0.0 ) + { + w = _w; x = _x; y = _y; z = _z; + } + + KQuaternion ( const KQuaternion & q ) { w = q.w; x = q.x; y = q.y; z = q.z; } + KQuaternion ( const KVector & v ) { w = 0.0; x = v[X]; y = v[Y]; z = v[Z]; } + + static KQuaternion rotationAroundVector ( float theta, const KVector & vector ) + { + KVector v(vector); + v.normalize(); + float t = DEG2RAD(theta)/2.0; + float s = sin(t); + return KQuaternion(cos(t), v[X]*s, v[Y]*s, v[Z]*s).normalize(); + } + + KVector rotate ( const KVector & v ) const + { + KQuaternion result = (*this) * KQuaternion(v) * this->getConjugate(); + return KVector(result.x, result.y, result.z); + } + + KQuaternion & normalize () + { + float l = sqrt(w*w + x*x + y*y + z*z); + if (l != 0.0) + { + w /= l; x /= l; y /= l; z /= l; + } + return (*this); + } + + KQuaternion & invert () + { + float l = sqrt(w*w + x*x + y*y + z*z); + if (l != 0.0) + { + w /= l; x = -x/l; y = -y/l; z = -z/l; + } + return (*this); + } + + void reset () { w=1.0; x=y=z=0.0; } + KQuaternion & conjugate () { x = -x; y = -y; z = -z; return (*this); } + KQuaternion getNormal () const { return KQuaternion(*this).normalize(); } + KQuaternion getConjugate () const { return KQuaternion(*this).conjugate(); } + KQuaternion getInverse () const { return KQuaternion(*this).invert(); } + float length () const { return sqrt(w*w + x*x + y*y + z*z); } + void glRotate () const { KMatrix(*this).glMultMatrix(); } + + KQuaternion slerp ( const KQuaternion & quat, float t ) const; + + operator KVector() const { return KVector(x, y, z); } + KQuaternion & operator += ( float f ) { w += f; return(*this); } + KQuaternion & operator -= ( float f ) { w -= f; return(*this); } + KQuaternion & operator *= ( float f ) { w *= f; x *= f; y *= f; z *= f; return(*this); } + KQuaternion & operator /= ( float f ) { w /= f; x /= f; y /= f; z /= f; return(*this); } + + KQuaternion & operator += ( const KQuaternion & quat ) + { + w += quat.w; x += quat.x; y += quat.y; z += quat.z; + return (*this); + } + + KQuaternion & operator -= ( const KQuaternion & quat ) + { + w -= quat.w; x -= quat.x; y -= quat.y; z -= quat.z; + return (*this); + } + + KQuaternion & operator *= ( const KQuaternion & quat ) + { + float A, B, C, D, E, F, G, H; + + A = (w + x)*(quat.w + quat.x); + B = (z - y)*(quat.y - quat.z); + C = (w - x)*(quat.y + quat.z); + D = (y + z)*(quat.w - quat.x); + E = (x + z)*(quat.x + quat.y); + F = (x - z)*(quat.x - quat.y); + G = (w + y)*(quat.w - quat.z); + H = (w - y)*(quat.w + quat.z); + + w = B +(-E - F + G + H)/2; + x = A - (E + F + G + H)/2; + y = C + (E - F + G - H)/2; + z = D + (E - F - G + H)/2; + + return (*this); + } + + KQuaternion operator * ( const KQuaternion & quat ) const + { + return (KQuaternion(*this) *= quat); + } +}; + +// -------------------------------------------------------------------------------------------------------- +inline KQuaternion operator - (const KQuaternion & q) +{ + return KQuaternion(-q.w,-q.x,-q.y,-q.z); +} + +// -------------------------------------------------------------------------------------------------------- +inline KQuaternion operator * ( float f, const KQuaternion & quat ) +{ + KQuaternion result(quat); + result *= f; + return result; +} + +// -------------------------------------------------------------------------------------------------------- +inline bool operator == (const KQuaternion & lquat, const KQuaternion & rquat) +{ + return ((rquat.w == lquat.w) && (rquat.x == lquat.x) && + (rquat.y == lquat.y) && (rquat.z == lquat.z)); +} + +// -------------------------------------------------------------------------------------------------------- +inline bool operator != (const KQuaternion & lquat, const KQuaternion & rquat) +{ + return(!(lquat == rquat)); +} + +#endif + diff --git a/coffee/lib/class.coffee b/coffee/lib/class.coffee new file mode 100644 index 0000000..207ba64 --- /dev/null +++ b/coffee/lib/class.coffee @@ -0,0 +1,12 @@ +# 0000000 000 0000000 0000000 0000000 +# 000 000 000 000 000 000 +# 000 000 000000000 0000000 0000000 +# 000 000 000 000 000 000 +# 0000000 0000000 000 000 0000000 0000000 + +class Class + + constructor: () -> + + +module.exports = Class diff --git a/coffee/lib/position.coffee b/coffee/lib/position.coffee new file mode 100644 index 0000000..ec81630 --- /dev/null +++ b/coffee/lib/position.coffee @@ -0,0 +1,15 @@ +# 00000000 0000000 0000000 000 000000000 000 0000000 000 000 +# 000 000 000 000 000 000 000 000 000 000 0000 000 +# 00000000 000 000 0000000 000 000 000 000 000 000 0 000 +# 000 000 000 000 000 000 000 000 000 000 0000 +# 000 0000000 0000000 000 000 000 0000000 000 000 + +class Position + + constructor: (@x=0, @y=0) -> + + plus: (s) -> new Position @w+s.w,@h+s.h + minus: (s) -> new Position @w-s.w,@h-s.h + eql: (s) -> @x == s.x and @y == s.y + +module.exports = Position diff --git a/coffee/lib/quaternion.coffee b/coffee/lib/quaternion.coffee new file mode 100644 index 0000000..840559d --- /dev/null +++ b/coffee/lib/quaternion.coffee @@ -0,0 +1,137 @@ + +# 0000000 000 000 0000000 000000000 00000000 00000000 000 000 000 0000000 000 000 +# 000 000 000 000 000 000 000 000 000 000 0000 000 000 000 000 0000 000 +# 000 00 00 000 000 000000000 000 0000000 0000000 000 0 000 000 000 000 000 0 000 +# 000 0000 000 000 000 000 000 000 000 000 000 0000 000 000 000 000 0000 +# 00000 00 0000000 000 000 000 00000000 000 000 000 000 000 0000000 000 000 + +Vector = require './vector' + +class Quaternion + + constructor: (@w=1, @x=0, @y=0, @z=0) -> + if @w instanceof Vector + @x = @w.x + @y = @w.y + @z = @w.z + @w = 0 + else if @w instanceof Quaternion + @x = @w.x + @y = @w.y + @z = @w.z + @w = @w.w + + @rotationAroundVector: (theta, vector) -> + v = new Vector vector + v.normalize() + t = Vector.DEG2RAD(theta)/2.0 + s = Math.sin(t) + new Quaternion(Math.cos(t), v.x*s, v.y*s, v.z*s).normalize() + + add: (quat) -> + @w += quat.w + @x += quat.x + @y += quat.y + @z += quat.z + @ + + sub: (quat) -> + @w -= quat.w + @x -= quat.x + @y -= quat.y + @z -= quat.z + @ + + rotate: (v) -> + qv = new Quaternion v + rq = @mul qv.mul @getConjugate() + new Vector rq.x, rq.y, rq.z + + normalize: -> + l = Math.sqrt(w*w + x*x + y*y + z*z) + if l != 0.0 + w /= l; x /= l; y /= l; z /= l + @ + + invert: -> + l = Math.sqrt(w*w + x*x + y*y + z*z) + if l != 0.0 + w /= l; x = -x/l; y = -y/l; z = -z/l + @ + + reset: -> + @x=@y=@z=0 + @w=1.0 + @ + + conjugate: -> + @x = -@x + @y = -@y + @z = -@z + @ + + getNormal: -> new Quaternion(@).normalize() + getConjugate: -> new Quaternion(@).conjugate() + getInverse: -> new Quaternion(@).invert() + neg: -> new Quaternion -@w,-@x,-@y,-@z + vector: -> new Vector @x, @y, @z + length: -> Math.sqrt @w*@w + @x*@x + @y*@y + @z*@z + eql: (q) -> @w==q.w and @x=q.x and @y==q.y and @z==q.z + + # glRotate () const { KMatrix(*this).glMultMatrix(); } + + # Quaternion & operator += ( float f ) { w += f; return(*this); } + # Quaternion & operator -= ( float f ) { w -= f; return(*this); } + # Quaternion & operator *= ( float f ) { w *= f; x *= f; y *= f; z *= f; return(*this); } + # Quaternion & operator /= ( float f ) { w /= f; x /= f; y /= f; z /= f; return(*this); } + + mul: (quatOrScalar) -> + if quatOrScalar instanceof Quaternion + quat = quatOrScalar + A = (@w + @x)*(quat.w + quat.x) + B = (@z - @y)*(quat.y - quat.z) + C = (@w - @x)*(quat.y + quat.z) + D = (@y + @z)*(quat.w - quat.x) + E = (@x + @z)*(quat.x + quat.y) + F = (@x - @z)*(quat.x - quat.y) + G = (@w + @y)*(quat.w - quat.z) + H = (@w - @y)*(quat.w + quat.z) + new Quaternion B +(-E - F + G + H)/2, + A - (E + F + G + H)/2, + C + (E - F + G - H)/2, + D + (E - F - G + H)/2 + else + new Quaternion @w*f, @x*f, @y*f, z*f + + slerp: (quat, t) -> + + to1 = [0,0,0,0] + cosom = @x * quat.x + @y * quat.y + @z * quat.z + @w * quat.w # calc cosine + + if cosom < 0 # adjust signs (if necessary) + cosom = -cosom + to1[0] = -quat.x + to1[1] = -quat.y + to1[2] = -quat.z + to1[3] = -quat.w + else + to1[0] = quat.x + to1[1] = quat.y + to1[2] = quat.z + to1[3] = quat.w + + if (1.0 - cosom) > 0.001 # calculate coefficients + omega = Math.acos(cosom) # standard case (slerp) + sinom = Math.sin(omega) + scale0 = Math.sin((1.0 - t) * omega) / sinom + scale1 = Math.sin(t * omega) / sinom + else # "from" and "to" quaternions are very close -> we can do a linear interpolation + scale0 = 1.0 - t + scale1 = t + + new Quaternion scale0 * w + scale1 * to1[3], + scale0 * x + scale1 * to1[0], + scale0 * y + scale1 * to1[1], + scale0 * z + scale1 * to1[2] + +module.exports = Quaternion \ No newline at end of file diff --git a/coffee/lib/size.coffee b/coffee/lib/size.coffee new file mode 100644 index 0000000..19dbfc2 --- /dev/null +++ b/coffee/lib/size.coffee @@ -0,0 +1,19 @@ +# 0000000 000 0000000 00000000 +# 000 000 000 000 +# 0000000 000 000 0000000 +# 000 000 000 000 +# 0000000 000 0000000 00000000 + +class Size + + constructor: (@w, @h) -> + @x = @w + @y = @h + + div: (d) -> new Size parseInt(@w/d), parseInt(@h/d) + mul: (d) -> new Size parseInt(@w*d), parseInt(@h*d) + minus: (s) -> new Size @w-s.w,@h-s.h + plus: (s) -> new Size @w+s.w,@h+s.h + eql: (s) -> @w == s.w and @h == s.h + +module.exports = Size diff --git a/coffee/lib/vector.coffee b/coffee/lib/vector.coffee new file mode 100644 index 0000000..0e10fa8 --- /dev/null +++ b/coffee/lib/vector.coffee @@ -0,0 +1,111 @@ + +# 000 000 00000000 0000000 000000000 0000000 00000000 +# 000 000 000 000 000 000 000 000 000 +# 000 000 0000000 000 000 000 000 0000000 +# 000 000 000 000 000 000 000 000 +# 0 00000000 0000000 000 0000000 000 000 + +#define kMinMax(a,b,c) (kMax((a), kMin((b), (c)))) +#define kAbsMax(a,b) ((kAbs((a)) >= kAbs((b))) ? (a) : (b)) +#define kAbsMin(a,b) ((kAbs((a)) < kAbs((b))) ? (a) : (b)) + +# X = 0 +# SX = 0 +# Y = 1 +# Z = 2 +# W = 3 +# SY = 5 +# SZ = 10 +# TX = 12 +# TY = 13 +# TZ = 14 + +class Vector + + constructor: (@x,@y,@z,@w) -> + if @x instanceof Vector + @copy @x + + copy: (v) -> + @x = v.x + @y = v.y + @z = v.z + @w = v.w + @ + + normal: -> new Vector(@).normalize() + + parallel: (n) -> + dot = @x*n.x + @y*n.y + @z*n.z + new Vector dot*n.x, dot*n.y, dot*n.z + + # returns the projection of normalized vector n to vector that is perpendicular to this + perpendicular: (n) -> + dot = @x*n.x + @y*n.y + @z*n.z + new Vector @x-dot*n.x, @y-dot*n.y, @z-dot*n.z + + reflect: (n) -> + dot = 2*(@x*n.x + @y*n.y + @z*n.z) + new Vector @x-dot*n.x, @y-dot*n.y, @z-dot*n.z + + cross: (v) -> new Vector @y*v.z-@z*v.y, @z*v.x-@x*v.z, @x*v.y-@y*v.x + normalize: -> + l = @length() + if l + l = 1.0/l + @x *= l + @y *= l + @z *= l + @w *= l + @ + + xyperp: -> new Vector -@y, @x + round: -> new Vector rint(@x), rint(@y), rint(@z), @w + + xyangle: (v) -> + thisXY = new Vector(@x, @y).normal() + otherXY = new Vector(v.x, v.y).normal() + if thisXY.xyperp() * otherXY >= 0 + return Vector.RAD2DEG(Math.acos(thisXY * otherXY)) + -Vector.RAD2DEG(Math.acos(thisXY * otherXY)); + + length: -> Math.sqrt @x*@x+@y*@y+@z*@z+@w*@w + angle: (v) -> Vector.RAD2DEG Math.acos @normal()*v.normal() + dot: (v) -> @x*v.x + @y*v.y + @z*v.z + @w*v.w + + mul: (f) -> new Vector @x*f, @y*f, @z*f, @w*f + div: (d) -> new Vector @x/d, @y/d, @z/d, @w/d + plus: (v) -> new Vector @x+v.x, @y+v.y, @z+v.z, @w+v.w + minus: (v) -> new Vector @x-v.x, @y-v.y, @z-v.z, @w-v.w + + add: (v) -> + @x += v.x + @y += v.y + @z += v.z + @w += v.w + @ + + sub: (v) -> + @x -= v.x + @y -= v.y + @z -= v.z + @w -= v.w + @ + + scale: (f) -> + @x *= f + @y *= f + @z *= f + @w *= f + @ + + reset: -> + @x = @y = @z = @w = 0 + @ + + # glTranslate: () -> glTranslatef @x,@y,@z + + @DEG2RAD: (d) -> Math.PI*d/180.0 + @RAD2DEG: (r) -> r*180.0/Math.PI + +module.exports = Vector \ No newline at end of file diff --git a/coffee/main.coffee b/coffee/main.coffee index 4eefe83..7315946 100644 --- a/coffee/main.coffee +++ b/coffee/main.coffee @@ -15,10 +15,7 @@ class Kiki extends Stage constructor: (@view) -> super @view start: -> - - world = new KikiWorld() - log 'hello world' - + @elem = document.createElement 'div' @elem.style.position = 'absolute' @elem.style.top = '0' @@ -85,6 +82,9 @@ class Kiki extends Stage # # @mesh = new THREE.Mesh @geom, @material # @scene.add @mesh + + world = new KikiWorld() + log 'hello world' @animate() @@ -115,7 +115,7 @@ class Kiki extends Stage resized: (w,h) -> @aspect = w/h @camera?.aspect = @aspect - @camera.updateProjectionMatrix() + @camera?.updateProjectionMatrix() @renderer?.setSize w,h module.exports = Kiki diff --git a/coffee/world.coffee b/coffee/world.coffee index cdac490..c1c21f4 100644 --- a/coffee/world.coffee +++ b/coffee/world.coffee @@ -16,27 +16,44 @@ class KikiWorld # execfile (kikipy_path + "highscore.py") # execfile (kikipy_path + "intro.py") - globals().rot0 = KQuaternion() - globals().rotz180 = KQuaternion.rotationAroundVector(180, KVector(0,0,1)) - globals().rotz90 = KQuaternion.rotationAroundVector(90, KVector(0,0,1)) - globals().roty270 = KQuaternion.rotationAroundVector(270, KVector(0,1,0)) - globals().roty180 = KQuaternion.rotationAroundVector(180, KVector(0,1,0)) - globals().roty90 = KQuaternion.rotationAroundVector(90, KVector(0,1,0)) - globals().roty0 = KQuaternion.rotationAroundVector(0, KVector(0,1,0)) - globals().rotx180 = KQuaternion.rotationAroundVector(180, KVector(1,0,0)) - globals().rotx90 = KQuaternion.rotationAroundVector(90, KVector(1,0,0)) + 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)) @levelList = [ - "start", "steps", "move", "electro", "elevate", "throw", # intro - "gold", "jump", "escape", "gears", "gamma", "cube", "switch", "borg", # easy - "mini", "blocks", "bombs", "sandbox", "energy", "maze", "love", - "towers", "edge", "random", "plate", "nice", "entropy", # medium - "grasp", "fallen", "cheese", "invisimaze", "spiral", # owen hay's levels (TODO: sort in) - "slick", "bridge", "flower", "stones", "walls", "grid", # difficult - "rings", "core", "bronze", "pool", # difficult - "hidden", "church", "strange", "mesh", "columns", "machine", # tough - "neutron", "captured", "circuit", "regal", "conductor", "evil", # very hard - "mutants", # outro + # intro + "start", "steps", "move", "electro", "elevate", "throw", + # easy + "gold", "jump", "escape", "gears", + # "gamma", + "cube", "switch", "borg", + "mini", + # "blocks", + "bombs", "sandbox", "energy", "maze", "love", + # medium + "towers", "edge", "random", "plate", "nice", "entropy", + # owen hay's levels (TODO: sort in) + "grasp", "fallen", "cheese", "invisimaze", "spiral", + # difficult + "slick", "bridge", "flower", "stones", "walls", "grid", + "rings", + # "core", + "bronze", "pool", + # tough + "hidden", "church", + # "strange", + "mesh", "columns", "machine", + # very hard + # "neutron", + "captured", "circuit", "regal", "conductor", "evil", + # outro + "mutants", ] @levelDict = {}