Silverlight3D与样式行为的深入解析
立即解锁
发布时间: 2025-08-26 01:40:51 阅读量: 13 订阅数: 21 AIGC 

### Silverlight 3D与样式行为的深入解析
#### 1. Silverlight 3D 变换操作
在Silverlight 3D中,世界矩阵(World Matrix)可以看作是对对象到目前为止所应用的所有变换的快照。常见的变换操作包括平移和旋转。
##### 1.1 平移操作
可以通过多次应用平移矩阵来实现对象的移动,例如:
```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;
```
##### 1.2 旋转操作
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轴,旋转时对象会绕轴移动,就像行星绕太阳公转一样。
为了获得预期的旋转效果,需要先将形状放置在要旋转的轴上,通常将形状的中心点放在原点(0,0,0)。在应用变换时,先进行旋转,再进行平移,或者一次性完成:
```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属性更有用,它返回自上次Draw事件触发以来经过的时间。
以下是一个使用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;
```
绘图代码负责在渲染场景之前将相机放置在正确的位置:
```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()
{
CullMode = CullMode.None
};
// 旋转立方体
if (rotate)
{
Matrix rotation = Matrix.CreateRotationY(
MathHelper.PiOver4 * (float)e.DeltaTime.TotalMilliseconds / 2000f);
cube.World = cube.World * rotation;
}
// 为当前相机位置和方向创建视图
cameraTarget = cameraPosition + cameraLook;
Matrix view = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);
cube.View = view;
floor.View = view;
// 绘制形状
floor.Draw(device);
cube.Draw(device);
//
```
0
0
复制全文
相关推荐










