x01 发表于 2013-1-3 15:38:06

x01.EarthRun

<div id="cnblogs_post_body">月亮绕着地球转,地球绕着太阳转,一个 TranslateTransform3D + RotationTransform3D 即可搞定。难的是球体(Sphere)绘制。
作为球体,由经度、纬度划分为一小块一小块的。球体的绘制,说白了,就是这一小块一小块的绘制。除上下极点外,每小块由四个点(Point3D)构成,即两个三角形。
现在,只要求出了这些 Point3D,问题即可解决。为简便,不妨设球心 O 为(0,0,0),半径 r 为 1 。(WPF 3D 坐标:左到右 x 轴,下到上 y 轴,屏幕里到外 z 轴)
如何求球面某经纬度交叉点 A (x,y,z)的 3D 坐标呢?
1. 忽略 z 轴,设角 AOX (纬度偏移)度数为 a,则 x = cos(a); y = sin(a); 同理,z = cos(a);
2. 设经度偏移角度 AOZ 为 b,此时,y 不变。忽略 y 轴,则 x = cos(a)*sin(b); z = cos(a)*cos(b);
即:(cos(a)*sin(b), sin(a), cos(a)*cos(b)) 为 A 3D 坐标。参考代码如下:
<div class="cnblogs_code" >http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gifhttp://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gifTrangulate<div id="cnblogs_code_open_ae55b94f-540d-4811-8eb8-86e133ade64d" class="cnblogs_code_hide">protected void Triangulate(DependencyPropertyChangedEventArgs e,            Point3DCollection vertices, Vector3DCollection normals,            Int32Collection indices, PointCollection textures)      {            vertices.Clear();            normals.Clear();            indices.Clear();            textures.Clear();            for (int stack = 0; stack <= Stacks; stack++)            {                double phi = Math.PI / 2 - stack * Math.PI / Stacks;                double y = Radius * Math.Sin(phi);                double scale = -Radius * Math.Cos(phi);                for (int slice = 0; slice <= Slices; slice++)                {                  double theta = slice * 2 * Math.PI / Slices;                  double x = scale * Math.Sin(theta);                  double z = scale * Math.Cos(theta);                  Vector3D normal = new Vector3D(x, y, z);                  normals.Add(normal);                  vertices.Add(normal + Center);                  textures.Add(new Point((double)slice / Slices, (double)stack / Stacks));                }            }            // stack == 0            for (int slice = 0; slice < Slices; slice++)            {                indices.Add(slice + 1);                indices.Add(Slices + 1 + slice);                indices.Add(Slices + 1 + slice + 1);            }            for (int stack = 1; stack < Stacks - 1; stack++)            {                for (int slice = 0; slice < Slices; slice++)                {                  indices.Add(stack * (Slices + 1) + slice);                  indices.Add((stack + 1) * (Slices + 1) + slice);                  indices.Add(stack * (Slices + 1) + slice + 1);                  indices.Add(stack * (Slices + 1) + slice + 1);                  indices.Add((stack + 1) * (Slices + 1) + slice);                  indices.Add((stack + 1) * (Slices + 1) + slice + 1);                }            }            // stack == Stacks - 1            for (int slice = 0; slice < Slices; slice++)            {                int stack = Stacks - 1;                indices.Add(stack * (Slices + 1) + slice);                indices.Add((stack + 1) * (Slices + 1) + slice);                indices.Add(stack * (Slices + 1) + slice + 1);            }      }
页: [1]
查看完整版本: x01.EarthRun