FDF - Wireframe Maker

This program takes in a text map and generates pixel by pixel a wireframe model in a perspective view.

I learned about how the general bresenham line drawing algorithm works, and as well using the miniMLX graphics library.

Libraries: Libft, MLX

Language: C

Compiling:

If running on MacOSX please use the normal Makefile, however if you are running on Linux please use Makefile_Linux and have the following libraries installed:

Libx11-dev

Libxext-dev

Build-essential

Clang

To install all the packages use the following command:

sudo apt-get install git libx11-dev libxext-dev build-essential clang

Git Repo

creategrid.c

#include "fdf.h" int *magiccopy(char *str) { int *str2; int i; int i2; int strlen; i = 0; i2 = 0; strlen = ft_strlen(str); str2 = ft_memalloc((strlen) * sizeof(int)); while (i < strlen) { if (!(ft_isspace(str[i])) && str[i] != '\0') { str2[i2] = magic_atoi(&str[i]); i += ft_nbrlen(str[i]); i2++; } else i++; } i2 = 0; while (i2 < 11) i2++; return (str2); } int **makemap(int fd, t_lemap *magicmap) { char *str; int i; i = 0; while (i != magicmap->h + 1) { if (get_next_line(fd, &str) > 0) { magicmap->map[i] = magiccopy(str); ft_bzero(str, ft_strlen(str)); free(str); } i++; } close(fd); return (magicmap->map); } int linewidth2(char **str) { int i; i = 0; while (str[i]) i++; return (i); } void lineheight(int fd, t_lemap *maplist) { char **superline; char *line; int width; int i; width = 0; i = 0; if (get_next_line(fd, &line) > 0) { superline = ft_strsplit(line, ' '); maplist->w = linewidth2(superline); while (superline[i]) free(superline[i++]); free(superline); free(line); width++; } while (get_next_line(fd, &line) > 0) { width++; free(line); } maplist->h = width; close(fd); }

draweverything.c

#include "fdf.h" void checkdatline(char *str) { int i; i = 0; while (str[i] != '\0') { if (isletter(str[i])) { if (str[i] == 'G') break ; errorcheck("Line has alphabet characters"); } if ((str[i] == '-' && (!(ft_isdigit(str[i + 1])))) || str[i] == '\t') errorcheck("Line aint right"); i++; } } int increasez(int key, t_lemap *magicmap) { if (key == 17) { magicmap->height = 0; while (magicmap->height != magicmap->h) { magicmap->width = 0; while (magicmap->width != magicmap->w) { if (magicmap->map[magicmap->height][magicmap->width] != 0) magicmap->map[magicmap->height][magicmap->width] += 10; magicmap->xgrid[magicmap->height][magicmap->width] = magicmap->xgrid[magicmap->height][magicmap->width] - magicmap->map[magicmap->height][magicmap->width]; magicmap->width++; } magicmap->height++; } } drawgrid(magicmap); return (0); } void setvar_drawline(t_lemap *magicmap) { magicmap->x = magicmap->x1; magicmap->y = magicmap->y1; magicmap->dx = abs(magicmap->x2 - magicmap->x1); magicmap->dy = abs(magicmap->y2 - magicmap->y1); magicmap->sign1 = (magicmap->x2 > magicmap->x1) ? 1 : -1; magicmap->sign2 = (magicmap->y2 > magicmap->y1) ? 1 : -1; magicmap->i = 0; magicmap->swapit = 0; } void draw_line(t_lemap *magicmap) { setvar_drawline(magicmap); if (magicmap->dy > magicmap->dx) { ft_swap(&magicmap->dx, &magicmap->dy); magicmap->swapit = 1; } magicmap->d = 2 * magicmap->dy - magicmap->dx; while (magicmap->i++ < magicmap->dx) { mlx_pixel_put(magicmap->mlx, magicmap->win, magicmap->x, magicmap->y, magicmap->color); while (magicmap->d >= 0) { magicmap->d = magicmap->d - 2 * magicmap->dx; if (magicmap->swapit) magicmap->x += magicmap->sign1; else magicmap->y += magicmap->sign2; } magicmap->d = magicmap->d + 2 * magicmap->dy; if (magicmap->swapit) magicmap->y += magicmap->sign2; else magicmap->x += magicmap->sign1; } }

draweverything2.c

