Index: draw.html ================================================================== --- draw.html +++ draw.html @@ -1,29 +1,15 @@ <html> <script src='matrix_vector_lib.js' ></script> <script> -// -// Editor modes -// -// Motion mode -- change the camera center using the original movement system -// --------Camera mode -- adjust the camera, scale zoom and position zoom, make it stationary or rotating about the center -// Edit mode -- create points at camera center, move points, create lines by clicking on successive points, create closed polygons etc. - -// Editing Strategy - -// During draw mode only the very edges of the screen rotate the view, and at reduced speed -// pressing enter or clicking on the center point creates a new point. -// points are moved with the arrow keys, the direction is absolute, that means it does not depend on the camera angle. -// the arrow keys move the selected point. -// clicking on a second point when one point is already selected creates a line. - -// TODO control with zoom scales the selected object -// control with rotate rotates the selected objects - -// TODO clicking and dragging on a line allows you to place a point somewhere on that line. Perhaps with the ctrl key it would break up the existing line into line segments. + +// TODO control with zoom rotate or pan means that action is only applied to the camera not the selected points. + + +// TODO clicking and dragging on a line allows you to place a point somewhere on that line. Perhaps with the modifier key it would break up the existing line into line segments. // TODO when lines are deleted, readd the solo points to the solo_points list // // TODO z for undo shift + z for redo. @@ -133,11 +119,10 @@ keyDown({keyCode: keycode}); } // it seems the keyCode of the original event cant be overwritten. document.body.onmousewheel = function(event){ var delta = event.wheelDelta; - //if(editor_mode == MODE_DRAWING){ if(delta < 0) zoom_dist /= zoom_factor; else if(delta > 0) zoom_dist *= zoom_factor; } @@ -187,21 +172,15 @@ function forwardPress(e, s, lasts){ changeVelocity(2, true, s, lasts); } function zoomInPress(e, s, lasts){ - //if(editor_mode == MODE_CAMERA_POSITION) - // changeVelocity(2, true, s, lasts); - //else if(editor_mode == MODE_CAMERA_ROTATION) - zoom_dist *= zoom_factor; } + zoom_dist *= zoom_factor; } function zoomOutPress(e, s, lasts){ - //if(editor_mode == MODE_CAMERA_POSITION) - // changeVelocity(2, true, s, lasts); - //else if(editor_mode == MODE_CAMERA_ROTATION) - zoom_dist *= zoom_factor; } + zoom_dist *= zoom_factor; } function copySelectedPoints(e, s, lasts){ if(s){ var new_selection = []; @@ -248,12 +227,10 @@ addKeyListener(81, downPress); addKeyListener(88, function(e, s, lasts){ // x - //if(editor_mode == MODE_DRAWING && s){ // alert('deleting points'); - if(s){ if(highlight_object !== null && highlight_object > 0){ // delete highlighted object if(highlight_object < point_projections.length){ // point points[highlight_object] = null; } @@ -269,89 +246,81 @@ cleanupDeletedPoints(); highlight_object = null; selected_points.length = 0; }}); -// addKeyListener(1000, aForwardPress); // mouse buttons -// addKeyListener(1002, cameraBackwardPress); - - - -// addKeyListener(13, function(e, s, lasts){ if(s) nextMode(); }); // switch modes - - + // select point addKeyListener(1000, function(e, s, lasts){ - //if(editor_mode == MODE_DRAWING){ - if(s){ - if(highlight_object !== null){ - if(highlight_object == -1) - highlight_object = addPoint(origin); // create a new point at the origin - - - var alreadySelected = false; // only set for shift clicks - - if(key_state[16] && key_state[16].state){ // shift key is pressed. - - for(var i = 0; i < selected_points.length; ++i){ - if(selected_points[i] == highlight_object){ - selected_points.splice(i, 1); // deselect point - alreadySelected = true; - break; }}} - else{ - selected_points.length = 0;} - - if(!alreadySelected) selected_points.push(highlight_object); } - - else if(!key_state[16] || !key_state[16].state) - selected_points.length = 0; } - - - else if(lasts && mouse_dragging ){ // drag actions - - // connect selected points to highlight point with lines - if(selected_points.length && (!key_state[16] || !key_state[16].state)){ // TODO right now this really only works for drawing a single line, - - if(highlight_object !== null && highlight_object < point_projections.length){ - if(highlight_object == -1) highlight_object = addPoint(origin); - - for(var i = 0; i < selected_points.length; ++i){ - var pt = selected_points[i]; - if(pt == highlight_object) continue; - addLine(pt, highlight_object); } - selected_points.length = 0; }} - - // select points inside selection rectangle - else if(mouse_loc && last_mouse_down){ - - var minx = Math.min(mouse_loc[0], last_mouse_down[0]); - var maxx = Math.max(mouse_loc[0], last_mouse_down[0]); - var miny = Math.min(mouse_loc[1], last_mouse_down[1]); - var maxy = Math.max(mouse_loc[1], last_mouse_down[1]); - - - var selected_point_map = {}; - - if(!key_state[16] || !key_state[16].state){ - selected_points.length = 0; - selected_lines.length = 0; } - else{ - for(var i = 0; i < selected_points.length; ++i){ - selected_point_map[selected_points[i]] = i; }} - - for(var i = 0; i < point_projections.length; ++i){ - if(selected_point_map[i]) continue; // already selected. - - var pt = point_projections[i]; - if(!pt) continue; - var _x = pt[0]; - var _y = pt[1]; - - if(minx < _x && _x < maxx - && miny < _y && _y < maxy){ - selected_points.push(i); }}} + if(s){ + if(highlight_object !== null){ + if(highlight_object == -1) + highlight_object = addPoint(origin); // create a new point at the origin + + + var alreadySelected = false; // only set for shift clicks + + if(key_state[16] && key_state[16].state){ // shift key is pressed. + + for(var i = 0; i < selected_points.length; ++i){ + if(selected_points[i] == highlight_object){ + selected_points.splice(i, 1); // deselect point + alreadySelected = true; + break; }}} + else{ + selected_points.length = 0;} + + if(!alreadySelected) selected_points.push(highlight_object); } + + else if(!key_state[16] || !key_state[16].state) + selected_points.length = 0; } + + + else if(lasts && mouse_dragging ){ // drag actions + + // connect selected points to highlight point with lines + if(selected_points.length && (!key_state[16] || !key_state[16].state)){ // TODO right now this really only works for drawing a single line, + + if(highlight_object !== null && highlight_object < point_projections.length){ + if(highlight_object == -1) highlight_object = addPoint(origin); + + for(var i = 0; i < selected_points.length; ++i){ + var pt = selected_points[i]; + if(pt == highlight_object) continue; + addLine(pt, highlight_object); } + selected_points.length = 0; }} + + // select points inside selection rectangle + else if(mouse_loc && last_mouse_down){ + + var minx = Math.min(mouse_loc[0], last_mouse_down[0]); + var maxx = Math.max(mouse_loc[0], last_mouse_down[0]); + var miny = Math.min(mouse_loc[1], last_mouse_down[1]); + var maxy = Math.max(mouse_loc[1], last_mouse_down[1]); + + + var selected_point_map = {}; + + if(!key_state[16] || !key_state[16].state){ + selected_points.length = 0; + selected_lines.length = 0; } + else{ + for(var i = 0; i < selected_points.length; ++i){ + selected_point_map[selected_points[i]] = i; }} + + for(var i = 0; i < point_projections.length; ++i){ + if(selected_point_map[i]) continue; // already selected. + + var pt = point_projections[i]; + if(!pt) continue; + var _x = pt[0]; + var _y = pt[1]; + + if(minx < _x && _x < maxx + && miny < _y && _y < maxy){ + selected_points.push(i); }}} }}); @@ -372,52 +341,11 @@ var delta_horizontal_angle = 0; var delta_vertical_angle = 0; var delta_position = [0,0,0]; -// var MODE_DRAWING = 0; -// var MODE_CAMERA_POSITION = 1; // change the camera focus point -// var MODE_CAMERA_ROTATION = 2; // rotate and zoom camera - -// var editor_mode = MODE_DRAWING; - -/* -function drawMode(){ - editor_mode = MODE_DRAWING; - delta_position = [0,0,0]; - // delta_horizontal_angle = 0; - // delta_vertical_angle = 0; - if(last_zoom_dist) zoom_dist = last_zoom_dist; - else zoom_dist = 1; - - document.body.style.cursor = "crosshair"; } - -function cameraPositionMode(){ - document.body.style.cursor = "default"; - last_zoom_dist = zoom_dist; - delta_horizontal_angle = 0; - delta_vertical_angle = 0; - zoom_dist = NAVIGATION_ZOOM_DIST; - editor_mode = MODE_CAMERA_POSITION; } - -function cameraRotationMode(){ - document.body.style.cursor = "default"; - delta_horizontal_angle = 0; - delta_vertical_angle = 0; - if(last_zoom_dist) zoom_dist = last_zoom_dist; - else zoom_dist = 1; - editor_mode = MODE_CAMERA_ROTATION; } - -function nextMode(){ - if(editor_mode == MODE_DRAWING) cameraPositionMode(); - else if(editor_mode == MODE_CAMERA_POSITION) drawMode(); } - - // skipping camera rotation mode - //else if(editor_mode == MODE_CAMERA_POSITION) cameraRotationMode(); - //else if(editor_mode == MODE_CAMERA_ROTATION) drawMode(); } - - */ + var points = []; //global var solo_points = {}; var lines = []; @@ -572,53 +500,11 @@ function addLine(pt0, pt1){ delete solo_points[pt0]; delete solo_points[pt1]; lines.push([pt0, pt1]); - return lines.length - 1; } - -function addBox(xyz, wdh){ - var x = xyz[0]; - var y = xyz[1]; - var z = xyz[2]; - - var w = wdh[0]; - var d = wdh[1]; - var h = wdh[2]; - - var x0 = x - w/2; - var y0 = y - d/2; - var z0 = z - d/2; - - var x1 = x + w/2; - var y1 = y + d/2; - var z1 = z + h/2; - - var a = addPoint([x0, y0, z0]); - var b = addPoint([x1, y0, z0]); - var c = addPoint([x1, y1, z0]); - var d = addPoint([x0, y1, z0]); - var e = addPoint([x0, y0, z1]); - var f = addPoint([x1, y0, z1]); - var g = addPoint([x1, y1, z1]); - var h = addPoint([x0, y1, z1]); - - - addLine(a, b); - addLine(b, c); - addLine(c, d); - addLine(d, a); - addLine(e, f); - addLine(f, g); - addLine(g, h); - addLine(h, e); - - addLine(a, e); - addLine(b, f); - addLine(c, g); - addLine(d, h); } - + return lines.length - 1; } function draw(canvas){ var ctx = canvas.getContext('2d'); @@ -676,11 +562,10 @@ if(pt) ctx.fillRect(pt[0] - 2, pt[1] - 2, 4, 4); } - //if(editor_mode == MODE_DRAWING){ ctx.fillStyle = "rgba(250, 0, 0, 0.9)"; ctx.fillRect(w/2 - 2, h/2 - 2, 4, 4); for(var i = 0; i < selected_points.length; ++i){ var pt; @@ -755,81 +640,10 @@ ctx.fillStyle = "rgb(0,0,0)"; ctx.fillText(msg, 5, 20); } -//function buildFractal(children, func, levels, origin, scale, baseonly){ - -//} - - -function serpenskiPyramid(level, origin, scale){ - if(!scale) scale = 1; - if(!origin) origin = [0, 0, 0]; - if(level === undefined) level = 4; - - var spoints = [[0,0,0], [0.5,0,0], [0, -0.5, 0], [0, 0, 0.5]]; - - - for(var i = 0; i < spoints.length; ++i){ - var x = spoints[i]; - vector_scale(x, scale); - vector_add(x, origin, x); } - - - if(level > 0){ - for(var i = 0; i < spoints.length; ++i){ - var point = spoints[i]; - vector_add(origin, point, origin); - serpenskiPyramid(level - 1, origin, 0.5 * scale); - vector_minus(origin, point, origin); } - - } - else if(level == 0){ - var pointRefs = []; - for(var i = 0; i < spoints.length; ++i){ - vector_scale(spoints[i], 2); // scale to points to full length; - pointRefs[i] = addPoint(spoints[i]); } - - - for(var i = 0; i < spoints.length; ++i){ - var a = pointRefs[i]; - - for(var j = i + 1; j < spoints.length; ++j){ - var b = pointRefs[j]; - addLine(a, b); }}} -} - - -function buildArray(origin, increment, size, buildfunc, extra1, extra2, extra3){ - var point = origin.slice(0); - point_indexes = []; - - for(var i = 0; i < size.length; ++i){ - point_indexes[i] = 0; } - - var last_index = point_indexes.length - 1; - var index = last_index; - - // build object at origin. - buildfunc(point, extra1, extra2, extra3); - - while(index >= 0){ - //depth first - - if(point_indexes[index] == size[index] - 1){ - point[index] = origin[index]; - point_indexes[index] = 0; - --index; } - else{ - ++point_indexes[index]; - point[index] += increment[index]; - index = last_index; // always go to the end position - buildfunc(point, extra1, extra2, extra3); }} -} - - window.onload = function(){ // load localStorage saved state. if(localStorage.points && localStorage.lines){ points = JSON.parse(localStorage.points); @@ -844,31 +658,10 @@ window.onresize = function(){ canvas.width = window.innerWidth - 20; canvas.height = window.innerHeight - 20; } - //addBox([0, 0, 0], [.5, .5, .5]); - - /* - buildArray( [0, 0, 0], // origin - [2, 2, 2], // increment - [11, 1, 11], // size - addBox, - [.5, .5, .5]); */ - - //var a = addPoint([0, 0, 1]); - //var b = addPoint([.5, 0, 1]); - //var c = addPoint([0, .5, 1]); - - - - //addLine(a, b); - //addLine(b, c); - //addLine(c, a); - - //serpenskiPyramid(5, null, 1); - function getRotationAngle(x, size, max, center_size){ if(!center_size) center_size = 0.25; // the proportional size of the area in which no rotation is effected by the mouse movement @@ -902,25 +695,12 @@ var dist2 = _x*_x + _y*_y; if(dist2 > MIN_DRAG_DIST * MIN_DRAG_DIST){ mouse_dragging = true; }} - /* - if(editor_mode == MODE_CAMERA_ROTATION){ // rotate about center - - delta_horizontal_angle = getRotationAngle(x, w, max_angle_delta/frame_rate); - delta_vertical_angle = -getRotationAngle(y, h, max_angle_delta/frame_rate); } - - - if(editor_mode == MODE_CAMERA_POSITION){ - - delta_horizontal_angle = -getRotationAngle(x, w, max_angle_delta/frame_rate); - delta_vertical_angle = getRotationAngle(y, h, max_angle_delta/frame_rate); } - - - else if(editor_mode == MODE_DRAWING){ */ - + + delta_horizontal_angle = getRotationAngle(x, w, max_angle_delta/frame_rate, no_rotate_area); delta_vertical_angle = -getRotationAngle(y, h, max_angle_delta/frame_rate, no_rotate_area); var min_point_dist2 = LINE_HIGHLIGHT_DIST * LINE_HIGHLIGHT_DIST; highlight_object = null; @@ -974,22 +754,18 @@ // function animateLoop(){ - //if(editor_mode == MODE_DRAWING){ if(selected_points.length){ // move selection if exists for(var i = 0; i < selected_points.length; ++i){ var pt = points[selected_points[i]]; vector_add(pt, delta_position, pt); }} else{ moveCamera(delta_position, false); } - - //else if(editor_mode == MODE_CAMERA_POSITION){ - // if(delta_position) moveCamera(delta_position, true); } // motion depends on camera angle - + if(delta_horizontal_angle) rotateHorizontal(delta_horizontal_angle); if(delta_vertical_angle) rotateVertical(delta_vertical_angle); // overwrite point projections