Compare commits

...

53 Commits

Author SHA1 Message Date
Milang f8da258442 add a log 2019-10-31 11:46:25 +01:00
Milang fc77fef9a7 gitignore update 2019-10-31 11:02:10 +01:00
Milang 0fc0adac49 finish all functions. It is the beginning of beta phase ! 2019-10-31 11:00:26 +01:00
Milang 6d745d454a move render folder 2019-10-31 10:59:54 +01:00
Milang 51d65485ac add first fe_renderlist function 2019-10-30 19:49:59 +01:00
Milang 3c66554835 add renderlist header (incomplete) 2019-10-30 11:34:23 +01:00
Milang fc0071f83e rename incorrect variables 2019-10-26 15:51:43 +02:00
Milang f8129c8b18 add & 2019-10-26 15:50:41 +02:00
Milang 84e656d30a ipoint -> vertex 2019-10-26 15:49:58 +02:00
Milang 8b8f8d511a add ; 2019-10-26 15:48:13 +02:00
Milang a413ec89a9 string.h stdlib.h 2019-10-26 15:47:35 +02:00
Milang cf9e329580 = -> == 2019-10-26 15:46:07 +02:00
Milang 6911776aca update object 2019-10-26 15:44:56 +02:00
Milang 1730d98911 complete fxengine files 2019-10-26 15:17:02 +02:00
Milang 4c534571fd add check vram 2019-10-26 15:13:33 +02:00
Milang 33396b4af2 correct fe_vram address 2019-10-26 15:10:09 +02:00
Milang 1f6ba41298 object.h corrections 2019-10-26 15:08:45 +02:00
Milang 2c8e7cb263 add #include 2019-10-26 15:05:08 +02:00
Milang f69227192d change object.h location and update contents 2019-10-26 15:02:44 +02:00
Milang c01a6cd9c0 adding new object model 2019-10-26 14:39:59 +02:00
Milang 7a621ae56b -; 2019-10-26 14:26:18 +02:00
Milang e882cfbfee triangle 2019-10-26 14:25:52 +02:00
Milang 05b98c77e3 "translated" => "target" 2019-10-26 14:22:57 +02:00
Milang e21d481b78 stdint 2019-10-26 14:21:49 +02:00
Milang 4dd7b142c4 merge "vertex" and "point" 2019-10-26 14:18:16 +02:00
Milang f2e3c92f65 c 2019-10-25 22:52:49 +02:00
Milang 06a4bf2fc8 b 2019-10-25 22:52:10 +02:00
Milang 771524e4eb a 2019-10-25 22:51:24 +02:00
Milang 53c5489da6 s s3 2019-10-25 22:49:56 +02:00
Milang b9c84f7823 min max 2019-10-25 22:48:30 +02:00
Milang 9731133706 -> . 2019-10-25 22:47:17 +02:00
Milang be6214a41e correct names 2019-10-25 22:46:36 +02:00
Milang 371251f049 :) 2019-10-25 22:43:34 +02:00
Milang 8a49bb2c9a -; 2019-10-25 22:42:41 +02:00
Milang 83ef2c7465 ipoint -> point 2019-10-25 22:41:55 +02:00
Milang c806ee9c07 triangle.c 2019-10-25 20:42:58 +02:00
Milang 54a31fdbca replace models by model 2019-10-25 20:39:51 +02:00
Milang 69c2f79095 w 2019-10-25 20:38:33 +02:00
Milang f11d89d4cf zzz 2019-10-25 20:37:17 +02:00
Milang 33c45d0718 rename variable 2019-10-25 20:35:12 +02:00
Milang f32a2bc7b6 correct syntax error 2019-10-24 19:25:56 +02:00
Milang 419b74c5d0 correct bmp func names 2019-10-24 17:36:57 +02:00
Milang 29d85cd5a9 comment object, which is currently not implemented 2019-10-24 17:31:05 +02:00
Milang e59dac5b8d correct syntax error 2019-10-24 17:29:29 +02:00
Milang b9620fdebc correct #include 2019-10-24 17:28:09 +02:00
Milang fc2389d605 adding triple buffering 2019-10-24 17:27:13 +02:00
Milang 8c48f584f0 merge camera and matrix, and delete camera source file 2019-10-24 11:53:16 +02:00
Milang f18ebfd828 . 2019-10-23 20:07:39 +02:00
Milang 1db17f353a reorg. fxengine 2019-10-23 19:14:23 +02:00
Milang 501a36ec69 add the last functions in the bmp doc, and remove old comments in bitmap header 2019-10-23 15:41:07 +02:00
Milang 25534c69af correct link in bmp doc 2019-10-23 15:34:13 +02:00
Milang 39e25c13e5 Complete bitmap doc 2019-10-23 15:32:40 +02:00
Milang da72997a6e Adding doc, and organizing the structure 2019-10-23 14:53:06 +02:00
33 changed files with 838 additions and 844 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@ Doxyfile
*.tar.xz
*.cfg
*.directory

View File

@ -1,30 +0,0 @@
#ifndef FE_CAMERA
#define FE_CAMERA
#include <fxengine/space.h>
struct fe_camera
{
fe_ipoint pos; // point of view
fe_fpoint pos_temp; // floating copy used while moving
double dh, dv, roll;
};
typedef struct fe_camera fe_camera;
/**
* @brief Sets up the translation matrices for a new rendering cycle
* There is no need to call this function if you have already called render_update()
*
* @param[in] dh Camera's horizontal direction (rad)
* @param[in] dv Camera's vertical direction (rad)
* @param[in] roulis Optionnal rotation around the middle of the screen
* @param[in] camera The camera's coordinates, as an integer position
*/
void fe_view_set_param(const double dh, const double dv, const double roulis, const fe_ipoint * camera);
void fe_view_set(const fe_camera * cam);
#endif

View File

@ -1,20 +1,19 @@
#ifndef FE_FXENGINE
#define FE_FXENGINE
#include <stdint.h>
#include <fxengine/model/object.h>
/**
* @brief Clears zbuffer, counts fps and log settings
*
* @param[in] libprof_channel The libprof channel to be used to count_fps
* if you don't use libprof channel, (default), you send what you want,
* it doesn't matters ;)
*/
void fe_update(const uint32_t libprof_channel);
void fe_add_object(fe_object * const o);
void fe_del_object(fe_object * const o);
/* updates and clears vram, than calls fe_update */
void fe_display(const uint32_t libprof_channel);
void fe_load(); // Lance le thread de rendering
void fe_quit(); // Appelee depuis un timer, cette fonction rend la main au programme à la fin de la frame
void fe_custom_panic();
// Callbacks (a executer au début et à la fin d'une interruption intervenant sur l'affichage)
void fe_callback_start();
void fe_callback_end();
void fe_draw(); // draw image, mais pour le rendu 3D
uint32_t fe_get_fps(); // Pas la fréquence d'affichage, mais la fréquence de rendu
#endif

26
include/fxengine/math.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef FE_MATH
#define FE_MATH
#include <stdint.h>
// Custom calculation depth for trigonometric functions
void fe_set_trigo(uint32_t p);
uint32_t fe_get_trigo(void);
double fe_modulo_2pi(double a);
double fe_cos(double angle);
double fe_sin(const double angle);
/**
* mathematics constants
* TODO déplacer dans caméra
*/
#define pi 3.14159265358
#define pi2 6.28318530718
#define pi_sur_2 1.57079632679
#endif

