This post describes a simple example, which draws a perspective representation of a 3D cube using wire-frame representation (i.e. with all edges visible).
The example is implemented using Javascript and Silverlight. We first define three Javascript classes to represent points in different coordinate systems:
Point2D –2D Cartesian coordinate system
Point3D – 3D Cartesian coordinate system
PointSpherical - 3D Spherical coordinate system
function Point2D(x , y) { this.x = x; this.y = y; } function Point3D(x , y, z) { this.x = x; this.y = y; this.z = z; } function PointSpherical(rho , theta, phi) { this.rho = rho; this.theta = theta; this.phi = phi; }
The perspective function implements the viewing and perspective transformations. By using the function, a point in 3D space can be projected to 2D screen coordinates. The perspective function takes three input parameters. i.e.
p – a Point3D object that defines the point in 3D Cartesian coordinate system
eye – a PointSpherical object that defines the vanishing point in 3D Spherical coordinate system
d – defines the distance between the vanishing point and the screen
The function returns a Point2D object that defines the projected point on the screen.
function perspective(p, eye, d) { var costh = Math.cos(eye.theta); var sinth = Math.sin(eye.theta); var cosph = Math.cos(eye.phi); var sinph = Math.sin(eye.phi); var v11 = -sinth; var v12 = -cosph * costh; var v13 = sinph * costh; var v21 = costh; var v22 = -cosph * sinth; var v23 = sinph * sinth; var v32 = sinph; var v33 = cosph; var v43 = -1* eye.rho; //viewing transformation var x = v11 * p.x + v21 * p.y; var y = v12 * p.x + v22 * p.y + v32 * p.z; var z = v13 * p.x + v23 * p.y + v33 * p.z + v43; //perspective transformation return new Point2D(-d * x / z, -d * y / z); }
The drawWireFrameCube function is called during the Silverlight onLoad event, which defines the cube vertices and draws the cube edges by creating Silverlight Line objects.
Silverlight.createObjectEx( { source: "#xamlContent_wire_frame_cube", parentElement: document.getElementById( "pluginHost_wire_frame_cube"), id: "plugin_wire_frame_cube", properties: { width: "300", height: "300", version: "1.0", background: "White" }, events: {onLoad: drawWireFrameCube} } ); function drawWireFrameCube(plugin, context, sender) { var v = new Array(); // Bottom surface: v[0] = new Point3D(1, -1, -1); v[1] = new Point3D(1, 1, -1); v[2] = new Point3D(-1, 1, -1); v[3] = new Point3D(-1, -1, -1); // Top surface: v[4] = new Point3D(1, -1, 1); v[5] = new Point3D(1, 1, 1); v[6] = new Point3D(-1, 1, 1); v[7] = new Point3D(-1, -1, 1); var eye = new PointSpherical(18, 0.5,1.0); var d = 1000; var center = new Point2D(150,150); var scrPoints = new Array(); for(var i=0; i<8;i++) { scrPoints[i] = perspective(v[i], eye, d); } line(sender,scrPoints[0],scrPoints[1],center); line(sender,scrPoints[1],scrPoints[2],center); line(sender,scrPoints[2],scrPoints[3],center); line(sender,scrPoints[3],scrPoints[0],center); line(sender,scrPoints[4],scrPoints[5],center); line(sender,scrPoints[5],scrPoints[6],center); line(sender,scrPoints[6],scrPoints[7],center); line(sender,scrPoints[7],scrPoints[4],center); line(sender,scrPoints[0],scrPoints[4],center); line(sender,scrPoints[1],scrPoints[5],center); line(sender,scrPoints[2],scrPoints[6],center); line(sender,scrPoints[3],scrPoints[7],center); } function line(sender, p1, p2, center) { var plugin = sender.getHost(); var l = plugin.content.createFromXaml("<Line/>"); l.X1 = center.x + p1.x; l.Y1 = center.y - p1.y; l.X2 = center.x + p2.x; l.Y2 = center.y - p2.y; l.Stroke = "WhiteSmoke"; sender.children.add(l); }
No comments:
Post a Comment