本文描述了一个使用透视法在Silverlight中绘制三维线框模型的立方体的例程。所谓的线框模型指的是立方体的各条边线都在视图中可见。
首先定义了三个Javascript类来描述不同的坐标系统中的点。
Point2D –二维笛卡尔坐标系
Point3D – 三维笛卡尔坐标系
PointSpherical - 三维球坐标系
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; }
下述的perspective函数实现了从三维坐标到二维坐标的透视画法。该函数接受以下三个输入参数,并返回一个Point2D对象.使用该函数,一个三维空间中的点可以被投影到二维屏幕坐标中。
p – 三维笛卡尔坐标系中的一个点 eye – 透视没影点,(三维球坐标系) d – 透视没影点和屏幕之间的距离
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); }
Silverlight的onLoad事件触发以下的drawWireFrameCube方法。该方法定义了立方体的顶点坐标,并使用Silverlight Line对象绘制立方体边线。
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); }
没有评论:
发表评论