-1
\$\begingroup\$

So I spent some time thinking of how I'm going to make a camera similar to what's used in Homeworld (a 3D space RTS, in which your camera can be rotated around your units to look at them from any angle or distance). I'm relatively new to game development so building a camera from scratch is something I've never even conceptualized.

What I came up with that I think could work is having an invisible object as the camera's look-at point. When you pan the camera at the edges, the object moves with the camera just in the opposite direction on some axes. When you zoom there is a min and max distance the camera can translate from and to this object. When you focus on a selected unit, this object moves to the coordinates of that selected unit, forcing the camera to look at it and translate based on the min-max distance, and when you orbit the camera it will orbit around this object.

This seems great to me unless someone has an easier or more efficient method?

\$\endgroup\$

closed as unclear what you're asking by Anko, Seth Battin, Sean Middleditch, bummzack, MrCranky Feb 27 '14 at 15:01

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 4
    \$\begingroup\$ This isn't really the place for "do you think X would work or should I try something else?" type questions. It'd be better if you attempted implementing your solution, then come back with any specific questions if you run into trouble. \$\endgroup\$ – MichaelHouse Feb 19 '14 at 14:42
  • \$\begingroup\$ For reference, our meta conversation on whether or not to accept "would X work" questions: meta.gamedev.stackexchange.com/questions/1048/… \$\endgroup\$ – Trevor Powell Feb 20 '14 at 2:51
2
\$\begingroup\$

I would suggest creating an arc-ball camera. This is a camera that can orbit around the point-of-interest and change its distance from the point-of-interest (basically zooming in and out).

By simpling changing the location of the point-of-interest you get panning for free ;).

Have a look at this code snippet: http://roy-t.nl/index.php/2010/02/21/xna-simple-arcballcamera/

(disclaimer: link to my own blog)

Edit: added full code so it wont be lost.

public class ArcBallCamera
{

    public ArcBallCamera(float aspectRation, Vector3 lookAt)
        : this(aspectRation, MathHelper.PiOver4, lookAt, Vector3.Up, 0.1f, float.MaxValue) { }

    public ArcBallCamera(float aspectRatio, float fieldOfView, Vector3 lookAt, Vector3 up, float nearPlane, float farPlane)
    {
        this.aspectRatio = aspectRatio;
        this.fieldOfView = fieldOfView;            
        this.lookAt = lookAt;
        this.nearPlane = nearPlane;
        this.farPlane = farPlane;
    }

    /// <summary>
    /// Recreates our view matrix, then signals that the view matrix
    /// is clean.
    /// </summary>
    private void ReCreateViewMatrix()
    {
        //Calculate the relative position of the camera                        
        position = Vector3.Transform(Vector3.Backward, Matrix.CreateFromYawPitchRoll(yaw, pitch, 0));
        //Convert the relative position to the absolute position
        position *= zoom;
        position += lookAt;

        //Calculate a new viewmatrix
        viewMatrix = Matrix.CreateLookAt(position, lookAt, Vector3.Up);
        viewMatrixDirty = false;
    }

