summaryrefslogtreecommitdiff
path: root/src/Camera.java
blob: 1db6f37d5c1fb9b48e3c805a5328e9af22738756 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

import robotrace.Vector;
import static java.lang.Math.*;
import robotrace.GlobalState;

/**
 * Implementation of a camera with a position and orientation.
 */
class Camera {

    /** The position of the camera. */
    public Vector eye = new Vector(3f, 6f, 5f);

    /** The point to which the camera is looking. */
    public Vector center = Vector.O;

    /** The up vector. */
    public Vector up = Vector.Z;
    
    /** Race track used. */
    private RaceTrack track;

    /**
     * A reference to the global game state from RobotRace.
     */
    private final GlobalState gs;

    /**
     * Robots that are to be tracked by the camera.
     */
    private final Robot[] robots;

    public Camera(GlobalState gs, RaceTrack track, Robot[] robots) {
        this.gs = gs;
        this.track = track;
        this.robots = robots;
    }

    /**
     * Updates the camera viewpoint and direction based on the
     * selected camera mode.
     */
    public void update(int mode) {
        if (1 == mode) { // Helicopter mode
            setHelicopterMode();
        } else if (2 == mode) { // Motor cycle mode
            setMotorCycleMode();
        } else if (3 == mode) { // First person mode
            setFirstPersonMode();
        } else if (4 == mode) { // Auto mode
            // code goes here...
        } else { // Default mode
            setDefaultMode();
        }
    }

    /**
     * Computes {@code eye}, {@code center}, and {@code up}, based
     * on the camera's default mode.
     */
    private void setDefaultMode() {
        /*        z |
         *          |   vDist %
         *          |    %    * Ez
         *          |%________*________ y
         *      Ex /    %     *
         *      /        s %  *
         * x /  - - - - - - - *
         *           Ey
         * phi is angle between vDist and XY plane (Z direction)
         * theta is angle between X-axis and s (XY plane)
         * E = (Ex, Ey, Ez)
         * sin phi  = Ez / vDist => Ez = vDist * sin phi
         * cos phi = s / vDist => s = vDist * cos phi
         * Ex = s * sin theta
         * Ey = s * cos theta
         */
        float Ex, Ey, Ez, s;
        Ez = gs.vDist * (float) sin(gs.phi);
        s = gs.vDist * (float) cos(gs.phi);
        Ex = s * (float) sin(gs.theta);
        Ey = s * (float) cos(gs.theta);

        eye = new Vector(Ex, Ey, Ez);

        // WASD action: center point and eye point translate
        double Cx, Cy, Cz;
        // x and y are swapped because robot looks in y direction
        Cx = -gs.cnt.y();
        Cy = gs.cnt.x();
        Cz = gs.cnt.z();
        center = new Vector(Cx, Cy, Cz);
        eye = eye.add(center);

        // just look straight forward
        up = Vector.Z;
    }

    /**
     * Computes {@code eye}, {@code center}, and {@code up}, based
     * on the helicopter mode.
     */
    private void setHelicopterMode() {
        /**
         * In the Helicopter view, the camera (eye point) is located above the
         * robots. Take the average time of the robots and use that to determine
         * the position and direction.
         */
        double time_sum = 0;
        for (Robot robot : robots) {
            time_sum += robot.getTimePos();
        }
        // for now stay in the middle of the robots, later we could follow the
        // fastest (or slowest) robot if desired.
        double time_avg = time_sum / robots.length;

        // center at the center lane
        center = track.getPointForLane(time_avg, robots.length / 2 + .5);

        // look in the direction where the robots walks, namely the tangent
        up = track.getTangent(time_avg);

        // "above" is 10 meters.
        eye = center.add(new Vector(0, 0, 10f));
    }

    /**
     * Computes {@code eye}, {@code center}, and {@code up}, based
     * on the motorcycle mode.
     */
    private void setMotorCycleMode() {
        // code goes here ...
    }

    /**
     * Computes {@code eye}, {@code center}, and {@code up}, based
     * on the first person mode.
     */
    private void setFirstPersonMode() {
        // code goes here ...
    }
}