首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >网格开始在摄像机的旋转/运动中跳跃

网格开始在摄像机的旋转/运动中跳跃
EN

Stack Overflow用户
提问于 2012-11-08 13:41:45
回答 1查看 399关注 0票数 3

嘿,一起,

第一次在这里发帖,因为我被困住了.

离原点(0,0,0)越远的网格,在旋转或移动相机时越“跳跃”/“闪烁”。很难描述这种效果:就像网格在抖动/颤抖/颤抖,随着距离的增加,这种震动变得越来越大。

对我来说,它开始在距离原点大约100000单位的地方被观测到,例如在(0,0,100000)。翻译的轴和网格的类型(从Mesh.Create创建的默认网格.或assimp.NET进口3ds网眼)对此有影响。当发生此效果时,网格位置的值不会改变,请通过记录位置来检查此值。

如果我没有遗漏一些东西,这就把它缩小到两种可能性:

  1. 我的相机代码
  2. DirectX设备

至于DirectX设备,这是我的设备初始化代码:

代码语言:javascript
复制
    private void InitializeDevice()
    {
        //Initialize D3D
        _d3dObj = new D3D9.Direct3D();

        //Set presentation parameters
        _presParams = new D3D9.PresentParameters();
        _presParams.Windowed = true;
        _presParams.SwapEffect = D3D9.SwapEffect.Discard;
        _presParams.AutoDepthStencilFormat = D3D9.Format.D16;
        _presParams.EnableAutoDepthStencil = true;
        _presParams.PresentationInterval = D3D9.PresentInterval.One;
        _presParams.BackBufferFormat = _d3dObj.Adapters.DefaultAdapter.CurrentDisplayMode.Format;
        _presParams.BackBufferHeight = _d3dObj.Adapters.DefaultAdapter.CurrentDisplayMode.Height;
        _presParams.BackBufferWidth = _d3dObj.Adapters.DefaultAdapter.CurrentDisplayMode.Width;

        //Set form width and height to current backbuffer width und height
        this.Width = _presParams.BackBufferWidth;
        this.Height = _presParams.BackBufferHeight;

        //Checking device capabilities
        D3D9.Capabilities caps = _d3dObj.GetDeviceCaps(0, D3D9.DeviceType.Hardware);
        D3D9.CreateFlags devFlags = D3D9.CreateFlags.SoftwareVertexProcessing;
        D3D9.DeviceType devType = D3D9.DeviceType.Reference;

        //setting device flags according to device capabilities
        if ((caps.VertexShaderVersion >= new Version(2, 0)) && (caps.PixelShaderVersion >= new Version(2, 0)))
        {
            //if device supports vertexshader and pixelshader >= 2.0
            //then use the hardware device
            devType = D3D9.DeviceType.Hardware;

            if (caps.DeviceCaps.HasFlag(D3D9.DeviceCaps.HWTransformAndLight))
            {
                devFlags = D3D9.CreateFlags.HardwareVertexProcessing;
            }
            if (caps.DeviceCaps.HasFlag(D3D9.DeviceCaps.PureDevice))
            {
                devFlags |= D3D9.CreateFlags.PureDevice;
            }
        }

        //initialize the device
        _device = new D3D9.Device(_d3dObj, 0, devType, this.Handle, devFlags, _presParams);
        //set culling
        _device.SetRenderState(D3D9.RenderState.CullMode, D3D9.Cull.Counterclockwise);
        //set texturewrapping (needed for seamless spheremapping)
        _device.SetRenderState(D3D9.RenderState.Wrap0, D3D9.TextureWrapping.All);
        //set lighting
        _device.SetRenderState(D3D9.RenderState.Lighting, false);
        //enabling the z-buffer
        _device.SetRenderState(D3D9.RenderState.ZEnable, D3D9.ZBufferType.UseZBuffer);
        //and setting write-access exlicitly to true...
        //i'm a little paranoid about this since i had to struggle for a few days with weirdly overlapping meshes
        _device.SetRenderState(D3D9.RenderState.ZWriteEnable, true);
    }

我是不是漏掉了一面旗帜还是一个国家?有什么东西会导致这种奇怪的/扭曲的行为吗?

我的相机类是基于迈克尔·西尔弗曼C++四元数相机

代码语言:javascript
复制
//every variable prefixed with an underscore is 
//a private static variable initialized beforehand
public static class Camera
{
    //gets called every frame
    public static void Update()
    {
        if (_filter)
        {
            _filteredPos = Vector3.Lerp(_filteredPos, _pos, _filterAlpha);
            _filteredRot = Quaternion.Slerp(_filteredRot, _rot, _filterAlpha);
        }

        _device.SetTransform(D3D9.TransformState.Projection, Matrix.PerspectiveFovLH(_fov, _screenAspect, _nearClippingPlane, _farClippingPlane));
        _device.SetTransform(D3D9.TransformState.View, GetViewMatrix());
    }