#include "fdf.h" int createbox(t_lemap *magicmap) { int width; int height; int number; number = findspacing(magicmap); magicmap->x1 = 0; magicmap->y1 = 0; height = 0; while (height != magicmap->h) { magicmap->x1 = 0; width = 0; while (width != magicmap->w) { magicmap->x1 += number; magicmap->xgrid[height][width] = magicmap->x1; magicmap->ygrid[height][width] = magicmap->y1; width++; } magicmap->y1 += number; height++; } return (0); } int distortbox(t_lemap *magicmap) { int width; int height; height = 0; while (height != magicmap->h) { magicmap->x1 = 0; width = 0; while (width != magicmap->w) { magicmap->xgrid[height][width] = magicmap->xgrid[height][width] - magicmap->map[height][width]; magicmap->ygrid[height][width] = magicmap->ygrid[height][width] + ((magicmap->xgrid[height][width] + magicmap->map[height][width]) / 2); width++; } height++; } return (0); } int centerbox(t_lemap *magicmap) { int width; int height; height = 0; while (height != magicmap->h) { magicmap->x1 = 0; width = 0; while (width != magicmap->w) { magicmap->xgrid[height][width] += (magicmap->winwidth / magicmap->w) + (magicmap->winwidth * .05); magicmap->ygrid[height][width] += (magicmap->winheight / magicmap->h) + (magicmap->winheight * .0925); mlx_pixel_put(magicmap->mlx, magicmap->win, magicmap-> xgrid[height][width], magicmap->ygrid[height][width], magicmap->color); width++; } height++; } return (0); } void ft_swap(int *one, int *two) { int temp; temp = *one; *one = *two; *two = temp; }

draweverything3.c

#include "fdf.h" void drawvir(t_lemap *magicmap) { magicmap->height = 0; magicmap->width = 0; while (magicmap->height != magicmap->h) { magicmap->width = 0; while (magicmap->width != magicmap->w) { magicmap->x1 = magicmap->xgrid[magicmap->height][magicmap->width]; magicmap->y1 = magicmap->ygrid[magicmap->height][magicmap->width]; if (magicmap->height + 1 != magicmap->h) { magicmap->x2 = magicmap->xgrid[magicmap->height + 1][magicmap->width]; magicmap->y2 = magicmap->ygrid[magicmap->height + 1][magicmap->width]; } draw_line(magicmap); magicmap->width++; } magicmap->height++; } } void drawhor(t_lemap *magicmap) { magicmap->height = 0; magicmap->width = 0; while (magicmap->height != magicmap->h) { magicmap->width = 0; while (magicmap->width != magicmap->w) { magicmap->x1 = magicmap->xgrid[magicmap->height][magicmap->width]; magicmap->y1 = magicmap->ygrid[magicmap->height][magicmap->width]; if (magicmap->width + 1 != magicmap->w) { magicmap->x2 = magicmap->xgrid[magicmap->height][magicmap->width + 1]; magicmap->y2 = magicmap->ygrid[magicmap->height][magicmap->width + 1]; } draw_line(magicmap); magicmap->width++; } magicmap->height++; } } void drawgrid(t_lemap *magicmap) { drawhor(magicmap); drawvir(magicmap); }

getinfo.c

nclude "fdf.h" void freestuff(char *str, char **str2) { free(str); free(str2); } int linewidth(char **str) { int i; i = 0; while (str[i]) i++; return (i); } void lineheight(int fd, t_lemap *maplist) { char **superline; char *line; int width; int i; width = 0; i = 0; if (get_next_line(fd, &line) > 0) { superline = ft_strsplit(line, ' '); maplist->w = linewidth(superline); while (superline[i]) free(superline[i++]); free(superline); free(line); width++; } while (get_next_line(fd, &line) > 0) { width++; free(line); } maplist->h = width; close(fd); } int ft_nbrlen(int nbr) { int i; i = 1; while (nbr > 9) { nbr /= 10; i++; } return (i); } int *magiccopy(char *str) { int *str2; int i; int i2; int strlen; i = 0; i2 = 0; strlen = ft_strlen(str); str2 = ft_memalloc((strlen) * usizeof(int)); while (i < strlen) { if (!(ft_isspace(str[i])) && str[i] != '\0') { str2[i2] = magic_atoi(&str[i]); i += ft_nbrlen(str[i]); i2++; } else i++; } return (str2); }

main.c

