Index: test_wireframe_model.html
==================================================================
--- test_wireframe_model.html
+++ test_wireframe_model.html
@@ -79,10 +79,36 @@
+
+
+window.onload = function(){
+
+ var canvas = document.createElement("canvas");
+
+ canvas.width = 500;
+ canvas.height = 500;
+
+ document.body.appendChild(canvas);
+
+ var ctx = canvas.getContext("2d");
+
+
+ var model = new WireframeModel();
+ model.addPoint([0, 0, 0]);
+ model.addPoint([0, .1, 0]);
+ model.addPoint([0, 0, .1]);
+ model.addPoint([-.1, .1, 0]);
+ model.addPoint([-.1, 0, .1]);
+
+ model.draw(canvas);
+
+
+}
+
Index: wireframe_model.js
==================================================================
--- wireframe_model.js
+++ wireframe_model.js
@@ -9,10 +9,135 @@
(function(){
+
+
+
+// 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 alternate 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, colinear_point){
+ if(!xyz) return null; // point has been deleted or does not exist
+
+ var view_transform = view.transform;
+ var origin = view.origin;
+ var zoom_scale = view.zoom_scale;
+ var zoom_dist = view.zoom_dist;
+
+ if(!zoom_scale) zoom_scale = 1;
+ if(!zoom_dist) zoom_dist = 0;
+ if(!origin) origin = [0,0,0];
+
+
+ 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){ // this point is on the wrong side of the viewer, find the closest point on the correct side if we can.
+ 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 ]; }
+
+
+
+// Just like the project function above but for a set of points.
+// It's put into a loop a little better.
+function project_all(canvas, points, point_projections, view){
+
+ var view_transform = view.transform;
+ var origin = view.origin;
+ var zoom_scale = view.zoom_scale;
+ var zoom_dist = view.zoom_dist;
+
+ if(!zoom_scale) zoom_scale = 1;
+ if(!zoom_dist) zoom_dist = 0;
+ if(!origin) origin = [0,0,0];
+
+
+ if(!point_projections) point_projections = [];
+ point_projections.length = points.length;
+
+ var w = canvas.width;
+ var h = canvas.height;
+ var w_2 = w/2;
+ var h_2 = h/2;
+
+ var scale = zoom_scale * Math.min(w, h);
+
+ var v00 = view_transform[0][0];
+ var v01 = view_transform[0][1];
+ var v02 = view_transform[0][2];
+ var v10 = view_transform[1][0];
+ var v11 = view_transform[1][1];
+ var v12 = view_transform[1][2];
+ var v20 = view_transform[2][0];
+ var v21 = view_transform[2][1];
+ var v22 = view_transform[2][2];
+
+
+ for(var i = 0; i < points.length; ++i){
+ var pt = points[i];
+
+ var x = pt[0];
+ var y = pt[1];
+ var z = pt[2];
+
+ if(origin){
+ x -= origin[0];
+ y -= origin[1];
+ z -= origin[2]; }
+
+ var depth = x*v20 + y*v21 + z*v22;
+ var scale2 = scale / (zoom_dist + depth);
+
+ if(!point_projections[i]) point_projections[i] = [0, 0];
+
+ var point_projection = point_projections[i];
+
+ point_projection[0] = scale2 * (x*v00 + y*v01 + z*v02) + w_2;
+ point_projection[1] = scale2 * (x*v10 + y*v11 + z*v22) + h_2; }
+
+ return point_projections; }
+
+
+
// A wireframe model and all the controls needed to move the camera and draw.
// despite the name, it may also include polygon surfaces.
function __WireframeModel(){
@@ -24,22 +149,30 @@
[0, 0, 1]];
var points = []; //global
- var solo_points = {};
+ var point_projections = [];
+ //var solo_points = {};
var lines = [];
-
+ var zoom_scale = 1;
+ var zoom_dist = 1;
// just because these actual objects is returned
// doesn't mean you should modify it externally if you can help it.
WFMObj.getPoints = function getPoints(){
return points; }
+
+ WFMObj.getPoint = function getPoint(index){
+ return points[index].slice(0); }
WFMObj.getLines = function getLines(){
return lines; }
+
+ WFMObj.getLine = function getLine(index){
+ return lines[index].slice(0); }
WFMObj.getViewTransform = function getViewTransform(){
return view_transform; }
@@ -76,12 +209,28 @@
if(ptindex < 0 || ptindex >= points.length){
throw "pt ref at index " + i + " of line was not in bounds: " + ptindex; }}
lines.push(line);
return lines.length - 1; }
-
-
+
+
+ WFMObj.draw = function draw(canvas){
+ var ctx = canvas.getContext("2d");
+
+ var view = {};
+ view.transform = view_transform;
+ view.origin = view_origin;
+ view.zoom_scale = zoom_scale;
+ view.zoom_dist = zoom_dist;
+
+ project_all(canvas, points, point_projections, view);
+ // project_all()
+
+ for(var i = 0; i < point_projections.length; ++i){
+ var point_projection = point_projections[i];
+ if(point_projection) ctx.fillRect(point_projection[0] - 1, point_projection[1] - 1, 2, 2); }
+ }
}
// use constructor as global namespace object.
WireframeModel = __WireframeModel;
@@ -114,60 +263,12 @@
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.