10
include/fxengine/matrix.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef FE_MATRIX
#define FE_MATRIX
#include <fxengine/model/vertex.h>
#include <fxengine/model/camera.h>
void fe_vertex_translate(fe_vertex const * const source, fe_vertex * target);
void fe_set_matrix(fe_camera const cam);
#endif

View File

@ -0,0 +1,37 @@
#ifndef FE_MODEL_BITMAP
#define FE_MODEL_BITMAP
#include <stdint.h>
#include <stdbool.h>
/* bitmap model
transparency is in the layout
this color type is monochrome only ! */
typedef struct
{
uint32_t size_px_x;
uint32_t size_px_y;
uint32_t size_o_y;
uint32_t * color;
bool color_dynamic;
uint32_t * layout;
bool layout_dynamic;
} fe_bitmap;
fe_bitmap* fe_bitmap_new(uint32_t size_px_x, uint32_t size_px_y, uint32_t* color, bool copy_color, uint32_t *layout, bool copy_layout);
void fe_bitmap_del(fe_bitmap * bmp);
/* fe_bitmap_get_pixel()
returns the color of a pixel in the gint's type*/
uint8_t fe_bitmap_get_px(const fe_bitmap * bmp, uint32_t x, uint32_t y);
/* fe_bitmap_display_pixel()
display a specific rich bitmap pixel on the screen (on vram) */
void fe_bitmap_display_px(const fe_bitmap * bmp, uint32_t bmp_x, uint32_t bmp_y, uint32_t scr_x, uint32_t scr_y);
#endif

View File

@ -0,0 +1,60 @@
# Fxengine::Bitmap
This is part of the [fxengine](/Milang/fxengine) project.
This file refers to [fxengine/model/bitmap.h](bitmap.h) header.
## Dependencies
<none>
## Presentation
The `fe_bitmap` data structure is a way to use pictures in fxengine. These pictures are saved with a format which is near to the `*.bmp` type.
## Detail
```c
typedef struct
{
uint32_t size_px_x;
uint32_t size_px_y;
uint32_t * color;
uint32_t * layout;
bool color_dynamic;
bool layout_dynamic;
uint16_t size_o_y;
} fe_bitmap;
```
Here are the most used parameters, the others are used internally by the machine, so they do not need to be initialized.
### Size
`size_px_x` and `size_px_y` are the bitmap's height and width, in pixels.
### Color and layout encoding
- `*color` is a pointer to a monochrome bitmap.
The format is the following : one bit per pixel: 1 = black, 0 = white.
- `*layout` is a pointer to a layout for the previous bitmap.
It is one bit per pixel too, and then, 1=visible, 0=invisible.
## Use
### Create
It is not recommended to create a bitmap as this :
```c
fe_bitmap bmp
{...};
```
Please use the function
```c
fe_bitmap_rich* fe_bitmap_new(
uint32_t size_px_x, uint32_t size_px_y, // bitmap size
uint32_t* color, bool copy_color, // color table address and type (static | dynamic)
uint32_t *layout, bool copy_layout // layout table address and type (static | dynamic)
);
```
The `bool copy_<...>` lets you choose:
- if the bitmap header takes data from the pointer you have given.
- if the bitmap header needs to copy data itself.
### Delete
The bitmap is dynamically allocated, so it should be deleted by using `free()` method. However, it contains some complex data, which is itself dynamically allocated, so you need to call that method: `fe_bitmap_del()`.
The only argument to pass is the bitmap's address.
### Display
You cannot display the bitmap yet, but in fxengine, it is not a priority.
However, you can display a specific pixel with `fe_bitmap_display_px()`, or you can get its color with `fe_bitmap_get_px`.

View File

@ -0,0 +1,12 @@
#ifndef FE_CAMERA
#define FE_CAMERA
#include <fxengine/model/vertex.h>
typedef struct
{
fe_vertex pos; // point of view
double dh, dv, roll;
} fe_camera;
#endif

View File

@ -0,0 +1,39 @@
#ifndef FE_MODEL_OBJECT
#define FE_MODEL_OBJECT
#include <fxengine/model/vertex.h>
#include <fxengine/model/triangle.h>
#include <stdbool.h>
#include <stdint.h>
typedef struct
{
fe_vertex centre; // Emplacement de l'objet
fe_vertex * vertex_table; // Coordonnées du modèle
uint32_t vt_size;
bool vt_own;
fe_triangle * face_table;
uint32_t ft_size;
bool ft_own;
// Plage de travail privée
fe_vertex * vertex_t0; // vertex_table[x]+centre
fe_vertex * vertex_t1; // fe_translate(vertex_t0)
fe_vertex old_centre; // Avoid changes during one frame :E
} fe_object;
void fe_object_init(fe_object * object); // Create the object on the zone you allocated
void fe_object_set_vertex(fe_object * object, fe_vertex * points, uint32_t n, bool copy);
void fe_object_set_faces(fe_object * object, fe_triangle * faces, uint32_t n, bool copy);
void fe_object_delete(fe_object * object);
void fe_object_display(fe_object * object);
fe_vertex* fe_object_getvx(const fe_object * object, const int n);
#endif

View File

@ -0,0 +1,25 @@
#ifndef FE_MODEL_TRIANGLE
#define FE_MODEL_TRIANGLE
#include <fxengine/model/vertex.h>
#include <fxengine/model/bitmap.h>
#include <stdbool.h>
/* fe_triangle model
this struct makes 3d displaying easier */
typedef struct
{
fe_vertex * s1;
fe_vertex * s2;
fe_vertex * s3;
fe_bitmap * texture1;
fe_bitmap * texture2;
bool texture_half;
} fe_triangle;
/* fe_display_triangle()
displays a triangle from the previous model */
void fe_display_triangle(const fe_triangle * face);
#endif

View File

@ -0,0 +1,25 @@
# Fxengine::Bitmap
This is part of the [fxengine](/Milang/fxengine) project.
This file refers to [fxengine/model/triangle.h](triangle.h) header.
## Dependencies
[bitmap.h](bitmap.h) ([doc](bitmap.md))
[vertex.h](vertex.h) ([doc](vertex.md))
## Presentation
The `fe_triangle` data structure is a way to display easily faces in fxengine. It helps while you are creating models, or just if you want to reduce code size.
## Detail
```c
typedef struct
{
fe_vertex * s1; // The 3 vertexes
fe_vertex * s2;
fe_vertex * s3;
fe_bitmap * texture1; // side 1
fe_bitmap * texture2; // side 2
bool texture_half; // the half used for the textures
} fe_triangle;
```

View File

@ -0,0 +1,20 @@
#ifndef FE_MODEL_VERTEX
#define FE_MODEL_VERTEX
#include <stdint.h>
typedef struct
{
int32_t x;
int32_t y;
int32_t z;
} fe_vertex;
typedef struct
{
double x;
double y;
double z;
} fe_vertex_d;
#endif

View File

