Giter Site home page Giter Site logo

fdf's Introduction

fdf

’fil de fer' wireframe 3d model

this project is about representing a landscape as a 3D object in which all surfaces are outlined in lines.

render

how to install

follow the instructions of official minilibx repo to build and include the 'libmlx.a' and 'mlx.h' to your system tl;dr: you should have the libmlx.a on your /usr/local/bin and mlx.h on /usr/local/include (also you can modify the MLX variable on my makefile, if you know wacha doin')

now just clone my repo and build it!

git clone --recurse-submodules [email protected]:fkyros/fdf.git
cd fdf && make

so cool! i wanna do it as well!!!

this project is so visual and interesting to develop that i wanted to record everything needed to develop it. all you need is some C knowledge, refresh some maths, and a lot of patience. i tried to gather all the useful information i found through the net and summarize it for me, so i hope this can help to anyone interested. if you are keen to know everything and as curious as me, make sure to check the resources i used to get to know more about the topics covered! enjoy :)

preamble

mlx is a bit hard to comprehend, but only the math aside is another story. let me introduce you to concepts and vocabulary I came across during the realization of this project in order to succeed in it (or at least try it)

  • rasterisation: taking an image described in vectors and convert it into a series of pixels which, when displayed together look, create the image which was represented via shapes (so a raster is a representation of it)

  • aliasing (staircasing) effect: distortion that happens when a signal is reconstructed in a smaller resolution than the original sample

  • bits per pixel (bpp): the amount of color information contained in each pixel in an image. also called 'depth of image'

  • size line (line length): number of bytes used to store one line of the image in memory

  • interpolation: process in which we use known values to guess unknown values

minilibx

oh god. here we go.

in short, minilib is the graphical library we will use in order to create the project.

to compile properly (on macOS) make sure to add -lmlx -framework OpenGL -framework AppKit flags!!! for other windows, good luck. if you are a linux user, check the flags on my makefile if it works for your distro :) here are some of the functions you may encounter in order for it to work

  • mlx_init() initializes the graphic system to your computer. returns a pointer identifying your mlx unning instance

  • mlx_new_window() creates a window and returns a pointer that identifies it on memory

  • mlx_key_hook() given the window pointer of mlx, a function given as a parameter can handle the key event

  • mlx_loop() mantains the window open until a SIGINT is sent. its always waiting for an event

  • mlx_get_data_addr() used to obtain window info from the system. given the issue of pixel_put, we need this info to create mlx images. we can obtain from this function:

    • bpp
    • line length: how many bytes does a word of the display memory (VRAM) is long
    • endian: how does the system manage the order of bytes
  • mlx_put_image_to_window() displays everything from the image memory into the screen

make sure to check the official manual for more detailed information.

mlx images

a windows is made up of pixels. here, a pixel stores 4 different values: ALPHA and RGB color encoding.

  • ALPHA: refers to the opacity of the pixel
  • RGB: represents the color in 3 hexadecimal values determining the amount of red, green and blue respectively

(usually) each of these values occupies 1B of memory, so every pixel requires 4B of memory (ARGB econding). if this numbers do not ring a bell to you, get your bits per pixel with the mlx_get_color_value() function.

why use mlx images instead of pixel_put?

using pixel put takes way longer than managing an image in memory. to display just one pixel it has to access the program, draw the pixel on the desired coordinate, and return an integer.

we rather buffer everything onto an image where we input all the information we want, and then draw everything at once.

writing our own pixel_put for mlx images

in order to write on the proper place of the window image, we need to calculate where on memory is this pixel located

given two coordinates (a point, make sure its in bounds of the window size!!) and the mlx_image memory direction, we can calculate the position in the window with:

	offset = (y * mlx->size_line) + (x * mlx->bpp/8);
	pixel_pos = mlx->img + offset;

'y' is the row where you want to write the pixel, multiplying it by the line length of a row, you get the total number of bytes in all preceding rows, getting where the row in memory is.

the 'x' coordinate represents the column in which the pixel is located. multiplying it by bpp/8 gives the total number of bytes in all preceding pixels within the same row. the division by 8 is necessary because the bpp represents the number of bits per pixel, and each byte is 8 bits.

so now, the pixel we want is at the begining of the image plus this offset we calculated. later on, we can access this memory place to write which color we want to display.

yea but how do i draw?

let me introduce you to Jack Elton Bresenham and his famous algorithm developed back then in 1965 back then at IBM. his line plotting algorithm is a simple and rapid method that determines the points with a close approximation of a straight line between two points. the reason why I chose this algorithm is because of its efficiency. by only using substraction, addition and multiplication, you can draw almost anything. this will be the basis for the project (given that everything drawn in here are lines lol)

rasterizing a line

source pic

lets see how it works, and my implementation:

void    bresenham(t_fdf *fdf, t_point from, t_point to)
{
    t_point diff;
    t_point sign;
    t_point point;
    int     err;
    int     factor;

	//the differences refer to how distant are the initial to the final points
    diff.x = ft_abs(to.x - from.x);
    diff.y = ft_abs(to.y - from.y);
	//the sign defines in which direction should we advance inside the grid
    sign.x = -1;
    sign.y = -1;
    if (from.x < to.x)
        sign.x = 1;
    if (from.y < to.y)
        sign.y = 1;

    point.x = from.x;
    point.y = from.y;
    err = diff.x - diff.y; //decision parameter to know in which direction move (x or y) in each step (dx - dy its convention)
    //in each instance, the mesh point nearest to the desired line segment is selected
    while (point.x != to.x || point.y != to.y)
    {
        img_pixel_put(fdf->mlx, point.x, point.y); //paint
        factor = err * 2; //used for optimization in the algo: removes redundant operations
        if (factor > - diff.y) //if the dx portion on err is bigger than the dy
        {
            point.x += sign.x; //we have to diminish the error by getting closer to the direction of x
            err -= diff.y; //we reduce the error by "dy" factor because of increasing 1 nudge in the x direction
        }
        if (factor < diff.x)
        {
            point.y += sign.y;
            err += diff.x;
        }
    }
}

the decision making inside the loop is based on HOW the error parameter of the interpolation method is made

now you have to read the whole map and draw it with this algo :)

great grid, but where is the z dimension??

TODO: explain isometric and orthogonemtric perspectives

what we need to do to achieve the classic isometric view and apply altitude to our raster, we need to rotate 45º the grid and squash it in half (as the gif shows)

iso grid

credits to Jordan West for the visuals

after that, apply the altitude value on the z coord. but spoiler!!! its a 2D enviroment, so we need to trick the y axis value to represent this.

OMG can i color it??

sure! let's add some keybinds to change the background color for another cooler view hehe

carbon_render

TODO: gradient explanation

lets get playful

TODO: explain mlx events and modifiable parameters

TODOs thing

this project began to take me too long for what the intra thinks its worth, so i had to leave it as it is, without implementing some other cool features i had planned as raster bending or color gradients... lets hope for the best in my cursus :')

resources

this could haven't happened without these golden archives:

fdf's People

Contributors

fkyros avatar

Watchers

 avatar

fdf's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.