Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 13 additions & 15 deletions hidden.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,22 +264,19 @@ function intercept_lines(p0,p1,p2,p3)
// returns a list of segments that are visible
// TODO: best if triangles is sorted by z depth
// TODO: figure out a better representation for the screen map
function hidden_wire(s, screen_map, work_queue)
function hidden_wire(s, interval, work_queue)
{
let segments = [];

let min_key_x = Math.trunc(Math.min(s.p0.x, s.p1.x) / stl_key2d_scale);
let min_key_y = Math.trunc(Math.min(s.p0.y, s.p1.y) / stl_key2d_scale);
let max_key_x = Math.trunc(Math.max(s.p0.x, s.p1.x) / stl_key2d_scale);
let max_key_y = Math.trunc(Math.max(s.p0.y, s.p1.y) / stl_key2d_scale);
if (!p_max) p_max = createVector();
if (!p_min) p_min = createVector();

for(let x = min_key_x ; x <= max_key_x ; x++)
{
for(let y = min_key_y ; y <= max_key_y ; y++)
{
let triangles = screen_map[x + "," + y];
if (!triangles)
continue;
v3max(p_max, s.p0, s.p1);
v3min(p_min, s.p0, s.p1);

let triangles = interval.query(p_min.x,p_min.y,p_max.x,p_max.y);
//console.log("occlude ", triangles.length);
//triangles.sort((a,b) => a.min.z - b.min.z);

for(let t of triangles)
{
Expand All @@ -300,7 +297,10 @@ function hidden_wire(s, screen_map, work_queue)
// this triangle, which means that no other
// triangles on the sorted list can occlude
// the segment, so we're done.
break;
//break;

// but the interval tree isn't sorted (yet)
continue;
}

if (rc == tri_clipped
Expand All @@ -317,8 +317,6 @@ function hidden_wire(s, screen_map, work_queue)
// huh?
console.log("occlude() returned? ", rc)
}
}
}

// if we have made it all the way here, the remaining part
// of this segment is visible and should be added to the draw list
Expand Down
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<script src="p5/p5.min.js"></script>
<script src="p5/addons/p5.dom.min.js"></script>
<script src="p5/addons/p5.sound.min.js"></script>
<script src="interval.js"></script>
<script src="stl.js"></script>
<script src="camera.js"></script>
<script src="triangle.js"></script>
Expand Down
92 changes: 92 additions & 0 deletions interval.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* 2D interval tree for sorting triangles.
*/

function Interval(x,y,scale)
{
this.x = x;
this.y = y;
this.scale = scale;

console.log("Interval("+x+","+y+","+scale+")");

this.quads = [
null,
null,
null,
null,
];

this.span = [];

this.quad_mask = function (min_x,min_y,max_x,max_y)
{
let q0 = (this.x < max_x && this.y < max_y) ? 0x01: 0x00;
let q1 = (min_x < this.x && this.y < max_y) ? 0x02: 0x00;
let q2 = (min_x < this.x && min_y < this.y) ? 0x04: 0x00;
let q3 = (this.x < max_x && min_y < this.y) ? 0x08: 0x00;
let span = ((min_x < this.x && this.x < max_x)
|| (min_y < this.y && this.y < max_y)) ? 0x10 : 0x00;;

return span | q0 | q1 | q2 | q3;
};

this.insert = function (t,min_x,min_y,max_x,max_y) {
if (min_x > max_x || min_y > max_y)
console.log(t);

if (this.scale > 8)
{
let quads = this.quad_mask(min_x,min_y,max_x,max_y);
//console.log(t, quads);

for (let quad = 0 ; quad < 4 ; quad++)
{
if (quads != (1 << quad))
continue;
return this.quad(quad).insert(t,min_x,min_y,max_x,max_y);
}
}

// multiple quadrants, put this in the span list
this.span.push(t);
return this;
};

this.quad = function (q) {
if (this.quads[q])
return this.quads[q];

let ns = this.scale / 2;
let nx = this.x + (q == 0 || q == 3 ? ns : -ns);
let ny = this.y + (q == 0 || q == 1 ? ns : -ns);
this.quads[q] = new Interval(nx,ny,ns);
return this.quads[q];
};

this.query = function(min_x,min_y,max_x,max_y) {
if (min_x > max_x || min_y > max_y)
console.log("error:", min_x,min_y,max_x,max_y);

let quads = this.quad_mask(min_x,min_y,max_x,max_y);
let quad_list = [];

for (let quad = 0 ; quad < 4 ; quad++)
{
if ((quads & (1 << quad)) == 0)
continue;
if (!this.quads[quad])
continue;

let new_list = this.quads[quad].query(min_x,min_y,max_x,max_y);
quad_list = quad_list.concat(new_list);
}

// multiple quadrants? put this in the span list
//if ((quads & 0x10) != 0)
quad_list = quad_list.concat(this.span);

//console.log("query:", this.x, this.y, min_x,min_y,max_x,max_y, quads, quad_list);
return quad_list;
};
};
2 changes: 1 addition & 1 deletion sketch.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,6 @@ function draw()
pop();

// they are dragging; do not try to do any additional work
if (!mouseIsPressed && !vx && !vy)
if (!mouseIsPressed)
redraw = stl.do_work(camera, 200);
}
27 changes: 25 additions & 2 deletions stl.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,19 @@ function STL(rawbytes_arraybuffer)
this.visible_segments = [];
this.segments = [];
this.coplanar = [];
this.interval = null;

