C# 使用DrawUserPrimitive并将其与一些矩阵进行转换

C# 使用DrawUserPrimitive并将其与一些矩阵进行转换,c#,matrix,xna,primitive,C#,Matrix,Xna,Primitive,这里是我所拥有的:一个定制的DrawableGameComponent,其中包含一些我称之为DrawUserPrimitve的子级。每个子项都可以包含子项等。 我在每个组件中存储一个描述其形状的顶点列表,并存储一个矩阵来存储其相对位置(以及最终的变换)。 因此,在我“DrawUserPrimitive”之前,我需要“应用”一个矩阵。该矩阵必须是组件的变换及其父级和父级的父级等的乘积 这个系统允许我保持组件变量的独立性,如果我理解正确,这就是方法 为此,我在XNA中看到了basicefect对象,

这里是我所拥有的:一个定制的
DrawableGameComponent
,其中包含一些我称之为
DrawUserPrimitve
的子级。每个子项都可以包含子项等。 我在每个组件中存储一个描述其形状的顶点列表,并存储一个矩阵来存储其相对位置(以及最终的变换)。 因此,在我“
DrawUserPrimitive
”之前,我需要“应用”一个矩阵。该矩阵必须是组件的变换及其父级和父级的父级等的乘积

这个系统允许我保持组件变量的独立性,如果我理解正确,这就是方法

为此,我在XNA中看到了
basicefect
对象,我可以用它应用一些矩阵。因此,我试图用我的
组件.Transformation
矩阵
)乘以
基本效果.World

所以我应该继续询问,但现在它没有给我我所期待的结果。我想知道我是否选择了好的方法来做这件事。我看到两个系统的结果相同:

  • 我现在做得怎么样,有点像有一支固定的铅笔,但移动你的纸
  • 或者在绘图之前添加一个穿过所有顶点的循环,以根据预期的变换修改这些顶点。有点像移动铅笔而不是纸

  • 一些代码用于说明:

    public void override Draw(GameTime gameTime){
    
        Game.basicEffect.World *= Transformation;
    
        foreach(var child in this.Children){
            child.Draw(gameTime);
        }
    
        Game.basicEffect.World *= Matrix.Invert(Transformation);
    
    }
    

    多亏@nico schertler的评论,我才得以成功

    使用矩阵堆栈存储“铅笔”的当前状态是解决方案。但有一点我遗漏了:

    每次深入对象层次(例如:机器人的手臂)时,将新矩阵乘以当前矩阵,并将得到的矩阵放到堆栈上。因此,堆栈始终具有(在其顶部)必须用于绘制的矩阵。当您处理完这个对象并返回到它的父对象时,只要弹出一次,您就可以检索用于它的矩阵。 (我正在堆叠每个矩阵,然后每次都重新计算要使用的结果矩阵。)

    备注:请注意乘法的顺序。矩阵的乘法不是可交换的!始终将子矩阵乘以当前矩阵

    internal void HandleDraw(GameTime gameTime)
    {
        Draw(gameTime);
    
        if (Children.Count > 0)
        {
            // draw children
            foreach (Control child in Children.Values.OfType<Control>())
            {
                if (child.Visible)
                {
                    Engine.CurrentTransformation.Push(Matrix.Multiply(
                        child.Transformation,
                        Engine.CurrentTransformation.Peek()
                    ));
    
                    child.HandleDraw(gameTime);
    
                    Engine.CurrentTransformation.Pop();
                }
            }
        }
    }
    
    internalvoid HandleDraw(游戏时间游戏时间)
    {
    抽签(游戏时间);
    如果(Children.Count>0)
    {
    //画孩子
    foreach(Children.Values.OfType()中的控件子级)
    {
    if(子级可见)
    {
    引擎。电流转换。推送(矩阵。乘法(
    儿童转化,
    Engine.CurrentTransformation.Peek()
    ));
    儿童手绘(游戏时间);
    Engine.CurrentTransformation.Pop();
    }
    }
    }
    }
    
    结果中到底出了什么问题?根据变换的不同,使用
    World=Transformation*World
    计算
    World
    矩阵可能更合理。我需要对其进行更多测试,以查看,但使用2个深度级别,第2个是错误的,但第3个是好的。这在我的代码中看起来确实是个问题,而不是在逻辑中。但我想问的是,是否有一个通用的解决方案可以使用。通常,像这样的场景图是用矩阵堆栈实现的。导航到子级时,将世界矩阵推到堆栈顶部,然后使用变换矩阵进行修改。当作用域离开子级时,将删除顶部矩阵,并将世界矩阵恢复为该值。因此,您不必使用昂贵的
    Invert
    功能。但一般来说,如果所有的孩子行为都一样,代码也应该这样做。有关矩阵以及如何组合矩阵的更多信息,请参见此处:谢谢,我假设以这种方式执行操作而不是使用堆栈将获得更好的性能,但是如果您这样说,我将返回使用堆栈,因为它听起来也更干净。好吧,你加上这个方法,我就保留它。谢谢