@ -1,36 +0,0 @@
#ifndef FE_OBJECT
#define FE_OBJECT
#include <fxengine/space.h>
#include <fxengine/triangle.h>
#include <stdint.h>
#include <stdbool.h>
struct fe_object
{
fe_triangle * faces;
uint32_t f_size;
bool f_owner;
fe_ivertex * points;
uint32_t p_size;
bool p_owner;
};
typedef struct fe_object fe_object;
void fe_object_init(fe_object * object);
void fe_object_set_points(fe_object * object, fe_ivertex * points, uint32_t n, bool copy);
void fe_object_set_faces(fe_object * object, fe_triangle * faces, uint32_t n, bool copy);
void fe_object_delete(fe_object * object);
void fe_object_display(fe_object * object);
void fe_object_debug(const fe_object * object);
fe_ipoint* fe_object_get_vertex(const fe_object * object, const int n);
#endif

View File

@ -1,18 +0,0 @@
#ifndef FE_RENDER_PARAM
#define FE_RENDER_PARAM
// Render param
// You change it as you want before compiling ;)
#define fe_width 128
#define fe_height 64
#define fe_x_mid ((fe_width - 1) / 2) // depends on screen width
#define fe_y_mid ((fe_height - 1) / 2)
#define fe_max_dist 3000
#define fe_min_dist 1
#endif

View File

@ -0,0 +1,14 @@
#ifndef RENDER_BUFFER
#define RENDER_BUFFER
#define fe_width 128
#define fe_height 64
void fe_clear_zbuffer();
#include <stdbool.h>
#include <stdint.h>
bool fe_zbuffer_set_px(const uint32_t x, const uint32_t y, const uint32_t dist); // true if you are allowed to draw the pixel on vram
#endif

View File

@ -0,0 +1,32 @@
#ifndef RENDER_TRIANGLE
#define RENDER_TRIANGLE
#include <fxengine/model/vertex.h>
#include <fxengine/model/bitmap.h>
#include <stdbool.h>
// ERR CODES
#define RENDER_SUCCESSFULLY_RENDERED 0
#define RENDER_NOBMP -1
#define RENDER_OUT_OF_SCREEN -2
#define RENDER_INVISIBLE -3
#define RENDER_DEBUG_MODE
/* render_triangle()
renders a face supporting backface culling, or dual textures */
int render_triangle(fe_vertex const s1, fe_vertex const s2, fe_vertex const s3,
fe_bitmap const * side_0, fe_bitmap const * side_1, bool texture_half);
/* render_triangle_nobfc()
renders a face without backface culling */
int render_triangle_nobfc(fe_vertex const s1, fe_vertex const s2, fe_vertex const s3,
fe_bitmap const * side, bool texture_half);
// Object overlay
#include <fxengine/render/triangle.h>
#include <fxengine/model/triangle.h>
void fe_display_triangle(const fe_triangle * face);
#endif

View File

@ -0,0 +1,19 @@
#ifndef FR_RENDERLIST
#define FR_RENDERLIST
#include <fxengine/model/object.h>
// Returns object ID or -1 if it fails
int fe_renderlist_add(fe_object * const object);
// Returns object ID
int fe_renderlist_remove(fe_object * const object);
// Returns object address
fe_object * fe_renderlist_remove_id(int id);
void fe_renderlist_clear(void);
void fe_render(void);
#endif

View File

@ -1,103 +0,0 @@
#ifndef FE_SPACE
#define FE_SPACE
// Diverses representations de points dans l'espace
#include <stdint.h>
#include <fxengine/parameters.h>
/**
* @brief this struct is a point in 3d, which has coords save as uint32_t
* this is the recommended type for high performance rendering, because the sh3eb-elf architecture
* is 32 bits
* This is also the type used by the rendering triangles.
*/
struct fe_ipoint
{
int32_t x,
y,
z;
};
typedef struct fe_ipoint fe_ipoint;
/**
* @brief this struct is a point in 3d, which has coords save as double
* it is not recommended to use it for high performances rendering,
* because of the sh3eb-elf architecture, which does not support natively floating calculation
*/
struct fe_fpoint
{
double x,
y,
z;
};
typedef struct fe_fpoint fe_fpoint;
/**
* @brief This is a point which is used for 3d translations and rendering
* integer mode is the best solution to increase perfs, and that's why I didn't have implemented
* the floating_points yet. (Maybe I will never add them)
* To render a triangle, you have to set &point.translated as s1, s2 or even s3
*/
struct fe_ivertex
{
fe_ipoint real,
translated;
};
typedef struct fe_ivertex fe_ivertex;
/**
* @brief Translate a point with camera settings
*
* @param point The point to translate
*/
void fe_vertex_translate(fe_ivertex * v);
/**
* @brief Sets up an angle mesure between -pi and +pi
*
* @param[in] a the angle (rad)
*
* @return angle mesure which respect the following contraint :
* -pi <= angle <= pi
*/
double fe_modulo_2pi(double a);
/**
* @brief Homemade cosinus implementation, which is faster than casio provided cosinus function
*
* @param[in] angle The angle (rad)
*
* @return cos angle
*/
double fe_cos(double angle);
/**
* @brief Homemade sinus implementation, which is faster than casio provided sinus function
*
* @param[in] angle The angle (rad)
*
* @return sin angle
*/
double fe_sin(const double angle);
/**
* mathematics constants
* TODO déplacer dans caméra
*/
#define pi 3.14159265358
#define pi2 6.28318530718
#define pi_sur_2 1.57079632679
// translate matrix
extern double fe_matrix[3][3];
extern fe_ipoint fe_translate_delta;
#endif

View File

@ -1,84 +0,0 @@
#ifndef FE_TEXTURE
#define FE_TEXTURE
#include <stdint.h>
#include <stdbool.h>
/**
* @brief texture rich type
* transparency is in the layout
* @warning Monochrome only !
*/
struct fe_texture_rich
{
uint32_t size_px_x;
uint32_t size_px_y;
uint32_t size_o_y;
uint32_t * color;
bool color_dynamic;
uint32_t * layout;
bool layout_dynamic;
};
typedef struct fe_texture_rich fe_texture_rich;
/**
* @brief { function_description }
*
* @param[in] size_px_x The width in px
* @param[in] size_px_y The height in px
* @param color color origin
* @param[in] copy_color if you want to make a copy, or only to make a link
* @param layout layout origin -> can be set as 0 if it isn't needed
* @param[in] copy_layout if you want to make a copy, or to make a link
*
* @return a rich texture, ready to use !
*/
fe_texture_rich* fe_texture_new_rich(uint32_t size_px_x, uint32_t size_px_y, uint32_t* color, bool copy_color,
uint32_t *layout, bool copy_layout);
/**
* @brief delete a rich texture created with texture_new_rich()
*
* @param txtr The texture to delete
*/
void fe_texture_delete_rich(fe_texture_rich * txtr);
/**
* @brief get the color of pixel from rich texture
*
* @param[in] txtr The texture
* @param[in] x The texture x coordinate (in pixels)
* @param[in] y The texture y coordinate (in pixels)
*
* @return the color coded in a unsigned char :
* if (color >> 1)
* switch (color%2)
* {
* case 0:
* // WHITE
* break;
* case 1:
* // BLACK
* }
* else
*/
uint8_t fe_texture_get_pixel_r(const fe_texture_rich * txtr, uint32_t x, uint32_t y);
/**
* @brief display a specific rich texture pixel on the screen (on vram)
*
* @param[in] txtr The texture
* @param[in] txtr_x The texture x coordinate (in pixels)
* @param[in] txtr_y The texture y coordinate (in pixels)
* @param[in] x screen : x coordinate
* @param[in] y screen : y coordinate
*/
void fe_texture_display_pixel_r(const fe_texture_rich * txtr, uint32_t txtr_x, uint32_t txtr_y, uint32_t x, uint32_t y);
void fe_texture_debug(fe_texture_rich * txtr);
#endif

