3

一緒にねえ、

初めてここに投稿するのは、私が立ち往生しているからです...

メッシュが(0、0、0)の原点から離れるほど、カメラを回転または移動するときにメッシュが「ジャンプ」/「ちらつき」ます。この効果を説明するのはどういうわけか難しいです。メッシュが少し揺れ/震え/震えているようで、原点までの距離が長くなるにつれて、この震えはどんどん大きくなります。
私の場合、原点から約100000単位の距離で観測できるようになります。たとえば、(0、0、100000)で観測できるようになります。平行移動の軸もメッシュのタイプ(Mesh.Create ...から作成されたデフォルトのメッシュまたはassimp.NETがインポートされた3dsメッシュを使用)もこの効果に影響を与えません。この効果が発生してもメッシュの位置の値は変化しません。位置をログに記録して確認してください。

私が何かを見逃していない場合、これはそれを2つの可能性に絞り込みます:

  1. 私のカメラコード
  2. DirectXデバイス

DirectX-Deviceに関しては、これは私のデバイス初期化コードです。

    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);
    }

フラグまたはrenderstateがありませんか?そのような奇妙な/歪んだ行動を引き起こす可能性のあるものはありますか?

私のカメラクラスはMichaelSilvermansC ++QuaternionCameraに基づいています。

//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が100kを超える距離を処理できないとは想像できません。ソーラーシステムをレンダリングすることになっていて、1ユニット=1kmを使用しています。したがって、地球は太陽までの最大距離(0、0、152100000)でレンダリングされます(例として)。これらの「ジャンプ」が発生し続けると、これは不可能になります。最後に、システムが原点から100k / -100kの距離を超えないように、すべてを縮小することを考えましたが、原点からの距離が大きくなると「ジッター」が大きくなるため、これは機能しないと思います。すべてを縮小すると、ジャンプ動作も縮小されると思います。

4

1 に答える 1

1

この質問に答えないままにしないために(@jcoderのクレジット、質問のコメントを参照):

メッシュの奇妙な動作は、DXの浮動小数点精度に起因します。世界が大きくなるほど、位置を正確に計算するための精度が低下します。

この問題を解決するには、次の2つの可能性があります。

  1. 全世界を縮小すると、
    これは「銀河系」の世界では問題になる可能性があります。この世界では、位置のオフセットが非常に大きく、小さいものもあります(つまり、惑星から太陽までの距離は非常に大きいですが、宇宙船の距離は非常に大きいです)。惑星の軌道上では本当に小さいかもしれません)
  2. このように世界を小さなチャンクに分割するには、
    他の何かに関連するすべての位置を表現するか(stackoverflow.com/questions/1930421を参照)、複数の世界を作成してそれらの間を移動する必要があります
于 2012-11-18T15:25:46.020 に答える