在 XNA 中旋转立方体

发布于 2024-09-13 11:09:13 字数 2175 浏览 2 评论 0原文

到目前为止,我已经成功创建了一个用于旋转的四元数。现在唯一的问题是,如何将其仅应用于某些立方体?当我按下键盘上的右键时,每个立方体都围绕原点不断旋转。

作为参考,我有 8 个立方体,其设置与魔方 (2x2x2) 类似。因此,当我按下右/左箭头时,“立方体”(由 8 个较小立方体组成的大立方体)的右/左面顺时针/逆时针旋转 90 度。

立方体之一(总共八个立方体)声明的示例:

GameObject subCube3 = new GameObject();  
Vector3 subCube3Pos = new Vector3(-0.55f, -0.55f, 0.55f); 

在我的更新方法中:

// declare rotation floats     
float updownRotation = 0.0f;     
float leftrightRot = 0.0f;     

// get state of keyboard     
KeyboardState keys = Keyboard.GetState();     

// if key is pressed, change value of rotation     
if (keys.IsKeyDown(Keys.Right))     
{     
    leftrightRot = -0.10f;     
}

// if key is pressed, change value of rotation     
if (keys.IsKeyDown(Keys.Left))     
{     
    leftrightRot = 0.1f;     
}     

// if key is pressed, change value of rotation     
if (keys.IsKeyDown(Keys.Up))     
{
    updownRotation = 0.1f;     
}

// rotation around axis     
Quaternion addRot = Quaternion.CreateFromAxisAngle(new Vector3(1.0f, 0.0f, 0.0f), leftrightRot);

//rotation of cubes     
cubeRotation = cubeRotation * addRot; 

我的绘制函数:

void DrawGameObject(GameObject gameobject)
{     
    //graphics.GraphicsDevice.RenderState.CullMode = CullMode.None;     
    foreach (ModelMesh mesh in gameobject.model.Meshes)     
    {     
        foreach (BasicEffect effect in mesh.Effects)     
        {     
            effect.EnableDefaultLighting();     
            effect.PreferPerPixelLighting = true;     
            effect.World =     
                Matrix.CreateScale(gameobject.scale) *     
                Matrix.CreateFromQuaternion(cubeRotation) *     
                Matrix.CreateTranslation(gameobject.position);     

            effect.Projection = cameraProjectionMatrix;     
            effect.View = cameraViewMatrix;     
        }
        mesh.Draw();     
    }
}

我认为问题在于 Matrix.CreateTranslation(gameobject.position) 是显然影响了我所有的立方体。我尝试创建新的 Vector3 即: c_component1 = Vector3.Transform(cube1pos,cubeRotation); 但即便如此,我也不确定将其放在哪里并实际使用它。

有人有什么想法吗?任何帮助将不胜感激。

So far I have managed to create a Quaternion for rotation. Only problem is now, how do I apply it to only certain cubes? As when I press the right key on the keyboard at the moment, every cube is being rotated continiously around the origin.

For reference, I have 8 cubes positioned in a similar set-up to that of a Rubik's Cube (2x2x2). So when I press the right/left arrow, the right/left face of the 'Cube' (big cube made up of the 8 smaller cubes), rotates 90 degrees clockwise/anti-clockwise.

An example of one of the Cubes (out of eight cubes in total) declaration:

GameObject subCube3 = new GameObject();  
Vector3 subCube3Pos = new Vector3(-0.55f, -0.55f, 0.55f); 

In my update method:

// declare rotation floats     
float updownRotation = 0.0f;     
float leftrightRot = 0.0f;     

// get state of keyboard     
KeyboardState keys = Keyboard.GetState();     

// if key is pressed, change value of rotation     
if (keys.IsKeyDown(Keys.Right))     
{     
    leftrightRot = -0.10f;     
}

// if key is pressed, change value of rotation     
if (keys.IsKeyDown(Keys.Left))     
{     
    leftrightRot = 0.1f;     
}     

// if key is pressed, change value of rotation     
if (keys.IsKeyDown(Keys.Up))     
{
    updownRotation = 0.1f;     
}

// rotation around axis     
Quaternion addRot = Quaternion.CreateFromAxisAngle(new Vector3(1.0f, 0.0f, 0.0f), leftrightRot);

//rotation of cubes     
cubeRotation = cubeRotation * addRot; 

My draw function:

void DrawGameObject(GameObject gameobject)
{     
    //graphics.GraphicsDevice.RenderState.CullMode = CullMode.None;     
    foreach (ModelMesh mesh in gameobject.model.Meshes)     
    {     
        foreach (BasicEffect effect in mesh.Effects)     
        {     
            effect.EnableDefaultLighting();     
            effect.PreferPerPixelLighting = true;     
            effect.World =     
                Matrix.CreateScale(gameobject.scale) *     
                Matrix.CreateFromQuaternion(cubeRotation) *     
                Matrix.CreateTranslation(gameobject.position);     

            effect.Projection = cameraProjectionMatrix;     
            effect.View = cameraViewMatrix;     
        }
        mesh.Draw();     
    }
}

What I think is the problem is that Matrix.CreateTranslation(gameobject.position) is obviously affecting all my cubes. I've tried creating new Vector3 i.e: c_component1 = Vector3.Transform(cube1pos, cubeRotation); but even then, I am unsure where to put that and actually use it.

Any ideas anyone? Any help will be much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月朦胧 2024-09-20 11:09:13

对于 rubix 立方体场景,除了已有的四元数之外,每个较小的立方体还需要一个四元数。这些较小的季铵盐代表它们与整个批次(您当前拥有的)季铵盐之间的方向差异。认为这里的层次结构与骨骼系统没有什么不同。当您只想旋转几个立方体(例如,全部在左侧)时,您只需将旋转四角乘以那些特定的较小立方体的四角,其他不旋转。

然后,为了绘图,您可以通过将小立方体的四边形与大立方体的四边形连接来创建最终的方向四边形。对每个小立方体都这样做。

您也需要使用相同的向量 3 结构来表示所有较小立方体的位置。

因此,假设您有一个名为 SmallCube 的类,并且已实例化它 8 次。它包含一个 quat 和一个 Vector3(用于位置)。

假设立方体分布在世界各地的原点和终点。你只想旋转上面的。

Foreach(smallCube sc in smallCubes)
{
   if(sc.Position.Y > 0.1f)
   {
     Quaternion addRot = Quaternion.CreateFromAxisAngle(Vector3.Up, MathHelper.ToRadians(90));
     sc.quat *= addRot
     sc.Position = Vector3.Transform(sc.Position, addRot);
   }
}

使用四元数而不是矩阵还有一个额外的好处。您可以使用内置的 Quaternion.Dot() 方法来测试求解。如果所有小立方体方向都相同,则所有颜色必须对齐。发生这种情况时,所有点积将为 1.0f。矩阵中没有同等的功能。

For a rubix cube scenario, in addition to the quat you already have, you would need a quaternion for each smaller cube. these smaller quats represent the orientation difference between them and the quat for the entire batch (the one you currently have). Think hierarchy structure here not unlike a bone sys. When you want to rotate only a few cubes (say, all on the left side) you would only multiply a rotation quat to those specific smaller cube's quats, the others don't rotate.

Then, for drawing, you create the final orientation quat by concatenating the small cube's quat with the big cube's quat. Do that for each small cube.

You will need the same structure for vector3s representing the positions of all the smaller cubes too.

So, let's say you have a class called SmallCube and have instantiated it 8 times. It holds a quat and a Vector3 (for position).

Assume the cubes are laid out around the world origin & you only want to rotate the upper ones.

Foreach(smallCube sc in smallCubes)
{
   if(sc.Position.Y > 0.1f)
   {
     Quaternion addRot = Quaternion.CreateFromAxisAngle(Vector3.Up, MathHelper.ToRadians(90));
     sc.quat *= addRot
     sc.Position = Vector3.Transform(sc.Position, addRot);
   }
}

Using Quaternions for this as opposed to Matrices has an additional benefit. You can use the built in Quaternion.Dot() method to test for solve. If all small cube orientations are the same, all colors must be lined up. When this occurs, all dot product will be 1.0f. There is no equivelent capability in matrices.

别想她 2024-09-20 11:09:13

您需要一些技术来选择您想要旋转的特定立方体,例如通过单击它(对于初学者来说在 XNA 中相当困难)或按键盘上的某个数字,然后在每个游戏对象中,您可以检查它是否被选中并如果是的话,仅应用旋转。

希望这是有道理的......

You would need some technique to select the specific cube you wish to rotate, like by clicking it (pretty hard in XNA for a beginner) or by pressing some number on the keypad, then in each GameObject, you could check if it is selected and only apply the rotation if it is.

Hope this makes sense...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文