#include "fdf.h" void errorcheck(char *str) { ft_putendl(str); exit(0); } int magic_atoi(char *str) { size_t i; size_t z; size_t sign; i = 0; z = 0; sign = 1; if (str[z] == '-' || str[z] == '+') { sign = (str[z] == '-' ? -1 : 1); z++; } while (str[z] != '\0' && str[z] >= '0' && str[z] <= '9') { i = i * 10 + str[z] - '0'; z++; } return (i * sign); } void printstrs(t_lemap *magicmap) { mlx_string_put(magicmap->mlx, magicmap->win, 10, 30, COLOR, S1); mlx_string_put(magicmap->mlx, magicmap->win, 10, 45, COLOR, S2); mlx_string_put(magicmap->mlx, magicmap->win, 10, 60, COLOR, S3); mlx_string_put(magicmap->mlx, magicmap->win, 10, 75, COLOR, S4); mlx_string_put(magicmap->mlx, magicmap->win, 10, 90, COLOR, S1); } void makewindow(t_lemap *magicmap) { magicmap->mlx = mlx_init(); magicmap->win = mlx_new_window(magicmap->mlx, magicmap->winwidth, magicmap->winheight, "FDF"); mlx_key_hook(magicmap->win, clockingout, magicmap); magicmap->xgrid = creategrid(magicmap); magicmap->ygrid = creategrid(magicmap); createbox(magicmap); distortbox(magicmap); centerbox(magicmap); drawgrid(magicmap); printstrs(magicmap); mlx_loop(magicmap->mlx); } int main(int argc, char **argv) { t_lemap *magicmap; int fd; if (argc != 2) errorcheck("Too much stuff"); if ((fd = open(argv[1], O_RDONLY)) == -1) errorcheck("Didn't Open"); if (!(magicmap = (t_lemap *)ft_memalloc(sizeof(t_lemap)))) errorcheck("memalloc error"); magicmap->winwidth = 1200; magicmap->winheight = 1200; magicmap->color = 0xffffff; checkfile(fd, argv[1]); fd = open(argv[1], O_RDONLY); lineheight(fd, magicmap); magicmap->map = createmap(magicmap); fd = open(argv[1], O_RDONLY); magicmap->map = makemap(fd, magicmap); makewindow(magicmap); fd = magicmap->h - 1; while (fd >= 0) free(magicmap->map[fd--]); free(magicmap->map); }

makemap.c

#include "fdf.h" int isletter(char c) { if ((c <= 'Z' && c >= 'A') || (c <= 'z' && c >= 'a')) return (1); return (0); } void checkwidth(int fd, int width, int truewidth) { char *str; char **str2; if (get_next_line(fd, &str) > 0) { checkdatline(str); if (!(str2 = ft_strsplit(str, ' '))) errorcheck("Line Wrong"); if (!(truewidth = linewidth(str2))) errorcheck("Width"); freestuff(str, str2); } else errorcheck("File is Empty"); while (get_next_line(fd, &str) > 0) { checkdatline(str); if (!(str2 = ft_strsplit(str, ' '))) errorcheck("Line Wrong"); width = linewidth(str2); if (truewidth != width) errorcheck("Width Uneven"); freestuff(str, str2); } } void checkfile(int fd, char *filename) { int width; int truewidth; width = 0; truewidth = 0; if (ft_strstr(filename, ".fdf") == 0) errorcheck("Wrong File Name"); checkwidth(fd, width, truewidth); close(fd); } int **makemap(int fd, t_lemap *magicmap) { char *str; int i; i = 0; while (i != magicmap->h + 1) { if (get_next_line(fd, &str) > 0) { magicmap->map[i] = magiccopy(str); ft_bzero(str, ft_strlen(str)); free(str); } i++; } close(fd); return (magicmap->map); } int **createmap(t_lemap *maplist) { int **map; int amount; map = (int **)ft_memalloc(sizeof(int *) * maplist->h); amount = maplist->h - 1; while (amount >= 0) { map[amount] = 0; amount--; } return (map); }

mlxkeys.c