// project the triangles into the screen mapping
console.log("projecting triangles");
for(let t of this.triangles)
this.project_triangle(t, camera);

/*
// sort the screen mapped triangles by Z
console.log("sorting triangles");
for(let key in this.screen_map)
this.screen_map[key].sort((a,b) => a.min.z - b.min.z);
*/
}

this.project_triangle = function(t,camera)
Expand Down Expand Up @@ -142,7 +145,7 @@ function STL(rawbytes_arraybuffer)
this.segments.push({ p0: t2, p1: t0 });
}


/*
// build the screen map for all of the sectors
// that might contain this triangle's projection
let min_key_x = Math.trunc(t.min.x/stl_key2d_scale);
Expand All @@ -161,6 +164,7 @@ function STL(rawbytes_arraybuffer)
this.screen_map[key] = [t];
}
}
*/
}


Expand All @@ -186,6 +190,7 @@ function STL(rawbytes_arraybuffer)
}

this.project(camera);

return true;
}

Expand All @@ -194,6 +199,24 @@ function STL(rawbytes_arraybuffer)
// only processes some of the segments per call.
this.do_hidden = function(camera,ms)
{
if (!this.interval)
{
// ofload the interval work until we are
// starting to compute hidden lines
this.interval = new Interval(0,0,width/2);

// insert the triangle into the interval tree for
// faster queries of segment intersections
for(t of this.triangles)
{
if (t.invisible)
continue;
this.interval.insert(t, t.min.x, t.min.y, t.max.x, t.max.y);
}

return true;
}

let num_segments = this.segments.length;
if (num_segments == 0)
return false;
Expand All @@ -207,7 +230,7 @@ function STL(rawbytes_arraybuffer)
while(this.segments.length != 0)
{
let s = this.segments.shift();
let visible_segment = hidden_wire(s, this.screen_map, this.segments);
let visible_segment = hidden_wire(s, this.interval, this.segments);
if (visible_segment)
this.visible_segments.push(visible_segment);
count++;
Expand Down
18 changes: 17 additions & 1 deletion triangle.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ function Triangle(p0, p1, p2)
// either off-screen or backface culling
this.invisible = false;

// discarded triangles are completely eliminated, so they will
// not be processed ever again.
this.discarded = false;


// compute the coordinates in screen space and decide
// if it is onscreen or backfaced culled
Expand All @@ -83,6 +87,9 @@ function Triangle(p0, p1, p2)
this.generation = generation;
this.invisible = true; // assume it will be discarded

if (this.discarded)
return false;

let s0 = camera.project(this.model[0], this.screen[0]);
let s1 = camera.project(this.model[1], this.screen[1]);
let s2 = camera.project(this.model[2], this.screen[2]);
Expand Down Expand Up @@ -161,7 +168,10 @@ function Triangle(p0, p1, p2)
// all three points match; this must be a duplicate
// triangle of some sort.
if (matches == 0b111)
console.log("three points match? " + this + " " + t);
{
//console.log("three points match? " + this + " " + t);
return -1;
}

return 0;
}
Expand All @@ -176,6 +186,12 @@ function Triangle(p0, p1, p2)
for(let t of triangle_map[stl_key3d(p)])
{
let edges = this.coplanar_check(t);
if (edges === -1)
{
t.discarded = true;
continue;
}

if (edges == 0)
continue;

Expand Down