Silverlight3D与样式行为全解析
立即解锁
发布时间: 2025-08-26 01:38:42 阅读量: 2 订阅数: 18 


Silverlight 5编程与应用实例解析
### Silverlight 3D与样式行为全解析
#### 1. Silverlight 3D 变换基础
在Silverlight 3D开发中,世界矩阵(World Matrix)是一个关键概念,它可以看作是对对象到目前为止所应用的所有变换的快照。常见的变换操作包括平移和旋转。
平移操作可以通过多次连续应用来实现,例如:
```csharp
effect.World *= translation;
translation = Matrix.CreateTranslation(-1, 0, 0);
effect.World *= translation;
```
这等同于使用一次平移:
```csharp
Matrix translation = Matrix.CreateTranslation(-3, 5, 0);
effect.World = effect.World * translation;
```
旋转操作则相对复杂一些,`Matrix`类提供了多种旋转方法,具体如下表所示:
| 方法 | 描述 |
| --- | --- |
| `CreateRotationX()` | 围绕x轴旋转形状,旋转角度以弧度指定 |
| `CreateRotationY()` | 围绕y轴旋转形状,旋转角度以弧度指定 |
| `CreateRotationZ()` | 围绕z轴旋转形状,旋转角度以弧度指定 |
| `CreateFromYawPitchRoll()` | 同时围绕三个轴旋转形状,pitch是x轴的旋转角度,yaw是y轴的旋转角度,roll是z轴的旋转角度 |
| `CreateFromAxisAngle()` | 围绕自定义轴(作为向量)旋转形状,该自定义轴不必与x、y或z轴对齐 |
以下是一个围绕y轴旋转1/8圈的示例:
```csharp
// 一个圆有2*Pi弧度,所以这个旋转是其1/8
Matrix rotation = Matrix.CreateRotationY(MathHelper.PiOver4);
effect.World *= rotation;
```
在进行旋转操作时,还需要考虑对象与旋转轴之间的距离。如果y轴正好穿过对象的中心,使用`CreateRotationY()`创建的旋转将使对象原地旋转;但如果对象偏离y轴,`CreateRotationY()`将使对象绕轴移动,就像行星绕太阳公转一样。
为了获得预期的旋转效果,需要合理安排对象的位置和变换顺序。通常,先将形状放置在要旋转的轴上,然后进行旋转,最后再进行平移操作。例如:
```csharp
effect.World = effect.World * rotation * translation;
```
而如果顺序变为:
```csharp
effect.World = effect.World * translation * rotation;
```
则会先进行平移,然后围绕(现在已远离的)轴进行旋转。
此外,`Matrix`类还提供了`CreateScale()`方法,用于改变对象的比例,可以对对象在x、y或z轴上进行不成比例的缩放。
#### 2. 形状动画
要创建动画形状,首先需要确保绘图逻辑持续运行,可在`DrawingSurface.Draw`事件处理程序的末尾添加以下语句:
```csharp
e.InvalidateSurface();
```
然后,每次`Draw`事件触发时应用旋转。但不同的显卡执行绘图代码的速度不同,为了确保在所有计算机上旋转速度一致,需要将旋转量与连续`Draw`事件之间的时间间隔相关联。`DrawEventArgs`对象提供了`TotalTime`和`DeltaTime`两个属性,可用于在动画中使用时间信息。以下是一个使用`DeltaTime`使纹理立方体缓慢旋转的事件处理程序示例:
```csharp
private void drawingSurface_Draw(object sender, DrawEventArgs e)
{
GraphicsDevice device = GraphicsDeviceManager.Current.GraphicsDevice;
device.Clear(new Color(0, 0, 0));
// 旋转立方体
Matrix rotation = Matrix.CreateRotationY(
MathHelper.PiOver4 * (float)e.DeltaTime.TotalMilliseconds / 2000f);
cube.World = cube.World * rotation;
cube.Draw(device);
// 保持绘图表面更新
e.InvalidateSurface();
}
```
#### 3. 相机的旋转与移动
创建一个用户可以使用键盘移动和定向的“第一人称”相机是一个更复杂的任务。相机不是一个独立的对象,也没有自己的世界矩阵,而是通过视图的属性进行修改。
首先,需要添加三个`Vector3`字段来跟踪相机信息:
```csharp
// 相机的位置,初始时几乎位于原点
private Vector3 cameraPosition = new Vector3(0, 0, 0.01f);
// 相机的朝向,初始时沿z轴向下看向场景前方
private Vector3 cameraLook = new Vector3(0,0,-1);
// 相机位置和其朝向的组合
private Vector3 cameraTarget;
```
`cameraTarget`是相机所指向的点,`cameraLook`是相机的朝向,将`cameraPosition`和`cameraLook`向量相加即可得到`cameraTarget`。
页面加载时,构造函数会创建视图、立方体和地板:
```csharp
Matrix view = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);
// 立方体的位置经过精心安排,使y轴穿过中间,以便其原地旋转
cube = new Cube3D(device, new Vector3(-1, -1, -1), 2, uri, 1.33f, view);
floor = new Floor3D(device, 1.33f, view);
// 将相机向后移动,使场景可见
cameraPosition -= cameraLook * 6;
```
绘图代码负责在渲染场景之前将`cameraPosition`和`cameraLook`组合起来,将相机放置在正确的位置:
```csharp
private bool rotate = true;
private void drawingSurface_Draw(object sender, DrawEventArgs e)
{
GraphicsDevice device = GraphicsDeviceManager.Current.GraphicsDevice;
device.Clear(new Color(0, 0, 0));
// 允许在穿过立方体时看到其内部
device.RasterizerState = new RasterizerState()
```
0
0
复制全文
相关推荐










