From dc4db9d58f9868694d71b697e5351596cadc4054 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Fri, 31 Oct 2014 21:45:57 -0400 Subject: intersect3 clamping distance from wall --- public/assets/test/intersect3.html | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'public/assets/test/intersect3.html') diff --git a/public/assets/test/intersect3.html b/public/assets/test/intersect3.html index 4fec891..e897e8a 100644 --- a/public/assets/test/intersect3.html +++ b/public/assets/test/intersect3.html @@ -35,7 +35,7 @@ var scene = new MX.Scene() var w = canvas.width = window.innerWidth var h = canvas.height = window.innerHeight -var cursor = new Rect( 150, 250, 150, 250 ) +var cursor = new Rect( new vec2(564, 203), new vec2(734, 372) ) var wall_vec = new Rect ( 0, 0, 0, 0 ) var points = [ cursor.x, cursor.y ] @@ -70,7 +70,6 @@ Rooms.grouper.build() var r = 4 var intersect = new vec2 () -var intersects = [] var dragging = false, dragging_a, dragging_b var delta = new vec2( 0, 0 ) @@ -116,7 +115,7 @@ function draw () { drawLine(cursor.x, cursor.y, "#f00") hud.innerHTML = "" - intersects.length = 0 + var closest_face, closest_intersect, t, min_t = 1 Walls.list.forEach(function(wall, i){ if (wall.side & LEFT_RIGHT) { @@ -134,7 +133,7 @@ function draw () { drawLine(wall_vec.x, wall_vec.y, "#888", true) drawLine(origins.x, origins.y, "rgba(0,0,0,0.1)") - var t = perp(origins, wall_vec) / ( perp(cursor, wall_vec) || 0.0000001 ) + t = perp(origins, wall_vec) / ( perp(cursor, wall_vec) || 0.0000001 ) intersect.a = cursor.x.a + ( cursor.y.a - cursor.x.a ) * t intersect.b = cursor.x.b + ( cursor.y.b - cursor.x.b ) * t @@ -168,19 +167,30 @@ function draw () { } drawPoint(intersect) - if (intersecting_face) { - hud.innerHTML += intersecting_face.y.a + "
" + if (actually_intersects && intersecting_face && t < min_t) { + min_t = t + hud.innerHTML += t + "
" var clone = intersect.clone() clone.t = t - intersects.push( clone ) + closest_face = intersecting_face + closest_intersect = clone } }) - if (intersects.length) { - // get the intersect with smallest T value - // get the angle of the cam/pos vector + if (closest_face) { + var a = angle(cursor) + closest_intersect.a -= scene.camera.radius * cos(a) + closest_intersect.b -= scene.camera.radius * sin(a) + + ctx.fillStyle = "#00f" + drawPoint(closest_intersect) + drawLine(cursor.x, closest_intersect, "#00f") + // closest_face.vec + + // get the closest intersect, i.e. the one with smallest t value + // get the angle of the cursor // move the desired position to pos - 20px - // display this point + } } function drawLine (pa, pb, color, headless) { @@ -197,6 +207,12 @@ function drawPoint (p) { var y = p.b - r ctx.fillRect(x, y, r*2, r*2) } +function angle (va) { + return atan2(va.y.b - va.x.b, va.y.a - va.x.a) +} +function dot (va, vb) { + return (va.y.a - va.x.a) * (vb.y.a - vb.x.a) + (va.y.b - va.x.b) * (vb.y.b - vb.x.b) +} function perp (va, vb) { return (va.y.a - va.x.a) * (vb.y.b - vb.x.b) - (va.y.b - va.x.b) * (vb.y.a - vb.x.a) } -- cgit v1.2.3-70-g09d2 From a61ad3cea5b7a76777d594d1a6d960943a0e776f Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Fri, 31 Oct 2014 22:38:27 -0400 Subject: correctly intercepting walls in mover --- .../javascripts/rectangles/engine/rooms/mover.js | 188 +++++++++++---------- public/assets/test/intersect3.html | 10 +- 2 files changed, 105 insertions(+), 93 deletions(-) (limited to 'public/assets/test/intersect3.html') diff --git a/public/assets/javascripts/rectangles/engine/rooms/mover.js b/public/assets/javascripts/rectangles/engine/rooms/mover.js index 8ce00fe..69e821f 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/mover.js +++ b/public/assets/javascripts/rectangles/engine/rooms/mover.js @@ -4,6 +4,14 @@ Rooms.mover = new function(){ base.room = null base.noclip = false + var cursor = base.cursor = new Rect (0,0,0,0) + var wall_vec = new Rect (0,0,0,0) + var intersect = new vec2(0,0) + + var origins = new Rect() + origins.x = cursor.x + origins.y = wall_vec.x + base.init = function(){ base.bind() base.update(scene.camera) @@ -33,6 +41,14 @@ Rooms.mover = new function(){ return } + var intersect = base.intersect(pos) + + if (intersect && ! base.noclip) { + cam.x = intersect.a + cam.z = intersect.b + return + } +/* // check if we've breached one of the walls.. clamp position if so var collision = base.room.collidesDisc(cam, pos, radius) @@ -41,96 +57,13 @@ Rooms.mover = new function(){ cam.z = (collision & FRONT_BACK) ? base.room.rect.y.clampDisc(pos.z, radius) : pos.z return } - +*/ // in this case, we appear to have left the room.. // $(".face.active").removeClass("active") Walls.clearBodyColor() base.room = null } -/* - var dz = new vec2( cam.z, pos.z ) - dz.normalize() - - var dx = new vec2( cam.x, pos.x ) - dx.normalize() - - // first check if the cam-pos movement intersects the wall. - // next check if it intersects any of the surface frames - // if we can pass through the wall at this point, we do not need to clamp. - // otherwise, get the distance along the cam-pos vector where we would hit the wall and clamp to it. - Walls.list.forEach(function(wall){ - var t = -1 - switch (wall.side) { - case FRONT: - if (cam.z >= wall.edge + radius && wall.edge + radius >= pos.z && wall.vec.intersects(dx) ) { - t = check_intersection( front_back_intersection, cam, pos, dx, wall, radius ) - } - break - case BACK: - // console.log(cam.z|0, wall.edge-radius, pos.z|0, wall.vec.intersects(dx)) - if (cam.z <= wall.edge - radius && wall.edge - radius <= pos.z && wall.vec.intersects(dx) ) { - t = check_intersection( front_back_intersection, cam, pos, dx, wall, -radius ) - console.log(t) - } - break - case LEFT: - if (cam.x >= wall.edge + radius && wall.edge + radius >= pos.x && wall.vec.intersects(dz) ) { - t = check_intersection( left_right_intersection, cam, pos, dz, wall, radius ) - } - break - case RIGHT: - if (cam.x <= wall.edge - radius && wall.edge - radius <= pos.x && wall.vec.intersects(dz) ) { - t = check_intersection( left_right_intersection, cam, pos, dz, wall, -radius ) - } - break - } - if (0 <= t && t <= 1) { - pos.x = cam.x + (pos.x - cam.x) * t - pos.z = cam.z + (pos.z - cam.z) * t - - dz = new vec2( cam.z, pos.z ) - dz.normalize() - - dx = new vec2( cam.x, pos.x ) - dx.normalize() - } - }) - - function check_intersection(intersection_function, cam, pos, cam_pos_vector, wall, radius) { - var t = -1 - wall.surface.faces.some(function(face, i){ - if (face.y.a == 0 && face.x.intersects(cam_pos_vector)) { - t = intersection_function( cam, pos, wall, face, radius ) - console.log(">>", t) - if (0 <= t && t <= 1) { - return true - } - else { - t = -1 - } - } - return false - }) - return t - } - function left_right_intersection (cam, pos, wall, face, radius) { - var perp_n = (face.x.a - face.x.b) * (wall.edge - cam.z + radius) - var perp_d = (face.x.a - face.x.b) * (pos.z - cam.z) - if (perp_d == 0) return Infinity - return perp_n / perp_d - } - function front_back_intersection (cam, pos, wall, face, radius) { - // va.vx*vb.vy - va.vy*vb.vx - var perp_n = (face.x.b - face.x.a) * (wall.edge - cam.x + radius) - var perp_d = (face.x.b - face.x.a) * (pos.x - cam.x) - - console.log((pos.x - cam.x), wall.edge - cam.x, radius) - - if (perp_d == 0) return Infinity - return perp_n / perp_d - } -*/ // collision test failed, so update position cam.x = pos.x cam.z = pos.z @@ -148,7 +81,92 @@ Rooms.mover = new function(){ } app.tube("change-room", { room: base.room }) } - } + base.intersect = function(pos){ + var closest_intersect, t, min_t = 1 + + cursor.x.a = cam.x + cursor.x.b = cam.z + cursor.y.a = pos.x + cursor.y.b = pos.z + + var a = angle(cursor) + cursor.y.a += scene.camera.radius * cos(a) + cursor.y.b += scene.camera.radius * sin(a) + + Walls.list.forEach(function(wall, i){ + var actually_intersects, intersecting_face + + if (wall.side & LEFT_RIGHT) { + wall_vec.x.a = wall.edge + wall_vec.x.b = wall.vec.a + wall_vec.y.a = wall.edge + wall_vec.y.b = wall.vec.b + } + else { + wall_vec.x.a = wall.vec.a + wall_vec.x.b = wall.edge + wall_vec.y.a = wall.vec.b + wall_vec.y.b = wall.edge + } + t = perp(origins, wall_vec) / ( perp(cursor, wall_vec) || 0.0000001 ) + + if ( min_t < t || t < 0 || 1 < t ) return + + intersect.a = cursor.x.a + ( cursor.y.a - cursor.x.a ) * t + intersect.b = cursor.x.b + ( cursor.y.b - cursor.x.b ) * t + + if ( ! is_collinear( intersect, wall_vec ) ) return + + if (wall.side & LEFT_RIGHT) { + intersecting_face = wall.surface.face_for_x(intersect.b) + } + else { + intersecting_face = wall.surface.face_for_x(intersect.a) + } + + actually_intersects = !! (intersecting_face && intersecting_face.y.a == 0) + if (actually_intersects) { + closest_intersect = intersect.clone() + min_t = t + } + }) + + if (min_t < 1) { + var a = angle(cursor) + closest_intersect.a -= scene.camera.radius * cos(a) + closest_intersect.b -= scene.camera.radius * sin(a) + } + return closest_intersect + } + function angle (va) { + return atan2(va.y.b - va.x.b, va.y.a - va.x.a) + } + function dot (va, vb) { + return (va.y.a - va.x.a) * (vb.y.a - vb.x.a) + (va.y.b - va.x.b) * (vb.y.b - vb.x.b) + } + function perp (va, vb) { + return (va.y.a - va.x.a) * (vb.y.b - vb.x.b) - (va.y.b - va.x.b) * (vb.y.a - vb.x.a) + } + function is_collinear (p, vec) { + var on_x, on_y + var pa = round(p.a), pb = round(p.b) + + if (vec.x.a < vec.y.a) { + on_x = vec.x.a <= pa && pa <= vec.y.a + } + else { + on_x = vec.x.a >= pa && pa >= vec.y.a + } + + if (vec.x.b < vec.y.b) { + on_y = vec.x.b <= pb && pb <= vec.y.b + } + else { + on_y = vec.x.b >= pb && pb >= vec.y.b + } + + return !! (on_x && on_y) + } } diff --git a/public/assets/test/intersect3.html b/public/assets/test/intersect3.html index e897e8a..1e2a1a4 100644 --- a/public/assets/test/intersect3.html +++ b/public/assets/test/intersect3.html @@ -167,12 +167,12 @@ function draw () { } drawPoint(intersect) - if (actually_intersects && intersecting_face && t < min_t) { + if (actually_intersects && t < min_t) { min_t = t hud.innerHTML += t + "
" var clone = intersect.clone() clone.t = t - closest_face = intersecting_face + closest_intersect = intersecting_face closest_intersect = clone } }) @@ -185,12 +185,6 @@ function draw () { ctx.fillStyle = "#00f" drawPoint(closest_intersect) drawLine(cursor.x, closest_intersect, "#00f") - // closest_face.vec - - // get the closest intersect, i.e. the one with smallest t value - // get the angle of the cursor - // move the desired position to pos - 20px - } } function drawLine (pa, pb, color, headless) { -- cgit v1.2.3-70-g09d2 From 4aeefb7b2ba7065f98702eaebe317a19d764d22d Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Sat, 1 Nov 2014 00:48:39 -0400 Subject: pushing against wall correctly, projecting vector --- public/assets/test/intersect3.html | 99 +++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 27 deletions(-) (limited to 'public/assets/test/intersect3.html') diff --git a/public/assets/test/intersect3.html b/public/assets/test/intersect3.html index 1e2a1a4..b916f5f 100644 --- a/public/assets/test/intersect3.html +++ b/public/assets/test/intersect3.html @@ -67,7 +67,7 @@ Rooms.clipper.update() Rooms.builder.build() Rooms.grouper.build() -var r = 4 +var r = 6 var intersect = new vec2 () @@ -115,27 +115,39 @@ function draw () { drawLine(cursor.x, cursor.y, "#f00") hud.innerHTML = "" - var closest_face, closest_intersect, t, min_t = 1 - + var closest_intersect, cursor_copy = new Rect(0,0,0,0), t, min_t = 1 + var cursor_copy = cursor.plus(scene.camera.radius) + Walls.list.forEach(function(wall, i){ - if (wall.side & LEFT_RIGHT) { - wall_vec.x.a = wall.edge - wall_vec.x.b = wall.vec.a - wall_vec.y.a = wall.edge - wall_vec.y.b = wall.vec.b - } - else { + if (wall.side & LEFT) { + wall_vec.x.a = wall.edge + wall_vec.x.b = wall.vec.b + wall_vec.y.a = wall.edge + wall_vec.y.b = wall.vec.a + } + else if (wall.side & RIGHT) { + wall_vec.x.a = wall.edge + wall_vec.x.b = wall.vec.a + wall_vec.y.a = wall.edge + wall_vec.y.b = wall.vec.b + } + else if (wall.side & FRONT) { wall_vec.x.a = wall.vec.a wall_vec.x.b = wall.edge wall_vec.y.a = wall.vec.b wall_vec.y.b = wall.edge } - drawLine(wall_vec.x, wall_vec.y, "#888", true) - drawLine(origins.x, origins.y, "rgba(0,0,0,0.1)") + else if (wall.side & BACK) { + wall_vec.x.a = wall.vec.b + wall_vec.x.b = wall.edge + wall_vec.y.a = wall.vec.a + wall_vec.y.b = wall.edge + } + drawLine(wall_vec.x, wall_vec.y, "#088") - t = perp(origins, wall_vec) / ( perp(cursor, wall_vec) || 0.0000001 ) - intersect.a = cursor.x.a + ( cursor.y.a - cursor.x.a ) * t - intersect.b = cursor.x.b + ( cursor.y.b - cursor.x.b ) * t + t = perp(origins, wall_vec) / ( perp(cursor_copy, wall_vec) || 0.0000001 ) + intersect.a = cursor_copy.x.a + ( cursor_copy.y.a - cursor_copy.x.a ) * t + intersect.b = cursor_copy.x.b + ( cursor_copy.y.b - cursor_copy.x.b ) * t var collinear = is_collinear( intersect, wall_vec ) var long_enough_to_intersect = 0 <= t && t <= 1 @@ -169,22 +181,42 @@ function draw () { drawPoint(intersect) if (actually_intersects && t < min_t) { min_t = t - hud.innerHTML += t + "
" - var clone = intersect.clone() - clone.t = t - closest_intersect = intersecting_face - closest_intersect = clone + closest_intersect = intersect.clone() + closest_wall = wall_vec.clone() } }) - if (closest_face) { - var a = angle(cursor) - closest_intersect.a -= scene.camera.radius * cos(a) - closest_intersect.b -= scene.camera.radius * sin(a) + if (closest_intersect) { + var a = angle(closest_wall) + var ac = angle(cursor_copy) + wall_vec.assign(closest_wall) + wall_vec.x.a -= scene.camera.radius * sin(a) + wall_vec.x.b += scene.camera.radius * cos(a) + wall_vec.y.a -= scene.camera.radius * sin(a) + wall_vec.y.b += scene.camera.radius * cos(a) - ctx.fillStyle = "#00f" - drawPoint(closest_intersect) - drawLine(cursor.x, closest_intersect, "#00f") + drawLine(wall_vec.x, wall_vec.y, "rgba(0,255,255,1.0)") + + var new_t = perp(origins, wall_vec) / ( perp(cursor_copy, wall_vec) || 0.0000001 ) + var closest_intersect2 = new vec2() + closest_intersect2.a = cursor_copy.x.a + ( cursor_copy.y.a - cursor_copy.x.a ) * new_t + closest_intersect2.b = cursor_copy.x.b + ( cursor_copy.y.b - cursor_copy.x.b ) * new_t + + ctx.fillStyle = "#0ff" + drawPoint(closest_intersect2) + drawLine(cursor.x, closest_intersect2, "#00f") + + var len = (1-min_t) * sqrt(dot(cursor, cursor)) + if (max(a,ac)-min(a,ac) > PI/2) { + a += PI + } + var end_of_ray = closest_intersect2.clone() + + end_of_ray.a += len * cos(a) + end_of_ray.b += len * sin(a) + + drawPoint(end_of_ray) + drawLine(closest_intersect2, end_of_ray, "#00f") } } function drawLine (pa, pb, color, headless) { @@ -204,12 +236,18 @@ function drawPoint (p) { function angle (va) { return atan2(va.y.b - va.x.b, va.y.a - va.x.a) } +function angle2 (pa, pb) { + return atan2(pb.b - pa.b, pb.a - pa.a) +} function dot (va, vb) { return (va.y.a - va.x.a) * (vb.y.a - vb.x.a) + (va.y.b - va.x.b) * (vb.y.b - vb.x.b) } function perp (va, vb) { return (va.y.a - va.x.a) * (vb.y.b - vb.x.b) - (va.y.b - va.x.b) * (vb.y.a - vb.x.a) } +function norm(va) { + return c +} function is_collinear (p, vec) { var on_x, on_y var pa = round(p.a), pb = round(p.b) @@ -230,6 +268,13 @@ function is_collinear (p, vec) { return !! (on_x && on_y) } +cursor.plus = function(n){ + var a = angle(this) + var clone = this.clone() + clone.y.a += n*cos(a) + clone.y.b += n*sin(a) + return clone +} function animate(){ requestAnimationFrame(animate) -- cgit v1.2.3-70-g09d2 From 17ed9ecb646ea063b1484c484877e11c42ebabb6 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Sat, 1 Nov 2014 20:59:43 -0400 Subject: handle pushing against wall --- public/assets/test/intersect3.html | 60 +++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 17 deletions(-) (limited to 'public/assets/test/intersect3.html') diff --git a/public/assets/test/intersect3.html b/public/assets/test/intersect3.html index b916f5f..040dca4 100644 --- a/public/assets/test/intersect3.html +++ b/public/assets/test/intersect3.html @@ -35,7 +35,7 @@ var scene = new MX.Scene() var w = canvas.width = window.innerWidth var h = canvas.height = window.innerHeight -var cursor = new Rect( new vec2(564, 203), new vec2(734, 372) ) +var cursor = new Rect( new vec2(400, 200), new vec2(800, 500) ) var wall_vec = new Rect ( 0, 0, 0, 0 ) var points = [ cursor.x, cursor.y ] @@ -114,7 +114,7 @@ function draw () { points.forEach(drawPoint) drawLine(cursor.x, cursor.y, "#f00") - hud.innerHTML = "" +// hud.innerHTML = "" var closest_intersect, cursor_copy = new Rect(0,0,0,0), t, min_t = 1 var cursor_copy = cursor.plus(scene.camera.radius) @@ -188,7 +188,6 @@ function draw () { if (closest_intersect) { var a = angle(closest_wall) - var ac = angle(cursor_copy) wall_vec.assign(closest_wall) wall_vec.x.a -= scene.camera.radius * sin(a) wall_vec.x.b += scene.camera.radius * cos(a) @@ -197,27 +196,45 @@ function draw () { drawLine(wall_vec.x, wall_vec.y, "rgba(0,255,255,1.0)") - var new_t = perp(origins, wall_vec) / ( perp(cursor_copy, wall_vec) || 0.0000001 ) + var new_t = perp(origins, wall_vec) / ( perp(cursor, wall_vec) || 0.0000001 ) + var wall_t = perp(origins, cursor) / ( perp(wall_vec, cursor) || 0.0000001 ) var closest_intersect2 = new vec2() - closest_intersect2.a = cursor_copy.x.a + ( cursor_copy.y.a - cursor_copy.x.a ) * new_t - closest_intersect2.b = cursor_copy.x.b + ( cursor_copy.y.b - cursor_copy.x.b ) * new_t + closest_intersect2.a = cursor.x.a + ( cursor.y.a - cursor.x.a ) * new_t + closest_intersect2.b = cursor.x.b + ( cursor.y.b - cursor.x.b ) * new_t ctx.fillStyle = "#0ff" drawPoint(closest_intersect2) drawLine(cursor.x, closest_intersect2, "#00f") - var len = (1-min_t) * sqrt(dot(cursor, cursor)) - if (max(a,ac)-min(a,ac) > PI/2) { - a += PI - } - var end_of_ray = closest_intersect2.clone() + var len = sqrt(dot(wall_vec, wall_vec)) - end_of_ray.a += len * cos(a) - end_of_ray.b += len * sin(a) + // here compare len to the length of the wall in the direction we are travelling + var aw = angle(closest_wall) + var dd = dot2(diff(closest_wall), diff(cursor)) + if (dd > 0) { + len *= 1-abs(wall_t) + } + else { + len *= abs(wall_t) + aw += PI + } + + len = clamp(len, 0, (1-min_t) * sqrt(dot(cursor, cursor))) + + hud.innerHTML = [ aw ].map(function(n){ return round(deg(n)) }) + hud.innerHTML = " " + (dd > 0 ? "gt": "lt") + " " + round(len) + " " + (1-min_t) + " " + round((1-min_t)*sqrt(dot2(diff(cursor), diff(cursor)))) + + var end_of_ray = closest_intersect2.clone() + end_of_ray.a += len * cos(aw) + end_of_ray.b += len * sin(aw) drawPoint(end_of_ray) drawLine(closest_intersect2, end_of_ray, "#00f") } + else { + hud.innerHTML = [ (angle(cursor) + TWO_PI) % TWO_PI ].map(function(n){ return round(deg(n)) }) + } + } function drawLine (pa, pb, color, headless) { ctx.fillStyle = color @@ -228,7 +245,10 @@ function drawLine (pa, pb, color, headless) { var y2 = pb.b drawArrow(ctx, x1, y1, x2, y2, 3, headless ? 0 : 1) } -function drawPoint (p) { +function drawPoint (p, color) { + if (color) { + ctx.fillStyle = color + } var x = p.a - r var y = p.b - r ctx.fillRect(x, y, r*2, r*2) @@ -239,15 +259,21 @@ function angle (va) { function angle2 (pa, pb) { return atan2(pb.b - pa.b, pb.a - pa.a) } +function normal (va) { + return atan2(va.x.a - va.y.a, va.y.b - va.x.b) +} function dot (va, vb) { return (va.y.a - va.x.a) * (vb.y.a - vb.x.a) + (va.y.b - va.x.b) * (vb.y.b - vb.x.b) } +function diff (v) { + return new vec2(v.y.a - v.x.a, v.y.b - v.x.b) +} +function dot2 (pa, pb) { + return pa.a * pb.a + pa.b * pb.b +} function perp (va, vb) { return (va.y.a - va.x.a) * (vb.y.b - vb.x.b) - (va.y.b - va.x.b) * (vb.y.a - vb.x.a) } -function norm(va) { - return c -} function is_collinear (p, vec) { var on_x, on_y var pa = round(p.a), pb = round(p.b) -- cgit v1.2.3-70-g09d2 From b5c6adb5fbc7225e7b655f02123d7f0995ae3b46 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Mon, 3 Nov 2014 01:20:37 -0500 Subject: extend vec in both directions --- .../assets/javascripts/rectangles/models/wall.js | 28 ++++++++++++ public/assets/test/intersect3.html | 53 ++++++++-------------- 2 files changed, 48 insertions(+), 33 deletions(-) (limited to 'public/assets/test/intersect3.html') diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 8590de7..a026c3c 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -25,6 +25,34 @@ Wall.prototype.toString = function(){ return this.vec.toString() } + Wall.prototype.get_points = function(wall_vec){ + wall_vec = wall_vec || new Rect () + if (this.side & LEFT) { + wall_vec.x.a = this.edge + wall_vec.x.b = this.vec.b + wall_vec.y.a = this.edge + wall_vec.y.b = this.vec.a + } + else if (this.side & RIGHT) { + wall_vec.x.a = this.edge + wall_vec.x.b = this.vec.a + wall_vec.y.a = this.edge + wall_vec.y.b = this.vec.b + } + else if (this.side & FRONT) { + wall_vec.x.a = this.vec.a + wall_vec.x.b = this.edge + wall_vec.y.a = this.vec.b + wall_vec.y.b = this.edge + } + else if (this.side & BACK) { + wall_vec.x.a = this.vec.b + wall_vec.x.b = this.edge + wall_vec.y.a = this.vec.a + wall_vec.y.b = this.edge + } + return wall_vec + } Wall.prototype.reset = function(){ } diff --git a/public/assets/test/intersect3.html b/public/assets/test/intersect3.html index 040dca4..13a8024 100644 --- a/public/assets/test/intersect3.html +++ b/public/assets/test/intersect3.html @@ -101,7 +101,7 @@ var mymouse = new mouse({ }, }) -function draw () { +function draw (time) { ctx.fillStyle = "#fff" ctx.fillRect(0,0,w,h) @@ -115,36 +115,16 @@ function draw () { drawLine(cursor.x, cursor.y, "#f00") // hud.innerHTML = "" - var closest_intersect, cursor_copy = new Rect(0,0,0,0), t, min_t = 1 - var cursor_copy = cursor.plus(scene.camera.radius) + var closest_intersect, t, min_t = 1 + var cursor_copy = cursor.extend_ends(scene.camera.radius) +hud.innerHTML = cursor_copy.x +drawPoint(cursor_copy.x, "#ff0") Walls.list.forEach(function(wall, i){ - if (wall.side & LEFT) { - wall_vec.x.a = wall.edge - wall_vec.x.b = wall.vec.b - wall_vec.y.a = wall.edge - wall_vec.y.b = wall.vec.a - } - else if (wall.side & RIGHT) { - wall_vec.x.a = wall.edge - wall_vec.x.b = wall.vec.a - wall_vec.y.a = wall.edge - wall_vec.y.b = wall.vec.b - } - else if (wall.side & FRONT) { - wall_vec.x.a = wall.vec.a - wall_vec.x.b = wall.edge - wall_vec.y.a = wall.vec.b - wall_vec.y.b = wall.edge - } - else if (wall.side & BACK) { - wall_vec.x.a = wall.vec.b - wall_vec.x.b = wall.edge - wall_vec.y.a = wall.vec.a - wall_vec.y.b = wall.edge - } + wall.get_points(wall_vec) drawLine(wall_vec.x, wall_vec.y, "#088") + origins.x = cursor_copy.x t = perp(origins, wall_vec) / ( perp(cursor_copy, wall_vec) || 0.0000001 ) intersect.a = cursor_copy.x.a + ( cursor_copy.y.a - cursor_copy.x.a ) * t intersect.b = cursor_copy.x.b + ( cursor_copy.y.b - cursor_copy.x.b ) * t @@ -196,6 +176,7 @@ function draw () { drawLine(wall_vec.x, wall_vec.y, "rgba(0,255,255,1.0)") + origins.x = cursor.x var new_t = perp(origins, wall_vec) / ( perp(cursor, wall_vec) || 0.0000001 ) var wall_t = perp(origins, cursor) / ( perp(wall_vec, cursor) || 0.0000001 ) var closest_intersect2 = new vec2() @@ -222,17 +203,21 @@ function draw () { len = clamp(len, 0, (1-min_t) * sqrt(dot(cursor, cursor))) - hud.innerHTML = [ aw ].map(function(n){ return round(deg(n)) }) - hud.innerHTML = " " + (dd > 0 ? "gt": "lt") + " " + round(len) + " " + (1-min_t) + " " + round((1-min_t)*sqrt(dot2(diff(cursor), diff(cursor)))) +// hud.innerHTML = [ aw ].map(function(n){ return round(deg(n)) }) +// hud.innerHTML = " " + (dd > 0 ? "gt": "lt") + " " + round(len) + " " + (1-min_t) + " " + round((1-min_t)*sqrt(dot2(diff(cursor), diff(cursor)))) var end_of_ray = closest_intersect2.clone() end_of_ray.a += len * cos(aw) end_of_ray.b += len * sin(aw) + + end_of_ray.a = clamp(end_of_ray.a, wall_vec.x.a, wall_vec.y.a) + end_of_ray.b = clamp(end_of_ray.b, wall_vec.x.b, wall_vec.y.b) + drawPoint(end_of_ray) drawLine(closest_intersect2, end_of_ray, "#00f") } else { - hud.innerHTML = [ (angle(cursor) + TWO_PI) % TWO_PI ].map(function(n){ return round(deg(n)) }) +// hud.innerHTML = [ (angle(cursor) + TWO_PI) % TWO_PI ].map(function(n){ return round(deg(n)) }) } } @@ -294,17 +279,19 @@ function is_collinear (p, vec) { return !! (on_x && on_y) } -cursor.plus = function(n){ +cursor.extend_ends = function(n){ var a = angle(this) var clone = this.clone() + clone.x.a -= n*cos(a) + clone.x.b -= n*sin(a) clone.y.a += n*cos(a) clone.y.b += n*sin(a) return clone } -function animate(){ +function animate(time){ requestAnimationFrame(animate) - draw() + draw(time) } animate() -- cgit v1.2.3-70-g09d2 From 4cd1bf2ab9944c1f0782e95b51b0da132909a189 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 3 Nov 2014 12:18:12 -0500 Subject: intersect doesnt need clamping --- public/assets/test/intersect3.html | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'public/assets/test/intersect3.html') diff --git a/public/assets/test/intersect3.html b/public/assets/test/intersect3.html index 13a8024..ed81346 100644 --- a/public/assets/test/intersect3.html +++ b/public/assets/test/intersect3.html @@ -118,13 +118,16 @@ function draw (time) { var closest_intersect, t, min_t = 1 var cursor_copy = cursor.extend_ends(scene.camera.radius) -hud.innerHTML = cursor_copy.x -drawPoint(cursor_copy.x, "#ff0") + hud.innerHTML = cursor_copy.x + drawPoint(cursor_copy.x, "#ff0") + Walls.list.forEach(function(wall, i){ wall.get_points(wall_vec) drawLine(wall_vec.x, wall_vec.y, "#088") origins.x = cursor_copy.x + origins.y = wall_vec.x + t = perp(origins, wall_vec) / ( perp(cursor_copy, wall_vec) || 0.0000001 ) intersect.a = cursor_copy.x.a + ( cursor_copy.y.a - cursor_copy.x.a ) * t intersect.b = cursor_copy.x.b + ( cursor_copy.y.b - cursor_copy.x.b ) * t @@ -177,9 +180,12 @@ drawPoint(cursor_copy.x, "#ff0") drawLine(wall_vec.x, wall_vec.y, "rgba(0,255,255,1.0)") origins.x = cursor.x + origins.y = wall_vec.x + var new_t = perp(origins, wall_vec) / ( perp(cursor, wall_vec) || 0.0000001 ) var wall_t = perp(origins, cursor) / ( perp(wall_vec, cursor) || 0.0000001 ) - var closest_intersect2 = new vec2() + + var closest_intersect2 = new vec2 () closest_intersect2.a = cursor.x.a + ( cursor.y.a - cursor.x.a ) * new_t closest_intersect2.b = cursor.x.b + ( cursor.y.b - cursor.x.b ) * new_t @@ -193,6 +199,7 @@ drawPoint(cursor_copy.x, "#ff0") var aw = angle(closest_wall) var dd = dot2(diff(closest_wall), diff(cursor)) +// hud.innerHTML += " " + dd + " " + round(deg(aw)) if (dd > 0) { len *= 1-abs(wall_t) } @@ -204,14 +211,14 @@ drawPoint(cursor_copy.x, "#ff0") len = clamp(len, 0, (1-min_t) * sqrt(dot(cursor, cursor))) // hud.innerHTML = [ aw ].map(function(n){ return round(deg(n)) }) -// hud.innerHTML = " " + (dd > 0 ? "gt": "lt") + " " + round(len) + " " + (1-min_t) + " " + round((1-min_t)*sqrt(dot2(diff(cursor), diff(cursor)))) +// hud.innerHTML += "__ " + (dd > 0 ? "gt": "lt") + " " + round(len) + " " + (1-min_t) + " " + round((1-min_t)*sqrt(dot2(diff(cursor), diff(cursor)))) var end_of_ray = closest_intersect2.clone() end_of_ray.a += len * cos(aw) end_of_ray.b += len * sin(aw) - end_of_ray.a = clamp(end_of_ray.a, wall_vec.x.a, wall_vec.y.a) - end_of_ray.b = clamp(end_of_ray.b, wall_vec.x.b, wall_vec.y.b) +// end_of_ray.a = clamp(end_of_ray.a, wall_vec.x.a, wall_vec.y.a) +// end_of_ray.b = clamp(end_of_ray.b, wall_vec.x.b, wall_vec.y.b) drawPoint(end_of_ray) drawLine(closest_intersect2, end_of_ray, "#00f") -- cgit v1.2.3-70-g09d2 From 6b9cf0e41c4e0c09a715e59c162380b5fad42cba Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 3 Nov 2014 12:44:23 -0500 Subject: different collision algo for mobile movement --- .../javascripts/rectangles/engine/rooms/mover.js | 179 +++++++++++++++------ public/assets/test/intersect3.html | 19 ++- 2 files changed, 147 insertions(+), 51 deletions(-) (limited to 'public/assets/test/intersect3.html') diff --git a/public/assets/javascripts/rectangles/engine/rooms/mover.js b/public/assets/javascripts/rectangles/engine/rooms/mover.js index 69e821f..5682be8 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/mover.js +++ b/public/assets/javascripts/rectangles/engine/rooms/mover.js @@ -5,6 +5,7 @@ Rooms.mover = new function(){ base.noclip = false var cursor = base.cursor = new Rect (0,0,0,0) + var cursor_copy = new Rect (0,0,0,0) var wall_vec = new Rect (0,0,0,0) var intersect = new vec2(0,0) @@ -28,6 +29,7 @@ Rooms.mover = new function(){ } base.update = function(pos){ + var intersect, collision, distance var radius = scene.camera.radius cam.y = pos.y @@ -41,23 +43,38 @@ Rooms.mover = new function(){ return } - var intersect = base.intersect(pos) + distance = sqrt(pow(cam.x-pos.x, 2), pow(cam.z-pos.z, 2)) + + // check if we've breached one of the walls.. clamp position if so. + // there are two algorithms for this now, ridiculously.. + // - the first one is smoother, best for keyboard use + // but if the distance travelled is greater than the min. distance from the wall, + // then there is a possibility of ejection from the room. so is bad for phone/mousewheel. - if (intersect && ! base.noclip) { - cam.x = intersect.a - cam.z = intersect.b - return + // - the second one determines fortuitously if we have breached any of the walls + // however it can get jumpy if you run into a wall.. thus it is best for devices like phone or mousewheel + // the benefit is you will never leave the room. + if (base.noclip) { + // in no-clip mode we walk through walls. } -/* - // check if we've breached one of the walls.. clamp position if so - var collision = base.room.collidesDisc(cam, pos, radius) + else if (distance < radius) { + collision = base.room.collidesDisc(cam, pos, radius) + + if (collision) { + cam.x = (collision & LEFT_RIGHT) ? base.room.rect.x.clampDisc(pos.x, radius) : pos.x + cam.z = (collision & FRONT_BACK) ? base.room.rect.y.clampDisc(pos.z, radius) : pos.z + return + } + } + else { + intersect = base.intersect(pos) + if (intersect) { + cam.x = intersect.a + cam.z = intersect.b + return + } + } - if (collision && ! base.noclip) { - cam.x = (collision & LEFT_RIGHT) ? base.room.rect.x.clampDisc(pos.x, radius) : pos.x - cam.z = (collision & FRONT_BACK) ? base.room.rect.y.clampDisc(pos.z, radius) : pos.z - return - } -*/ // in this case, we appear to have left the room.. // $(".face.active").removeClass("active") Walls.clearBodyColor() @@ -83,39 +100,30 @@ Rooms.mover = new function(){ } } base.intersect = function(pos){ - var closest_intersect, t, min_t = 1 - - cursor.x.a = cam.x - cursor.x.b = cam.z - cursor.y.a = pos.x - cursor.y.b = pos.z + var closest_intersect, closest_wall, new_t, wall_t, t, min_t = 1 - var a = angle(cursor) - cursor.y.a += scene.camera.radius * cos(a) - cursor.y.b += scene.camera.radius * sin(a) + cursor_copy.x.a = cursor.x.a = cam.x + cursor_copy.x.b = cursor.x.b = cam.z + cursor_copy.y.a = cursor.y.a = pos.x + cursor_copy.y.b = cursor.y.b = pos.z + + cursor_copy.extend_ends(scene.camera.radius) + + origins.x = cursor_copy.x + origins.y = wall_vec.x Walls.list.forEach(function(wall, i){ - var actually_intersects, intersecting_face + var actually_intersects = false, intersecting_face + + wall.get_points(wall_vec) - if (wall.side & LEFT_RIGHT) { - wall_vec.x.a = wall.edge - wall_vec.x.b = wall.vec.a - wall_vec.y.a = wall.edge - wall_vec.y.b = wall.vec.b - } - else { - wall_vec.x.a = wall.vec.a - wall_vec.x.b = wall.edge - wall_vec.y.a = wall.vec.b - wall_vec.y.b = wall.edge - } - t = perp(origins, wall_vec) / ( perp(cursor, wall_vec) || 0.0000001 ) + t = perp(origins, wall_vec) / ( perp(cursor_copy, wall_vec) || 0.0000001 ) if ( min_t < t || t < 0 || 1 < t ) return - intersect.a = cursor.x.a + ( cursor.y.a - cursor.x.a ) * t - intersect.b = cursor.x.b + ( cursor.y.b - cursor.x.b ) * t + intersect.a = cursor_copy.x.a + ( cursor_copy.y.a - cursor_copy.x.a ) * t + intersect.b = cursor_copy.x.b + ( cursor_copy.y.b - cursor_copy.x.b ) * t if ( ! is_collinear( intersect, wall_vec ) ) return @@ -128,24 +136,76 @@ Rooms.mover = new function(){ actually_intersects = !! (intersecting_face && intersecting_face.y.a == 0) if (actually_intersects) { - closest_intersect = intersect.clone() + closest_intersect = intersect.clone() + closest_wall = wall_vec.clone() min_t = t } }) - if (min_t < 1) { - var a = angle(cursor) - closest_intersect.a -= scene.camera.radius * cos(a) - closest_intersect.b -= scene.camera.radius * sin(a) + if (closest_intersect) { + + var aw, len, dd + aw = angle(closest_wall) + wall_vec.assign(closest_wall) + wall_vec.x.a -= scene.camera.radius * sin(aw) + wall_vec.x.b += scene.camera.radius * cos(aw) + wall_vec.y.a -= scene.camera.radius * sin(aw) + wall_vec.y.b += scene.camera.radius * cos(aw) + + origins.x = cursor.x + origins.y = wall_vec.x + + new_t = perp(origins, wall_vec) / ( perp(cursor, wall_vec) || 0.0000001 ) + wall_t = perp(origins, cursor) / ( perp(wall_vec, cursor) || 0.0000001 ) + + intersect.a = cursor.x.a + ( cursor.y.a - cursor.x.a ) * new_t + intersect.b = cursor.x.b + ( cursor.y.b - cursor.x.b ) * new_t + + // here compare len to the length of the wall in the direction we are travelling + dd = dot2(diff(closest_wall), diff(cursor)) + len = sqrt(dot(wall_vec, wall_vec)) + + if (dd > 0) { + len *= 1-abs(wall_t) + } + else { + len *= abs(wall_t) + aw += PI + } + + len = clamp(len, 0, (1-min_t) * sqrt(dot(cursor, cursor))) + + intersect.a += len * cos(aw) + intersect.b += len * sin(aw) + + wall_vec.normalize() + intersect.a = clamp(intersect.a, wall_vec.x.a, wall_vec.y.a) + intersect.b = clamp(intersect.b, wall_vec.x.b, wall_vec.y.b) + + return intersect + } + else { + return cursor.y } - return closest_intersect } + function diff (v) { + return new vec2(v.y.a - v.x.a, v.y.b - v.x.b) + } function angle (va) { return atan2(va.y.b - va.x.b, va.y.a - va.x.a) } - function dot (va, vb) { - return (va.y.a - va.x.a) * (vb.y.a - vb.x.a) + (va.y.b - va.x.b) * (vb.y.b - vb.x.b) - } + function angle2 (pa, pb) { + return atan2(pb.b - pa.b, pb.a - pa.a) + } + function normal (va) { + return atan2(va.x.a - va.y.a, va.y.b - va.x.b) + } + function dot (va, vb) { + return (va.y.a - va.x.a) * (vb.y.a - vb.x.a) + (va.y.b - va.x.b) * (vb.y.b - vb.x.b) + } + function dot2 (pa, pb) { + return pa.a * pb.a + pa.b * pb.b + } function perp (va, vb) { return (va.y.a - va.x.a) * (vb.y.b - vb.x.b) - (va.y.b - va.x.b) * (vb.y.a - vb.x.a) } @@ -169,4 +229,27 @@ Rooms.mover = new function(){ return !! (on_x && on_y) } + cursor_copy.extend_ends = function(n){ + var a = angle(this) + this.x.a -= n*cos(a) + this.x.b -= n*sin(a) + this.y.a += n*cos(a) + this.y.b += n*sin(a) + return this + } + wall_vec.normalize = function(){ + var carry + if (this.x.a > this.y.a) { + console.log("SWAP X") + carry = this.x.a + this.x.a = this.y.a + this.y.a = carry + } + if (this.x.b > this.y.b) { + console.log("SWAP Y") + carry = this.x.b + this.x.b = this.y.b + this.y.b = carry + } + } } diff --git a/public/assets/test/intersect3.html b/public/assets/test/intersect3.html index ed81346..5440a76 100644 --- a/public/assets/test/intersect3.html +++ b/public/assets/test/intersect3.html @@ -217,8 +217,9 @@ function draw (time) { end_of_ray.a += len * cos(aw) end_of_ray.b += len * sin(aw) -// end_of_ray.a = clamp(end_of_ray.a, wall_vec.x.a, wall_vec.y.a) -// end_of_ray.b = clamp(end_of_ray.b, wall_vec.x.b, wall_vec.y.b) + wall_vec.normalize() + end_of_ray.a = clamp(end_of_ray.a, wall_vec.x.a, wall_vec.y.a) + end_of_ray.b = clamp(end_of_ray.b, wall_vec.x.b, wall_vec.y.b) drawPoint(end_of_ray) drawLine(closest_intersect2, end_of_ray, "#00f") @@ -295,7 +296,19 @@ cursor.extend_ends = function(n){ clone.y.b += n*sin(a) return clone } - +wall_vec.normalize = function(){ + var carry + if (this.x.a > this.y.a) { + carry = this.x.a + this.x.a = this.y.a + this.y.a = carry + } + if (this.x.b > this.y.b) { + carry = this.x.b + this.x.b = this.y.b + this.y.b = carry + } +} function animate(time){ requestAnimationFrame(animate) draw(time) -- cgit v1.2.3-70-g09d2