var builder = new function(){ var base = this var els = [] base.init = function(){ base.bind() } base.bind = function(){ app.on("clip", rebuild) } function rebuild(){ if (window.scene) { clear() build() bind() } } function build (){ clipper.rooms = sort_rooms_by_id(clipper.rooms) clipper.regions.forEach(function(r){ build_walls(r).forEach(function(el){ els.push(el) scene.add(el) }) }) clipper.rooms = sort_rooms_by_height(clipper.rooms) clipper.rooms.forEach(function(r){ build_floors(r).forEach(function(el){ els.push(el) scene.add(el) }) }) } function bind (){ clipper.rooms.forEach(function(r){ r.bind() }) } function clear (){ els.forEach(function(el){ scene.remove(el) }) els = [] } function build_walls (r){ var rm = clipper.rooms[ r.id ] var list = [], el = null var width = r.x.length() var depth = r.y.length() var height = clipper.rooms[r.id].height if (r.sides & FRONT) { el = make_wall('.front') el.width = width el.height = height el.rotationY = PI el.x = r.x.a + width/2 el.y = height/2 el.z = r.y.a rm.$walls.push(el.el) list.push(el) } if (r.sides & BACK) { var el = make_wall('.back') el.width = width el.height = height el.rotationY = 0 el.x = r.x.b - width/2 el.y = height/2 el.z = r.y.b rm.$walls.push(el.el) list.push(el) } if (r.sides & LEFT) { el = make_wall('.left') el.rotationY = HALF_PI el.height = height el.width = depth el.x = r.x.a el.y = height/2 el.z = r.y.a + depth/2 rm.$walls.push(el.el) list.push(el) } if (r.sides & RIGHT) { el = make_wall('.right') el.rotationY = -HALF_PI el.height = height el.width = depth el.x = r.x.b el.y = height/2 el.z = r.y.b - depth/2 rm.$walls.push(el.el) list.push(el) } return list } function build_floors(rm){ var list = [], el = null var already_constructed = rm.intersects.filter(function(rr){ return rr.constructed }) sort_rooms_by_height(already_constructed) if (already_constructed.length > 0) { // render the regions that don't intersect with anything we've already rendered // if the height is different, calculate the overlapping sides and render half-walls rm.regions.forEach(function(r){ var intersected = false for (var i = 0; i < already_constructed.length; i++) { if (already_constructed[i].rect.contains(r)) { intersected = true // r.sides = 0xf // half_sides } else if (already_constructed[i].rect.intersects(r)) { intersected = true if (rm.height < already_constructed[i].height) { list = list.concat( make_ceiling_walls( rm, already_constructed[i], r ) ) } } } if (! intersected) { el = make_floor(rm, r) list.push( el ) rm.$floor.push(el.el) el = make_ceiling(rm, r) list.push( el ) rm.$ceiling.push(el.el) } }) } else { // render floor and ceiling for the entire rectangle el = make_floor(rm, rm.rect) list.push( el ) rm.$floor.push(el.el) el = make_ceiling(rm, rm.rect) list.push( el ) rm.$ceiling.push(el.el) } rm.constructed = true return list } function make_ceiling_walls( lo, hi, r ){ var list = [] var width = r.x.length() var depth = r.y.length() var height = hi.height - lo.height if (! (r.half_sides & LEFT) && r.x.a == hi.rect.x.a) { el = make_wall('.left') el.rotationY = HALF_PI el.height = height el.width = depth el.x = r.x.a el.y = lo.height + height/2 el.z = r.y.a + depth/2 list.push(el) hi.$walls.push(el.el) r.half_sides |= LEFT } if (! (r.half_sides & RIGHT) && r.x.b == hi.rect.x.b) { el = make_wall('.right') el.rotationY = -HALF_PI el.height = height el.width = depth el.x = r.x.b el.y = lo.height + height/2 el.z = r.y.b - depth/2 list.push(el) hi.$walls.push(el.el) r.half_sides |= RIGHT } if (! (r.half_sides & FRONT) && r.y.a == hi.rect.y.a) { el = make_wall('.front') el.width = width el.height = height el.rotationY = PI el.x = r.x.a + width/2 el.y = lo.height + height/2 el.z = r.y.a list.push(el) hi.$walls.push(el.el) r.half_sides |= FRONT } if (! (r.half_sides & BACK) && r.y.b == hi.rect.y.b) { el = make_wall('.back') el.width = width el.height = height el.rotationY = 0 el.x = r.x.b - width/2 el.y = lo.height + height/2 el.z = r.y.b list.push(el) hi.$walls.push(el.el) r.half_sides |= BACK } return list } function make_floor(rm, r){ var width = r.x.length() var depth = r.y.length() var el = make_wall('.floor') el.height = depth el.width = width el.x = r.x.a + width/2 el.y = 0 el.z = r.y.a + depth/2 el.rotationX = PI/2 return el } function make_ceiling(rm, r){ var width = r.x.length() var depth = r.y.length() var height = rm.height var el = make_wall('.ceiling') el.height = depth el.width = width el.x = r.x.a + width/2 el.y = height el.z = r.y.a + depth/2 el.rotationX = -PI/2 return el } function make_wall(klass){ var el = new MX.Object3D(".face" + (klass || "")) el.width = el.height = el.scaleX = el.scaleY = el.scaleZ = 1 el.z = el.y = el.x = 0 el.type = "Face" el.el.style.opacity = 1.0 return el } }