commit 9456beab576d8a918ec9efb15ece6a7be32bb158
parent fbd0007a1e3cede28d71dd1939595a44632caf6d
Author: William Casarin <jb55@jb55.com>
Date: Tue, 6 Nov 2018 18:20:26 -0800
spherical coord camera
Diffstat:
16 files changed, 148 insertions(+), 70 deletions(-)
diff --git a/src/event.c b/src/event.c
@@ -9,6 +9,9 @@ void process_events(struct game *game, float *camera) {
int mdx = 0;
int mdy = 0;
+ game->input.last_mx = game->input.mx;
+ game->input.last_my = game->input.my;
+
input_reset(&game->input);
while (SDL_PollEvent(&event)) {
@@ -27,14 +30,10 @@ void process_events(struct game *game, float *camera) {
game->input.mbuttons[event.button.button-1] = 0;
break;
case SDL_MOUSEMOTION:
- if (event.button.button) {
- /* printf("drag... %d %d\n", event.motion.xrel, event.motion.yrel); */
- game->input.last_mx = game->input.mx;
- game->input.last_my = game->input.mx;
- game->input.mx = event.motion.x;
- game->input.my = event.motion.y;
-
- }
+ game->input.mx = event.motion.x;
+ game->input.my = event.motion.y;
+ game->input.mdx += event.motion.xrel;
+ game->input.mdy += event.motion.yrel;
break;
case SDL_WINDOWEVENT:
switch (event.window.event) {
diff --git a/src/game.c b/src/game.c
@@ -31,16 +31,21 @@ struct entity *get_player(struct resources *res) {
return player;
}
+static void init_user_settings(struct user_settings *settings) {
+ SDL_SetRelativeMouseMode(SDL_TRUE);
+ settings->mouse_sens = 0.2;
+}
+
void game_init(struct game *game, int width, int height) {
init_gl(&game->test_resources, width, height);
init_entity_system();
+ init_user_settings(&game->user_settings);
check_gl();
- float pos[3];
struct resources *res = &game->test_resources;
mat4 *mvp = res->test_mvp;
struct node *root = &res->root;
- struct node *camera = &res->camera;
+ struct node *camera = &res->camera.node;
struct node *sun_camera = &res->sun_camera;
struct terrain *terrain = &game->terrain;
struct entity *player;
@@ -88,10 +93,6 @@ void game_init(struct game *game, int width, int height) {
game->test_resources.fog_on = 1;
game->test_resources.diffuse_on = 0;
- res->orbit_camera.azimuth = RAD(90.0);
- res->orbit_camera.inclination = RAD(180.0);
- res->orbit_camera.radius = RAD(180.0);
-
node_init(root);
node_init(camera);
node_init(sun_camera);
@@ -106,6 +107,10 @@ void game_init(struct game *game, int width, int height) {
node_attach(&player->node, root);
node_translate(&player->node, V3(terrain->size/2.,terrain->size/2.,0.0));
+ res->camera.coords.azimuth = -quat_yaw(player->node.orientation) - RAD(90.0);
+ res->camera.coords.inclination = RAD(60);
+ res->camera.coords.radius = 200.0;
+
struct entity *tower = new_entity(NULL);
ok = load_model(&tower->model, "tower");
assert(ok);
@@ -122,12 +127,12 @@ void game_init(struct game *game, int width, int height) {
root->label = "root";
camera->label = "camera";
- node_attach(camera, &player->node);
+ /* node_attach(camera, &player->node); */
- quat_axis_angle(V3(1,0,0), -45, camera->orientation);
+ /* quat_axis_angle(V3(1,0,0), -45, camera->orientation); */
- node_rotate(camera, V3(100, 0, 0));
- node_translate(camera, V3(0,-40,20));
+ /* node_rotate(camera, V3(100, 0, 0)); */
+ /* node_translate(camera, V3(0,-40,20)); */
input_init(&game->input);
diff --git a/src/game.h b/src/game.h
@@ -57,8 +57,7 @@ struct resources {
struct node root;
struct entity_id player_id;
- struct orbit orbit_camera;
- struct node camera;
+ struct orbit camera;
struct node sun_camera;
float time;
@@ -72,10 +71,15 @@ struct resources {
float proj_ortho[MAT4_ELEMS];
};
+struct user_settings {
+ float mouse_sens;
+};
+
struct game {
int counter;
int seed;
float dt;
+ struct user_settings user_settings;
struct ui ui;
struct resources test_resources;
struct input input;
diff --git a/src/input.c b/src/input.c
@@ -6,9 +6,10 @@
void input_init(struct input *input) {
/* memset(input->keys, 0, sizeof(input->keys[0]) * ARRAY_SIZE(input->keys)); */
input->keystates = SDL_GetKeyboardState(NULL);
- input->is_dragging = 0;
input->mx = 0;
input->my = 0;
+ input->mdx = 0;
+ input->mdy = 0;
input->last_mx = 0;
input->last_my = 0;
assert(input->keystates);
@@ -20,13 +21,10 @@ void handle_key(struct input *input, SDL_KeyboardEvent key) {
void input_reset(struct input *input) {
- input->is_dragging = 0;
-
- for (int i = 0; i < MOUSE_BUTTONS; ++i)
- input->mbuttons[i] = 0;
+ input->mdx = 0;
+ input->mdy = 0;
}
int input_is_dragging(struct input *input, int mouse_button) {
- return input->mbuttons[mouse_button-1] &&
- (input->last_mx != input->mx || input->last_my != input->my);
+ return input->mbuttons[mouse_button-1];
}
diff --git a/src/input.h b/src/input.h
@@ -19,7 +19,7 @@ struct input {
u8 const *keystates;
SDL_Keymod modifiers;
int mx, my, last_mx, last_my;
- int is_dragging;
+ int mdx, mdy;
int mbuttons[MOUSE_BUTTONS];
};
diff --git a/src/main.c b/src/main.c
@@ -73,7 +73,7 @@ int main(void)
struct render_config default_config = {
.draw_ui = 1,
.is_depth_pass = 0,
- .camera = game.test_resources.camera.mat,
+ .camera = game.test_resources.camera.node.mat,
.projection = game.test_resources.proj_persp,
.depth_vp = depth_vp
};
diff --git a/src/mat_util.c b/src/mat_util.c
@@ -1,10 +1,7 @@
#include "mat_util.h"
-mat4 *mat4_create_transform(float *pos, float *scale, quat *orientation, mat4 *dest) {
- float rot[9];
- quat_to_mat3(orientation, rot);
-
+mat4 *mat4_create_transform(float *pos, float *scale, float *rot, mat4 *dest) {
dest[0] = scale[0] * rot[0];
dest[1] = scale[0] * rot[1];
dest[2] = scale[0] * rot[2];
@@ -28,3 +25,12 @@ mat4 *mat4_create_transform(float *pos, float *scale, quat *orientation, mat4 *d
return dest;
}
+
+vec3 *vec3_forward(vec3 *v, quat *orientation, float *dir, float *dest) {
+ float q[4] = {0};
+ float movement[3] = {0};
+ quat_inverse(orientation, q);
+ quat_multiply_vec3(q, dir, movement);
+ vec3_add(v, movement, dest);
+ return dest;
+}
diff --git a/src/mat_util.h b/src/mat_util.h
@@ -8,6 +8,6 @@
void look_at(vec3 *eye, vec3 *target, vec3 *up, mat4 *dest);
mat4 *mat4_create_transform(float *pos, float *scale, quat *orientation, mat4 *dest);
-vec3 *vec3_forward(vec3 *p, quat orientation, vec3 *dest);
+vec3 *vec3_forward(vec3 *p, quat *orientation, vec3 *dir, float *dest);
#endif /* POLYADVENT_MAT_UTIL_H */
diff --git a/src/node.c b/src/node.c
@@ -2,6 +2,7 @@
#include "node.h"
#include "mat_util.h"
+#include <string.h>
#include <stdio.h>
#include <assert.h>
@@ -14,6 +15,7 @@ struct node *node_init(struct node *node) {
node->n_children = 0;
for (int i = 0; i < MAX_NODE_CHILDREN; ++i)
node->children[i] = NULL;
+ node->flags = 0;
node->parent = NULL;
node->label = "unknown";
node->needs_recalc = 0;
@@ -52,7 +54,8 @@ void node_rotate(struct node *node, vec3 *axis_angles) {
node_mark_for_recalc(node);
}
-int node_needs_recalc(struct node *node) {
+int node_needs_recalc(struct node *node)
+{
return (node->parent && node->parent->needs_recalc) || node->needs_recalc;
}
@@ -81,6 +84,7 @@ static void node_recalc_children(struct node *node) {
int node_recalc(struct node *node) {
assert(node);
+ float rot[9] = {1.0};
if (node->parent && node_needs_recalc(node->parent))
node_recalc(node->parent);
@@ -92,7 +96,8 @@ int node_recalc(struct node *node) {
node->needs_recalc = 0;
- mat4_create_transform(node->pos, node->scale, node->orientation, node->mat);
+ quat_to_mat3(node->orientation, rot);
+ mat4_create_transform(node->pos, node->scale, rot, node->mat);
if (node->parent) {
assert(!node->parent->needs_recalc);
@@ -116,11 +121,10 @@ void node_attach(struct node *node, struct node *to) {
}
void node_forward(struct node *node, float *dir) {
- float movement[3] = {0};
- float q[4] = {0};
- quat_inverse(node->orientation, q);
- quat_multiply_vec3(q, dir, movement);
- vec3_add(node->pos, movement, node->pos);
+ vec3_forward(node->pos, node->orientation, dir, node->pos);
+ /* quat_inverse(node->orientation, q); */
+ /* quat_multiply_vec3(q, dir, movement); */
+ /* vec3_add(node->pos, movement, node->pos); */
/* printf("dir %f %f %f\nmovement %f %f %f\nquat %f %f %f %f\n", */
/* dir[0], dir[1], dir[2], */
/* movement[0], movement[1], movement[2], */
diff --git a/src/node.h b/src/node.h
@@ -4,6 +4,10 @@
#define MAX_NODE_CHILDREN 4
+enum node_flags {
+ NODE_IGNORE_RECALC = 1 << 0
+};
+
struct node {
float pos[3];
float rot[3];
@@ -12,6 +16,7 @@ struct node {
float orientation[4];
char *label;
int needs_recalc;
+ int flags;
int n_children;
void (*custom_update)(struct node*);
void *custom_update_data;
diff --git a/src/orbit.c b/src/orbit.c
@@ -2,20 +2,45 @@
#include "orbit.h"
#include "node.h"
#include "vec3.h"
+#include "mat4.h"
#include "quat.h"
+#include "util.h"
#include <math.h>
-void orbit_to_mat4(struct orbit *orbit, float *m)
+float *spherical_to_cartesian(struct spherical *s, float *v3)
{
- quat_axis_angle(orbit->angles.ypr)
+ float theta = s->inclination;
+ float phi = s->azimuth;
+
+ float sin_theta = sin(theta);
+ float cos_phi = cos(phi);
+ float cos_theta = cos(theta);
+
+ // to cartesian
+ v3[0] = s->radius * sin_theta * cos_phi;
+ v3[1] = s->radius * sin_theta * sin(phi);
+ v3[2] = s->radius * cos_theta;
+
+ return v3;
}
-/* static void orbit_update_node(struct node *node) { */
-/* } */
-void orbit_to_node(struct orbit *orbit, struct node *node) {
- /* orbit_to_quat(orbit, node->orientation); */
- node_mark_for_recalc(node);
+// from: in
+// to: out
+float *spherical_pos(struct spherical *s, vec3 *from, vec3 *to) {
+ float spherical_offset[3];
+ spherical_to_cartesian(s, spherical_offset);
+ vec3_add(from, spherical_offset, to);
+ return to;
}
+float *spherical_look_at(struct spherical *s, vec3 *target, mat4 *mat) {
+ float eye[3];
+
+ spherical_pos(s, target, eye);
+ look_at(eye, target, V3(0.0, 0.0, 1.0), mat);
+ return mat;
+}
+
+
diff --git a/src/orbit.h b/src/orbit.h
@@ -2,24 +2,23 @@
#ifndef ORBIT_H
#define ORBIT_H
-struct node;
+#include "vec3.h"
+#include "node.h"
+#include "mat4.h"
+
+struct spherical {
+ float radius;
+ float inclination;
+ float azimuth;
+};
struct orbit {
- float dist;
- union {
- struct {
- float yaw;
- float pitch;
- float roll;
- };
-
- float ypr[3];
- } angles;
+ struct spherical coords;
+ struct node node;
};
-
-void orbit_to_node(struct orbit *orbit, struct node *node);
-void orbit_to_quat(struct orbit *, float *a);
-
+float *spherical_pos(struct spherical *s, vec3 *from, vec3 *to);
+float *spherical_look_at(struct spherical *s, vec3 *target, mat4 *mat);
+float *spherical_to_cartesian(struct spherical *s, float *v3);
#endif /* ORBIT_H */
diff --git a/src/quat.c b/src/quat.c
@@ -74,6 +74,11 @@ void quat_to_mat3(quat *quat, float *dest) {
dest[8] = 1.0 - (xx + yy);
}
+
+float quat_yaw(quat *q) {
+ return atan2(q[2],q[3])*2.0;
+}
+
void quat_multiply_vec3(quat *quat, float *vec, float *dest) {
float x = vec[0], y = vec[1], z = vec[2];
float qx = quat[0], qy = quat[1], qz = quat[2], qw = quat[3];
diff --git a/src/quat.h b/src/quat.h
@@ -11,6 +11,7 @@ void quat_multiply(quat *a, quat *b, quat *dest);
void quat_axis_angle(float *axis, float angle, quat *dest);
void quat_from_axes(float yaw, float pitch, float roll);
void quat_to_mat3(quat *quat, float *dest);
+float quat_yaw(quat *quat);
void quat_multiply_vec3(quat *quat, float *vec, float *dest);
quat *quat_inverse(quat *q, quat *dest);
diff --git a/src/update.c b/src/update.c
@@ -8,6 +8,7 @@
#include "camera.h"
#include "poisson.h"
#include "uniform.h"
+#include "mat_util.h"
#include "shader.h"
#include "file.h"
#include <math.h>
@@ -299,17 +300,42 @@ static void gravity(struct game *game) {
node_translate(&player->node, V3(0.0, 0.0, -1.0));
}
-static void player_update(struct game *game, struct entity *player) {
- struct orbit *orbit_camera = &game->test_resources.orbit_camera;
- /* orbit_camera->radius += game->dt * 4.0; */
- /* orbit_camera->inclination += game->dt * 2.0; */
- /* orbit_camera->azimuth += game->dt * 2.0; */
- /* orbit_to_node(orbit_camera, &game->test_resources.camera); */
+void orbit_update_from_mouse(struct orbit *camera, struct input *input,
+ float mouse_sens, struct entity *player,
+ float dt) {
+ float *target;
+ struct node *target_node = &player->node;
+
+ node_recalc(target_node);
+ target = node_world(target_node);
+
+ float mx = 0.0, my = 0.0;
+ if (input_is_dragging(input, SDL_BUTTON_LEFT) ||
+ input_is_dragging(input, SDL_BUTTON_RIGHT)) {
+ mx = -input->mdx * mouse_sens * dt;
+ my = -input->mdy * mouse_sens * dt;
+ }
+
+ camera->coords.azimuth += mx;
+ camera->coords.inclination += my;
+ spherical_look_at(&camera->coords, target, camera->node.mat);
+}
+static void player_update(struct game *game, struct entity *player) {
+ orbit_update_from_mouse(&game->test_resources.camera, &game->input,
+ game->user_settings.mouse_sens, player, game->dt);
+ // move player camera toward camera orientation
+ if (input_is_dragging(&game->input, SDL_BUTTON_RIGHT)) {
+ float yaw = game->test_resources.camera.coords.azimuth;
+ quat_axis_angle(V3(0.0, 0.0, 1.0), -yaw - RAD(90), player->node.orientation);
+ node_recalc(&player->node);
+ }
player_terrain_collision(&game->terrain, player);
}
+
+
void update (struct game *game) {
static int toggle_fog = 0;
static int first = 1;
@@ -331,7 +357,7 @@ void update (struct game *game) {
player_update(game, player);
if (game->input.modifiers & KMOD_LALT) {
- movement(game, &res->camera, 1.0);
+ movement(game, &res->camera.node, 1.0);
}
else if (game->input.modifiers & KMOD_RCTRL) {
movement(game, tnode, 5.0);
diff --git a/src/util.h b/src/util.h
@@ -16,6 +16,7 @@
} \
}
+#define UP_VEC V3(0.0, 0.0, 1.0)
#define PI 3.14159265
#define TAU 6.2831853