我对3D图形很新,我在旋转方面找到了很多例子,但我相信我的代码可以创建3D网格或旋转本身。我正在使用primatives example for xna的修改版本。
基本上我的问题归结为我绕着红色x线而不是蓝色x线旋转。理想情况下,我想旋转蓝色Y线和蓝色X线相交的地方。要查看旋转功能,请参阅下面列出的microsoft类Geometric Primative,并查看RotateX。
感谢您的帮助。
以下是我设置场景的方法:
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;
}
Microsoft class Geometric Primative的稍微修改版本:
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);
}
}
最后我的方形课程:
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);
}
}
答案 0 :(得分:1)
它与偏移(平移)网格的几何中心有关,使得所需的旋转点在轴上,并且该轴穿过世界原点,然后应用旋转,然后将其平移回到它的位置是。或者......修改代码以防止需要这样做。
您的代码中有足够的细微之处,我不得不使用它来提供一系列适用于您的代码,但这只是一两个想法。
AddVertex((position + topLeft), position);
AddVertex((position + topRight), position);
AddVertex((position + bottomRight), position);
AddVertex((position + bottomLeft), position);
通过在正方形的角上添加“位置”,您将偏移正方形的几何中心与网格的局部空间原点。
在旋转过程中,局部原点(和所有顶点)始终围绕穿过世界原点的轴旋转。您的代码将本地空间原点与该轴内联,但是您希望的旋转轴围绕几何中心(而不是在本地原点周围),在旋转期间需要平移偏移。
通常,您不会将'position'添加到这样的顶点(从而完全避免该问题)。您可以在局部空间中对称地构建原点周围的顶点,然后将它们的束转换为您希望它们位于世界空间中的任何位置。然后,旋转偏移 更容易处理。
乍一看,如果您从角顶点移除了“位置”数量,那么您的代码就可以按预期执行。
希望至少能为您提供一条线索,让您朝着正确的方向前进。