我正在尝试使用DrawUserIndexedPrimitives绘制由线条组成的模型,在XNA中制作3D WP7游戏 这一切都很好,但现在我想给每个模型一个自己的旋转。 目前我正在使用BasicEffect来绘制所有模型。我可以设置它的旋转,但是然后所有对象将具有相同的旋转。有没有办法为每个对象设置不同的旋转? 我目前提出了一些我可以使用的解决方案,但我对其中任何一个都不满意:
有没有建议路线到这里?
我不知道DrawUserIndexedPrimitives是否是最好的方法,我只想绘制线条并给它们一个旋转。如果有更好的方法,请告诉我:)
我目前的解决方案:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
foreach (var model in _models)
{
foreach (var pass in model.Effect.CurrentTechnique.Passes)
{
pass.Apply();
model.Effect.World = _model.GetWorld();
var points = model.GetPoints();
GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.LineList, points, 0, points.Length, model.Lines, 0, model.Lines.Length / 2);
_models[0].Draw(GraphicsDevice);
}
}
base.Draw(gameTime);
}
model.GetWorld()返回一个矩阵,其中包含对象的旋转,平移和缩放,model.GetPoints()一个带有points和model的列表.Lines是一个带有连接点索引的列表
答案 0 :(得分:2)
您通常只需要任何类型的效果之一(例如BasicEffect)。原因是因为效果包含两个主要内容:为GPU(照明等)编写的代码及其公开的参数(例如Effect.World,世界矩阵)。编译GPU代码的次数不会太多,因为每次都是相同的,所以我们唯一需要考虑的是参数。
注意调用pass.Apply()。实际上做的是每次在绘制之前将您在效果上设置的所有参数上传到GPU。有希望告诉你的是,你应该能够在每次绘制之前在单个效果上设置旋转并调用Apply,而不是创建一组具有单独设置旋转的效果。而且,设置Effect.World实际上应该在pass.Apply()。
之前要回答第二个要点,你完全正确。 GPU可以在具有大量并行性的点上进行转换,因此最好不要自己尝试,因为它会很慢。
对于DrawUserIndexedPrimitives,我不是图形buff,但一般来说,这个调用是为你的顶点不断变化的情况保留的(比如软体blob或布料),基本上你没有办法用它来描述网格只是翻译,旋转和尺度。 GPU暴露了称为VertexBuffer的特殊基元,其整个目标是在GPU内存中存储一堆点(这使得它们非常快速地访问)。从那里,如果你想移动它,GPU将转换每一点(但请注意,你需要传递它的所有内容是平移,旋转和缩放以及它的好处)。使用DrawUserIndexedPrimitives实际上必须每帧都将所有点发送到GPU,这比较慢(多少,谁知道这些天没有测试)。
幸运的是,显卡实际上实现了一种称为“线框”的特殊绘图模式,而不是绘制三角形,只是将三角形的边缘绘制为线条。要设置线框模式,请在调用Draw:
之前执行此操作this.GraphicsDevice.RasterizerState.FillMode = FillMode.WireFrame;
现在,在应用自己的旋转方面,您实际需要做的就是将世界矩阵乘以旋转矩阵(使用类似Matrix.CreateRotationX(yourAngle)的东西)。
答案 1 :(得分:0)
你当前的解决方案很好,但我会在pass.Apply()
之前做世界分配如果您的模型很少,可以使用变换传递到着色器和数组,并将顶点结构添加到此数组的索引。
通过这种方式,您可以一次性绘制所有模型。