C# 三维网格旋转
我对3D图形还比较陌生,我发现了很多关于旋转的例子,但是我相信我的代码在创建3D网格或旋转本身方面出了问题。我正在使用一个修改版本的 所以本质上我的问题归结为,我绕着红色的x线旋转,而不是蓝色的x线。理想情况下,我想在蓝色Y线和蓝色X线相交的地方旋转。也可以查看旋转函数,请参见下面列出的microsoft类几何函数,并查看RotateX 谢谢你的帮助 下面是我如何设置场景的:C# 三维网格旋转,c#,3d,xna,C#,3d,Xna,我对3D图形还比较陌生,我发现了很多关于旋转的例子,但是我相信我的代码在创建3D网格或旋转本身方面出了问题。我正在使用一个修改版本的 所以本质上我的问题归结为,我绕着红色的x线旋转,而不是蓝色的x线。理想情况下,我想在蓝色Y线和蓝色X线相交的地方旋转。也可以查看旋转函数,请参见下面列出的microsoft类几何函数,并查看RotateX 谢谢你的帮助 下面是我如何设置场景的: public RenderScene3D(short _depth, GraphicsDevice GD) : bas
public RenderScene3D(short _depth, GraphicsDevice GD) : base(_depth)
{
PrimativeCollection = new List<GeometricPrimitive>();
cameraPosition = new Vector3(0, 0, 2.5f);
fAspect = GD.Viewport.AspectRatio;
CameraWorld = Matrix.CreateTranslation(cameraPosition);
world = Matrix.CreateFromYawPitchRoll(0, 0, 0);
view = Matrix.CreateLookAt(cameraPosition, Vector3.Zero, Vector3.Up);
projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, fAspect, .01f, 500f);
// This serves as a base line for latter ray cursor calculations.
ScreenProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, fAspect, .01f, 2.5f);
graphicsDevice = GD;
}
public RenderScene3D(短深度,图形设备GD):基础(_深度)
{
PrimativeCollection=新列表();
摄像机位置=新矢量3(0,0,2.5f);
fAspect=GD.Viewport.AspectRatio;
CameraWorld=矩阵.CreateTranslation(cameraPosition);
world=Matrix.CreateFromYawPitchRoll(0,0,0);
视图=矩阵.CreateLookAt(摄像机位置,向量3.0,向量3.Up);
投影=矩阵.CreatePerspectiveFieldOfView(MathHelper.PiOver4,fAspect.01f,500f);
//这将作为后期光线光标计算的基线。
ScreenProjection=Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,fAspect.01f,2.5f);
图形设备=GD;
}
Microsoft class Geometric的稍微修改版本:
public abstract class GeometricPrimitive : IDisposable
{
#region Fields
// During the process of constructing a primitive model, vertex
// and index data is stored on the CPU in these managed lists.
protected List<VertexPositionNormal> vertices = new List<VertexPositionNormal>();
protected List<ushort> indices = new List<ushort>();
public Vector3 v3Position;
protected Matrix world;
protected Matrix worldPosition;
protected Matrix worldRotation;
// Once all the geometry has been specified, the InitializePrimitive
// method copies the vertex and index data into these buffers, which
// store it on the GPU ready for efficient rendering.
protected VertexBuffer vertexBuffer;
protected IndexBuffer indexBuffer;
protected BasicEffect basicEffect;
#endregion
#region Initialization
/// <summary>
/// Adds a new vertex to the primitive model. This should only be called
/// during the initialization process, before InitializePrimitive.
/// </summary>
protected void AddVertex(Vector3 _position, Vector3 normal)
{
vertices.Add(new VertexPositionNormal(_position, _position));
}
/// <summary>
/// Adds a new index to the primitive model. This should only be called
/// during the initialization process, before InitializePrimitive.
/// </summary>
protected void AddIndex(int index)
{
if (index > ushort.MaxValue)
throw new ArgumentOutOfRangeException("index");
indices.Add((ushort)index);
}
/// <summary>
/// Queries the index of the current vertex. This starts at
/// zero, and increments every time AddVertex is called.
/// </summary>
protected int CurrentVertex
{
get { return vertices.Count; }
}
/// <summary>
/// Once all the geometry has been specified by calling AddVertex and AddIndex,
/// this method copies the vertex and index data into GPU format buffers, ready
/// for efficient rendering.
public void InitializePrimitive(GraphicsDevice graphicsDevice)
{
// Create a vertex declaration, describing the format of our vertex data.
// Create a vertex buffer, and copy our vertex data into it.
vertexBuffer = new VertexBuffer(graphicsDevice,
typeof(VertexPositionNormal),
vertices.Count, BufferUsage.None);
vertexBuffer.SetData(vertices.ToArray());
// Create an index buffer, and copy our index data into it.
indexBuffer = new IndexBuffer(graphicsDevice, typeof(ushort),
indices.Count, BufferUsage.None);
indexBuffer.SetData(indices.ToArray());
// Create a BasicEffect, which will be used to render the primitive.
basicEffect = new BasicEffect(graphicsDevice);
basicEffect.EnableDefaultLighting();
RotateX(0);
UpdateWorld();
}
public void Move(Vector3 Position)
{
v3Position = Position;
worldPosition = Matrix.CreateTranslation(v3Position);
}
public void UpdateWorld()
{
world = worldRotation * worldPosition;
}
public void RotateX(float X)
{
Matrix rotation = worldPosition;
Matrix.CreateRotationX(X, out rotation);
worldRotation = rotation;
}
/// <summary>
/// Finalizer.
/// </summary>
~GeometricPrimitive()
{
Dispose(false);
}
/// <summary>
/// Frees resources used by this object.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Frees resources used by this object.
/// </summary>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (vertexBuffer != null)
vertexBuffer.Dispose();
if (indexBuffer != null)
indexBuffer.Dispose();
if (basicEffect != null)
basicEffect.Dispose();
}
}
#endregion
#region Draw
/// <summary>
/// Draws the primitive model, using the specified effect. Unlike the other
/// Draw overload where you just specify the world/view/projection matrices
/// and color, this method does not set any renderstates, so you must make
/// sure all states are set to sensible values before you call it.
/// </summary>
public void Draw(Effect effect)
{
GraphicsDevice graphicsDevice = effect.GraphicsDevice;
// Set our vertex declaration, vertex buffer, and index buffer.
graphicsDevice.SetVertexBuffer(vertexBuffer);
graphicsDevice.Indices = indexBuffer;
foreach (EffectPass effectPass in effect.CurrentTechnique.Passes)
{
effectPass.Apply();
int primitiveCount = indices.Count / 3;
graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices.Count, 0, primitiveCount);
}
}
/// <summary>
/// Draws the primitive model, using a BasicEffect shader with default
/// lighting. Unlike the other Draw overload where you specify a custom
/// effect, this method sets important renderstates to sensible values
/// for 3D model rendering, so you do not need to set these states before
/// you call it.
/// </summary>
public void Draw(Matrix view, Matrix projection, Color color)
{
// Set BasicEffect parameters.
basicEffect.World = world;
//Matrix worldMatrix = Matrix.CreateScale(0.0005f, 0.0005f, 0.0005f) * Matrix.CreateRotationY(MathHelper.Pi) * Matrix.CreateFromQuaternion(xwingRotation) * Matrix.CreateTranslation(xwingPosition);
//Matrix worldMatrix = Matrix.CreateScale(0.0005f, 0.0005f, 0.0005f) * Matrix.CreateRotationY(MathHelper.Pi) * Matrix.CreateFromQuaternion(xwingRotation) * Matrix.CreateTranslation(xwingPosition);
//Matrix test = view.Translation * new Vector3(0,0,0.001f);
basicEffect.View = view;
basicEffect.Projection = projection;
basicEffect.DiffuseColor = color.ToVector3();
basicEffect.Alpha = 128.0f / color.A;
GraphicsDevice device = basicEffect.GraphicsDevice;
// Reset the fill mode renderstate.
device.DepthStencilState = DepthStencilState.Default;
if (color.A < 255)
{
// Set renderstates for alpha blended rendering.
device.BlendState = BlendState.AlphaBlend;
}
else
{
// Set renderstates for opaque rendering.
device.BlendState = BlendState.AlphaBlend;
}
// Draw the model, using BasicEffect.
Draw(basicEffect);
}
}
公共抽象类GeometricPrimitive:IDisposable
{
#区域字段
//在构造基本模型的过程中,顶点
//索引数据存储在这些托管列表中的CPU上。
受保护的列表顶点=新列表();
受保护列表索引=新列表();
公共向量3 v3位置;
保护矩阵世界;
保护矩阵位置;
保护矩阵旋转;
//一旦指定了所有几何图形,则初始值Primitive
//方法将顶点和索引数据复制到这些缓冲区中
//将其存储在GPU上,以便高效渲染。
受保护的顶点缓冲区顶点缓冲区;
受保护的索引缓冲索引缓冲;
受保护的基本效果基本效果;
#端区
#区域初始化
///
///将新顶点添加到基本体模型中。应仅调用该顶点
///在初始化过程中,在初始化之前Primitive。
///
受保护的void AddVertex(向量3_位置,向量3法线)
{
添加(新顶点曝光法线(_位置,_位置));
}
///
///向基元模型添加新索引。只应调用此索引
///在初始化过程中,在初始化之前Primitive。
///
受保护的void AddIndex(整数索引)
{
如果(索引>ushort.MaxValue)
抛出新ArgumentOutOfRangeException(“索引”);
索引。添加((ushort)索引);
}
///
///查询当前顶点的索引。此操作从开始
///零,并在每次调用AddVertex时递增。
///
受保护的int-CurrentVertex
{
获取{返回顶点数;}
}
///
///调用AddVertex和AddIndex指定所有几何体后,
///此方法将顶点和索引数据复制到GPU格式缓冲区中,准备就绪
///用于高效渲染。
public void InitializePrimitive(图形设备图形设备)
{
//创建顶点声明,描述顶点数据的格式。
//创建顶点缓冲区,并将顶点数据复制到其中。
vertexBuffer=新的vertexBuffer(图形设备,
类型(垂直曝光正常),
顶点。计数,缓冲区使用率。无);
SetData(顶点.ToArray());
//创建一个索引缓冲区,并将索引数据复制到其中。
indexBuffer=新的indexBuffer(图形设备,类型(ushort),
索引。计数,缓冲区使用率。无);
SetData(index.ToArray());
//创建一个BasicFect,用于渲染基本体。
BasicFect=新的BasicFect(图形设备);
basicEffect.EnableDefaultLighting();
RotateX(0);
UpdateWorld();
}
公共无效移动(矢量3位置)
{
V3位置=位置;
worldPosition=Matrix.CreateTranslation(v3Position);
}
public void UpdateWorld()
{
世界=世界旋转*世界位置;
}
公共空间旋转(浮动X)
{
矩阵旋转=世界位置;
矩阵.CreateRotationX(X,向外旋转);
世界旋转=旋转;
}
///
///终结器。
///
~GeometricPrimitive()
{
处置(虚假);
}
///
///释放此对象使用的资源。
///
公共空间处置()
{
处置(真实);
总干事(本);
}
///
///释放此对象使用的资源。
///
受保护的虚拟void Dispose(bool disposing)
{
如果(处置)
{
if(vertexBuffer!=null)
vertexBuffer.Dispose();
if(indexBuffer!=null)
indexBuffer.Dispose();
if(basicEffect!=null)
基本效果处理();
}
}
#端区
#区域绘制
///
///使用指定的效果绘制基本体模型。与其他
///在仅指定世界/视图/投影矩阵的位置绘制重载
///和颜色,此方法不设置任何渲染状态,因此必须
///在调用之前,请确保所有状态都设置为合理值。
///
公共无效提取(效果)
{
GraphicsDevice GraphicsDevice=effect.GraphicsDevice;
//设置顶点声明、顶点缓冲区和索引缓冲区。
graphicsDevice.SetVertexBuffer(vertexBuffer);
graphicsDevice.Index=indexBuffer;
foreach(效应传递效应传入
public class SquarePrimitive : GeometricPrimitive
{
public float size;
/// <summary>
/// Constructs a new square primitive, using default settings.
/// </summary>
public SquarePrimitive(Vector3 position, Vector3 _v3Rotation)
: this(position, _v3Rotation, 1)
{
}
/// <summary>
/// Constructs a new square primitive, with the specified size.
/// </summary>
public SquarePrimitive(Vector3 position, Vector3 _v3Rotation, float _size)
{
size = _size;
// Get two vectors perpendicular to the face normal and to each other.
Vector3 topLeft = new Vector3(-size, size, 0);
Vector3 topRight = new Vector3(size, size, 0);
Vector3 bottomLeft = new Vector3(-size, -size, 0);
Vector3 bottomRight = new Vector3(size, -size, 0);
// Six indices (two triangles) per face.
AddIndex(CurrentVertex + 0);
AddIndex(CurrentVertex + 1);
AddIndex(CurrentVertex + 2);
AddIndex(CurrentVertex + 0);
AddIndex(CurrentVertex + 2);
AddIndex(CurrentVertex + 3);
// Four vertices per face.
size = 0.1f;
AddVertex((position + topLeft), position);
AddVertex((position + topRight), position);
AddVertex((position + bottomRight), position);
AddVertex((position + bottomLeft), position);
Move(position);
}
}
AddVertex((position + topLeft), position);
AddVertex((position + topRight), position);
AddVertex((position + bottomRight), position);
AddVertex((position + bottomLeft), position);