taisei/src/stageutils.c
2019-08-03 20:44:22 +03:00

151 lines
3.1 KiB
C

/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
*/
#include "taisei.h"
#include "stageutils.h"
#include "global.h"
#include "util/glm.h"
#include "video.h"
Stage3D stage_3d_context;
void init_stage3d(Stage3D *s, uint pos_buffer_size) {
memset(s, 0, sizeof(Stage3D));
s->projangle = 45;
s->pos_buffer_size = pos_buffer_size;
s->pos_buffer = calloc(s->pos_buffer_size, sizeof(vec3));
}
void add_model(Stage3D *s, SegmentDrawRule draw, SegmentPositionRule pos) {
s->models = realloc(s->models, (++s->msize)*sizeof(StageSegment));
s->models[s->msize - 1].draw = draw;
s->models[s->msize - 1].pos = pos;
}
void set_perspective_viewport(Stage3D *s, float n, float f, int vx, int vy, int vw, int vh) {
r_mat_mode(MM_PROJECTION);
r_mat_identity();
float facw = SCREEN_W/(float)VIEWPORT_W;
float fach = SCREEN_H/(float)VIEWPORT_H;
r_mat_perspective(glm_rad(s->projangle), 1, n, f);
r_mat_scale(facw,fach,1);
r_mat_translate(vx+vw/2.0, vy+vh/2.0, 0);
r_mat_mode(MM_MODELVIEW);
}
void set_perspective(Stage3D *s, float n, float f) {
set_perspective_viewport(s, n, f, VIEWPORT_X, VIEWPORT_Y, VIEWPORT_W, VIEWPORT_H);
}
void update_stage3d(Stage3D *s) {
for(int i = 0; i < 3; i++){
s->cx[i] += s->cv[i];
}
}
void draw_stage3d(Stage3D *s, float maxrange) {
r_mat_push();
if(s->crot[0])
r_mat_rotate_deg(-s->crot[0], 1, 0, 0);
if(s->crot[1])
r_mat_rotate_deg(-s->crot[1], 0, 1, 0);
if(s->crot[2])
r_mat_rotate_deg(-s->crot[2], 0, 0, 1);
if(s->cx[0] || s->cx[1] || s->cx[2])
r_mat_translate(-s->cx[0],-s->cx[1],-s->cx[2]);
for(uint i = 0; i < s->msize; i++) {
uint num = s->models[i].pos(s, s->cx, maxrange);
for(uint j = 0; j < num; ++j) {
s->models[i].draw(s->pos_buffer[j]);
}
}
r_mat_pop();
}
void free_stage3d(Stage3D *s) {
free(s->models);
free(s->pos_buffer);
}
uint linear3dpos(Stage3D *s3d, vec3 q, float maxrange, vec3 p, vec3 r) {
float n = 0, z = 0;
for(uint i = 0; i < 3; i++) {
n += q[i]*r[i] - p[i]*r[i];
z += r[i]*r[i];
}
float t = n/z;
int mod = 1;
int num = t;
uint size = 0;
while(size < s3d->pos_buffer_size) {
vec3 dif;
for(uint i = 0; i < 3; i++) {
dif[i] = q[i] - p[i] - r[i]*num;
}
if(glm_vec3_norm(dif) < maxrange) {
for(uint i = 0; i < 3; i++) {
s3d->pos_buffer[size][i] = p[i] + r[i]*num;
}
++size;
} else if(mod == 1) {
mod = -1;
num = t;
} else {
break;
}
num += mod;
}
return size;
}
uint single3dpos(Stage3D *s3d, vec3 q, float maxrange, vec3 p) {
assume(s3d->pos_buffer_size > 0);
vec3 d;
for(uint i = 0; i < 3; i++) {
d[i] = p[i] - q[i];
}
if(glm_vec3_norm(d) > maxrange) {
return 0;
} else {
memcpy(s3d->pos_buffer, p, sizeof(vec3));
return 1;
}
}
void skip_background_anim(void (*update_func)(void), int frames, int *timer, int *timer2) {
int targetframes = *timer + frames;
while(*timer < targetframes) {
++*timer;
if(timer2) {
++*timer2;
}
update_func();
}
}