#include "fdf.h" int changecolor(int key, t_lemap *magicmap) { if (key == 12) { mlx_clear_window(magicmap->mlx, magicmap->win); magicmap->color = 0x0b40e7; drawgrid(magicmap); } if (key == 13) { mlx_clear_window(magicmap->mlx, magicmap->win); magicmap->color = 0xfff2345; drawgrid(magicmap); } if (key == 14) { mlx_clear_window(magicmap->mlx, magicmap->win); magicmap->color = 0x11c300; drawgrid(magicmap); } if (key == 15) { mlx_clear_window(magicmap->mlx, magicmap->win); magicmap->color = 0xffffff; drawgrid(magicmap); } return (0); } int clockingout(int key, t_lemap *magicmap) { if (!(magicmap->win)) return (0); if (key == 12 || key == 13 || key == 14 || key == 15) changecolor(key, magicmap); if (key == 17) { mlx_clear_window(magicmap->mlx, magicmap->win); increasez(key, magicmap); } if (key == 53) { ft_putendl("Clocking out"); exit(0); } return (0); } int findz(int x, int y, t_lemap *magicmap) { int z; int width; z = 0; width = 0; while (width != y) { z = magicmap->map[x][width]; width++; if (width == magicmap->h + 1) errorcheck("Can't find Z value"); } return (z); } int **creategrid(t_lemap *maplist) { int **grid; int amount; grid = (int **)ft_memalloc(sizeof(int *) * maplist->h); amount = maplist->h - 1; while (amount >= 0) { grid[amount] = (int *)ft_memalloc(sizeof(int) * maplist->w); amount--; } return (grid); } int findspacing(t_lemap *magicmap) { int i; i = 0; if (magicmap->w >= 5) i = 40; if (magicmap->w >= 10) i = 30; if (magicmap->w >= 20) i = 20; if (magicmap->w >= 25) i = 12; if (magicmap->w >= 30) i = 10; if (magicmap->w >= 40) i = 5; if (magicmap->w >= 18 && magicmap->h <= 15) i = 30; if (magicmap->w >= 20 && magicmap->h <= 30) i = 25; if (magicmap->w >= 18 && magicmap->h <= 25) i = 40; if (magicmap->w <= 15 && magicmap->h <= 15) i = 60; return (i); }

fdf.h

#ifndef FDF_H # define FDF_H # define COLOR (0x98FB98) # define S1 "<<<<<<<<<<<<<<<>>>>>>>>>>>>>" # define S2 "To Quit Press: Esc" # define S3 "To Increase Z Axis Press: T" # define S4 "To Change Colors Press: Q through R" # include "libft/libft.h" # include "./minilibx/mlx.h" # include <stdlib.h> # include <fcntl.h> # include <math.h> typedef struct s_lemap { int **map; void *mlx; void *win; int color; int w; int h; int winwidth; int winheight; int **xgrid; int **ygrid; int dx; int dy; int d; int x1; int y1; int x2; int y2; int sign1; int sign2; int x; int y; int i; int swapit; int width; int height; } t_lemap; void errorcheck(char *str); int magic_atoi(char *str); int *magiccopy(char *str); int **makemap(int fd, t_lemap *magicmap); int **createmap(t_lemap *maplist); int **creategrid(t_lemap *maplist); int linewidth(char **str); void lineheight(int fd, t_lemap *maplist); void makewindow(t_lemap *magicmap); int clockingout(int key, t_lemap *magicmap); int changecolor(int key, t_lemap *magicmap); int increasez(int key, t_lemap *magicmap); int restorebox(int key, t_lemap *magicmap); void checkdatline(char *str); void checkwidth(int fd, int width, int truewidth); void checkfile(int fd, char *filename); int isletter(char c); int findspacing(t_lemap *magicmap); int createbox(t_lemap *magicmap); int distortbox(t_lemap *magicmap); int centerbox(t_lemap *magicmap); void ft_swap(int *one, int *two); void setvar_drawline(t_lemap *magicmap); void draw_line(t_lemap *magicmap); void drawvir(t_lemap *magicmap); void drawhor(t_lemap *magicmap); void drawgrid(t_lemap *magicmap); void makewindow(t_lemap *magicmap); int ft_nbrlen(int nbr); void printstrs(t_lemap *magicmap); void freestuff(char *str, char **str2); #endif

Makefile

NAME = fdf CC = clang FLAGS = -Wall -Wextra -Werror FLAGS2 = -L minilibx -lmlx -framework OpenGL -framework AppKit SRC = main.c mlxkeys.c makemap.c draweverything.c draweverything2.c draweverything3.c getinfo.c LIBFT_DIR = libft LIBS = libft/libft.a OBJS = $(SRC:.c=.o) HEADER = fdf.h all: $(NAME) $(LIBS): make -C $(LIBFT_DIR)