Overview
Comment: | started moving around code in files to factor stuff. |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
1514d83c2900c9083ef9ecce78ed7165 |
User & Date: | Derek on 2013-01-02 17:22:01 |
Other Links: | manifest | tags |
Context
2013-01-03
| ||
20:26 | starting basic work on wireframe_model.js wrote some test cases in seperate page check-in: e9599cdacc user: Derek tags: trunk | |
2013-01-02
| ||
17:22 | started moving around code in files to factor stuff. check-in: 1514d83c29 user: Derek tags: trunk | |
2012-12-30
| ||
22:51 | got rotation of selected points to work check-in: e34dd1120f user: Jacob tags: trunk | |
Changes
Modified draw.html from [2d990104f4] to [00f152a683].
1 2 3 4 | <html> <script src='matrix_vector_lib.js' ></script> <script> | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | <html> <script src='matrix_vector_lib.js' ></script> <script src='wireframe_model.js'></script> <script> /* // TODO rotate selected points // 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. // TODO // TODO drop down minimalist menu in top right of canvas. |
︙ | ︙ | |||
26 27 28 29 30 31 32 | // even in future code changes, ie statically configured with an initial. // // var canvas; | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | // even in future code changes, ie statically configured with an initial. // // var canvas; var frame_rate = 20; var saveTimeout = 10*1000; var last_zoom_dist = 1; var zoom_factor = 0.83; // camera animation var max_move_delta = 0.01; var max_angle_delta = Math.PI; var delta_horizontal_angle = 0; var delta_vertical_angle = 0; var delta_position = [0,0,0]; var selected_points = []; var selected_lines = []; var helpmsg = //"3D drawing tool\n\n" + "Select Left Click\n" + |
︙ | ︙ | |||
500 501 502 503 504 505 506 | if(vertical_camera_rotation + theta < -Math.PI/2) theta = -Math.PI/2 - vertical_camera_rotation; vertical_camera_rotation += theta; rotateView([1, 0, 0], theta, true); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 473 474 475 476 477 478 479 480 481 482 483 484 485 486 | if(vertical_camera_rotation + theta < -Math.PI/2) theta = -Math.PI/2 - vertical_camera_rotation; vertical_camera_rotation += theta; rotateView([1, 0, 0], theta, true); } window.onload = function(){ // load localStorage saved state. if(localStorage.points && localStorage.lines){ |
︙ | ︙ | |||
823 824 825 826 827 828 829 | canvas.height = window.innerHeight - 20; window.onresize = function(){ canvas.width = window.innerWidth - 20; canvas.height = window.innerHeight - 20; } | | < | 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | canvas.height = window.innerHeight - 20; window.onresize = function(){ canvas.width = window.innerWidth - 20; canvas.height = window.innerHeight - 20; } function getRotationAngle(x, size, max, center_size){ if(!center_size) center_size = 0.05; // the proportional size of the area in which no rotation is effected by the mouse movement if(!max) max = Math.PI/128; // center does nothing if(Math.abs(x) < size * center_size/2) x = 0; |
︙ | ︙ | |||
984 985 986 987 988 989 990 | var saveAction = function(){ localStorage.points = JSON.stringify(points); localStorage.lines = JSON.stringify(lines); } setInterval(saveAction, saveTimeout); } | | | 654 655 656 657 658 659 660 661 662 663 664 665 666 667 | var saveAction = function(){ localStorage.points = JSON.stringify(points); localStorage.lines = JSON.stringify(lines); } setInterval(saveAction, saveTimeout); } */ </script> <body></body> </html> |
Added wireframe_model.js version [0b9640f7fc].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | // global namespace object var WireframeModel; (function(){ // A wireframe model and all the controls needed to move the camera and draw. // despite the name, it may also include polygon surfaces. var origin = [0, 0, 0]; var points = []; //global var solo_points = {}; var lines = []; var point_projections = []; var line_midpoint_projections = []; var highlight_object = null; var mouse_dragging = false; var last_mouse_down = null; var mouse_loc = null; var zoom_scale = 2.667; // scalar zoom property. var zoom_dist = 1; function moveCamera(offset, cameracentric){ if(cameracentric) offset = matrix_mult(view_transform, [offset])[0]; //alert("offset: " + offset); vector_add(origin, offset, origin); } // converts a point from three space to the canvas plane. // Note: because of depth perspective, this conversion is not // easy to define if the point lies behind the camera. // There are two options: // When drawing a line, another colinear point in front of the camera may be provided // to help find an alertnate point. // if both points lie behind the camera or the colinear_point is not provided, // this function will return null. function project(canvas, xyz, view_transform, origin, colinear_point){ if(!xyz) return null; // point has been deleted or does not exist var w = canvas.width; var h = canvas.height; var scale = Math.min(w, h); var v = xyz.slice(0); if(origin) v = vector_minus(v, origin, v); var z = vector_dot(view_transform[2], v); if(z <= -zoom_dist){ if(!colinear_point) return null; var v2 = colinear_point.slice(0); if(origin) vector_minus(v2, origin, v2); var z2 = vector_dot(view_transform[2], v2); if(z2 < 0) return null; // get the coefficients for a complex combination. // t*z + (1-t)*z2 = 0.0002 -- z of new point is just barely infront of the camera. var t = (0.0002 - z2)/(z - z2); // no division by zero, z is negative, z2 is positive vector_add(vector_scale(v, t, v), vector_scale(v2, 1-t, v2), v); z = vector_dot(view_transform[2], v); } var scale2 = zoom_scale * scale / (zoom_dist + z); return [ scale2 * vector_dot(view_transform[0], v) + 0.5 * w, scale2 * vector_dot(view_transform[1], v) + 0.5 * h ]; } // removes deleted points and lines // works with global objects. function cleanupDeletedPoints(){ var newpoints = []; var newlines = []; var pointmap = {}; var j = 0; for(var i = 0; i < points.length; ++i){ if(points[i]){ newpoints.push(points[i]); pointmap[i] = j; ++j; } else{ pointmap[i] = -1; }} for(var i = 0; i < lines.length; ++i){ if(!lines[i]) continue; var a = lines[i][0]; var b = lines[i][1]; if(pointmap[a] != -1 && pointmap[b] != -1){ newlines.push([ pointmap[a], pointmap[b] ]); }} points = newpoints; lines = newlines; } function addPoint(pt){ points.push(pt.slice(0)); var index = points.length - 1; solo_points[index] = true; return index; } function addLine(pt0, pt1){ delete solo_points[pt0]; delete solo_points[pt1]; lines.push([pt0, pt1]); return lines.length - 1; } function draw(canvas){ var ctx = canvas.getContext('2d'); var w = canvas.width; var h = canvas.height; // ctx.fillStyle = "rgba(100, 100, 100, .05)"; ctx.beginPath(); for(var i = 0; i < lines.length; ++i){ var line = lines[i]; if(!line) continue; //draw line var pt0 = points[line[0]]; var pt1 = points[line[1]]; var _pt0 = point_projections[line[0]]; var _pt1 = point_projections[line[1]]; // finish the line even if one point is on wrong side of viewer. if(!_pt0 && _pt1){ _pt0 = project(canvas, pt0, view_transform, origin, pt1); } else if(_pt0 && !_pt1){ _pt1 = project(canvas, pt1, view_transform, origin, pt0); } if(!_pt0 || !_pt1) continue; var x0 = _pt0[0]; var y0 = _pt0[1]; var x1 = _pt1[0]; var y1 = _pt1[1]; ctx.moveTo(x0, y0); ctx.lineTo(x1, y1); } ctx.clearRect(0, 0, w, h); ctx.strokeStyle = "rgba(0, 0, 0, 0.9)"; ctx.stroke(); ctx.fillStyle = "rgba(0, 0, 0, 0.9)"; for(var k in solo_points){ var pt = point_projections[k]; if(pt) ctx.fillRect(pt[0] - 2, pt[1] - 2, 4, 4); } // // The following drawing of axes is to help provide an perspective // The nuances of this draw behavior are created to provide visual cues for interpreting perspective and depth. // // Because we use a 2d canvas library for the drawing the rest of the points/shapes after projection, these visual information nuances are important. // // axis lines and dots var faxis_pt = project(canvas, vector_add(origin, [0, 0, FORWARD_AXIS_LEN]), view_transform, origin); var vaxis_pt = project(canvas, vector_add(origin, [0, -VERTICAL_AXIS_LEN, 0]), view_transform, origin); ctx.fillStyle = AXIS_POINT_COLOR; var fdot = vector_dot(view_transform[2], [0, 0, 1]); var a = MIN_AXIS_POINT_RADIUS; //random letters for intermediate computations var b = MAX_AXIS_POINT_RADIUS; var c = (a+b)/2; var d = (b-a)/2; var fr = c - d * fdot; var vdot = vector_dot(view_transform[2], [0, -1, 0]); var vr = c - d * vdot; ctx.lineWidth = AXIS_LINE_WIDTH; ctx.beginPath(); if(fdot >=0 && faxis_pt){ // occlude this axis, draw first ctx.moveTo(w/2, h/2); ctx.lineTo(faxis_pt[0], faxis_pt[1]); ctx.fillRect(faxis_pt[0] - fr, faxis_pt[1] - fr, 2*fr, 2*fr); } if(vdot >=0 && vaxis_pt){ // occlude this axis, draw first ctx.moveTo(w/2, h/2); ctx.lineTo(vaxis_pt[0], vaxis_pt[1]); ctx.fillRect(vaxis_pt[0] - vr, vaxis_pt[1] - vr, 2*vr, 2*vr); } ctx.stroke(); // draw center red square ctx.fillStyle = CENTER_POINT_COLOR; var cr = CENTER_POINT_RADIUS; ctx.fillRect(w/2 - cr, h/2 - cr, 2*cr, 2*cr); ctx.fillStyle = AXIS_POINT_COLOR; if(fdot < 0 && faxis_pt){ ctx.beginPath(); ctx.moveTo(w/2, h/2); ctx.lineTo(faxis_pt[0], faxis_pt[1]); ctx.stroke(); ctx.fillRect(faxis_pt[0] - fr, faxis_pt[1] - fr, 2*fr, 2*fr); } if(vdot < 0 && vaxis_pt){ ctx.beginPath(); ctx.moveTo(w/2, h/2); ctx.lineTo(vaxis_pt[0], vaxis_pt[1]); ctx.stroke(); ctx.fillRect(vaxis_pt[0] - vr, vaxis_pt[1] - vr, 2*vr, 2*vr); } // reset line width ctx.lineWidth = LINE_WIDTH; for(var i = 0; i < selected_points.length; ++i){ var pt; if(selected_points[i] == -1) pt = [w/2, h/2]; else pt = point_projections[selected_points[i]]; ctx.fillStyle = POINT_COLOR; if(pt) ctx.fillRect(pt[0] - 4, pt[1] - 4, 8, 8); } if(highlight_object !== null){ if(highlight_object < point_projections.length){ var pt; if(highlight_object == -1) pt = [w/2, h/2]; else pt = point_projections[highlight_object]; ctx.fillStyle = "rgba(50, 50, 50, .6)"; ctx.fillRect(pt[0] - 4, pt[1] - 4, 8, 8); // TODO getting a error here that pt is null document.body.style.cursor = "hand"; } else if(highlight_object < point_projections.length + line_midpoint_projections.length){ // alert("drawing highlighted line"); var line = lines[highlight_object - point_projections.length]; if(line){ var pt1 = point_projections[line[0]]; var pt2 = point_projections[line[1]]; if(pt1 && pt2){ ctx.beginPath(); ctx.moveTo(pt1[0], pt1[1]); ctx.lineTo(pt2[0], pt2[1]); ctx.lineWidth = 3; ctx.stroke(); ctx.lineWidth = 1; }}} else{ throw "highlight object index to large"; }} else{ document.body.style.cursor = "crosshair"; } if(mouse_dragging){ if(selected_points.length && !getKeyState(16)){ // if shift is held, we are selecting more points. if(mouse_loc && getKeyState(1000)){ ctx.beginPath(); var pt = point_projections[selected_points[0]]; if(pt){ ctx.moveTo(mouse_loc[0], mouse_loc[1]); ctx.lineTo(pt[0], pt[1]); } ctx.stroke(); }} else if(mouse_loc && last_mouse_down){ if(getKeyState(1000)){ // select points inside square 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]); ctx.beginPath(); ctx.rect(minx, miny, maxx - minx, maxy - miny); ctx.stroke(); }} } ctx.fillStyle = "rgb(0,0,0)"; writeMsg(canvas, msg); } })(); |