View File

@ -1,42 +0,0 @@
#ifndef FE_TRIANGLE
#define FE_TRIANGLE
#include <fxengine/space.h>
#include <fxengine/texture.h>
#include <stdbool.h>
/**
* @brief Triangle struct used to render fonctions
* @param[out] part choose the used texture half
* @param[out] clockwised choose the visible side of the face
* @param[out] s1,s2,s3 three points
* @param[out] texture used texture
*/
struct fe_triangle
{
fe_ipoint * s1;
fe_ipoint * s2;
fe_ipoint * s3;
fe_texture_rich * texture;
bool part;
bool clockwised;
};
typedef struct fe_triangle fe_triangle;
/**
* @brief Renders a triangle with perspective deformation
*
* @param[in] face pointer to the face to draw
*/
void fe_display_triangle(const fe_triangle * face);
#endif

View File

@ -1,21 +0,0 @@
#ifndef RENDER_ZBUFFER
#define RENDER_ZBUFFER
#include <fxengine/parameters.h>
#include <stdint.h>
/** FE_zbuffer_clear
* effacer le z buffer pour un nouveau cycle de dessin
* TODO : ajouter effacement avec le DMA Controller pour les modèles ayant un processeur SH4-A
**/
void fe_zbuffer_clear();
#include <stdbool.h>
/** FE_zbuffer_set_dist
* change la distance d'un pixel du zbuffer
* retourne true si il faut dessiner le pixel
* retourne false si le pixel est déjà existant
**/
bool fe_zbuffer_set_px(const uint32_t x, const uint32_t y, const uint32_t dist); // if you are allowed to draw the pixel on vram
#endif

Binary file not shown.

View File

@ -1,39 +0,0 @@
#include <fxengine/camera.h>
#include <gint/std/string.h>
void fe_view_set(const fe_camera * cam)
{
fe_view_set_param(cam->dh, cam->dv, cam->roll, &cam->pos);
}
void fe_view_set_param(const double dh, const double dv, const double roulis, const fe_ipoint * camera)
{
const double A=fe_cos(dv);
const double B=fe_sin(dv);
const double C=fe_cos(roulis);
const double D=fe_sin(roulis);
const double E=fe_cos(dh);
const double F=fe_sin(dh);
// raccourcis
const double AD=A*D, BD=B*D;
fe_matrix[0][0]=C*E;
fe_matrix[0][1]=-C*F;
fe_matrix[0][2]=D;
fe_matrix[1][0]=BD*E+A*F;
fe_matrix[1][1]=-BD*F+A*E;
fe_matrix[1][2]=-B*C;
fe_matrix[2][0]=-AD*E+B*F;
fe_matrix[2][1]=AD*F+B*E;
fe_matrix[2][2]=A*C;
// assigner delta
memcpy(&fe_translate_delta, camera, sizeof(fe_ipoint));
}

View File

