关于3D场景中Camera的旋转

【本人初学,一点感悟,如有不当,请不吝指教】

       很多人想达到3D场景中,基于鼠标控制的Camera任意角度旋转,其实不难,分为其下两步:

一、 基于鼠标移动过程的建模

这一步,在于你是如何理解mouse在一个二维平面从previouspositioncurrentpositon所表示的意图,网络上有一种很通用的方法“virtual trackball”。本人目前也是采用的这种方法,故而在这里简单介绍一下

1. 直观感觉(Daniel Lehenbauer 主页)

      

 

Figure 1 Moving with mouse

 

2. 理解

 

                     

把整个空间的场景先归一化到一个单位立方体,视野里的平面即为一个中心切面,鼠标在平面(2维空间)的坐标可以映射到一个三维球面上(注意:这里是映射到3维球面上,如果你有更好的模型,完全可以映射到更好的三维空间中),这样就理解成球面上的移动,进而产生旋转的效果。

这是2维平面点映射到3维球面点的方法:

    private Vector3D TransTo3DPoint(Double width, Double height, Point point)

    {

        Double x = point.X / (width / 2);       // Scale so bounds map to [0,0] - [2,2]

        Double y = point.Y / (height / 2);

 

        x = x - 1;          // Translate 0,0 to the center

        y = 1 - y;          //Flip so y is up instead of down

 

        Double ztemp = 1 - x * x - y * y;       // z^2 + x^2 - y^2 = 1

        Double z = ztemp > 0 ? Math.Sqrt(ztemp) : 0;

        return new Vector3D(x, y, z);

    }

 

 

3. 根据模型球面上初始点和当前点,得到旋转轴和旋转角度,调用旋转Camera的方法,即可实现空间中的所有场景的自由旋转。

private void Rotate(Point currentPosition)

{

    // Call the TransTo3DPoint to get the currentPosition3D

    Vector3D currentPosition3D = TransTo3DPoint(GoWindow.ActualWidth, GoWindow.ActualHeight, currentPosition);

    // Call Vector3D.CrossProduct to realize the 叉乘

    Vector3D axis = Vector3D.CrossProduct(previousPosition3D, currentPosition3D);

    // Call Vector3D.AngleBetween to achieve the angle between two vectors

    Double angle = Vector3D.AngleBetween(previousPosition3D, currentPosition3D);

    // rotate the camera

    RotateCamera(axis, angle); 

    // erery time we should reset the previousPosition

    previousPosition3D = currentPosition3D;

}

 

 

二、 基于旋转向量和旋转角度的Camera旋转

首先需要定义Camera的旋转方式(我之前找这个无果,想到了用旋转矩阵这种方法,套用了一堆3维空间的坐标系旋转公式,效果并不理想):

<PerspectiveCamera.Transform>

                        <Transform3DGroup>

                            <RotateTransform3D x:Name="axisYRTransform">

                                <RotateTransform3D.Rotation>

                                    <AxisAngleRotation3D x:Name="axisYRotation" Angle="0" Axis="0 1 0" />

                                </RotateTransform3D.Rotation>

                            </RotateTransform3D>

                        </Transform3DGroup>

                    </PerspectiveCamera.Transform>

 

那么接下来要做的就是写上一个小小的函数用来旋转特定的Camera了:

private void RotateCamera(Vector3D axis, Double angle)

        {

            Vector3D vecZero = new Vector3D(0.0,0.0,0.0);

            if (vecZero == axis || 0 == angle)

                return;

 

            Quaternion delta = new Quaternion(axis, angle);

            // axisYRotation is the name of camera AxisAngleRotation3D

            Quaternion q = new Quaternion(axisYRotation.Axis, axisYRotation.Angle);

 

            q *= delta;

 

            if (Vector3D.Equals(q.Axis, vecZero))

                return;

 

            axisYRotation.Axis = q.Axis;

            axisYRotation.Angle = q.Angle;

        }

 

好,现在大功告成,其实真不难,哎,折腾了1天多,希望对大家有用,如果有更好的模型或者更好的实现方法,我希望能得到你的指点,我的邮箱:v-xyang@microsoft.com,谢谢你。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用PySide2生成可旋转3D场景,您可以使用Qt 3D框架的相机(QCamera)和视图(QViewport)组件。以下是一个简单的示例,演示如何使用PySide2创建可旋转3D场景: ```python import sys from PySide2.Qt3DCore import Qt3DCore from PySide2.Qt3DExtras import Qt3DExtras from PySide2.Qt3DRender import Qt3DRender from PySide2.QtGui import QGuiApplication from PySide2.QtWidgets import QWidget, QHBoxLayout app = QGuiApplication(sys.argv) # create a window and a 3D scene widget = QWidget() layout = QHBoxLayout(widget) view = Qt3DExtras.Qt3DWindow() scene = Qt3DCore.QEntity() # create a 3D model entity and add it to the scene model = Qt3DRender.QMesh() model.setSource(QUrl.fromLocalFile("path/to/model/file")) entity = Qt3DCore.QEntity(scene) entity.addComponent(model) # create a camera and a viewport camera = Qt3DRender.QCamera(scene) camera.setViewCenter(Qt3DCore.QVector3D(0, 0, 0)) camera.setPosition(Qt3DCore.QVector3D(0, 0, 40)) view_port = Qt3DExtras.QViewport(camera) view.setRootEntity(scene) view.setViewport(view_port) # add the scene to the view and show the window layout.addWidget(view.container()) widget.show() sys.exit(app.exec_()) ``` 在代码,我们创建了一个相机和一个视口,然后将它们添加到3D场景。我们还设置了相机的位置和视角心,以控制场景旋转。最后,我们将场景添加到视图,并显示窗口。 请注意,此示例仅演示了如何创建可旋转3D场景。如果您需要更复杂的3D场景,您可能需要使用其他Qt 3D组件和类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值