terrain

Real-time terrain generation using marching cubes
git clone git://git.christianermann.dev/terrain
Log | Files | Refs | README | LICENSE

camera.c (5118B)


      1 #include "camera.h"
      2 
      3 #include <math.h>
      4 #include <stdlib.h>
      5 
      6 Camera *Camera_make(Transform *t)
      7 {
      8     Camera *camera = malloc(sizeof *camera);
      9     camera->transform = t;
     10     Camera_defaultSettings(camera);
     11     Camera_updateMatrix(camera);
     12     Camera_updateFrustum(camera);
     13     return camera;
     14 }
     15 
     16 void Camera_free(Camera *camera)
     17 {
     18     if (camera)
     19     {
     20         free(camera);
     21     }
     22 }
     23 
     24 void Camera_defaultSettings(Camera* camera)
     25 {
     26     camera->fovy = 90.0f;
     27     camera->aspect = 1.0f;
     28     camera->near = 0.1f;
     29     camera->far = 200.0f;
     30 
     31     camera->near_h = 2 * tan(camera->fovy / 2) * camera->near;
     32     camera->near_w = camera->near_h * camera->aspect;
     33 
     34     camera->far_h = 2 * tan(camera->fovy / 2) * camera->far;
     35     camera->far_w = camera->far_h * camera->aspect;
     36 }
     37 
     38 void Camera_updateMatrix(Camera *camera)
     39 {
     40     Vec3 camera_target;
     41     Vec3_add(
     42             camera->transform->position,
     43             camera->transform->forward,
     44             camera_target
     45     );
     46 
     47     Mat4 view;
     48     Mat4_lookAt(
     49             camera->transform->position,
     50             camera_target,
     51             camera->transform->up,
     52             view
     53     );
     54 
     55     Mat4 projection;
     56     Mat4_perspective(
     57             radians(camera->fovy),
     58             camera->aspect,
     59             camera->near,
     60             camera->far,
     61             projection
     62     );
     63 
     64     Mat4_mul(projection, view, camera->matrix);
     65 }
     66 
     67 void Camera_updateFrustum(Camera *camera)
     68 {
     69     // Near plane
     70     camera->frustum[0].n[0] = camera->transform->forward[0];
     71     camera->frustum[0].n[1] = camera->transform->forward[1];
     72     camera->frustum[0].n[2] = camera->transform->forward[2];
     73     Vec3_scale(
     74             camera->transform->forward,
     75             camera->near,
     76             camera->frustum[0].p
     77     );
     78     Vec3_add(
     79             camera->transform->position,
     80             camera->frustum[0].p,
     81             camera->frustum[0].p
     82     );
     83 
     84     // Far plane
     85     camera->frustum[1].n[0] = -camera->transform->forward[0];
     86     camera->frustum[1].n[1] = -camera->transform->forward[1];
     87     camera->frustum[1].n[2] = -camera->transform->forward[2];
     88     Vec3_scale(
     89             camera->transform->forward,
     90             camera->far,
     91             camera->frustum[1].p
     92     );
     93     Vec3_add(
     94             camera->transform->position,
     95             camera->frustum[1].p,
     96             camera->frustum[1].p
     97     );
     98 
     99     // Used to store vector in plane
    100     Vec3 a;
    101 
    102     // Top plane
    103     Vec3_scale(
    104             camera->transform->up,
    105             camera->near_h / 2,
    106             camera->frustum[2].p
    107     );
    108     Vec3_add(
    109             camera->frustum[0].p,
    110             camera->frustum[2].p,
    111             camera->frustum[2].p
    112     );
    113 
    114     Vec3_sub(
    115             camera->frustum[2].p,
    116             camera->transform->position,
    117             a
    118     );
    119 
    120     Vec3_mul(
    121             a,
    122             camera->transform->right,
    123             camera->frustum[2].n
    124     );
    125     Vec3_normalize(
    126             camera->frustum[2].n,
    127             camera->frustum[2].n
    128     );
    129 
    130     // Bottom plane
    131     Vec3_scale(
    132             camera->transform->up,
    133             camera->near_h / 2,
    134             camera->frustum[3].p
    135     );
    136     Vec3_sub(
    137             camera->frustum[0].p,
    138             camera->frustum[3].p,
    139             camera->frustum[3].p
    140     );
    141 
    142     Vec3_sub(
    143             camera->frustum[3].p,
    144             camera->transform->position,
    145             a
    146     );
    147 
    148     Vec3_mul(
    149             camera->transform->right,
    150             a,
    151             camera->frustum[3].n
    152     );
    153     Vec3_normalize(
    154             camera->frustum[3].n,
    155             camera->frustum[3].n
    156     );
    157 
    158     // Left plane
    159     Vec3_scale(
    160             camera->transform->right,
    161             camera->near_w / 2,
    162             camera->frustum[4].p
    163     );
    164     Vec3_sub(
    165             camera->frustum[0].p,
    166             camera->frustum[4].p,
    167             camera->frustum[4].p
    168     );
    169 
    170     Vec3_sub(
    171             camera->frustum[4].p,
    172             camera->transform->position,
    173             a
    174     );
    175 
    176     Vec3_mul(
    177             a,
    178             camera->transform->up,
    179             camera->frustum[4].n
    180     );
    181     Vec3_normalize(
    182             camera->frustum[4].n,
    183             camera->frustum[4].n
    184     );
    185 
    186     // Right plane
    187     Vec3_scale(
    188             camera->transform->right,
    189             camera->near_w / 2,
    190             camera->frustum[5].p
    191     );
    192     Vec3_add(
    193             camera->frustum[0].p,
    194             camera->frustum[5].p,
    195             camera->frustum[5].p
    196     );
    197 
    198     Vec3_sub(
    199             camera->frustum[5].p,
    200             camera->transform->position,
    201             a
    202     );
    203 
    204     Vec3_mul(
    205             camera->transform->up,
    206             a,
    207             camera->frustum[5].n
    208     );
    209     Vec3_normalize(
    210             camera->frustum[5].n,
    211             camera->frustum[5].n
    212     );
    213 
    214 }
    215 
    216 static f32 planeSDF(const Plane *p, const Vec3 r)
    217 {
    218     return Vec3_dot(p->n, r) - Vec3_dot(p->n, p->p);
    219 }
    220 
    221 b8 Camera_sphereInFrustum(const Camera *camera, Vec3 p, f32 r)
    222 {
    223     for (i32 i = 0; i < 6; i++)
    224     {
    225         f32 distance = planeSDF(&camera->frustum[i], p);
    226         if (distance < -r)
    227         {
    228             return false;
    229         }
    230         else if (distance < r)
    231         {
    232             return true;
    233         }
    234     }
    235     return true;
    236 }
    237