@ -1,112 +1,111 @@
#include <fxengine/fxengine.h>
#include <fxengine/zbuffer.h>
#define GINT_NEED_VRAM
#include <gint/std/stdio.h>
#include <gint/display.h>
#include <gint/exc.h>
#include <gint/defs/attributes.h>
#include <stdint.h>
#include <fxengine/fxengine.h>
#include <gint/std/stdlib.h>
#include <gint/std/string.h>
#include <stdbool.h>
#include <fxengine/renderlist.h>
#include <fxengine/render/buffer.h>
#ifdef USE_LIBLOG
#include <liblog.h>
#endif
#ifdef USE_LIBPROF
// FPS count
#ifdef USE_LIBPROF
#include <libprof.h>
#endif
#ifdef USE_LIBLOG
#include <liblog.h>
GNORETURN void system_error(uint32_t code)
{
ll_display();
while(1)
getkey();
}
#endif
void fe_custom_panic()
{
#ifdef USE_LIBLOG
gint_panic_set(system_error);
#endif
}
#ifdef USE_LIBPROF
static uint32_t frame_interval_min=1000000;
static uint32_t frame_interval_max=1;
static uint32_t fps=0;
#endif
int32_t fe_get_fps()
uint32_t fe_get_fps()
{
#ifdef USE_LIBPROF
return fps;
#else
return -1;
#endif
}
void fe_display(const uint32_t libprof_channel)
{
fe_update(libprof_channel);
dupdate();
#ifdef USE_LIBLOG
ll_send("VRAM contents sent.");
#endif
// Triple buffering
#define BUFFER_SIZE 256
static uint32_t triple_buffering_area[2*BUFFER_SIZE]; // 2 buffers supplémentaires
static uint32_t * const temp_buffers[2] = {&triple_buffering_area[0], &triple_buffering_area[BUFFER_SIZE]};
static uint32_t * gint_vram=0;
static uint32_t working_buffer=0;
static void check_vram()
{
if (gint_vram==0)
gint_vram=vram;
}
void fe_callback_start()
{
vram=gint_vram;
}
void fe_callback_end()
{
vram=temp_buffers[working_buffer];
}
void fe_draw()
{
memcpy(gint_vram, temp_buffers[1-working_buffer], sizeof(uint32_t)*BUFFER_SIZE);
}
void switch_frame()
{
working_buffer=1-working_buffer;
vram=temp_buffers[working_buffer];
dclear(C_WHITE);
#ifdef USE_LIBLOG
ll_send("VRAM cleared.");
#endif
}
static volatile bool quit=true;
void fe_update(const uint32_t libprof_channel)
void fe_load()
{
///dupdate();
#ifdef USE_LIBPROF
// gestion du temps avec libprof
if (prof_elapsed)
{
prof_leave(libprof_channel);
uint32_t frame_interval = prof_time(libprof_channel);
//sleep_us(0, MINIMUM_FRAME_DELAY-frame_interval);
if (frame_interval<frame_interval_min)
frame_interval_min = frame_interval;
if (frame_interval>frame_interval_max)
frame_interval_max = frame_interval;
fps=1000000/frame_interval;
}
else
{
prof_init(libprof_channel+1, 0);
}
//dupdate();
prof_clear(libprof_channel);
prof_enter(libprof_channel);
#endif
fe_zbuffer_clear();
#ifdef USE_LIBLOG
ll_send("fxEngine loader :\n");
#endif
check_vram();
#ifdef USE_LIBLOG
ll_send(">> Got vram\n");
#endif
fe_callback_end();
#ifdef USE_LIBLOG
ll_send(">> Started triple \n buffering\n");
#endif
#ifdef USE_LIBLOG
char fps_str[10];
sprintf(fps_str, ">> FPS = %d", fps);
ll_send(fps_str);
#else
ll_send(">> FPS not available");
#endif
//dclear(C_WHITE);
quit=false;
#ifdef USE_LIBLOG
ll_send("run fxEng. thread\n");
#endif
while (1)
{
fe_clear_zbuffer();
fe_render();
#ifdef USE_LIBLOG
ll_send("Frame rendered.\n");
#endif
switch_frame();
if (quit)
break;
}
#ifdef USE_LIBLOG
ll_send("ended fxEngine.\n");
#endif
// Free some malloc
//// as object list
}
void fe_quit()
{
quit=1;
}

36
src/math.c Normal file
View File

@ -0,0 +1,36 @@
#include <fxengine/math.h>
static double reducted_cos(const double a)
{
double u= 1.0;
const double a2 = a * a;
for(int32_t p = 17; p>=1; p -= 2)
u = 1 - a2 / (p * p + p) * u;
return u;
}
// return a with -pi<=a<pi
double fe_modulo_2pi(double a)
{
while (a<=-pi)
a += pi2;
while (a>pi)
a -= pi2;
return a;
}
double fe_cos(double angle)
{
angle = fe_modulo_2pi(angle);
if (angle<0)
angle=-angle;
if (angle>=pi_sur_2)
return -reducted_cos(angle - pi);
else
return reducted_cos(angle);
}
double fe_sin(double angle)
{
return fe_cos(angle - pi_sur_2);
}

73
src/matrix.c Normal file
View File

@ -0,0 +1,73 @@
#include <fxengine/matrix.h>
#include <fxengine/model/vertex.h>
#include <stdint.h>
typedef int32_t matrix_type;
static matrix_type matrix[3][3]=
{
{0,0,0},
{0,0,0},
{0,0,0}
};
#define matrix_unit 1024
static fe_vertex pos_delta;
#define sgn(x) (x>=0?x:-x)
void fe_vertex_translate(fe_vertex const * const source, fe_vertex * target)
{
static fe_vertex temp;
temp.x = source->x - pos_delta.x;
temp.y = source->y - pos_delta.y;
temp.z = source->z - pos_delta.z;
target->x = matrix[0][0]*temp.x*matrix_unit + matrix[0][1]*temp.y + matrix[0][2]*temp.z;
target->z = matrix[1][0]*temp.x*matrix_unit + matrix[1][1]*temp.y + matrix[1][2]*temp.z;
target->y = matrix[2][0]*temp.x*matrix_unit + matrix[2][1]*temp.y + matrix[2][2]*temp.z;
target->z/=(matrix_unit/8);
if (target->z>0)
{
target->x/=target->z;
target->y/=target->z;
}
else
{
target->x*=256*sgn(target->z);
target->y*=256*sgn(target->z);
}
target->x+=63;
target->y+=31;
}
void fe_set_matrix(fe_camera const cam)
{
pos_delta.x = cam.pos.x;
pos_delta.y = cam.pos.y;
pos_delta.z = cam.pos.z;
const matrix_type A=matrix_unit*fe_cos(cam.dv);
const matrix_type B=matrix_unit*fe_sin(cam.dv);
const matrix_type C=matrix_unit*fe_cos(cam.roll);
const matrix_type D=matrix_unit*fe_sin(cam.roll);
const matrix_type E=matrix_unit*fe_cos(cam.dh);
const matrix_type F=matrix_unit*fe_sin(cam.dh);
// raccourcis
const matrix_type AD=A*D/matrix_unit, BD=B*D/matrix_unit;
matrix[0][0]=C*E/matrix_unit;
matrix[0][1]=-C*F/matrix_unit;
matrix[0][2]=D;
matrix[1][0]=(BD*E+A*F)/matrix_unit;
matrix[1][1]=(-BD*F+A*E)/matrix_unit;
matrix[1][2]=-B*C/matrix_unit;
matrix[2][0]=(-AD*E+B*F)/matrix_unit;
matrix[2][1]=(AD*F+B*E)/matrix_unit;
matrix[2][2]=A*C/matrix_unit;
}

View File

@ -1,35 +1,55 @@
#include <fxengine/object.h>
#include <fxengine/model/object.h>
#include <gint/std/stdlib.h>
#include <gint/std/stdio.h>
#include <gint/std/string.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/std/stdlib.h>
void fe_object_init(fe_object * object)
{
memset(object, 0, sizeof(fe_object));
}
void fe_object_set_points(fe_object * object, fe_ivertex * points, uint32_t n, bool copy)
static void fe_object_delete_vertex(fe_object * object)
{
if (object->vertex_table==0 && object->vertex_t0==0 && object->vertex_t1==0 && object->vt_size==0)
return;
if (object->vt_own)
free(object->vertex_table);
else
free(object->vertex_t0);
object->vertex_table=0;
object->vertex_t0=0;
object->vertex_t1=0;
object->vt_size=0;
object->vt_own=0;
}
void fe_object_set_vertex(fe_object * object, fe_vertex * points, uint32_t n, bool copy)
{
fe_object_delete_vertex(object);
if (copy)
{
object->points = malloc(n*sizeof(fe_ipoint));
if (!object->points)
object->vertex_table = malloc(3*n*sizeof(fe_vertex)); // Centraliser les données de copie
if (!object->vertex_table)
return;
memcpy(object->points, points, n*sizeof(fe_ipoint));
//memcpy()
memcpy(object->vertex_table, points, n*sizeof(fe_vertex));
object->vertex_t0 = &object->vertex_table[n];
object->vertex_t1 = &object->vertex_table[2*n];
}
else
{
object->points = points;
object->vertex_t0 = malloc(2*n*sizeof(fe_vertex));
if (!object->vertex_t0)
return;
object->vertex_t1 = &object->vertex_t0[n];
object->vertex_table = points;
}
object->p_owner = copy;
object->p_size = n;
object->vt_own = copy;
object->vt_size = n;
}
@ -37,46 +57,68 @@ void fe_object_set_faces(fe_object * object, fe_triangle * faces, uint32_t n, bo
{
if (copy)
{
object->faces = malloc(n*sizeof(fe_ipoint));
if (!object->faces)
object->face_table = malloc(n*sizeof(fe_vertex));
if (!object->face_table)
return;
memcpy(object->faces, faces, n*sizeof(fe_ipoint));
memcpy(object->face_table, faces, n*sizeof(fe_vertex));
}
else
{
object->faces = faces;
object->face_table = faces;
}
object->f_owner = copy;
object->f_size = n;
object->ft_own = copy;
object->ft_size = n;
}
static void fe_object_delete_faces(fe_object * object)
{
if (object->face_table && object->ft_own && object->ft_size)
free(object->face_table);
object->face_table=0;
object->ft_size=0;
object->ft_own=0;
}
void fe_object_delete(fe_object * object)
{
if (object->points && object->p_owner)
free(object->points);
fe_object_delete_vertex(object);
if (object->faces && object->f_owner)
free(object->faces);
fe_object_delete_faces(object);
fe_object_init(object);
}
fe_vertex* fe_object_getvx(const fe_object * object, const int n)
{
return &object->vertex_t1[n];
}
void fe_object_display(fe_object * object)
{
for (int i = 0; i < object->p_size; i++)
fe_vertex_translate(&object->points[i]);
object->old_centre.x=object->centre.x;
object->old_centre.y=object->centre.y;
object->old_centre.z=object->centre.z;
for (int i = 0; i < object->f_size; i++)
fe_display_triangle(&object->faces[i]);
for (int i = 0; i < object->vt_size; i++)
{
object->vertex_t0[i].x = object->old_centre.x + object->vertex_table[i].x;
object->vertex_t0[i].y = object->old_centre.y + object->vertex_table[i].y;
object->vertex_t0[i].z = object->old_centre.z + object->vertex_table[i].z;
fe_vertex_translate(&object->vertex_t0[i]);
}
for (int i = 0; i < object->p_size; i++)
dpixel(object->points[i].translated.x, object->points[i].translated.y, C_BLACK);
for (int i = 0; i < object->ft_size; i++)
fe_display_triangle(&object->face_table[i]);
// for (int i = 0; i < object->p_size; i++)
// dpixel(object->points[i].translated.x, object->points[i].translated.y, C_BLACK);
}
/*
void fe_object_debug(const fe_object * object)
{
dclear(C_WHITE);
@ -105,9 +147,5 @@ void fe_object_debug(const fe_object * object)
dupdate();
getkey();
}
*/
fe_ipoint* fe_object_get_vertex(const fe_object * object, const int n)
{
return &object->points[n].translated;
}

147
src/render/triangle.c Normal file
View File

@ -0,0 +1,147 @@
#include <fxengine/render/triangle.h>
#include <fxengine/render/buffer.h>
#include <fxengine/model/vertex.h>
#include <fxengine/model/bitmap.h>
#include <stdint.h>
#include <stdbool.h>
#include <gint/display.h>
void fe_display_triangle(const fe_triangle * face)
{
render_triangle(*face->s1, *face->s2, *face->s3, face->texture1, face->texture2, face->texture_half);
}
int render_triangle(fe_vertex const s1, fe_vertex const s2, fe_vertex const s3,
fe_bitmap const * side_0, fe_bitmap const * side_1, bool texture_half)
{
// Backface culling
const int32_t area = s1.x * s2.y
- s2.x * s1.y
+ s2.x * s3.y
- s3.x * s2.y
+ s3.x * s1.y
- s1.x * s3.y;
if (area < 0)
return render_triangle_nobfc(s1,s2,s3,side_0,texture_half);
else
return render_triangle_nobfc(s1,s2,s3,side_1,texture_half);
}
// Render Core
// Macros
#define min(x,y) (x<y?x:y)
#define max(x,y) (x>y?x:y)
#define abs(x) (x<0?-x:x)
// gestion des arètes
typedef struct
{
int32_t x,y,z;
int32_t dx,dy,dz;
int8_t no_line; // si les deux points sont confondus (se comporte comme un bool)
} line;
static void line_set(line* l,fe_vertex const * s1, fe_vertex const * s2)
{
l->x = s1->x; l->y = s1->y; l->z = s1->z;
l->dx = s2->x - s1->x; l->dy = s2->y - s1->y; l->dz = s2->z - s1->z;
l->no_line = (l->dx==0 && l->dy==0);
}
static bool line_get_x(int32_t y, line const * l, int32_t * x) // retourne false si impossible, ou alors écrit dans x
{
y -= l->y;
if (y < 0 && l->dy > 0)
return false;
if (y > 0 && l->dy < 0)
return false;
if (abs(y) > abs(l->dy))
return false;
if (l->dy != 0)
*x = l->x + (y * l->dx) / l->dy;
else if (y==0)
*x = l->x + l->dx;
else
return false;
return true;
}
int render_triangle_nobfc(fe_vertex const s1, fe_vertex const s2, fe_vertex const s3,
fe_bitmap const * side, bool texture_half)
{
if (!side) return RENDER_NOBMP;
// clipping (incomplete)
if (s1.x < 0 && s2.x < 0 && s3.x < 0) return RENDER_OUT_OF_SCREEN;
if (s1.x >= fe_width && s2.x >= fe_width && s3.x >= fe_width) return RENDER_OUT_OF_SCREEN;
if (s1.y < 0 && s2.y < 0 && s3.y < 0) return RENDER_OUT_OF_SCREEN;
if (s1.y >= fe_height && s2.y >= fe_height && s3.y >= fe_height) return RENDER_OUT_OF_SCREEN;
if (s1.z <= 0 && s2.z <= 0 && s3.z <= 0) return RENDER_OUT_OF_SCREEN;
line cotes[3];
line_set(&cotes[0], &s1, &s2);
line_set(&cotes[1], &s1, &s3);
line_set(&cotes[2], &s2, &s3);
if (cotes[0].no_line || cotes[1].no_line || cotes[2].no_line) return RENDER_INVISIBLE;
const int32_t ymin = max(min(s1.y, min(s2.y, s3.y)), 0);
const int32_t ymax = min(max(s1.y, max(s2.y, s3.y)), 63);
const int32_t xAB = s2.x - s1.x, yAB = s2.y - s1.y, zAB=s2.z-s1.z;
const int32_t xAC = s3.x - s1.x, yAC = s3.y - s1.y, zAC=s3.z-s1.z;
const int32_t diviseur_commun = (xAB * yAC - yAB * xAC);
const int32_t fact_1= (32768 * yAC) / diviseur_commun, fact_2 = (32768 * xAC) / diviseur_commun;
const int32_t fact_3= (32768 * xAB) / diviseur_commun, fact_4 = (32768 * yAB) / diviseur_commun;
for (int32_t y = ymin; y <= ymax; y++)
{
int32_t tx1,tx2;
for (int t=0;t<3;t++)
{
if (line_get_x(y,&cotes[t],&tx1))
break;
}
for (int32_t t=0;t<3;t++)
{
if (line_get_x(y,&cotes[t],&tx2) && tx1!=tx2)
break;
}
const int32_t txmin=max(min(tx1,tx2),0), txmax=min(max(tx1,tx2),127);
for (int32_t x=txmin; x<=txmax; x++)
{
int32_t vx, vy, z;
const int32_t xcalc = x - s1.x, ycalc = y - s1.y;
// calcul de vx, vy
vx = (xcalc*fact_1 - ycalc*fact_2);
vy = (ycalc*fact_3 - xcalc*fact_4);
z = s1.z + (vx * zAB + vy * zAC)/32768;
if (z>0)
{
int32_t vx2= ( vx*side->size_px_x/s2.z ) / ((32768-vx)/s1.z + vx/s2.z);
int32_t vy2= ( vy*side->size_px_y/s3.z ) / ((32768-vy)/s1.z + vy/s3.z);
// Affichage du point
const uint8_t color = fe_bitmap_get_px(side, vx2, vy2);
if (color >> 1)
{
#ifdef RENDER_DEBUG_MODE
dpixel(x,y, C_BLACK);
#else
if (fe_zbuffer_set_px(x,y,z))
dpixel(x, y, 3 * (color % 2)); // 3* means cast to black and white, and vx,and vy casted between 0 and 7
#endif
}
}
}
}
return RENDER_SUCCESSFULLY_RENDERED;
}

View File

@ -1,4 +1,6 @@
#include <fxengine/zbuffer.h>
#include <fxengine/render/buffer.h>
/*
#include <fxengine/parameters.h>
#include <stdbool.h>
@ -9,7 +11,7 @@
#include <gint/keyboard.h>
#include <gint/defs/attributes.h>
#include <gint/hardware.h>
*/
static const int size_uint32 = fe_width * fe_height;
@ -20,26 +22,18 @@ static const int size_char = size_uint32 * sizeof(uint32_t);
static int32_t *zbuffer = (void *)0x88080000 - (((size_char >> 5) << 5) + 1);
// gint doesn't provide any prototype for that function which is implemented
// AND THE DMA STILL DON'T WOOORK :(
extern void dma_memset(void *dst, uint32_t l, size_t size);
void fe_zbuffer_clear()
void fe_clear_zbuffer()
{
uint32_t indice = 0;
for (indice = 0; indice < size_uint32; indice ++)
zbuffer[indice] = fe_max_dist;
#ifdef USE_LIBLOG
ll_send(">> ZBuffer cleared.");
#endif
zbuffer[indice] = 20000000;
}
bool fe_zbuffer_set_px(const uint32_t x, const uint32_t y, const uint32_t dist)
{
const int indice = x * fe_height + y;
const uint32_t indice = x * fe_height + y;
if (zbuffer[indice]>dist && dist>=fe_min_dist && dist<=fe_max_dist)
if (zbuffer[indice]>dist && dist)
{
zbuffer[indice] = dist;
return true;

75
src/renderlist.c Normal file
View File

@ -0,0 +1,75 @@
#include <fxengine/renderlist.h>
#include <fxengine/model/object.h>
#include <gint/std/stdlib.h>
static fe_object ** list = 0;
static int list_size = 0;
int fe_renderlist_add(fe_object * const object)
{
if (object==0)
return -1;
for (int i=0; i<list_size; i++)
if (list[i]==object)
return -1;
for (int i=0; i<list_size; i++)
{
if (list[i]==0)
{
list[i]=object;
return i;
}
}
if (list==0)
{
list_size++;
list=malloc(sizeof(fe_object*));
list[0]=object;
}
else
{
list_size++;
list=realloc(list, list_size*sizeof(fe_object*));
list[list_size-1]=object;
}
}
int fe_renderlist_remove(fe_object * const object)
{
if (object==0)
return -1;
for (int i=0; i<list_size; i++)
if (list[i]==object)
{
list[i]=0;
return i;
}
return -1;
}
fe_object * fe_renderlist_remove_id(int id)
{
if (id>=list_size)
return 0;
else
{
fe_object * tmp = list[id];
list[id]=0;
return tmp;
}
}
void fe_renderlist_clear(void)
{
free(list);
list_size=0;
return;
}
void fe_render(void)
{
for (int i=0; i<list_size; i++)
if (list[i])
fe_object_display(list[i]);
}

View File

@ -1,98 +0,0 @@
#include <fxengine/space.h>
#include <fxengine/camera.h>
#include <gint/std/stdlib.h>
#include <gint/std/stdio.h>
#include <gint/std/string.h>
#ifdef USE_LIBLOG
#include <liblog.h>
#endif
double fe_matrix[3][3]=
{
{0,0,0},
{0,0,0},
{0,0,0}
};
fe_ipoint fe_translate_delta;
static double reducted_cos(const double a)
{
double u= 1.0;
const double a2 = a * a;
for(int32_t p = 17; p>=1; p -= 2)
u = 1 - a2 / (p * p + p) * u;
return u;
}
// return a with -pi<=a<pi
double fe_modulo_2pi(double a)
{
while (a<=-pi)
a += pi2;
while (a>pi)
a -= pi2;
return a;
}
double fe_cos(double angle)
{
angle = fe_modulo_2pi(angle);
if (angle<0)
angle=-angle;
if (angle>=pi_sur_2)
return -reducted_cos(angle - pi);
return reducted_cos(angle);
}
double fe_sin(double angle)
{
return fe_cos(angle - pi_sur_2);
}
#define sgn(x) (x>=0?x:-x)
void fe_vertex_translate(fe_ivertex * v)
{
static fe_ipoint temp;
temp.x = 64*(v->real.x - fe_translate_delta.x);
temp.y = 64*(v->real.y - fe_translate_delta.y);
temp.z = 64*(v->real.z - fe_translate_delta.z);
v->translated.x = (double)(fe_matrix[0][0]*(double)temp.x + fe_matrix[0][1]*(double)temp.y + fe_matrix[0][2]*(double)temp.z);
v->translated.z = (double)(fe_matrix[1][0]*(double)temp.x + fe_matrix[1][1]*(double)temp.y + fe_matrix[1][2]*(double)temp.z);
v->translated.y = (double)(fe_matrix[2][0]*(double)temp.x + fe_matrix[2][1]*(double)temp.y + fe_matrix[2][2]*(double)temp.z);
//v->translated.x*=10;
//v->translated.y*=10;
v->translated.z/=64;
if (v->translated.z>0)
{
v->translated.x/=v->translated.z;
v->translated.y/=v->translated.z;
}
else
{
v->translated.x*=256*sgn(v->translated.z);
v->translated.y*=256*sgn(v->translated.z);
}
//(v->translated.x*1024)/v->translated.z;
//(v->translated.y*1024)/v->translated.z;
v->translated.x+=fe_x_mid;
v->translated.y+=fe_y_mid;
#ifdef USE_LIBLOG
char str[50];
sprintf(str, "Vrtx %p\n >> X:%d Y:%d Z:%d\n",
v,
v->translated.x,
v->translated.y,
v->translated.z);
ll_send(str);
#endif
}

View File

@ -1,12 +1,12 @@
#include <fxengine/texture.h>
#include <fxengine/model/bitmap.h>
#include <gint/display.h>
#include <gint/std/string.h>
#include <gint/std/stdlib.h>
fe_texture_rich* fe_texture_new_rich(uint32_t size_px_x, uint32_t size_px_y, uint32_t* color, bool copy_color, uint32_t *layout, bool copy_layout)
fe_bitmap* fe_bitmap_new(uint32_t size_px_x, uint32_t size_px_y, uint32_t* color, bool copy_color, uint32_t *layout, bool copy_layout)
{
fe_texture_rich* bmp = malloc(sizeof(fe_texture_rich));
fe_bitmap* bmp = malloc(sizeof(fe_bitmap));
if (!bmp)
return 0;
@ -52,33 +52,7 @@ fe_texture_rich* fe_texture_new_rich(uint32_t size_px_x, uint32_t size_px_y, uin
return bmp;
}
void fe_texture_debug(fe_texture_rich * txtr)
{
dclear(C_WHITE);
if (txtr)
{
char text[21];
sprintf(text, "ADDRESS : %p", txtr);
dtext(1,1, text, C_BLACK, C_NONE);
sprintf(text, "size %d %d", txtr->size_px_x, txtr->size_px_y);
dtext(1,9, text, C_BLACK, C_NONE);
sprintf(text, "color %p %d", txtr->color, txtr->color_dynamic);
dtext(1,17, text, C_BLACK, C_NONE);
sprintf(text, "layout %p %d", txtr->layout, txtr->layout_dynamic);
dtext(1,25, text, C_BLACK, C_NONE);
}
else
{
dtext(1,1, "Texture set as NULL", C_BLACK, C_NONE);
}
dupdate();
getkey();
}
void fe_texture_delete_rich(fe_texture_rich * bmp)
void fe_bitmap_del(fe_bitmap * bmp)
{
if (!bmp)
return;
@ -92,7 +66,7 @@ void fe_texture_delete_rich(fe_texture_rich * bmp)
free(bmp);
}
uint8_t fe_texture_get_pixel_r(const fe_texture_rich * bmp, uint32_t x, uint32_t y)
uint8_t fe_bitmap_get_px(const fe_bitmap * bmp, uint32_t x, uint32_t y)
{
if (x >= bmp->size_px_x || y >= bmp->size_px_y)
return 0;
@ -108,9 +82,9 @@ uint8_t fe_texture_get_pixel_r(const fe_texture_rich * bmp, uint32_t x, uint32_t
}
void fe_texture_display_pixel_r(const fe_texture_rich * bmp, uint32_t bmp_x, uint32_t bmp_y, uint32_t x, uint32_t y)
void fe_bitmap_display_px(const fe_bitmap * bmp, uint32_t bmp_x, uint32_t bmp_y, uint32_t scr_x, uint32_t scr_y)
{
uint8_t color = fe_texture_get_pixel_r(bmp, bmp_x, bmp_y);
uint8_t color = fe_bitmap_get_px(bmp, bmp_x, bmp_y);
if (color)
dpixel(x, y, 3 * (color % 2));
dpixel(scr_x, scr_y, 3 * (color % 2));
}

View File

@ -1,190 +0,0 @@
#include <fxengine/triangle.h>
#include <fxengine/texture.h>
#include <fxengine/space.h>
#include <fxengine/zbuffer.h>
#ifdef USE_LIBPROF
#include <libprof.h>
#endif
#include <gint/display.h>
#include <gint/clock.h>
/**
* @brief Orientation of the face
*
* @param face The face
*
* @return if it is true the it is clockwised else it isn't clockwised
*/
static bool is_colckwised(fe_triangle const * face)
{
int32_t area = 0;
area += face->s1->x * face->s2->y;
area -= face->s2->x * face->s1->y;
area += face->s2->x * face->s3->y;
area -= face->s3->x * face->s2->y;
area += face->s3->x * face->s1->y;
area -= face->s1->x * face->s3->y;
return (area < 0);
}
// gestion locale des arètes
typedef struct line line;
struct line
{
int32_t x,y,z;
int32_t dx,dy,dz;
int32_t no_line; // si les deux points sont confondus (se comporte comme un bool)
};
/**
* @brief Sets up a line with 2 points
*
* @param l The line
* @param s1 The s 1
* @param s2 The s 2
*/
static void line_set(line* l,fe_ipoint const * s1, fe_ipoint const * s2)
{
l->x = s1->x;
l->y = s1->y;
l->z = s1->z;
l->dx = s2->x - s1->x;
l->dy = s2->y - s1->y;
l->dz = s2->z - s1->z;
l->no_line = (l->dx==0 && l->dy==0);
}
static int32_t max(int32_t x, int32_t y)
{
return (x>y ? x : y);
}
static int32_t min(int32_t x, int32_t y)
{
return (x<y ? x : y);
}
static int32_t abs(int32_t x)
{
return(x<0 ? -x : x);
}
/**
* @brief get the corresponding x from the y coordinate
*
* @param[in] y the y coordinate
* @param l the line
* @param x address where x is written
*
* @return if given point coordinate belongs to the l
*/
static bool line_get_x(int32_t y, line const * l, int32_t * x)
{
y -= l->y;
if (y < 0 && l->dy > 0)
return false;
if (y > 0 && l->dy < 0)
return false;
if (abs(y) > abs(l->dy))
return false;
if (l->dy != 0)
*x = l->x + (y * l->dx) / l->dy;
else if (y==0)
*x = l->x + l->dx;
else
return false;
return true;
}
void fe_display_triangle(const fe_triangle * face)
{
// backface culling
if (is_colckwised(face) != face->clockwised)
return;
// incomplete clipping
if (face->s1->x < 0 && face->s2->x < 0 && face->s3->x < 0)
return;
if (face->s1->x >= fe_width && face->s2->x >= fe_width && face->s3->x >= fe_width)
return;
if (face->s1->y < 0 && face->s2->y < 0 && face->s3->y < 0)
return;
if (face->s1->y >= fe_height && face->s2->y >= fe_height && face->s3->y >= fe_height)
return;
if (face->s1->z <= 0 && face->s2->z <= 0 && face->s3->z <= 0)
return;
line cotes[3];
line_set(&cotes[0], face->s1, face->s2);
line_set(&cotes[1], face->s1, face->s3);
line_set(&cotes[2], face->s2, face->s3);
if (cotes[0].no_line || cotes[1].no_line || cotes[2].no_line)
return;
const int32_t ymin = max(min(face->s1->y, min(face->s2->y, face->s3->y)), 0);
const int32_t ymax = min(max(face->s1->y, max(face->s2->y, face->s3->y)), 63);
const int32_t xAB = face->s2->x - face->s1->x, yAB = face->s2->y - face->s1->y, zAB=face->s2->z-face->s1->z;
const int32_t xAC = face->s3->x - face->s1->x, yAC = face->s3->y - face->s1->y, zAC=face->s3->z-face->s1->z;
const int32_t diviseur_commun = (xAB * yAC - yAB * xAC);
const int32_t fact_1= (32768 * yAC) / diviseur_commun, fact_2 = (32768 * xAC) / diviseur_commun;
const int32_t fact_3= (32768 * xAB) / diviseur_commun, fact_4 = (32768 * yAB) / diviseur_commun;
for (int32_t y = ymin; y <= ymax; y++)
{
// xmin and xmax determination
int32_t tx1,tx2;
for (int t=0;t<3;t++)
{
if (line_get_x(y,&cotes[t],&tx1))
break;
}
for (int32_t t=0;t<3;t++)
{
if (line_get_x(y,&cotes[t],&tx2) && tx1!=tx2)
break;
}
const int32_t txmin=max(min(tx1,tx2),0), txmax=min(max(tx1,tx2),127);
for (int32_t x=txmin; x<=txmax; x++)
{
int32_t vx, vy, z;
const int32_t xcalc = x - face->s1->x, ycalc = y - face->s1->y;
// calcul de vx, vy
vx = (xcalc*fact_1 - ycalc*fact_2);
vy = (ycalc*fact_3 - xcalc*fact_4);
z = face->s1->z + (vx * zAB + vy * zAC)/32768;
int32_t vx2= ( vx*face->texture->size_px_x/face->s2->z ) / ((32768-vx)/face->s1->z + vx/face->s2->z);
int32_t vy2= ( vy*face->texture->size_px_y/face->s3->z ) / ((32768-vy)/face->s1->z + vy/face->s3->z);
/* Perspective correction
vx /= (double) face->s2->z / ((1 - vx) / face->s1->z + vx / (double) face->s2->z);
vy /= (double) face->s3->z / ((1 - vy) / face->s1->z + vy / (double) face->s3->z);
*/
// Affichage du point
const uint8_t color = fe_texture_get_pixel_r(face->texture, vx2, vy2);
if (color >> 1)
{
//dpixel(x,y, C_BLACK);
if (fe_zbuffer_set_px(x,y,z))
dpixel(x, y, 3 * (color % 2)); // 3* means cast to black and white, and vx,and vy casted between 0 and 7
}
}
}
}