How do I fix the warped perspective in my raycaster? - c

I am writing a raycaster using SDL's C API. I have spent weeks trying to fix the notorious fisheye effect to no avail. According to this source, I can multiply my calculated distance by the cosine of half of the FOV to fix it. That has not worked for me. I still have the cosine correction in my code nonetheless.
Here are two images demonstrating the distortion:
I think a core problem of my code may be that my angle increment is constant, while the increment should be smaller as I'm closer to the screen borders. Unfortunately, I don't know how to start implementing this.
If possible, could anyone please take a look at my code and give me a tip on how to remove the fisheye? To move in any direction, use the arrow keys. Use the 'a' and 's' keys to turn left and right respectively.
This is how I'm compiling: clang `pkg-config --cflags --libs sdl2` raycaster.c
#include <SDL2/SDL.h>
#include <math.h>
typedef struct {
float x, y, prev_x, prev_y, angle, fov;
} Player;
enum {
map_width = 12, map_height = 15,
screen_width = 800, screen_height = 500
};
const float
move_speed_decr = 0.08,
angle_turn = 2.0,
ray_theta_step = 0.4,
ray_dist_step = 0.8,
darkening = 1.8,
width_ratio = (float) screen_width / map_width,
height_ratio = (float) screen_height / map_height;
const unsigned char map[map_height][map_width] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1},
{1, 0, 4, 3, 2, 0, 0, 0, 2, 0, 0, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 1},
{1, 0, 0, 0, 4, 3, 2, 1, 4, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
SDL_Window* window;
SDL_Renderer* renderer;
float to_radians(float degrees) {
return degrees * M_PI / 180;
}
float distance(float x0, float y0, float x1, float y1) {
return sqrt(((x1 - x0) * (x1 - x0)) + ((y1 - y0) * (y1 - y0)));
}
void shade(int* color, int darkener) {
int darkened = *color - darkener;
*color = darkened < 0 ? 0 : darkened;
}
void draw_rectangle(SDL_Rect rectangle, int r, int g, int b) {
SDL_SetRenderDrawColor(renderer, r, g, b, SDL_ALPHA_OPAQUE);
SDL_RenderFillRect(renderer, &rectangle);
SDL_RenderDrawRect(renderer, &rectangle);
}
void raycast(Player player) {
float relative_x = player.x * width_ratio;
float relative_y = player.y * height_ratio;
float half_fov = player.fov / 2;
float width_fov_ratio = (screen_width / player.fov) / 2;
float distort_adjust = cos(to_radians(half_fov));
// the core of my problem may be in the constant increment of my angle
for (float theta = player.angle - half_fov, screen_x = 0;
theta < player.angle + half_fov;
theta += ray_theta_step, screen_x += width_fov_ratio) {
float radian_theta = to_radians(theta);
float cos_theta = cos(radian_theta), sin_theta = sin(radian_theta);
float d = 0, new_x, new_y;
while (d += ray_dist_step) {
new_x = cos_theta * d + relative_x;
new_y = sin_theta * d + relative_y;
int map_x = new_x / width_ratio, map_y = new_y / height_ratio;
int map_point = map[map_y][map_x];
if (map_point) {
int dist_wall = distance(relative_x, relative_y, new_x, new_y) * distort_adjust;
int twice_dist_wall = 2 * dist_wall;
if (twice_dist_wall >= screen_height) break;
else if (map_point) { // succeeds when a wall is present
int r, g, b;
switch (map_point) {
case 1: r = 255, g = 255, b = 0; break;
case 2: r = 0, g = 128, b = 128; break;
case 3: r = 255, g = 165, b = 0; break;
case 4: r = 255, g = 0, b = 0; break;
}
int color_decr = dist_wall / darkening;
shade(&r, color_decr);
shade(&g, color_decr);
shade(&b, color_decr);
SDL_Rect vertical_line = {
screen_x, dist_wall,
width_fov_ratio + 1,
screen_height - twice_dist_wall
};
draw_rectangle(vertical_line, r, g, b);
break;
}
}
}
}
}
void handle_input(const Uint8* keys, Player* player) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
exit(0);
}
else if (event.type == SDL_KEYDOWN) {
float radian_theta = to_radians(player -> angle);
float move_x = cos(radian_theta) * move_speed_decr,
move_y = sin(radian_theta) * move_speed_decr;
// handle arrow keys
if (keys[SDL_SCANCODE_UP]) player -> x += move_x, player -> y += move_y;
if (keys[SDL_SCANCODE_DOWN]) player -> x -= move_x, player -> y -= move_y;
if (keys[SDL_SCANCODE_LEFT]) player -> x += move_y, player -> y -= move_x;
if (keys[SDL_SCANCODE_RIGHT]) player -> x -= move_y, player -> y += move_x;
// handle 'a' and 's' for angle changes
if (keys[SDL_SCANCODE_A]) player -> angle -= angle_turn;
if (keys[SDL_SCANCODE_S]) player -> angle += angle_turn;
// safeguards for invalid positions and angles
if (player -> x < 0) player -> x = 0;
else if (player -> x > screen_width) player -> x = screen_width;
if (player -> y < 0) player -> y = 0;
else if (player -> y > screen_height) player -> y = screen_height;
// move the player to their previous coordinate if they're in a wall
if (map[(int) player -> y][(int) player -> x])
player -> y = player -> prev_y, player -> x = player -> prev_x;
if (player -> angle > 360) player -> angle = 0;
else if (player -> angle < 0) player -> angle = 360;
player -> prev_y = player -> y, player -> prev_x = player -> x;
}
}
}
int main() {
SDL_CreateWindowAndRenderer(screen_width, screen_height, 0, &window, &renderer);
SDL_SetWindowTitle(window, "Raycaster");
Player player = {5, 5, 0, 0, 0, 60};
SDL_Rect the_ceiling = {0, 0, screen_width, screen_height / 2};
SDL_Rect the_floor = {0, screen_height / 2, screen_width, screen_height};
const Uint8* keys = SDL_GetKeyboardState(NULL);
while (1) {
handle_input(keys, &player);
draw_rectangle(the_ceiling, 96, 96, 96);
draw_rectangle(the_floor, 210, 180, 140);
raycast(player);
SDL_RenderPresent(renderer);
SDL_UpdateWindowSurface(window);
}
}
After help from RandomDavis, the distortion is lessened. Here is the new result. Nonetheless, some warping remains:
NOTE:
To anyone who is still struggling with this problem, I solved it here:
How do I fix warped walls in my raycaster?

