0

我正在使用 rajawali 库在 android 中加载 obj 模型,为此我使用包含访客检测器和访客侦听器的相机类,但我需要在此类中进行额外的平移操作:

public class ArcballCamera extends Camera 
{
    private Context mContext;
    private ScaleGestureDetector mScaleDetector;
    private View.OnTouchListener mGestureListener;
    private GestureDetector mDetector;
    private View mView;
    private boolean mIsRotating;
    private boolean mIsScaling;
    private Vector3 mCameraStartPos;
    private Vector3 mPrevSphereCoord;
    private Vector3 mCurrSphereCoord;
    private Vector2 mPrevScreenCoord;
    private Vector2 mCurrScreenCoord;
    private Quaternion mStartOrientation;
    private Quaternion mCurrentOrientation;
    private Object3D mEmpty;
    private Object3D mTarget;
    private Matrix4 mScratchMatrix;
    private Vector3 mScratchVector;
    private double mStartFOV;

    public ArcballCamera(Context context, View view) {
        this(context, view, null);
    }

    public ArcballCamera(Context context, View view, Object3D target) {
        super();
        mContext = context;
        mTarget = target;
        mView = view;
        initialize();
        addListeners();
    }

    private void initialize() {
        mStartFOV = mFieldOfView;
        mLookAtEnabled = true;
        setLookAt(0, 0, 0);
        mEmpty = new Object3D();
        mScratchMatrix = new Matrix4();
        mScratchVector = new Vector3();
        mCameraStartPos = new Vector3();
        mPrevSphereCoord = new Vector3();
        mCurrSphereCoord = new Vector3();
        mPrevScreenCoord = new Vector2();
        mCurrScreenCoord = new Vector2();
        mStartOrientation = new Quaternion();
        mCurrentOrientation = new Quaternion();
    }

    @Override
    public void setProjectionMatrix(int width, int height) {
        super.setProjectionMatrix(width, height);
    }

    private void mapToSphere(final float x, final float y, Vector3 out)
    {
        float lengthSquared = x * x + y * y;
        if (lengthSquared > 1)
        {
            out.setAll(x, y, 0);
            out.normalize();
        }
        else
        {
            out.setAll(x, y, Math.sqrt(1 - lengthSquared));
        }
    }

    private void mapToScreen(final float x, final float y, Vector2 out)
    {
        out.setX((2 * x - mLastWidth) / mLastWidth);
        out.setY(-(2 * y - mLastHeight) / mLastHeight);
    }

    private void startRotation(final float x, final float y)
    {
        mapToScreen(x, y, mPrevScreenCoord);

        mCurrScreenCoord.setAll(mPrevScreenCoord.getX(), mPrevScreenCoord.getY());

        mIsRotating = true;
    }

    private void updateRotation(final float x, final float y)
    {
        mapToScreen(x, y, mCurrScreenCoord);

        applyRotation();
    }

    private void endRotation()
    {
        mStartOrientation.multiply(mCurrentOrientation);
    }

    private void applyRotation()
    {
        if (mIsRotating)
        {
            mapToSphere((float) mPrevScreenCoord.getX(), (float) mPrevScreenCoord.getY(), mPrevSphereCoord);
            mapToSphere((float) mCurrScreenCoord.getX(), (float) mCurrScreenCoord.getY(), mCurrSphereCoord);

            Vector3 rotationAxis = mPrevSphereCoord.clone();
            rotationAxis.cross(mCurrSphereCoord);
            rotationAxis.normalize();

            double rotationAngle = Math.acos(Math.min(1, mPrevSphereCoord.dot(mCurrSphereCoord)));
            mCurrentOrientation.fromAngleAxis(rotationAxis, MathUtil.radiansToDegrees(rotationAngle));
            mCurrentOrientation.normalize();

            Quaternion q = new Quaternion(mStartOrientation);
            q.multiply(mCurrentOrientation);

            mEmpty.setOrientation(q);
        }
    }

    @Override
    public Matrix4 getViewMatrix() {
        Matrix4 m = super.getViewMatrix();

        if(mTarget != null) {                        mScratchMatrix.identity();
            mScratchMatrix.translate(mTarget.getPosition());
            m.multiply(mScratchMatrix);
        }

        mScratchMatrix.identity();
        mScratchMatrix.rotate(mEmpty.getOrientation());
        m.multiply(mScratchMatrix);

        if(mTarget != null) {
            mScratchVector.setAll(mTarget.getPosition());
            mScratchVector.inverse();

            mScratchMatrix.identity();
            mScratchMatrix.translate(mScratchVector);
            m.multiply(mScratchMatrix);
        }

        return m;
    }

    public void setFieldOfView(double fieldOfView) {
        synchronized (mFrustumLock) {
           mStartFOV = fieldOfView;
           super.setFieldOfView(fieldOfView);
        }
    }

...在这种方法中定义了访客检测器和听众,所以我需要在这里平移。

所以有人告诉我如何在这里使用平移...

            private void addListeners() {
                ((Activity) mContext).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mDetector = new GestureDetector(mContext, new GestureListener());
                        mScaleDetector = new ScaleGestureDetector(mContext, new ScaleListener());

                        mGestureListener = new View.OnTouchListener() {
                            public boolean onTouch(View v, MotionEvent event) {
                                mScaleDetector.onTouchEvent(event);

                                if (!mIsScaling) {
                                    mDetector.onTouchEvent(event);

                                    if (event.getAction() == MotionEvent.ACTION_UP) {
                                        if (mIsRotating) {
                                            endRotation();
                                            mIsRotating = false;
                                        }
                                    }
                                }

                                return true;
                            }
                        };
                        mView.setOnTouchListener(mGestureListener);
                    }
                });
            }

            public void setTarget(Object3D target) {
                mTarget = target;
                setLookAt(mTarget.getPosition());
            }

            public Object3D getTarget() {
                return mTarget;
            }


           private class GestureListener extends GestureDetector.SimpleOnGestureListener {
                @Override
                public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, float distanceY) {
                    if(!mIsRotating) {
                        startRotation(event2.getX(), event2.getY());
                        return false;
                    }
                    mIsRotating = true;
                    updateRotation(event2.getX(), event2.getY());
                    return false;
                }
          }


        private class ScaleListener
                    extends ScaleGestureDetector.SimpleOnScaleGestureListener
         {
                @Override
                public boolean onScale(ScaleGestureDetector detector) {
                    double fov = Math.max(30, Math.min(100, mStartFOV * (1.0 / detector.getScaleFactor())));
                    setFieldOfView(fov);
                    return true;
                }

                @Override
                public boolean onScaleBegin (ScaleGestureDetector detector) {
                    mIsScaling = true;
                    mIsRotating = false;
                    return super.onScaleBegin(detector);
                }

                @Override
                public void onScaleEnd (ScaleGestureDetector detector) {
                    mIsRotating = false;
                    mIsScaling = false;
                }
          }



        }**
4

0 回答 0