Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Some refactoring, initial physics work

  • Loading branch information...
commit 3162f51830255150489a122879970ae21eb856f6 1 parent 9615b9d
@jwagner authored
View
2  doc/talk
@@ -1 +1,3 @@
http://www.mobygames.com/game-group/visual-technique-style-voxel-graphics/offset,0/so,1d/
+
+Capsule for physics -> border-radius
View
2  src/main.js
@@ -40,7 +40,7 @@ var loader = new Loader(),
var cube, cube2;
function prepareScene(){
- window.world = new voxel.World({width: 8, height: 2, depth: 8, chunk_options: {size: 32, scale: 1.0}});
+ window.world = new voxel.World({width: 8, height: 2, depth: 8, chunk_size: 32, scale: 0.5});
voxel.random_world(window.world);
//voxel.flat_world(window.world, 10);
window.renderer = new glvoxel.Renderer(window.world);
View
52 src/voxel.js
@@ -14,18 +14,16 @@ var SimplexNoise = require('simplex-noise');
voxel.World = function VoxelWorld(options) {
extend(this, options);
- this.chunk_shift = Math.log(this.chunk_options.size)/Math.log(2);
- this.chunk_mask = this.chunk_options.size - 1;
+ this.chunk_shift = Math.log(this.chunk_size)/Math.log(2);
+ this.chunk_mask = this.chunk_size - 1;
+ this.iscale = 1.0/this.scale;
this.grid = [];
this.chunks = [];
this.init_chunks();
};
voxel.World.prototype = {
- chunk_options: {
- size: 32,
- // world size scale
- scale: 0.5
- },
+ chunk_size: 32,
+ scale: 0.5,
width: 32,
depth: 32,
height: 2,
@@ -57,7 +55,7 @@ voxel.World.prototype = {
for(var y = 0; y < this.height; y++) {
line = [];
for(var z = 0; z < this.depth; z++) {
- var chunk = new voxel.Chunk(this.key++, x, y, z, this.chunk_options);
+ var chunk = new voxel.Chunk(this.key++, x, y, z, this.chunk_size, this.scale);
line.push(chunk);
this.chunks.push(chunk);
}
@@ -67,12 +65,14 @@ voxel.World.prototype = {
}
},
voxel: function(position, value) {
- var cs = this.chunk_shift,
+ var scale = this.scale,
+ iscale = this.iscale,
+ cs = this.chunk_shift,
cm = this.chunk_mask,
- fx = Math.floor(position[0]),
- fy = Math.floor(position[1]),
- fz = Math.floor(position[2]),
- size = this.chunk_options.size,
+ fx = Math.floor(position[0]*iscale),
+ fy = Math.floor(position[1]*iscale),
+ fz = Math.floor(position[2]*iscale),
+ size = this.chunk_size,
limit_x = size*this.width,
limit_y = size*this.height,
limit_z = size*this.depth,
@@ -84,18 +84,21 @@ voxel.World.prototype = {
return -1;
}
var chunk = this.grid[gx][gy][gz];
- if(value != null){
+ if(value !== undefined){
//debugger;
chunk.voxels[cx+cy+cz] = value;
chunk.version++;
return value;
}
else {
+ //console.log(cx, cy, cz, iscale, position, cs, cm, gx, gy, gz);
return chunk.voxels[cx+cy+cz];
}
},
ray_query: function(ray, maxT, location, last_location) {
- var x = ray[0], y = ray[1], z = ray[2],
+ var iscale = this.iscale,
+ scale = this.scale,
+ x = ray[0]*iscale, y = ray[1]*iscale, z = ray[2]*iscale,
// last positions
dx = ray[3], dy = ray[4], dz = ray[5],
// the direction of the steps on each axis
@@ -116,7 +119,7 @@ voxel.World.prototype = {
tx = Math.floor(x+dx*maxT),
ty = Math.floor(y+dy*maxT),
tz = Math.floor(z+dz*maxT),
- size = this.chunk_options.size,
+ size = this.chunk_size,
limit_x = size*this.width,
limit_y = size*this.height,
limit_z = size*this.depth,
@@ -193,20 +196,21 @@ voxel.World.prototype = {
//console.log('miss');
}
if(hit){
- location[0] = fx;
- location[1] = fy;
- location[2] = fz;
- last_location[0] = lx;
- last_location[1] = ly;
- last_location[2] = lz;
+ location[0] = fx*scale;
+ location[1] = fy*scale;
+ location[2] = fz*scale;
+ last_location[0] = lx*scale;
+ last_location[1] = ly*scale;
+ last_location[2] = lz*scale;
}
return hit;
}
};
-voxel.Chunk = function (key, x, y, z, options){
- extend(this, options);
+voxel.Chunk = function (key, x, y, z, size, scale){
this.position = vec3.create([x, y, z]);
+ this.size = size || 32;
+ this.scale = scale || 0.5;
this.key = key;
this.init_aabb(x, y, z);
this.voxels = new Uint8Array(this.size*this.size*this.size);
View
112 test/physics-test.js
@@ -0,0 +1,112 @@
+var buster = require("buster"),
+ assert = buster.assert,
+ refute = buster.refute;
+
+function clipSegmentSegment(a0, a1, b0, b1){
+ // before
+ if(b1 < a0) {
+ return a0-b1;
+ }
+ if(b0 > a1){
+ return a1-b0;
+ }
+ return 0.0;
+}
+function clipSegmentPoint(a0, a1, b0){
+ if(b0 < a0) return a0-b0;
+ if(b0 > a1) return a1-b0;
+ return 0.0;
+}
+function collideAABBYCapsule(aabb, capsule, penetration){
+ var xd = clipSegmentPoint(aabb[0], aabb[3], capsule[0]),
+ yd = clipSegmentSegment(aabb[1], aabb[4], capsule[1], capsule[3]),
+ zd = clipSegmentPoint(aabb[2], aabb[5], capsule[2]),
+ d2 = xd*xd+yd*yd+zd*zd,
+ r = capsule[4];
+ if(d2 > r*r){
+ return false;
+ }
+ var d = Math.sqrt(d2),
+ s = (d-r)/d;
+ penetration[0] = xd*s;
+ penetration[1] = yd*s;
+ penetration[2] = zd*s;
+ return true;
+}
+
+buster.testCase('clipping', {
+ clipSegmentPoint:{
+ before: function(){
+ assert.equals(clipSegmentPoint(3, 5, 1), 2);
+ assert.equals(clipSegmentPoint(3, 5, -0.5), 3.5);
+ },
+ within: function(){
+ assert.equals(clipSegmentPoint(3, 5, 3), 0);
+ assert.equals(clipSegmentPoint(3, 5, 4.5), 0);
+ assert.equals(clipSegmentPoint(3, 5, 5), 0);
+ },
+ after: function(){
+ assert.equals(clipSegmentPoint(3, 5, 7), -2);
+ assert.equals(clipSegmentPoint(3, 5, 8.5), -3.5);
+ }
+ },
+ clipSegmentSegment: {
+ before: function(){
+ assert.equals(clipSegmentSegment(3, 5, 1, 2), 1);
+ assert.equals(clipSegmentSegment(3, 5, -0.5, 0.5), 2.5);
+ },
+ beforeOverlap: function(){
+ assert.equals(clipSegmentSegment(3, 5, 1, 3), 0);
+ assert.equals(clipSegmentSegment(3, 5, -0.5, 3.5), 0);
+ },
+ bInA: function(){
+ assert.equals(clipSegmentSegment(3, 5, 4, 4.5), 0);
+ assert.equals(clipSegmentSegment(3, 5, 3, 5), 0);
+ },
+ aInB: function(){
+ assert.equals(clipSegmentSegment(3, 5, 2, 6), 0);
+ assert.equals(clipSegmentSegment(3, 5, -1, 10), 0);
+ },
+ afterOverlap: function(){
+ assert.equals(clipSegmentSegment(3, 5, 5, 6), 0);
+ assert.equals(clipSegmentSegment(3, 5, 4, 8), 0);
+ },
+ after: function(){
+ assert.equals(clipSegmentSegment(3, 5, 5.5, 7), -0.5);
+ assert.equals(clipSegmentSegment(3, 5, 6, 8), -1);
+ },
+ collideAABBYCapsule:{
+ capsuleAboveAABB: function() {
+ var aabb = new Float32Array([0.0, 0.0, 0.0, 1.0, 1.0, 1.0]),
+ capsule = new Float32Array([0.5, 1.1, 0.5, 2.1, 0.5]),
+ penetration = new Float32Array(3);
+
+ var collision = collideAABBYCapsule(aabb, capsule, penetration);
+ assert(collision);
+ assert.near(penetration[0], 0, 0.001);
+ assert.near(penetration[1], 0.4, 0.001);
+ assert.near(penetration[2], 0, 0.001);
+ },
+ capsuleAboveAABBOutside: function() {
+ var aabb = new Float32Array([0.0, 0.0, 0.0, 1.0, 1.0, 1.0]),
+ capsule = new Float32Array([0.5, 1.51, 0.5, 2.1, 0.5]),
+ penetration = new Float32Array(3);
+
+ var collision = collideAABBYCapsule(aabb, capsule, penetration);
+ refute(collision);
+ },
+ capsuleBellowAABB: function() {
+ var aabb = new Float32Array([0.0, 0.0, 0.0, 1.0, 1.0, 1.0]),
+ capsule = new Float32Array([0.5, -1.1, 0.5, -0.1, 0.5]),
+ penetration = new Float32Array(3);
+
+ var collision = collideAABBYCapsule(aabb, capsule, penetration);
+ assert(collision);
+ assert.near(penetration[0], 0, 0.001);
+ assert.near(penetration[1], -0.4, 0.001);
+ assert.near(penetration[2], 0, 0.001);
+ },
+
+ }
+ }
+});
View
62 test/voxel-test.js
@@ -4,7 +4,7 @@ var buster = require("buster"),
vec3 = require('gl-matrix').vec3,
voxel = require('../src/voxel');
-var flat_world = new voxel.World({width: 2, height: 2, depth: 2, chunk_options: {size: 4}});
+var flat_world = new voxel.World({width: 2, height: 2, depth: 2, chunk_size: 4});
voxel.flat_world(flat_world, 1);
buster.testCase('world', {
@@ -13,18 +13,18 @@ buster.testCase('world', {
assert.equals(flat_world.chunk_mask, 3);
},
'should initialize chunks': function() {
- var world = new voxel.World({width: 2, height: 3, depth: 4, chunk_options: {size: 32}});
+ var world = new voxel.World({width: 2, height: 3, depth: 4, chunk_size: 1});
assert.equals(world.chunks.length, 2*3*4);
},
'voxel': function () {
- var flat_world = new voxel.World({width: 2, height: 2, depth: 2, chunk_options: {size: 4}});
+ var flat_world = new voxel.World({width: 2, height: 2, depth: 2, chunk_size: 4, scale: 0.5});
voxel.flat_world(flat_world, 1);
assert.equals(flat_world.voxel([0, 0, 0]), 2);
- assert.equals(flat_world.voxel([0, 1, 0]), 1);
- assert.equals(flat_world.voxel([0, 3, 0]), 0);
- assert.equals(flat_world.voxel([5, 6, 7]), 0);
- flat_world.voxel([5, 6, 7], 3);
- assert.equals(flat_world.voxel([5, 6, 7]), 3);
+ assert.equals(flat_world.voxel([0, 0.5, 0]), 1);
+ assert.equals(flat_world.voxel([0, 1.5, 0]), 0);
+ assert.equals(flat_world.voxel([2.5, 3, 3.5]), 0);
+ flat_world.voxel([2.5, 3, 3.5], 3);
+ assert.equals(flat_world.voxel([2.5, 3, 3.5]), 3);
assert.equals(flat_world.grid[1][1][1].voxels[1+2*4+3*4*4], 3);
assert.equals(flat_world.voxel([-1, 0, 0], 0), -1);
},
@@ -34,50 +34,50 @@ buster.testCase('world', {
this.last_location = vec3.create();
},
'no_hit': function() {
- var hit = flat_world.ray_query([0.5,2.5,0.5,0,0,-1], 10, this.location, this.last_location);
+ var hit = flat_world.ray_query([0.25,0.125,0.25,0,0,-1], 10, this.location, this.last_location);
refute(hit);
- hit = flat_world.ray_query([0.5,2.5,0.5,0,1,0], 10, this.location, this.last_location);
+ hit = flat_world.ray_query([0.25,1.25,0.25,0,1,0], 10, this.location, this.last_location);
refute(hit);
- hit = flat_world.ray_query([0.5,2.5,0.5,0,1,0], 10, this.location, this.last_location);
+ hit = flat_world.ray_query([0.25,1.25,0.25,0,1,0], 10, this.location, this.last_location);
refute(hit);
- hit = flat_world.ray_query([0.5,2.5,0.5,0, 0.00009999999950000001, 0.999999995], 10, this.location, this.last_location);
+ hit = flat_world.ray_query([0.25,1.25,0.25,0, 0.00009999999950000001, 0.999999995], 10, this.location, this.last_location);
refute(hit);
},
'hit': {
'same chunk -y': function() {
- var hit = flat_world.ray_query([0.5,2.5,0.5,0,-1,0], 10, this.location, this.last_location);
+ var hit = flat_world.ray_query([0.25,1.25,0.25,0,-1,0], 10, this.location, this.last_location);
assert(hit);
- assert.equals(this.location, vec3.create([0, 1, 0]));
- assert.equals(this.last_location, vec3.create([0, 2, 0]));
+ assert.equals(this.location, vec3.create([0, 0.5, 0]));
+ assert.equals(this.last_location, vec3.create([0, 1.0, 0]));
},
'same chunk -y +z': function() {
- var hit = flat_world.ray_query([0.5,2.5,0.9,0, -0.7071, 0.7071], 10, this.location, this.last_location);
+ var hit = flat_world.ray_query([0.25,1.25,0.45,0, -0.7071, 0.7071], 10, this.location, this.last_location);
assert(hit);
- assert.equals(this.location, vec3.create([0, 1, 1]));
- assert.equals(this.last_location, vec3.create([0, 2, 1]));
+ assert.equals(this.location, vec3.create([0, 0.5, 0.5]));
+ assert.equals(this.last_location, vec3.create([0, 1, 0.5]));
},
'same chunk -y +z higher up': function() {
- var hit = flat_world.ray_query([0.5,5.5,0.5,0, -0.7071, 0.7071], 10, this.location, this.last_location);
+ var hit = flat_world.ray_query([0.25,2.75,0.25,0, -0.7071, 0.7071], 10, this.location, this.last_location);
assert(hit);
- assert.equals(this.location, vec3.create([0, 1, 4]));
+ assert.equals(this.location, vec3.create([0, 0.5, 2]));
//console.log(this.location);
- assert.equals(this.last_location, vec3.create([0, 2, 4]));
+ assert.equals(this.last_location, vec3.create([0, 1, 2]));
},
'same chunk +x -y +z': function() {
- var hit = flat_world.ray_query([0.5,5.5,0.5,0.272, -0.68, 0.68], 10, this.location, this.last_location);
+ var hit = flat_world.ray_query([0.25,2.75,0.25,0.272, -0.68, 0.68], 10, this.location, this.last_location);
assert(hit);
- assert.equals(this.location, vec3.create([1, 1, 4]));
+ assert.equals(this.location, vec3.create([0.5, 0.5, 2]));
},
'outside -y': function() {
- var hit = flat_world.ray_query([0,10,0,0,-1,0], 10, this.location, this.last_location);
+ var hit = flat_world.ray_query([0,5,0,0,-1,0], 10, this.location, this.last_location);
assert(hit);
- assert.equals(this.location, vec3.create([0, 1, 0]));
- assert.equals(this.last_location, vec3.create([0, 2, 0]));
+ assert.equals(this.location, vec3.create([0, 0.5, 0]));
+ assert.equals(this.last_location, vec3.create([0, 1, 0]));
- hit = flat_world.ray_query([4,10,5,0,-1,0], 10, this.location, this.last_location);
+ hit = flat_world.ray_query([2,5,2.5,0,-1,0], 10, this.location, this.last_location);
assert(hit);
- assert.equals(this.location, vec3.create([4, 1, 5]));
- assert.equals(this.last_location, vec3.create([4, 2, 5]));
+ assert.equals(this.location, vec3.create([2, 0.5, 2.5]));
+ assert.equals(this.last_location, vec3.create([2, 1, 2.5]));
}
}
@@ -86,11 +86,13 @@ buster.testCase('world', {
buster.testCase('voxel.Chunk', {
'should be initialized empty': function(){
- var chunk = new voxel.Chunk();
+ var chunk = new voxel.Chunk(0, 0, 0, 0, 4, 0.5);
for(var i = 0; i < chunk.voxels.length; i++) {
var v = chunk.voxels[i];
assert.equals(v, 0);
}
+ assert.equals(chunk.voxels.length, 4*4*4);
assert.equals(chunk.nonempty_voxels, 0);
+ assert.equals(chunk.scale, 0.5);
}
});
Please sign in to comment.
Something went wrong with that request. Please try again.