    /// <summary>
    /// Recreates our projection matrix, then signals that the projection
    /// matrix is clean.
    /// </summary>
    private void ReCreateProjectionMatrix()
    {
        projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, AspectRatio, nearPlane , farPlane);
        projectionMatrixDirty = false;
    }

    #region HelperMethods

    /// <summary>
    /// Moves the camera and lookAt at to the right,
    /// as seen from the camera, while keeping the same height
    /// </summary>        
    public void MoveCameraRight(float amount)
    {
        Vector3 right = Vector3.Normalize(LookAt - Position); //calculate forward
        right = Vector3.Cross(right, Vector3.Up); //calculate the real right
        right.Y = 0;
        right.Normalize();
        LookAt += right * amount;
    }

    /// <summary>
    /// Moves the camera and lookAt forward,
    /// as seen from the camera, while keeping the same height
    /// </summary>        
    public void MoveCameraForward(float amount)
    {
        Vector3 forward = Vector3.Normalize(LookAt - Position);
        forward.Y = 0;
        forward.Normalize();
        LookAt += forward * amount;
    }

    #endregion

    #region FieldsAndProperties
    //We don't need an update method because the camera only needs updating
    //when we change one of it's parameters.
    //We keep track if one of our matrices is dirty
    //and reacalculate that matrix when it is accesed.
    private bool viewMatrixDirty = true;
    private bool projectionMatrixDirty = true;

    public float MinPitch = -MathHelper.PiOver2 + 0.3f;
    public float MaxPitch = MathHelper.PiOver2 - 0.3f;
    private float pitch;
    public float Pitch
    {
        get { return pitch; }
        set
        {
            viewMatrixDirty = true;
            pitch = MathHelper.Clamp(value, MinPitch, MaxPitch);               
        }
    }

    private float yaw;
    public float Yaw
    {
        get { return yaw; }
        set
        {
            viewMatrixDirty = true;
            yaw = value;
        }
    }

    private float fieldOfView;
    public float FieldOfView
    {
        get { return fieldOfView; }
        set
        {
            projectionMatrixDirty = true;
            fieldOfView = value;
        }
    }

    private float aspectRatio;
    public float AspectRatio
    {
        get { return aspectRatio; }
        set
        {
            projectionMatrixDirty = true;
            aspectRatio = value;
        }
    }

    private float nearPlane;
    public float NearPlane
    {
        get { return nearPlane; }
        set
        {
            projectionMatrixDirty = true;
            nearPlane = value;
        }
    }

    private float farPlane;
    public float FarPlane
    {
        get { return farPlane; }
        set
        {
            projectionMatrixDirty = true;
            farPlane = value;
        }
    }

    public float MinZoom = 1;
    public float MaxZoom = float.MaxValue;
    private float zoom = 1;
    public float Zoom
    {
        get { return zoom; }
        set
        {
            viewMatrixDirty = true;
            zoom = MathHelper.Clamp(value, MinZoom, MaxZoom);
        }
    }


    private Vector3 position;
    public Vector3 Position
    {
        get
        {
            if (viewMatrixDirty)
            {
                ReCreateViewMatrix();
            }
            return position;
        }
    }

    private Vector3 lookAt;
    public Vector3 LookAt
    {
        get { return lookAt; }
        set
        {
            viewMatrixDirty = true;
            lookAt = value;
        }
    }
    #endregion

    #region ICamera Members        
    public Matrix ViewProjectionMatrix
    {
        get {return ViewMatrix * ProjectionMatrix; }
    }

    private Matrix viewMatrix;        
    public Matrix ViewMatrix
    {
        get
        {
            if (viewMatrixDirty)
            {
                ReCreateViewMatrix();
            }
            return viewMatrix;
        }
    }

    private Matrix projectionMatrix;
    public Matrix ProjectionMatrix
    {
        get
        {
            if (projectionMatrixDirty)
            {
                ReCreateProjectionMatrix();
            }
            return projectionMatrix;
        }
    }
    #endregion
}
\$\endgroup\$
  • \$\begingroup\$ Please paste the code here. \$\endgroup\$ – Fire Feb 20 '14 at 3:10
  • 1
    \$\begingroup\$ @Fire by posting code on SE sites it's also licensed under CC by-sa 3.0, which may or may not be what the author wants. \$\endgroup\$ – congusbongus Feb 20 '14 at 5:34
  • \$\begingroup\$ @Fire you're absolutely right, I'll add the code here so its forever available (who doesn't hate dead links). I haven't thought of a license yet (actually I didn't even know that the license would be converted by posting here). But I usually go for. "Use it and don't sue me" \$\endgroup\$ – Roy T. Feb 25 '14 at 12:36
  • \$\begingroup\$ Hmm I read up a bit on the license and to be honest I would prefer MIT. But anyway here we go. \$\endgroup\$ – Roy T. Feb 25 '14 at 12:38
  • \$\begingroup\$ Yeah this is pretty similar to what I already have, so guess it's not bad for a first time attemp, only thing is I'm using Unity and without an actual game object as the p.o.i, I faced alot of problems. \$\endgroup\$ – Anomaly Feb 27 '14 at 14:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.