diff --git a/dfs_recipes.html b/dfs_recipes.html index 5d10ac3..0ded47b 100644 --- a/dfs_recipes.html +++ b/dfs_recipes.html @@ -127,11 +127,13 @@ const grey = new THREE.Color( 'rgb(100,100,100)' ); const dark_green = new THREE.Color( 'rgb(0,100,0)' ); const black = new THREE.Color( 'rgb(0,0,0)' ); + const yellow = new THREE.Color( 'rgb(255,255,0)' ); + const orange = new THREE.Color( 'rgb(255,165,0)' ); scene = new THREE.Scene(); scene.background = black; - line_segments = [[],[]]; + line_segments = [[],[]]; // [which_solution] const line_materials = [ new THREE.LineBasicMaterial({ color: grey }), new THREE.LineBasicMaterial({ color: dark_green }) ]; line_geometry = [ new THREE.BufferGeometry(), new THREE.BufferGeometry() ]; line_meshes = []; @@ -141,7 +143,7 @@ scene.add( line_meshes[i] ); } - points = [[],[]]; + points = [[],[]]; // [which_solution] const point_materials = [ new THREE.PointsMaterial({ color: grey }), new THREE.PointsMaterial({ color: dark_green }) ]; point_geometry = [ new THREE.BufferGeometry(), new THREE.BufferGeometry() ]; points_meshes = []; @@ -171,6 +173,18 @@ scene.add( transformed_points_mesh ); } + // show where mouse location gets transformed to + mouse_line_segments = [[],[]]; // [which_solution] + const mouse_line_materials = [ new THREE.LineBasicMaterial({ color: yellow }), new THREE.LineBasicMaterial({ color: orange }) ]; + mouse_line_geometry = [ new THREE.BufferGeometry(), new THREE.BufferGeometry() ]; + mouse_line_meshes = []; + for( var i = 0; i < 2; i++ ) { + mouse_line_geometry[i].setAttribute( 'position', new THREE.Float32BufferAttribute( mouse_line_segments[i], 3 ) ); + mouse_line_meshes[i] = new THREE.LineSegments( mouse_line_geometry[i], mouse_line_materials[i] ); + scene.add( mouse_line_meshes[i] ); + } + mouse_pos = new THREE.Vector3(); + // add axes axes = new THREE.GridHelper( 100, 100, 0x444444, 0x222222 ); axes.geometry.rotateX( Math.PI / 2 ); @@ -200,7 +214,7 @@ drag_controls.addEventListener( 'dragend', () => orbit_controls.enabled = true ); drag_controls.addEventListener( 'drag', onDragControlPoint, false ); - canvas.addEventListener( 'mousemove', render, false ); + canvas.addEventListener( 'mousemove', onMouseMove, false ); canvas.addEventListener( 'touchmove', render, false ); canvas.addEventListener( 'mousedown', render, false ); canvas.addEventListener( 'touchstart', render, false ); @@ -211,6 +225,74 @@ canvas.addEventListener( 'wheel', render, false ); } +function onMouseMove( e ) { + const { left, top, width, height } = e.currentTarget.getBoundingClientRect(); + mouse_pos.set( + ((e.clientX - left) / width) * 2 - 1, + -((e.clientY - top) / height) * 2 + 1, + (camera.near + camera.far) / (camera.near - camera.far), + ); + mouse_pos.unproject(camera); + + // show where the mouse location gets transformed to + var top_left = new THREE.Vector3(); + top_left.set(-1, 1, (camera.near + camera.far) / (camera.near - camera.far) ); + top_left.unproject(camera); + var bottom_right = new THREE.Vector3(); + bottom_right.set(1, -1, (camera.near + camera.far) / (camera.near - camera.far) ); + bottom_right.unproject(camera); + var pixel_scale = 20.0; // we don't actually have pixels here so this is for illustration + var pixel_width = pixel_scale * (bottom_right.x - top_left.x) / width; + var pixel_height = pixel_scale * (top_left.y - bottom_right.y) / height; + mouse_line_segments = [[],[]]; + // define a square around the current mouse location + var quad = []; + var num_quad_points = 10; + var p = new THREE.Vector3(mouse_pos.x - pixel_width / 2.0, mouse_pos.y + pixel_width / 2.0, 0); // start at top-left + quad.push(p); + for(var i=0; i < num_quad_points; i++) { p.x += pixel_width / num_quad_points; quad.push( new THREE.Vector3(p.x, p.y, 0)); } // move right + for(var i=0; i < num_quad_points; i++) { p.y -= pixel_width / num_quad_points; quad.push( new THREE.Vector3(p.x, p.y, 0)); } // move down + for(var i=0; i < num_quad_points; i++) { p.x -= pixel_width / num_quad_points; quad.push( new THREE.Vector3(p.x, p.y, 0)); } // move left + for(var i=0; i < num_quad_points; i++) { p.y += pixel_width / num_quad_points; quad.push( new THREE.Vector3(p.x, p.y, 0)); } // move up + // then for each transform: + for( var which_solution = 0; which_solution < recipes[ iRecipe ].num_solutions; which_solution++ ) { + if(! plot_solution[which_solution] ) { continue; } + // draw the square around the current pixel + for(var i=0; i < quad.length-1; i++) { + mouse_line_segments[which_solution].push(quad[i].x); + mouse_line_segments[which_solution].push(quad[i].y); + mouse_line_segments[which_solution].push(0); + mouse_line_segments[which_solution].push(quad[i+1].x); + mouse_line_segments[which_solution].push(quad[i+1].y); + mouse_line_segments[which_solution].push(0); + } + for( var transform_idx = 0; transform_idx < transforms[which_solution].length; transform_idx++ ) { + var m = transforms[which_solution][transform_idx]; + // draw a line from the center of this pixel + var transformed_mouse_pos = mobius_on_point(m, mouse_pos); + mouse_line_segments[which_solution].push(mouse_pos.x); + mouse_line_segments[which_solution].push(mouse_pos.y); + mouse_line_segments[which_solution].push(0); + mouse_line_segments[which_solution].push(transformed_mouse_pos.x); + mouse_line_segments[which_solution].push(transformed_mouse_pos.y); + mouse_line_segments[which_solution].push(0); + // draw a box around the edges of the transformed pixel + for(var i=0; i < quad.length-1; i++) { + var transformed_p = mobius_on_point(m, quad[i]); + mouse_line_segments[which_solution].push(transformed_p.x); + mouse_line_segments[which_solution].push(transformed_p.y); + mouse_line_segments[which_solution].push(0); + var transformed_p = mobius_on_point(m, quad[i+1]); + mouse_line_segments[which_solution].push(transformed_p.x); + mouse_line_segments[which_solution].push(transformed_p.y); + mouse_line_segments[which_solution].push(0); + } + } + } + + updateScene(); +} + function onDragControlPoint( e ) { const mesh = e.object; const iControlPoint = control_point_meshes.indexOf( mesh ); @@ -278,8 +360,10 @@ for( var i = 0; i < 2; i++ ) { line_geometry[i].setAttribute( 'position', new THREE.Float32BufferAttribute( line_segments[i], 3 ) ); point_geometry[i].setAttribute( 'position', new THREE.Float32BufferAttribute( points[i], 3 ) ); + mouse_line_geometry[i].setAttribute( 'position', new THREE.Float32BufferAttribute( mouse_line_segments[i], 3 ) ); line_geometry[i].computeBoundingSphere() point_geometry[i].computeBoundingSphere() + mouse_line_geometry[i].computeBoundingSphere() } render(); } @@ -294,6 +378,8 @@ line_meshes[1].visible = draw_control_points; points_meshes[0].visible = draw_control_points; points_meshes[1].visible = draw_control_points; + mouse_line_meshes[0].visible = draw_control_points; + mouse_line_meshes[1].visible = draw_control_points; if( draw_control_points ) { drag_controls.activate(); } else { drag_controls.deactivate(); } axes.visible = draw_control_points; render();