815 lines
20 KiB
C++
815 lines
20 KiB
C++
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <sys/socket.h>
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
#include <unistd.h>
|
|
#include <math.h>
|
|
|
|
#include <ft2build.h>
|
|
#include FT_FREETYPE_H
|
|
|
|
#include <SDL3/SDL.h>
|
|
|
|
#include "math/vec2.hpp"
|
|
#include "math/vec3.hpp"
|
|
#include "math/vec4.hpp"
|
|
#include "math/mat3x3.hpp"
|
|
#include "math/mat4x4.hpp"
|
|
|
|
using vec2 = vec<2, float>;
|
|
using vec3 = vec<3, float>;
|
|
using vec4 = vec<4, float>;
|
|
using mat3x3 = mat<3, 3, float>;
|
|
using mat4x4 = mat<4, 4, float>;
|
|
|
|
using vertex_position = vec<3, float>;
|
|
using vertex_normal = vec<3, float>;
|
|
using vertex_texture = vec<2, float>;
|
|
|
|
#include "model_collision.h"
|
|
|
|
struct glyph {
|
|
int32_t width;
|
|
int32_t height;
|
|
|
|
int32_t horiBearingX;
|
|
int32_t horiBearingY;
|
|
int32_t horiAdvance;
|
|
|
|
SDL_Texture * texture;
|
|
};
|
|
|
|
static struct glyph glyphs[0x80 - 0x20] = {0};
|
|
int32_t face_height;
|
|
|
|
int
|
|
load_outline_char(SDL_Renderer * renderer,
|
|
const FT_Face face,
|
|
const FT_Int32 load_flags,
|
|
const FT_Render_Mode render_mode,
|
|
const FT_ULong char_code)
|
|
{
|
|
FT_Error error;
|
|
FT_UInt glyph_index = FT_Get_Char_Index(face, char_code);
|
|
|
|
error = FT_Load_Glyph(face, glyph_index, load_flags);
|
|
if (error) {
|
|
printf("FT_Load_Glyph %s\n", FT_Error_String(error));
|
|
return -1;
|
|
}
|
|
|
|
error = FT_Render_Glyph(face->glyph, render_mode);
|
|
if (error) {
|
|
printf("FT_Render_Glyph %s\n", FT_Error_String(error));
|
|
return -1;
|
|
}
|
|
|
|
struct glyph * glyph = &glyphs[char_code - 0x20];
|
|
|
|
glyph->width = face->glyph->bitmap.width;
|
|
glyph->height = face->glyph->bitmap.rows;
|
|
glyph->horiBearingX = face->glyph->metrics.horiBearingX;
|
|
glyph->horiBearingY = face->glyph->metrics.horiBearingY;
|
|
glyph->horiAdvance = face->glyph->metrics.horiAdvance;
|
|
|
|
if (face->glyph->bitmap.pitch != 0) {
|
|
SDL_Surface * surface = SDL_CreateSurface(face->glyph->bitmap.width,
|
|
face->glyph->bitmap.rows,
|
|
SDL_PIXELFORMAT_RGBA8888);
|
|
|
|
SDL_LockSurface(surface);
|
|
|
|
for (unsigned int y = 0; y < face->glyph->bitmap.rows; y++) {
|
|
for (unsigned int x = 0; x < face->glyph->bitmap.width; x++) {
|
|
int s_ix = y * face->glyph->bitmap.pitch + x;
|
|
int d_ix = y * surface->pitch + x * 4;
|
|
uint8_t gray = face->glyph->bitmap.buffer[s_ix];
|
|
((uint8_t *)surface->pixels)[d_ix + 0] = gray;
|
|
((uint8_t *)surface->pixels)[d_ix + 1] = gray;
|
|
((uint8_t *)surface->pixels)[d_ix + 2] = gray;
|
|
((uint8_t *)surface->pixels)[d_ix + 3] = 255;
|
|
}
|
|
}
|
|
|
|
SDL_UnlockSurface(surface);
|
|
|
|
if (glyph->texture != NULL)
|
|
SDL_DestroyTexture(glyph->texture);
|
|
glyph->texture = SDL_CreateTextureFromSurface(renderer, surface);
|
|
if (glyph->texture == NULL) {
|
|
printf("%s\n", SDL_GetError());
|
|
}
|
|
assert(glyph->texture != NULL);
|
|
|
|
SDL_DestroySurface(surface);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int load_font(SDL_Renderer * renderer, int font_size)
|
|
{
|
|
FT_Library library;
|
|
FT_Face face;
|
|
FT_Error error;
|
|
|
|
error = FT_Init_FreeType(&library);
|
|
if (error) {
|
|
printf("FT_Init_FreeType\n");
|
|
return -1;
|
|
}
|
|
|
|
error = FT_New_Face(library, "/home/bilbo/timer/DejaVuSansMono.ttf", 0, &face);
|
|
if (error) {
|
|
printf("FT_New_Face\n");
|
|
return -1;
|
|
}
|
|
|
|
error = FT_Set_Pixel_Sizes(face, 0, font_size);
|
|
if (error) {
|
|
printf("FT_Set_Pixel_Sizes: %s %d\n", FT_Error_String(error), error);
|
|
return -1;
|
|
}
|
|
|
|
for (int char_code = 0x20; char_code <= 0x7f; char_code++) {
|
|
load_outline_char(renderer, face, FT_LOAD_DEFAULT, FT_RENDER_MODE_NORMAL, char_code);
|
|
}
|
|
|
|
printf("loaded size %ld\n", face->size->metrics.height >> 6);
|
|
face_height = face->size->metrics.height;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t render_text(SDL_Renderer * renderer, int32_t x, int32_t y, const char * s, int length)
|
|
{
|
|
int32_t x_advance = x;
|
|
int32_t y_advance = y;
|
|
for (int i = 0; i < length; i++) {
|
|
char c = s[i];
|
|
struct glyph * glyph = &glyphs[c - 0x20];
|
|
x_advance += glyph->horiAdvance;
|
|
if (glyph->texture != NULL) {
|
|
float x = (float)(x_advance + glyph->horiBearingX) / 64.f;
|
|
float y = (float)(y_advance - glyph->horiBearingY) / 64.f;
|
|
SDL_FRect srect = {
|
|
.x = 0.f,
|
|
.y = 0.f,
|
|
.w = (float)glyph->width,
|
|
.h = (float)glyph->height
|
|
};
|
|
SDL_FRect drect = {
|
|
.x = x,
|
|
.y = y,
|
|
.w = (float)glyph->width,
|
|
.h = (float)glyph->height
|
|
};
|
|
SDL_RenderTexture(renderer, glyph->texture, &srect, &drect);
|
|
}
|
|
}
|
|
return x_advance;
|
|
}
|
|
|
|
struct line3 {
|
|
vec3 a;
|
|
vec3 b;
|
|
};
|
|
|
|
constexpr int num_lines = 5;
|
|
|
|
struct state {
|
|
struct line3 line[num_lines];
|
|
vec3 normal;
|
|
vec3 mouse_position;
|
|
};
|
|
|
|
struct state state = {
|
|
.line = {
|
|
{{ 0, -0.5, 0 }, { 0, 0.5, 0 }},
|
|
{{ 0, -0.5, -0.5 }, { 0, 0.5, -0.5 }},
|
|
{{ 0, -0.5, 0.5 }, { 0, 0.5, 0.5 }},
|
|
{{ 0, 0.5, 0.5 }, { 0, 0.5, -0.5 }},
|
|
{{ 0, -0.5, 0.5 }, { 0, -0.5, -0.5 }},
|
|
},
|
|
.normal = { -1, 0, 0 },
|
|
};
|
|
|
|
struct edge_normal {
|
|
struct line3 edge;
|
|
vec3 normal;
|
|
};
|
|
|
|
struct edge_normal quad[4] = {
|
|
{
|
|
.edge = {{-1, -1, 0}, { 1, -1, 0}},
|
|
.normal = {0, -1, 0},
|
|
},
|
|
{
|
|
.edge = {{ 1, -1, 0}, { 1, 1, 0}},
|
|
.normal = {1, 0, 0},
|
|
},
|
|
{
|
|
.edge = {{ 1, 1, 0}, {-1, 1, 0}},
|
|
.normal = {0, 1, 0},
|
|
},
|
|
{
|
|
.edge = {{-1, 1, 0}, {-1, -1, 0}},
|
|
.normal = {-1, 0, 0},
|
|
},
|
|
};
|
|
|
|
static int window_width = 1;
|
|
static int window_height = 1;
|
|
|
|
static inline int max(int a, int b)
|
|
{
|
|
return (a > b) ? a : b;
|
|
}
|
|
|
|
static inline int min(int a, int b)
|
|
{
|
|
return (a > b) ? b : a;
|
|
}
|
|
|
|
const float deg = 0.017453292519943295;
|
|
float deg45 = 0.7853981633974483;
|
|
static float vtheta = 0.5;
|
|
|
|
mat4x4 trans;
|
|
|
|
vec3 screen_transform_vertex(vec3 v)
|
|
{
|
|
float dim = ((float)min(window_height, window_width)) / 2.0f;
|
|
|
|
return {
|
|
v.x * dim + window_width / 2.0f,
|
|
v.y * dim + window_height / 2.0f,
|
|
v.z,
|
|
};
|
|
}
|
|
|
|
vec3 _transform_vertex(vec3 v, float w)
|
|
{
|
|
vec4 v4 = {v.x, v.y, v.z, w};
|
|
vec4 v4t = trans * v4;
|
|
|
|
return {v4t.x, v4t.y, v4t.z};
|
|
}
|
|
|
|
vec3 transform_vertex(vec3 v, float scale)
|
|
{
|
|
return screen_transform_vertex(_transform_vertex(v * scale, 1.0f));
|
|
}
|
|
|
|
vec3 inverse_transform(float x, float y)
|
|
{
|
|
float dim = ((float)min(window_height, window_width)) / 2.0f;
|
|
assert(dim != 0);
|
|
|
|
return {
|
|
-(window_width - 2 * x) / (2 * dim),
|
|
-(window_height - 2 * y) / (2 * dim),
|
|
0,
|
|
};
|
|
}
|
|
|
|
struct line3 transform_line(struct line3 line, float scale)
|
|
{
|
|
return {
|
|
transform_vertex(line.a, scale),
|
|
transform_vertex(line.b, scale),
|
|
};
|
|
}
|
|
|
|
static inline void render_line(SDL_Renderer * renderer, struct line3 line)
|
|
{
|
|
assert(SDL_RenderLine(renderer, line.a.x, line.a.y, line.b.x, line.b.y));
|
|
}
|
|
|
|
static inline void render_line_vtx(SDL_Renderer * renderer, vec3 a, vec3 b)
|
|
{
|
|
assert(SDL_RenderLine(renderer, a.x, a.y, b.x, b.y));
|
|
}
|
|
|
|
void render_basis(SDL_Renderer * renderer)
|
|
{
|
|
// magenta: Z
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 1, 0, 1, 1));
|
|
render_line(renderer, transform_line({{0, 0, 0}, {0, 0, 1}}, 1.0f));
|
|
|
|
// yellow: Y
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 1, 1, 0, 1));
|
|
render_line(renderer, transform_line({{0, 0, 0}, {0, 1, 0}}, 1.0f));
|
|
|
|
// cyan: X
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 0, 1, 1, 1));
|
|
render_line(renderer, transform_line({{0, 0, 0}, {1, 0, 0}}, 1.0f));
|
|
|
|
vec3 z = transform_vertex({0, 0, 1}, 1.1);
|
|
vec3 y = transform_vertex({0, 1, 0}, 1.1);
|
|
vec3 x = transform_vertex({1, 0, 0}, 1.1);
|
|
|
|
render_text(renderer, ((z.x - 30) * 64), ((z.y + 10) * 64), "+z", 2);
|
|
render_text(renderer, ((y.x - 30) * 64), ((y.y + 10) * 64), "+y", 2);
|
|
render_text(renderer, ((x.x - 30) * 64), ((x.y + 10) * 64), "+x", 2);
|
|
}
|
|
|
|
vec3 update_light(SDL_Renderer * renderer)
|
|
{
|
|
static float ltheta = 0;
|
|
|
|
vec3 light_origin = {0, 0, 0};
|
|
vec3 light_pos = {1, 1, 1};
|
|
mat3x3 rot = {
|
|
cos(ltheta), -sin(ltheta), 0,
|
|
sin(ltheta), cos(ltheta), 0,
|
|
0, 0, 1,
|
|
};
|
|
light_pos = rot * light_pos;
|
|
ltheta += deg / 4;
|
|
vec3 light_vec = light_origin - light_pos;
|
|
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 0, 1, 0, 1));
|
|
render_line(renderer, transform_line({light_origin, light_pos}, 0.5f));
|
|
|
|
return light_vec;
|
|
}
|
|
|
|
void _render_quad(SDL_Renderer * renderer, vec3 light_vec)
|
|
{
|
|
for (int i = 0; i < 4; i++) {
|
|
float d = dot(light_vec, quad[i].normal);
|
|
|
|
if (d > 0)
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 1, 1, 1, 1));
|
|
else
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 0, 0, 1, 1));
|
|
render_line(renderer, transform_line(quad[i].edge, 0.25f));
|
|
|
|
vec3 origin = (quad[i].edge.a + quad[i].edge.b) / 2.0f;
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 1, 0, 0, 1));
|
|
render_line(renderer, transform_line({origin, origin + quad[i].normal}, 0.25f));
|
|
}
|
|
}
|
|
|
|
void set_edge_coloring(uint8_t * edge_coloring,
|
|
const int edge_stride,
|
|
float l_dot_n, int a, int b)
|
|
{
|
|
bool d = l_dot_n > 0;
|
|
|
|
int ma = min(a, b);
|
|
int mb = max(a, b);
|
|
|
|
int bit = 1 << ((int)d);
|
|
|
|
edge_coloring[ma * edge_stride + mb] |= bit;
|
|
}
|
|
|
|
mat4x4 translate(const vec3 v)
|
|
{
|
|
return (mat4x4){
|
|
1, 0, 0, v.x,
|
|
0, 1, 0, v.y,
|
|
0, 0, 1, v.z,
|
|
0, 0, 0, 1,
|
|
};
|
|
}
|
|
|
|
void render_quad(SDL_Renderer * renderer,
|
|
const vec3 * position,
|
|
const vec3 * normal,
|
|
const quadrilateral * quadrilateral,
|
|
const vec3 light_vec,
|
|
uint8_t * edge_coloring,
|
|
const int edge_stride)
|
|
{
|
|
vec3 n = normal[quadrilateral->a.normal];
|
|
float l_dot_n = dot(light_vec, n);
|
|
|
|
if (l_dot_n > 0)
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 1, 1, 1, 1));
|
|
else
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 0, 0, 1, 1));
|
|
|
|
float scale = 0.5f;
|
|
|
|
set_edge_coloring(edge_coloring,
|
|
edge_stride,
|
|
l_dot_n,
|
|
quadrilateral->a.position,
|
|
quadrilateral->b.position);
|
|
set_edge_coloring(edge_coloring,
|
|
edge_stride,
|
|
l_dot_n,
|
|
quadrilateral->b.position,
|
|
quadrilateral->c.position);
|
|
set_edge_coloring(edge_coloring,
|
|
edge_stride,
|
|
l_dot_n,
|
|
quadrilateral->c.position,
|
|
quadrilateral->d.position);
|
|
set_edge_coloring(edge_coloring,
|
|
edge_stride,
|
|
l_dot_n,
|
|
quadrilateral->d.position,
|
|
quadrilateral->a.position);
|
|
|
|
vec3 ap = position[quadrilateral->a.position];
|
|
vec3 bp = position[quadrilateral->b.position];
|
|
vec3 cp = position[quadrilateral->c.position];
|
|
vec3 dp = position[quadrilateral->d.position];
|
|
vec3 n10 = n * 0.1f;
|
|
|
|
vec3 a = transform_vertex(ap + n10, scale);
|
|
vec3 b = transform_vertex(bp + n10, scale);
|
|
vec3 c = transform_vertex(cp + n10, scale);
|
|
vec3 d = transform_vertex(dp + n10, scale);
|
|
|
|
render_line_vtx(renderer, a, b);
|
|
render_line_vtx(renderer, b, c);
|
|
render_line_vtx(renderer, c, d);
|
|
render_line_vtx(renderer, d, a);
|
|
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 1, 0, 0, 1));
|
|
|
|
vec3 origin = (position[quadrilateral->a.position] +
|
|
position[quadrilateral->b.position] +
|
|
position[quadrilateral->c.position] +
|
|
position[quadrilateral->d.position]) / 4.0f;
|
|
|
|
vec3 origin_t = transform_vertex(origin, scale);
|
|
vec3 origin_n_t = transform_vertex(origin + n, scale);
|
|
render_line_vtx(renderer, origin_t, origin_n_t);
|
|
}
|
|
|
|
void render_silhouette(SDL_Renderer * renderer,
|
|
const vec3 * position,
|
|
const uint8_t * edge_coloring,
|
|
const int edge_stride)
|
|
{
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 1, 0.5, 0, 1));
|
|
|
|
for (int a = 0; a < edge_stride; a++) {
|
|
for (int b = 0; b < edge_stride; b++) {
|
|
uint8_t coloring = edge_coloring[a * edge_stride + b];
|
|
if (coloring == 0b11) {
|
|
vec3 ap = position[a];
|
|
vec3 bp = position[b];
|
|
|
|
float scale = 0.5f;
|
|
vec3 av = transform_vertex(ap, scale);
|
|
vec3 bv = transform_vertex(bp, scale);
|
|
render_line_vtx(renderer, av, bv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mat3x3 rotate_to(vec3 old_normal, vec3 new_normal)
|
|
{
|
|
vec3 s = cross(old_normal, new_normal);
|
|
float c = dot(old_normal, new_normal);
|
|
mat3x3 i = mat3x3();
|
|
|
|
mat3x3 v = {
|
|
0, -s.z, s.y,
|
|
s.z, 0, -s.x,
|
|
-s.y, s.x, 0,
|
|
};
|
|
|
|
float mag = magnitude(s);
|
|
|
|
mat3x3 v2 = v * v;
|
|
|
|
float c_mag2 = (1 - c) / (mag * mag);
|
|
|
|
mat3x3 v2_c_mag2 = (v2 * c_mag2);
|
|
|
|
mat3x3 t = i + v + v2_c_mag2;
|
|
|
|
return t;
|
|
}
|
|
|
|
mat4x4 look_at(vec3 eye, vec3 center, vec3 up)
|
|
{
|
|
vec3 x;
|
|
vec3 y;
|
|
vec3 z;
|
|
|
|
z = eye - center;
|
|
z = z / magnitude(z);
|
|
|
|
y = up;
|
|
|
|
x = cross(y, z);
|
|
y = cross(z, x);
|
|
|
|
x = x / magnitude(x);
|
|
y = y / magnitude(y);
|
|
|
|
mat4x4 t = {
|
|
x.x, x.y, x.z, -dot(x, eye),
|
|
y.x, y.y, y.z, -dot(y, eye),
|
|
z.x, z.y, z.z, -dot(z, eye),
|
|
0, 0, 0, 1.0f
|
|
};
|
|
|
|
return t;
|
|
}
|
|
|
|
void render_lines(SDL_Renderer * renderer)
|
|
{
|
|
// line
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 1, 0.5, 0.5, 1));
|
|
for (int i = 0; i < num_lines; i++) {
|
|
struct line3 tl = transform_line(state.line[i], 1.0f);
|
|
render_line(renderer, tl);
|
|
}
|
|
|
|
// normal
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 1, 0, 0, 1));
|
|
struct line3 normal_line = {{0, 0, 0}, state.normal};
|
|
render_line(renderer, transform_line(normal_line, 0.5f));
|
|
|
|
// mouse
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 0, 0, 1, 1));
|
|
struct line3 mouse_line = {{0, 0, 0}, state.mouse_position};
|
|
render_line(renderer, transform_line(mouse_line, 0.5f));
|
|
|
|
// foo
|
|
mat3x3 t = rotate_to(state.normal, -state.mouse_position);
|
|
vec3 nr = t * state.normal;
|
|
//mat4x4 t = look_at({0, 0, 0}, state.mouse_position - state.normal, {0, 0, 1});
|
|
//vec4 nr4 = t * (vec4){state.normal.x, state.normal.y, state.normal.z, 0};
|
|
//vec3 nr = {nr.x, nr.y, nr.z};
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 0, 1, 0, 1));
|
|
struct line3 nr_line = {{0, 0, 0}, nr};
|
|
render_line(renderer, transform_line(nr_line, 0.5f));
|
|
|
|
{
|
|
assert(SDL_SetRenderDrawColorFloat(renderer, 0.5, 1, 0.5, 1));
|
|
for (int i = 0; i < num_lines; i++) {
|
|
struct line3 l = state.line[i];
|
|
/*
|
|
vec4 a4 = t * l.a;
|
|
vec4 b4 = t * l.b;
|
|
vec3 a = {a4.x, a4.y, a4.z};
|
|
vec3 b = {b4.x, b4.y, b4.z};
|
|
*/
|
|
vec3 a = t * l.a;
|
|
vec3 b = t * l.b;
|
|
struct line3 tl = {a, b};
|
|
render_line(renderer, transform_line(tl, 1.0f));
|
|
}
|
|
}
|
|
}
|
|
|
|
void render_text_state(SDL_Renderer * renderer)
|
|
{
|
|
int32_t x_advance = 10 << 6;
|
|
int32_t y_advance = face_height;
|
|
x_advance = render_text(renderer, x_advance, y_advance, "dot: ", 5);
|
|
|
|
|
|
//float d = dot(state.normal, state.mouse_position);
|
|
/*
|
|
float d = dot({0, 1}, state.mouse_position);
|
|
char buf[64];
|
|
int len = snprintf(buf, 64, "%.03f", d);
|
|
x_advance = render_text(renderer, x_advance, y_advance, buf, len);
|
|
*/
|
|
}
|
|
|
|
bool collided[256] = {0};
|
|
|
|
void render_collision(SDL_Renderer * renderer)
|
|
{
|
|
const struct model * model = &haunted_mansion_collision_model;
|
|
const struct object * object = &haunted_mansion_collision_house_coll_display;
|
|
|
|
float scale = 1.f;
|
|
|
|
for (int i = 0; i < object->line_count; i++) {
|
|
|
|
const union line * line = &object->line[i];
|
|
|
|
if (collided[i])
|
|
SDL_SetRenderDrawColor(renderer, 255, 100, 100, 255);
|
|
else
|
|
SDL_SetRenderDrawColor(renderer, 100, 100, 255, 255);
|
|
|
|
render_line_vtx(renderer,
|
|
transform_vertex(model->position[line->a], scale),
|
|
transform_vertex(model->position[line->b], scale));
|
|
}
|
|
}
|
|
|
|
static float theta = 0;
|
|
|
|
void update_mouse_position()
|
|
{
|
|
vec3 pos = {0, 1, 1};
|
|
pos = pos / magnitude(pos);
|
|
|
|
mat3x3 rot1 = {
|
|
cos(theta), -sin(theta), 0,
|
|
sin(theta), cos(theta), 0,
|
|
0, 0, 1,
|
|
};
|
|
|
|
state.mouse_position = rot1 * pos;
|
|
theta += deg;
|
|
}
|
|
|
|
vec2 line_intersection(vec2 a1, vec2 a2,
|
|
vec2 b1, vec2 b2)
|
|
{
|
|
float x1 = a1.x;
|
|
float y1 = a1.y;
|
|
float x2 = a2.x;
|
|
float y2 = a2.y;
|
|
|
|
float x3 = b1.x;
|
|
float y3 = b1.y;
|
|
float x4 = b2.x;
|
|
float y4 = b2.y;
|
|
|
|
float x1x2 = x1 - x2;
|
|
float x1x3 = x1 - x3;
|
|
float x3x4 = x3 - x4;
|
|
float y1y2 = y1 - y2;
|
|
float y1y3 = y1 - y3;
|
|
float y3y4 = y3 - y4;
|
|
|
|
float div = 1.0f / (x1x2 * y3y4 - y1y2 * x3x4);
|
|
|
|
float t = (x1x3 * y3y4 - y1y3 * x3x4) * div;
|
|
float u = -(x1x2 * y1y3 - y1y2 * x1x3) * div;
|
|
|
|
return {t, u};
|
|
}
|
|
|
|
bool line_has_collision(vec3 a1, vec3 a2)
|
|
{
|
|
const struct model * model = &haunted_mansion_collision_model;
|
|
const struct object * object = &haunted_mansion_collision_house_coll_display;
|
|
|
|
for (int i = 0; i < object->line_count; i++) {
|
|
|
|
const union line * line = &object->line[i];
|
|
|
|
vec3 b1 = _transform_vertex(model->position[line->a], 1.0f);
|
|
vec3 b2 = _transform_vertex(model->position[line->b], 1.0f);
|
|
|
|
vec2 tu = line_intersection({a1.x, a1.y},
|
|
{a2.x, a2.y},
|
|
{b1.x, b1.y},
|
|
{b2.x, b2.y});
|
|
|
|
if (tu.x >= 0.0f && tu.x <= 1.0f && tu.y >= 0.0f && tu.y <= 1.0f) {
|
|
collided[i] = true;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void move(SDL_Renderer * renderer, vec3 direction)
|
|
{
|
|
SDL_SetRenderDrawColor(renderer, 128, 255, 50, 255);
|
|
render_line_vtx(renderer,
|
|
screen_transform_vertex({0, 0, 0}),
|
|
screen_transform_vertex(-direction * 2.0f));
|
|
|
|
if (!line_has_collision({0, 0, 0}, -direction * 1.0f))
|
|
trans = translate(direction) * trans;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
SDL_Window * window;
|
|
SDL_Renderer * renderer;
|
|
|
|
bool success = SDL_Init(SDL_INIT_VIDEO);
|
|
if (!success) printf("error: `%s`\n", SDL_GetError());
|
|
assert(success == true);
|
|
|
|
window = SDL_CreateWindow("sandbox",
|
|
640, // w
|
|
480, // h
|
|
SDL_WINDOW_RESIZABLE);// | SDL_WINDOW_MAXIMIZED);
|
|
|
|
int num_drivers = SDL_GetNumRenderDrivers();
|
|
printf("available drivers:\n");
|
|
for (int i = 0; i < num_drivers; i++) {
|
|
const char * s = SDL_GetRenderDriver(i);
|
|
printf(" %s\n", s);
|
|
}
|
|
renderer = SDL_CreateRenderer(window, "opengles2");
|
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
|
|
|
SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
|
|
|
|
const char * name = SDL_GetRendererName(renderer);
|
|
assert(name != NULL);
|
|
printf("renderer: %s\n", name);
|
|
const SDL_PixelFormat * formats = (const SDL_PixelFormat *)SDL_GetPointerProperty(props, SDL_PROP_RENDERER_TEXTURE_FORMATS_POINTER, NULL);
|
|
assert(formats != NULL);
|
|
while (*formats != SDL_PIXELFORMAT_UNKNOWN) {
|
|
printf("%s\n", SDL_GetPixelFormatName(*formats++));
|
|
}
|
|
|
|
uint64_t ticks = SDL_GetTicks();
|
|
|
|
int font_size = 25;
|
|
load_font(renderer, font_size);
|
|
|
|
trans = {
|
|
1, 0, 0, 0,
|
|
0, 1, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1,
|
|
};
|
|
trans = trans * 0.2f;
|
|
|
|
mat4x4 rot1 = {
|
|
cos(deg45), -sin(deg45), 0, 0,
|
|
sin(deg45), cos(deg45), 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1,
|
|
};
|
|
mat4x4 rot2 = {
|
|
1, 0, 0, 0,
|
|
0, cos(deg45), -sin(deg45), 0,
|
|
0, sin(deg45), cos(deg45), 0,
|
|
0, 0, 0, 1,
|
|
};
|
|
mat4x4 rot3 = {
|
|
cos(-deg45), 0, sin(-deg45), 0,
|
|
0, 1, 0, 0,
|
|
sin(-deg45), 0, cos(-deg45), 0,
|
|
0, 0, 0, 1,
|
|
};
|
|
(void)rot1; (void)rot2; (void)rot3;
|
|
|
|
trans = rot2 * rot1 * trans;
|
|
|
|
|
|
while (1) {
|
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
|
SDL_RenderClear(renderer);
|
|
bool success = SDL_GetWindowSizeInPixels(window, &window_width, &window_height);
|
|
assert(success == true);
|
|
|
|
render_text_state(renderer);
|
|
render_basis(renderer);
|
|
render_collision(renderer);
|
|
|
|
SDL_Event event;
|
|
while (SDL_PollEvent(&event)) {
|
|
switch (event.type) {
|
|
case SDL_EVENT_QUIT:
|
|
goto exit;
|
|
case SDL_EVENT_KEY_DOWN:
|
|
if (event.key.key == SDLK_ESCAPE)
|
|
goto exit;
|
|
if (event.key.key == SDLK_LEFT)
|
|
move(renderer, {0.03, 0.0, 0.0});
|
|
if (event.key.key == SDLK_RIGHT)
|
|
move(renderer, {-0.03, 0.0, 0.0});
|
|
if (event.key.key == SDLK_UP)
|
|
move(renderer, {0.0, 0.03, 0.0});
|
|
if (event.key.key == SDLK_DOWN)
|
|
move(renderer, {0.0, -0.03, 0.0});
|
|
|
|
break;
|
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
|
if (event.button.button == 1) {
|
|
//vec3 mv = inverse_transform(event.button.x, event.button.y);
|
|
//float m = magnitude(mv);
|
|
//state.mouse_position = mv / m;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
while (SDL_GetTicks() - ticks < (1000 / 60)) { SDL_Delay(1); }
|
|
SDL_RenderPresent(renderer);
|
|
ticks = SDL_GetTicks();
|
|
|
|
//update_mouse_position();
|
|
//vtheta += deg / 10;
|
|
}
|
|
|
|
exit:
|
|
SDL_DestroyRenderer(renderer);
|
|
SDL_DestroyWindow(window);
|
|
SDL_Quit();
|
|
}
|