Okay I found a guide which talks about this exact issue.
Before drawing the wall, there is one problem that must be taken care of. This problem is known as the "fishbowl effect." Fishbowl effect happens because ray-casting implementation mixes polar coordinate and Cartesian coordinate together. Therefore, using the above formula on wall slices that are not directly in front of the viewer will gives a longer distance. This is not what we want because it will cause a viewing distortion such as illustrated below.
Thus to remove the viewing distortion, the resulting distance obtained from equations in Figure 17 must be multiplied by cos(BETA); where BETA is the angle of the ray that is being cast relative to the viewing angle. On the figure above, the viewing angle (ALPHA) is 90 degrees because the player is facing straight upward. Because we have 60 degrees field of view, BETA is 30 degrees for the leftmost ray and it is -30 degrees for the rightmost ray.

Related

How do I fix warped walls in my raycaster?

I am writing a raycaster using the SDL library with C. I have been dealing with the fisheye effect for many weeks now. For a field of view like 60 degrees, I multiply the distance to the wall by the cosine of the relative angle (ranging from -30 to 30), but still, I get the same fisheye. Here's what that looks like:
I don't know what to do at this point, given that so many sources have recommended cosine correction and it just does not fix the distortion in my case.
I am compiling like this:
clang `pkg-config --cflags --libs sdl2` raycaster.c
To go forward and back, press the up and down keys. Press left and right to strafe. You can use the a and s keys to turn left and right respectively.
My code is below if you want to take a look. If you manage to figure out why I am getting a warped perspective in my engine, please let me know.
#include <SDL2/SDL.h>
#include <math.h>
#define SET_COLOR(r, g, b) SDL_SetRenderDrawColor(renderer, r, g, b, SDL_ALPHA_OPAQUE)
typedef struct {
float x, y, prev_x, prev_y, angle, fov;
} Player;
enum {
map_width = 12, map_height = 15,
screen_width = 800, screen_height = 500
};
const float
move_speed_decr = 0.08,
angle_turn = 2.0,
theta_step = 0.05,
dist_step = 0.8,
width_ratio = (float) screen_width / map_width,
height_ratio = (float) screen_height / map_height;
const unsigned char map[map_height][map_width] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1},
{1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1},
{1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
SDL_Window* window;
SDL_Renderer* renderer;
float to_radians(float degrees) {
return degrees * (M_PI / 180.0f);
}
void draw_rectangle(SDL_Rect rectangle, int r, int g, int b) {
SET_COLOR(r, g, b);
SDL_RenderFillRect(renderer, &rectangle);
SDL_RenderDrawRect(renderer, &rectangle);
}
void raycast(Player player) {
SET_COLOR(210, 180, 140);
float
half_fov = player.fov / 2,
rel_x = player.x * width_ratio, rel_y = player.y * height_ratio;
float screen_x = 0, step_x = (screen_width / player.fov) * theta_step;
for (float theta = player.angle - half_fov; theta < player.angle + half_fov; theta += theta_step) {
float rad_theta = to_radians(theta);
float cos_theta = cos(rad_theta), sin_theta = sin(rad_theta);
float dist = 0;
while (dist += dist_step) {
float
new_x = cos_theta * dist + rel_x,
new_y = sin_theta * dist + rel_y;
if (map[(int) (new_y / height_ratio)][(int) (new_x / width_ratio)]) {
dist *= cos(to_radians(theta - player.angle));
float double_dist = 2 * dist;
if (double_dist >= screen_height) break;
SDL_Rect column = {screen_x, dist, step_x + 1, screen_height - double_dist};
SDL_RenderFillRect(renderer, &column);
SDL_RenderDrawRect(renderer, &column);
break;
}
}
screen_x += step_x;
}
}
void handle_input(const Uint8* keys, Player* player) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
exit(0);
}
else if (event.type == SDL_KEYDOWN) {
float radian_theta = to_radians(player -> angle);
float move_x = cos(radian_theta) * move_speed_decr,
move_y = sin(radian_theta) * move_speed_decr;
// handle arrow keys
if (keys[SDL_SCANCODE_UP]) player -> x += move_x, player -> y += move_y;
if (keys[SDL_SCANCODE_DOWN]) player -> x -= move_x, player -> y -= move_y;
if (keys[SDL_SCANCODE_LEFT]) player -> x += move_y, player -> y -= move_x;
if (keys[SDL_SCANCODE_RIGHT]) player -> x -= move_y, player -> y += move_x;
// handle 'a' and 's' for angle changes
if (keys[SDL_SCANCODE_A]) player -> angle -= angle_turn;
if (keys[SDL_SCANCODE_S]) player -> angle += angle_turn;
// safeguards for invalid positions and angles
if (player -> x < 0) player -> x = 0;
else if (player -> x > screen_width) player -> x = screen_width;
if (player -> y < 0) player -> y = 0;
else if (player -> y > screen_height) player -> y = screen_height;
// move the player to their previous coordinate if they're in a wall
if (map[(int) player -> y][(int) player -> x])
player -> y = player -> prev_y, player -> x = player -> prev_x;
if (player -> angle > 360) player -> angle = 0;
else if (player -> angle < 0) player -> angle = 360;
player -> prev_y = player -> y, player -> prev_x = player -> x;
}
}
}
int main() {
SDL_CreateWindowAndRenderer(screen_width, screen_height, 0, &window, &renderer);
SDL_SetWindowTitle(window, "Raycaster");
Player player = {5, 5, 0, 0, 0, 60};
SDL_Rect the_ceiling = {0, 0, screen_width, screen_height / 2};
SDL_Rect the_floor = {0, screen_height / 2, screen_width, screen_height};
const Uint8* keys = SDL_GetKeyboardState(NULL);
while (1) {
handle_input(keys, &player);
draw_rectangle(the_ceiling, 96, 96, 96);
draw_rectangle(the_floor, 255,69,0);
raycast(player);
SDL_RenderPresent(renderer);
SDL_UpdateWindowSurface(window);
}
}
You need to apply following diff:
diff --git a/so33.c b/so33.c
index e65cff8..b0f6d8a 100644
--- a/so33.c
+++ b/so33.c
## -56,7 +56,7 ## void raycast(Player player) {
float
half_fov = player.fov / 2,
- rel_x = player.x * width_ratio, rel_y = player.y * height_ratio;
+ rel_x = player.x, rel_y = player.y;
float screen_x = 0, step_x = (screen_width / player.fov) * theta_step;
## -70,12 +70,12 ## void raycast(Player player) {
new_x = cos_theta * dist + rel_x,
new_y = sin_theta * dist + rel_y;
- if (map[(int) (new_y / height_ratio)][(int) (new_x / width_ratio)]) {
+ if (map[(int) (new_y)][(int) (new_x)]) {
dist *= cos(to_radians(theta - player.angle));
- float double_dist = 2 * dist;
-
- if (double_dist >= screen_height) break;
- SDL_Rect column = {screen_x, dist, step_x + 1, screen_height - double_dist};
+ float wall_height = screen_height / dist;
+ if (wall_height > screen_height)
+ wall_height = screen_height;
+ SDL_Rect column = {screen_x, screen_height/2 - wall_height/2, step_x + 1, wall_height};
SDL_RenderFillRect(renderer, &column);
SDL_RenderDrawRect(renderer, &column);
A few issues were identified.
Coefficients width_ratio and height_ratio seems to mix coordinates in the map space with coordinates in the screen space. It is pointless. Moreover, it breaks navigation by moving faster along specific axis.
After projecting dist to the ray cast through the center of the screen (dist *= cos(...) you have to apply simple perspective to compute height of the wall (variable wall_height)
Finally, draw a rectangle of height wall_height around the middle horizontal line.
Edit. Set
dist_step = 0.01
There are two major problem in this code. The distance to the wall must be calculated for the intersection point of your ray to the wall instead of just relying that your endpoint lies inside the wall square.
Having a camera at C, the distortion is solved by casting rays from C through a sufficient number of points between A and B, just dividing this plane (your screen) to equally wide columns (pixels).
I'm fairly pessimistic about the cosine correction, since what I can tell, one should more likely adjust the drawn column width or position with it, than the column height.

stb_truetype.h and SDL2 change font color

I am using stb_truetype.h and SDL2 to render text. Is there an easy way to change the font color? Here is what I have (text is a char*):
while (*text) {
if (*text >= 32 && *text < 128) {
stbtt_aligned_quad q;
stbtt_GetBakedQuad(font->cdata, 512, 512, *text - 32, &x, &y, &q, 1);
SDL_Rect src_rect = {.x = (int)512 * q.s0 - 1,
.y = (int)512 * (q.t0) - 1,
.w = (int)512 * (q.s1 - q.s0) + 1,
.h = (int)512 * (q.t1 - q.t0) + 1};
SDL_Rect dst_rect = {
.x = q.x0, .y = q.y0, .w = q.x1 - q.x0, .h = q.y1 - q.y0};
// Has no effect because I am just grabbing a rect from the font data.
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
// Always renders the font white.
SDL_RenderCopy(renderer, font->texture, &src_rect, &dst_rect);
}
++text;
}
I would like to be able to render the font in different colors. Right now the font is always white.
Found a way to do this, using SDL_SetTextureColorMod : (https://wiki.libsdl.org/SDL_SetTextureColorMod)
SDL_SetTextureColorMod(font->texture, 255, 0, 0);
will turn the font red for example.
My original code using this:
while (*text) {
if (*text >= 32 && *text < 128) {
stbtt_aligned_quad q;
stbtt_GetBakedQuad(font->cdata, 512, 512, *text - 32, &x, &y, &q, 1);
SDL_Rect src_rect = {.x = (int)512 * q.s0 - 1,
.y = (int)512 * (q.t0) - 1,
.w = (int)512 * (q.s1 - q.s0) + 1,
.h = (int)512 * (q.t1 - q.t0) + 1};
SDL_Rect dst_rect = {
.x = q.x0, .y = q.y0, .w = q.x1 - q.x0, .h = q.y1 - q.y0};
// set the font texture to display red.
SDL_SetTextureColorMod(font->texture, 255, 0, 0);
SDL_RenderCopy(renderer, font->texture, &src_rect, &dst_rect);
}
++text;
}

Making projectile shoot using with allegro library in C

I'm trying to make a projectile shoot using with allegro library in C.And I couldn't do it in no way.My all code is below.My circle goes up but then disappear.Even if not I can't bring it down to the ground.I'm not good at physic so if my equals are wrong please forgive me.
#include <allegro.h>
#include < math.h >
void StartAlleg(); // my start program function
void EndAlleg();
int main() {
StartAlleg();
BITMAP *buffer = create_bitmap(640, 480);
int g = 10, Vo = 0 , Vx = 5, Vy = 475, angle= 0;
double time = 0, tUp = 0,hmax=0; //g is gravity
show_mouse(screen);
while (!key[KEY_ESC])
{
circle(buffer, Vx, Vy, 5, makecol(255, 0, 0));
if (key[KEY_UP]&&angle<360) angle++;
if (key[KEY_RIGHT]) Vo++;
if (key[KEY_DOWN] && angle>0) angle--;
if (key[KEY_LEFT] && Vo>0) Vo--;
textout_ex(buffer, font, "Player 1 : ", 0, 0, makecol(255, 255, 13), -1);
textprintf(buffer, font, 0, 25, makecol(255, 255, 13), "Angle = %d ",angle);
textprintf(buffer, font, 0, 15, makecol(255, 255, 13), "Speed = %d ", Vo);
if (key[KEY_Z] ){
Vx = Vo*cos(double(angle));
Vy = Vo*sin(double(angle));
if (angle== 180 || angle == 360) Vy = 0;
if (angle== 90 || angle== 270) Vx = 0;
if (Vx < 0) Vx *= (-1);
if (Vy < 0) Vy *= (-1);
tUp = Vy / g;
time = tUp * 2;
hmax = (Vy*Vy) / (2*g);
}
textprintf(buffer, font, 0, 35, makecol(255, 255, 13), "tUp Value = %.2f ", tUp);
for (int i = 1; i <= time; i++)
{
if (i<tUp){ Vx = Vx + g; Vy += g; }
else{ Vy -= g; Vx = Vx + g; }
}
blit(buffer, screen, 0, 0, 0, 0, 640, 480);
rest(60);
clear_bitmap(buffer);
}
EndAlleg(); // my end program function
return 0;
}
END_OF_MAIN()
void StartAlleg() {
int depth, res;
allegro_init();
depth = desktop_color_depth();
if (depth == 0) depth = 32;
set_color_depth(depth);
res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
if (res != 0) {
allegro_message(allegro_error);
exit(-1);
}
install_timer();
install_keyboard();
install_mouse();
install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, "A");
}
void EndAlleg() {
clear_keybuf();
}
I think , the main problem is here :
for (int i = 1; i <= time; i++)
{
if (i<tUp){ Vx = Vx + g; Vy += g; }
else{ Vy -= g; Vx = Vx + g; }
}
I didn't try to understand all your code, but it seems that your calculations are wrong.
Here is how gravity can be implemented :
First, you need to keep track of your projectile position, with variables like Px Py. This position will give you the drawing coordinates.
Then you need to keep track of its speed, usually horizontal and vertical speed, with variables like Vx Vy. If your initial speed is a single vector with angle, convert it once.
Every tick of your game (every loop iteration in your case), you add the speeds to the positions. Then to add gravity, you subtract 10 to the vertical speed, also at every tick (it implements acceleration of -10).
And thats all. Negative speeds and accelerations are normal, you don't need to check, but you can check for borders for positions. Also, you should note that you usually divide the speeds and accelerations by the frequency of your ticks, or else the faster your loop the faster the projectile will move.
You should note that this isn't the best way to implement gravity, because this only approximate physics (more ticks per second will give you more accurate simulation). You should google "game implement gravity properly" for an accurate algorithm, I'm not an expert.

no more memory for NDSolve

I am Solving a nonlinear partial differential equation and I have to apply very small steps since I am dealing with a physical phenomenon.But as I decrease the step size and even I am using MaxSteps, I still get the error no more memory for NDSolve.
Here is my program:
a = 0.05; b = 0.5; L = 20; T = 6 \[Pi]; h = 4;
NDSolve[{b*D[u[t, x], t, t] + a*D[u[t, x], t] ==
D[u[t, x], x, x] - Sin[u[t, x]], u[0, x] == 0,
Derivative[1, 0][u][0, x] == 0,
Derivative[0, 1][u][t, 0] == h*Sin[t],
Derivative[0, 1][u][t, L] == 0}, u, {t, 0, T}, {x, 0, L},
MaxStepSize -> 0.0001, MaxSteps -> 10^6]

Have to load view matrix twice. Don't know why

This is the weirdest bug i have ever encountered. My triangle will not be drawn unless I Load the view matrix twice. What is going on?
If i remove one of the gfxSetCamera(&camera->t); nothing is drawn.
void shipDraw() {
glPushMatrix();
glMultMatrixf(ship->t.m);
glBegin(GL_TRIANGLES);
glColor3f(0,0,1);
glVertex3f(0, 0, -1);
glVertex3f(0, 1, 1);
glVertex3f(0, -1, 1);
glEnd();
glPopMatrix();
}
//Draw loop
while(!gfxUserQuit()) {
entUpdateAll();
gfxPrepare(1,1);
gfxSetCamera(&camera->t); //Have to call this twice!?!?
gfxSetCamera(&camera->t);
entDrawAll();
gfxPresent();
}
//Graphics code
void gfxPrepare(int clearColor, int clearStencil) {
//TODO parse args
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
}
void gfxPresent() {
glfwSwapBuffers();
}
void gfxSetCamera(transform *t) {
float *m = t->m;
float viewmatrix[16]={
m[0], m[4], m[8], 0,
m[1], m[5], m[9], 0,
m[2], m[6], m[10], 0,
-(m[0]*m[12] +
m[1]*m[13] +
m[2]*m[14]),
-(m[4]*m[12] +
m[5]*m[13] +
m[6]*m[14]),
-(m[8]*m[12] +
m[9]*m[13] +
m[10]*m[14]), 1};
glLoadMatrixf(viewmatrix);
}
EDIT: I have reduced the error down to the following
while(!gfxUserQuit()) {
entUpdateAll();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float *m = camera->t.m;
float viewmatrix[16]={
m[0], m[4], m[8], 0,
m[1], m[5], m[9], 0,
m[2], m[6], m[10], 0,
-(m[0]*m[12] +
m[1]*m[13] +
m[2]*m[14]),
-(m[4]*m[12] +
m[5]*m[13] +
m[6]*m[14]),
-(m[8]*m[12] +
m[9]*m[13] +
m[10]*m[14]), 1};
float viewmatrix2[16]={
m[0], m[4], m[8], 0,
m[1], m[5], m[9], 0,
m[2], m[6], m[10], 0,
-(m[0]*m[12] +
m[1]*m[13] +
m[2]*m[14]),
-(m[4]*m[12] +
m[5]*m[13] +
m[6]*m[14]),
-(m[8]*m[12] +
m[9]*m[13] +
m[10]*m[14]), 1};
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(viewmatrix2);
entDrawAll();
glfwSwapBuffers();
}
If i remove the definition and initialization of 'float viewmatrix' nothing is draw to screen. If i restore it it renders as normal. Is this some memory corruption or something?
EDIT2 they are different.
How can i debug this?
EDIT3 I was calling glfwGetTime() without including the file. This is what was breaking it :O
What if, from your second example, you replaced "float viewmatrix...;" with "char tmpbuffer[16 * sizeof(float);" and then (assuming that did nothing) added "memset(tmpbuffer, 0, sizeof(tmpbuffer));"?
It sounds like something is corrupting your stack and that the first viewmatrix definition "fixes" it for the second one. What I'm suggesting should verify the problem is something along this line.

Resources