XNA 中的四元数旋转

2024-02-18

我这样做对吗?

显然不是因为否则我不会在这里发布问题,但我正在尝试围绕另一个模型对一个模型进行四元数旋转。

假设我有一个具有向量 3 位置和浮动旋转角度的盒模型。 我还有一个指向盒子模型的截头锥体模型,其位置可以说距盒子模型 50 个单位。平截头体还有一个向量 3 位置和一个四元数旋转。

在场景 1 中,长方体和平截头体“未旋转”。这一切都很好。 在场景 2 中,我仅旋转盒子,并且希望平截头体随之旋转(有点像追逐相机),平截头体始终直接指向盒子,并且距盒子的距离与未旋转距离相同。显然,如果我只是通过对盒子和平截头体使用 Matrix.CreateRotationY() 来旋转模型和平截头体,则平截头体会稍微向侧面偏移。

所以我认为平截头体围绕盒子的四元数旋转是最好的? 为此,我尝试了以下方法,但没有成功。它在屏幕上绘制我的模型,但它也会在屏幕上绘制看起来像一个巨大盒子的东西,无论我将相机移动多远,盒子总是挡住路

为了测试的目的,我有 3 个盒子和它们的 3 个相关的平截头体 在我的 Game1 类中,我用位置和旋转初始化了 box[0]

boxObject[0].Position = new Vector3(10, 10, 10);
boxObject[1].Position = new Vector3(10, 10, 10);
boxObject[2].Position = new Vector3(10, 10, 10);

boxObject[0].Rotation = 0.0f;
boxObject[1].Rotation = 45.0f;
boxObject[2].Rotation = -45.0f;

因此,所有 3 个盒子都绘制在相同位置但角度不同。 然后为了做截锥体,我开始他们的位置:

float f = 50.0f;
frustumObject[0].Position = new Vector3(boxObject[0].Position.X,
            boxObject[0].Position.Y, boxObject[0].Position.Z + f);
frustumObject[1].Position = new Vector3(boxObject[1].Position.X,
            boxObject[1].Position.Y, boxObject[1].Position.Z + f);
frustumObject[2].Position = new Vector3(boxObject[2].Position.X,
            boxObject[2].Position.Y, boxObject[2].Position.Z + f);

然后尝试围绕其关联的盒子模型旋转:

frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X,
            boxObject[0].Position.Y, boxObject[0].Position.Z + f, 0);
frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X,
            boxObject[0].Position.Y, boxObject[0].Position.Z + f, 45);
frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X,
            boxObject[0].Position.Y, boxObject[0].Position.Z + f, -45);

最后,为了绘制模型,我在 GameModel 类中 Draw() 它们,该类还具有:

public Model CameraModel { get; set; }
public Vector3 Position { get; set; }
public float Rotation { get; set; }
public Quaternion ModelRotation { get; set; }

public void Draw(Matrix view, Matrix projection)
    {
        transforms = new Matrix[CameraModel.Bones.Count];
        CameraModel.CopyAbsoluteBoneTransformsTo(transforms);

        // Draw the model
        foreach (ModelMesh myMesh in CameraModel.Meshes)
        {
            foreach (BasicEffect myEffect in myMesh.Effects)
            {
                // IS THIS CORRECT?????
                myEffect.World = transforms[myMesh.ParentBone.Index] *
                    Matrix.CreateRotationY(Rotation) * Matrix.CreateFromQuaternion(ModelRotation) * Matrix.CreateTranslation(Position);

                myEffect.View = view;
                myEffect.Projection = projection;

                myEffect.EnableDefaultLighting();
                myEffect.SpecularColor = new Vector3(0.25f);
                myEffect.SpecularPower = 16;
            }

            myMesh.Draw();
        }
    }

谁能发现我哪里出错了?是因为我在 Draw() 中进行了两种类型的旋转吗?

myEffect.World = 变换[myMesh.ParentBone.Index] * Matrix.CreateRotationY(旋转) * Matrix.CreateFromQuaternion(ModelRotation) * Matrix.CreateTranslation(Position);


乍一看,最好使用静态创建方法来创建四元数,例如Quaternion.CreateFromAxisAngle(Vector3. UnitY, rotation)。四元数的 X、Y、Z 和 W 值与位置没有任何关系。方便的静态方法可以解决棘手的数学问题。

在您的情况下,似乎您希望在盒子旋转时保持平截头体指向盒子的同一侧,因此围绕盒子旋转平截头体。这需要对绘制方法中完成的转换采取稍微不同的方法。

为了围绕另一个对象旋转一个对象,首先需要平移该对象,以便所需旋转的中心位于原点。然后旋转对象并将其平移与第一步相同的量。

因此,在您的情况下,类似的事情应该可以做到(遵循未经测试的示例代码);

// Construct the objects

boxObject.Position = new Vector3(10, 10, 10);
boxObject.Rotation = 45.0f;

frustumObject.Position = new Vector3(0, 0, 50f); // Note: this will be relative to the box (makes the math a bit simpler)
frustumObject.TargetPosition = boxObject.Position;
frustumObject.ModelRotation = Quaternion.CreateFromAxisAngle(Vector3. UnitY, boxObject.Rotation); // Note: this rotation angle may need to be in radians.


// Box Draw()
// Draw the box at its position, rotated about its centre.
myEffect.World = transforms[myMesh.ParentBone.Index] * Matrix.CreateTranslation(Position) * Matrix.CreateRotationY(Rotation);

// Frustum Draw()
// Draw the frustum facing the box and rotated about the boxes centre.
myEffect.World = transforms[myMesh.ParentBone.Index] * Matrix.CreateTranslation(Position) * Matrix.CreateFromQuaternion(ModelRotation) * Matrix.CreateTranslation(TargetPosition);

假设:

  • 盒子绕自己的中心旋转
  • 平截头体保持面向盒子并绕盒子中心旋转

希望这可以帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XNA 中的四元数旋转 的相关文章

  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 为什么两个不同的 Base64 字符串的转换会返回相等的字节数组?

    我想知道为什么从 base64 字符串转换会为不同的字符串返回相同的字节数组 const string s1 dg const string s2 dq byte a1 Convert FromBase64String s1 byte a2
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况

随机推荐