    public static void Move(Vector3 delta)
    {
        _pos += delta;
    }

    public static void RotationYaw(float theta)
    {
        _rot = Quaternion.Multiply(Quaternion.RotationAxis(_up, -theta), _rot);
    }

    public static void RotationPitch(float theta)
    {
        _rot = Quaternion.Multiply(_rot, Quaternion.RotationAxis(_right, theta));
    }

    public static void SetTarget(Vector3 target, Vector3 up)
    {
        SetPositionAndTarget(_pos, target, up);
    }

    public static void SetPositionAndTarget(Vector3 position, Vector3 target, Vector3 upVec)
    {
        _pos = position;

        Vector3 up, right, lookAt = target - _pos;

        lookAt = Vector3.Normalize(lookAt);
        right = Vector3.Cross(upVec, lookAt);
        right = Vector3.Normalize(right);
        up = Vector3.Cross(lookAt, right);
        up = Vector3.Normalize(up);

        SetAxis(lookAt, up, right);
    }

    public static void SetAxis(Vector3 lookAt, Vector3 up, Vector3 right)
    {
        Matrix rot = Matrix.Identity;

        rot.M11 = right.X;
        rot.M12 = up.X;
        rot.M13 = lookAt.X;

        rot.M21 = right.Y;
        rot.M22 = up.Y;
        rot.M23 = lookAt.Y;

        rot.M31 = right.Z;
        rot.M32 = up.Z;
        rot.M33 = lookAt.Z;

        _rot = Quaternion.RotationMatrix(rot);
    }

    public static void ViewScene(BoundingSphere sphere)
    {
        SetPositionAndTarget(sphere.Center - new Vector3((sphere.Radius + 150) / (float)Math.Sin(_fov / 2), 0, 0), sphere.Center, new Vector3(0, 1, 0));
    }

    public static Vector3 GetLookAt()
    {
        Matrix rot = Matrix.RotationQuaternion(_rot);
        return new Vector3(rot.M13, rot.M23, rot.M33);
    }

    public static Vector3 GetRight()
    {
        Matrix rot = Matrix.RotationQuaternion(_rot);
        return new Vector3(rot.M11, rot.M21, rot.M31);
    }

    public static Vector3 GetUp()
    {
        Matrix rot = Matrix.RotationQuaternion(_rot);
        return new Vector3(rot.M12, rot.M22, rot.M32);
    }

    public static Matrix GetViewMatrix()
    {
        Matrix viewMatrix, translation = Matrix.Identity;
        Vector3 position;
        Quaternion rotation;

        if (_filter)
        {
            position = _filteredPos;
            rotation = _filteredRot;
        }
        else
        {
            position = _pos;
            rotation = _rot;
        }

        translation = Matrix.Translation(-position.X, -position.Y, -position.Z);
        viewMatrix = Matrix.Multiply(translation, Matrix.RotationQuaternion(rotation));

        return viewMatrix;
    }
}

你能在摄像机代码中发现任何可能导致这种行为的东西吗?

我无法想象DirectX不能处理超过100 K的距离。我应该渲染太阳系,我用的是1单位=1公里。因此,地球将在它与太阳的最大距离(0,0,152100000)处呈现出来(就像一个例子)。如果这些“跳跃”继续发生,这就变得不可能了。最后,我考虑缩小所有的范围,这样一个系统就不会超过从原点到100 k/-100 k的距离,但我认为这是行不通的,因为“抖动”随着距离的增大而变大。缩小每件事都会--我认为--也会减少跳跃的行为。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-11-18 15:25:46

为了不让这个问题没有答案( @jcoder的学分,请参阅问题的注释):

网格的怪异行为来源于DX的浮点精度。你的世界越大,精确计算位置的精度就越低。

解决这个问题有两种可能性:

  1. 降低全世界的规模 在“银河式”的世界中,这可能是个问题,在这个世界中,你有非常大的位置偏移量,也有非常小的位置偏移量(例如,行星与太阳的距离很大,但飞船在行星轨道上的距离可能真的很小)。
  2. 把世界分成小块 通过这种方式,您要么表示与其他事物相关的所有位置(参见stackoverflow.com网站/问询/1930421),要么创建多个世界,并以某种方式在它们之间移动
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13290098

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档