-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
73 lines (37 loc) · 29.1 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
var packfile = require('../index')
, idxparse = require('git-packidx-parser')
, Buffer = require('buffer').Buffer
, through = require('through')
, test = require('tape')
, pack_idx
test('setup', function(assert) {
idxparse()
.on('data', function(_d) { pack_idx = _d })
.on('end', function() { assert.end() })
.end(TEST_PACK_IDX)
})
test('works as expected', function(assert) {
var oid = new Buffer([0xc7, 0x88, 0x5a, 0x6f, 0x16, 0xb9, 0xf0, 0x5a, 0x2e, 0xcd, 0x70, 0x83, 0xc9, 0x0c, 0xe2, 0x46, 0xc1, 0x12, 0x25, 0x3d])
, pf = packfile(TEST_PACK.length, find_raw, read)
var loc = pack_idx.find(oid)
pf.read(loc.offset, loc.next, function(err, data) {
if(err) throw err
assert.equal(data.data.toString('utf8'), EXPECT)
assert.end()
})
function find_raw(oid, ready) {
var bits = pack_idx.find(oid)
if(!bits) {
return ready(new Error('no such object'))
}
pf.read(bits.offset, bits.next, ready)
}
function read(start, end) {
var stream = through()
process.nextTick(function() { stream.end(TEST_PACK.slice(start, end)) })
return stream
}
})
var TEST_PACK_IDX = new Buffer("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", 'base64')
var TEST_PACK = new Buffer("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", "base64")
var EXPECT = 'module.exports = physical\n\nvar aabb = require(\'aabb-3d\')\n , THREE = require(\'three\')\n\nfunction physical(avatar, collidables, dimensions, terminal) {\n return new Physical(avatar, collidables, dimensions, terminal)\n}\n\nfunction Physical(avatar, collidables, dimensions, terminal) {\n this.avatar = avatar\n this.terminal = terminal || new THREE.Vector3(30, 5.6, 30)\n this.dimensions = dimensions = dimensions || [1, 1, 1]\n this._aabb = aabb([0, 0, 0], dimensions)\n this.resting = {x: false, y: false, z: false}\n this.collidables = collidables\n this.friction = new THREE.Vector3(1, 1, 1)\n\n this.rotation = this.avatar.rotation\n this.default_friction = 1\n\n // default yaw/pitch/roll controls to the avatar\n this.yaw =\n this.pitch =\n this.roll = avatar\n\n this.forces = new THREE.Vector3(0, 0, 0)\n this.attractors = []\n this.acceleration = new THREE.Vector3(0, 0, 0)\n this.velocity = new THREE.Vector3(0, 0, 0)\n}\n\nvar cons = Physical\n , proto = cons.prototype\n , axes = [\'x\', \'y\', \'z\']\n , abs = Math.abs\n\n// make these *once*, so we\'re not generating\n// garbage for every object in the game.\nvar WORLD_DESIRED = new THREE.Vector3(0, 0, 0)\n , DESIRED = new THREE.Vector3(0, 0, 0)\n , START = new THREE.Vector3(0, 0, 0)\n , END = new THREE.Vector3(0, 0, 0)\n , DIRECTION = new THREE.Vector3()\n , LOCAL_ATTRACTOR = new THREE.Vector3()\n , TOTAL_FORCES = new THREE.Vector3()\n\nproto.applyWorldAcceleration = applyTo(\'acceleration\')\nproto.applyWorldVelocity = applyTo(\'velocity\')\n\nfunction applyTo(which) {\n return function(world) {\n var local = this.avatar.worldToLocal(world)\n this[which].x += local.x\n this[which].y += local.y\n this[which].z += local.z\n }\n}\n\nproto.tick = function(dt) {\n var forces = this.forces\n , acceleration = this.acceleration\n , velocity = this.velocity\n , terminal = this.terminal\n , friction = this.friction\n , desired = DESIRED\n , world_desired = WORLD_DESIRED\n , bbox\n , pcs\n TOTAL_FORCES.multiplyScalar(0)\n\n desired.x =\n desired.y =\n desired.z =\n world_desired.x =\n world_desired.y =\n world_desired.z = 0\n\n for(var i = 0; i < this.attractors.length; i++) {\n var distance_factor = this.avatar.position.distanceToSquared(this.attractors[i])\n LOCAL_ATTRACTOR.copy(this.attractors[i])\n LOCAL_ATTRACTOR = this.avatar.worldToLocal(LOCAL_ATTRACTOR)\n\n DIRECTION.sub(LOCAL_ATTRACTOR, this.avatar.position)\n\n DIRECTION.divideScalar(DIRECTION.length() * distance_factor)\n DIRECTION.multiplyScalar(this.attractors[i].mass)\n\n TOTAL_FORCES.addSelf(DIRECTION)\n }\n \n if(!this.resting.x) {\n acceleration.x /= 8 * dt\n acceleration.x += TOTAL_FORCES.x * dt\n acceleration.x += forces.x * dt\n\n velocity.x += acceleration.x * dt\n velocity.x *= friction.x\n\n if(abs(velocity.x) < terminal.x) {\n desired.x = (velocity.x * dt)\n } else if(velocity.x !== 0) {\n desired.x = (velocity.x / abs(velocity.x)) * terminal.x\n }\n } else {\n acceleration.x = velocity.x = 0\n }\n if(!this.resting.y) {\n acceleration.y /= 8 * dt\n acceleration.y += TOTAL_FORCES.y * dt\n acceleration.y += forces.y * dt\n\n velocity.y += acceleration.y * dt\n velocity.y *= friction.y\n\n if(abs(velocity.y) < terminal.y) {\n desired.y = (velocity.y * dt)\n } else if(velocity.y !== 0) {\n desired.y = (velocity.y / abs(velocity.y)) * terminal.y\n }\n } else {\n acceleration.y = velocity.y = 0\n }\n if(!this.resting.z) {\n acceleration.z /= 8 * dt\n acceleration.z += TOTAL_FORCES.z * dt\n acceleration.z += forces.z * dt\n\n velocity.z += acceleration.z * dt\n velocity.z *= friction.z\n\n if(abs(velocity.z) < terminal.z) {\n desired.z = (velocity.z * dt)\n } else if(velocity.z !== 0) {\n desired.z = (velocity.z / abs(velocity.z)) * terminal.z\n }\n } else {\n acceleration.z = velocity.z = 0\n }\n \n START.copy(this.avatar.position)\n this.avatar.translateX(desired.x)\n this.avatar.translateY(desired.y)\n this.avatar.translateZ(desired.z)\n END.copy(this.avatar.position)\n this.avatar.position.copy(START)\n world_desired.x = END.x - START.x\n world_desired.y = END.y - START.y\n world_desired.z = END.z - START.z\n this.friction.x =\n this.friction.y =\n this.friction.z = this.default_friction\n\n // run collisions\n this.resting.x =\n this.resting.y =\n this.resting.z = false\n\n bbox = this.aabb()\n pcs = this.collidables\n\n for(var i = 0, len = pcs.length; i < len; ++i) {\n if(pcs[i] !== this) {\n pcs[i].collide(this, bbox, world_desired, this.resting)\n }\n }\n\n // apply translation\n this.avatar.position.x += world_desired.x\n this.avatar.position.y += world_desired.y\n this.avatar.position.z += world_desired.z\n}\n\nproto.subjectTo = function(force) {\n this.forces.x += force[0]\n this.forces.y += force[1]\n this.forces.z += force[2]\n return this\n}\n\nproto.attractTo = function(vector, mass) {\n vector.mass = mass\n this.attractors.push(vector)\n}\n\nproto.aabb = function() {\n return aabb(\n [this.avatar.position.x, this.avatar.position.y, this.avatar.position.z]\n , this.dimensions\n )\n}\n\n// no object -> object collisions for now, thanks\nproto.collide = function(other, bbox, world_vec, resting) {\n return\n}\n\nproto.atRestX = function() {\n return this.resting.x\n}\n\nproto.atRestY = function() {\n return this.resting.y\n}\n\nproto.atRestZ = function() {\n return this.resting.z\n}\n'