1789 lines
50 KiB
C++
1789 lines
50 KiB
C++
//----------------------------------------------------------------------------------------------------
|
||
//
|
||
// WINDMILL
|
||
//
|
||
// version : 2.0
|
||
// Moteur de rendu 3D base sur la methode de rasterisation avec buffer de profondeur
|
||
//
|
||
// Cree par Olivier Lanneau, alias NineStars
|
||
// Planet-casio.fr
|
||
//
|
||
//----------------------------------------------------------------------------------------------------
|
||
|
||
|
||
#include "windmill.hpp"
|
||
|
||
//const Texture tex_black = {};
|
||
//const Texture tex_white = {};
|
||
extern Texture tex_white;
|
||
extern Texture tex_light;
|
||
extern Texture tex_dark;
|
||
extern Texture tex_black;
|
||
|
||
|
||
//----------------------------------------------------------------------------------------------------
|
||
// INITIALISATION
|
||
//----------------------------------------------------------------------------------------------------
|
||
Windmill::Windmill()
|
||
{
|
||
camera2 = NULL;
|
||
map = NULL;
|
||
object = NULL;
|
||
z_buffer = NULL;
|
||
set_viewport(0, 0, 128, 64);
|
||
|
||
nb_object_on_screen = 0;
|
||
temp_object_cursor = NULL;
|
||
temp_poly_cursor = -1;
|
||
}
|
||
|
||
|
||
void Windmill::set_camera(Camera* _camera)
|
||
{
|
||
camera2 = _camera;
|
||
}
|
||
|
||
|
||
void Windmill::set_viewport(int viewport_x1, int viewport_y1, int viewport_x2, int viewport_y2)
|
||
{
|
||
viewport.x1 = max(0, viewport_x1);
|
||
viewport.y1 = max(0, viewport_y1);
|
||
viewport.x2 = min(viewport_x2, DWIDTH);
|
||
viewport.y2 = min(viewport_y2, DHEIGHT);
|
||
|
||
//if (z_buffer != NULL) free(z_buffer);
|
||
free(z_buffer);
|
||
shift_x = (viewport.x1 + viewport.x2) / 2;
|
||
shift_y = (viewport.y1 + viewport.y2) / 2;
|
||
|
||
z_buffer_size = (viewport.x2 - viewport.x1) * (viewport.y2 - viewport.y1);
|
||
z_buffer = (unsigned short*) calloc(z_buffer_size, 2);
|
||
//if (z_buffer == NULL) debug_pop("ERROR ptr z_buffer NULL");
|
||
z_buffer_width = viewport.x2 - viewport.x1;
|
||
z_buffer_offset = - viewport.x1 - viewport.y1 * DWIDTH;
|
||
clear_z_buffer();
|
||
|
||
cursor_x = shift_x;
|
||
cursor_y = shift_y;
|
||
}
|
||
|
||
|
||
void Windmill::load_map(Map* _map)
|
||
{
|
||
loading = true;
|
||
|
||
if (map != _map)
|
||
{
|
||
// attribution de la map
|
||
map = _map;
|
||
|
||
// enregistrement des objets de la map dans un tableau
|
||
// ceci permet de trier les objets pour les afficher du plus
|
||
// pres au plus loin
|
||
list_object_length = map->list_object_length;
|
||
//delete[] object;
|
||
free(object);
|
||
//object = new Object* [list_object_length];
|
||
object = (Object**) malloc(list_object_length * sizeof(Object));
|
||
//if (object == NULL) debug_pop("ERROR ptr object NULL");
|
||
for (int i = 0; i<list_object_length; i++)
|
||
{
|
||
object[i] = map->object[i];
|
||
}
|
||
|
||
// generation des spheres englobantes
|
||
// pour chaque objet
|
||
for (int i = 0; i<map->list_object_length; i++)
|
||
{
|
||
Object* current_object = map->object[i];
|
||
int nb_point = 0;
|
||
int center_x = 0;
|
||
int center_y = 0;
|
||
int center_z = 0;
|
||
|
||
// pour chaque poly
|
||
for (int j = 0; j<current_object->modele_size; j++)
|
||
{
|
||
const Modele* current_poly = ¤t_object->modele[j];
|
||
|
||
// pour chaque point
|
||
for (int k = 0; k<current_poly->type; k++)
|
||
{
|
||
Point point = get_point(current_poly, k);
|
||
center_x += point.x;
|
||
center_y += point.y;
|
||
center_z += point.z;
|
||
|
||
nb_point++;
|
||
}
|
||
}
|
||
// barycentre
|
||
center_x /= nb_point;
|
||
center_y /= nb_point;
|
||
center_z /= nb_point;
|
||
|
||
// recherche du point le plus eloigne du centre
|
||
int radius_max = 0;
|
||
for (int j = 0; j<current_object->modele_size; j++)
|
||
{
|
||
const Modele* current_poly = ¤t_object->modele[j];
|
||
for (int k = 0; k<current_poly->type; k++)
|
||
{
|
||
Point point = get_point(current_poly, k);
|
||
int dx = point.x - center_x;
|
||
int dy = point.y - center_y;
|
||
int dz = point.z - center_z;
|
||
int radius = dx*dx + dy*dy + dz*dz;
|
||
//int rr = sqrtf(radius);
|
||
if (radius > radius_max)
|
||
{
|
||
radius_max = radius;
|
||
}
|
||
}
|
||
}
|
||
radius_max = sqrtf(radius_max) + 1;
|
||
|
||
current_object->sphere.x = center_x;
|
||
current_object->sphere.y = center_y;
|
||
current_object->sphere.z = center_z;
|
||
current_object->sphere.radius = radius_max;
|
||
}
|
||
}
|
||
|
||
loading = false;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
//----------------------------------------------------------------------------------------------------
|
||
// DESSIN
|
||
//----------------------------------------------------------------------------------------------------
|
||
void Windmill::draw()
|
||
{
|
||
// quitte si pas de camera, de map, d objet ou de z_buffer
|
||
if(camera2 == NULL or map == NULL or object == NULL or z_buffer == NULL) return;
|
||
|
||
// mets a jour les variables de la camera
|
||
camera2->update();
|
||
|
||
// cree une camera temporaire pour eviter les problemes de desynchronisation
|
||
copy_camera();
|
||
|
||
// fonction principale, l'ordre d'appel des fonctions suivantes est important
|
||
clear_z_buffer();
|
||
|
||
// trie les objets pour optimiser l affichage
|
||
sort_object();
|
||
|
||
// affiche le trait d'horizon
|
||
if (map->horizon) draw_horizon();
|
||
|
||
// affiche le sol
|
||
if (map->ground) draw_ground();
|
||
|
||
// affiche les objets de la scene
|
||
draw_objects();
|
||
|
||
// post traitement pour afficher les angles vifs
|
||
draw_post_treatment();
|
||
|
||
// affiche le corps du personnage
|
||
draw_body();
|
||
|
||
// affiche des informations
|
||
//show_fps();
|
||
//show_coordinates();
|
||
//show_repere();
|
||
}
|
||
|
||
|
||
void Windmill::draw_horizon()
|
||
{
|
||
Vertex horizon;
|
||
char* vram = get_vram_address();
|
||
int distance = 1000;
|
||
int hx = camera.x + distance * camera.cos_yaw;
|
||
int hy = camera.y + distance * camera.sin_yaw;
|
||
|
||
horizon.set_xyz(hx, hy, 0);
|
||
|
||
transform_world_to_camera(&horizon, 1);
|
||
transform_camera_to_screen(&horizon, 1);
|
||
if (inside_viewport(horizon.x, horizon.y))
|
||
{
|
||
dline(viewport.x1, horizon.y, viewport.x2, horizon.y, C_BLACK);
|
||
//ML_line(viewport.x1, horizon.y, viewport.x2, horizon.y, ML_BLACK);
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::draw_ground()
|
||
{
|
||
Vertex ground;
|
||
char* vram = get_vram_address();
|
||
unsigned char mask;
|
||
int distance = 50;
|
||
int esp = 20;
|
||
int nb = 6;
|
||
int nb2 = nb * nb;
|
||
float cx = camera.x + distance * camera.cos_yaw;
|
||
float cy = camera.y + distance * camera.sin_yaw;
|
||
int dx = int(cx) - int(cx)%esp;
|
||
int dy = int(cy) - int(cy)%esp;
|
||
|
||
for (int i=-nb; i<nb; i++)
|
||
{
|
||
for (int j=-nb; j<nb; j++)
|
||
{
|
||
if (i*i + j*j < nb2) // arrondi le carre en cercle
|
||
{
|
||
int x = dx + i*esp;
|
||
int y = dy + j*esp;
|
||
|
||
ground.set_xyz(x, y, 0);
|
||
transform_world_to_camera(&ground, 1);
|
||
if (ground.z > 0)
|
||
{
|
||
transform_camera_to_screen(&ground, 1);
|
||
if (inside_viewport(ground.x, ground.y) == true)
|
||
{
|
||
mask = 128 >> (ground.x & 7);
|
||
vram[(ground.y << 4) + (ground.x>>3)] |= mask;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::draw_objects()
|
||
{
|
||
nb_object_on_screen = 0;
|
||
temp_object_cursor = NULL;
|
||
temp_poly_cursor = -1;
|
||
|
||
Vertex vertex[10];
|
||
int vertex_length;
|
||
int width, height;
|
||
int cosinus, sinus;
|
||
|
||
for(i=0; i<map->list_object_length; i++)
|
||
{
|
||
//Object* current_object = map->object[i];
|
||
Object* current_object = object[i];
|
||
|
||
if (current_object->hidden == false)
|
||
{
|
||
// angle de l objet
|
||
compute_object_angle(current_object, &cosinus, &sinus);
|
||
|
||
// transforme la sphere dans le repere monde
|
||
Sphere current_sphere = transform_sphere_to_world(¤t_object->sphere, current_object, cosinus, sinus);
|
||
|
||
// verifie si la sphere englobante est dans le champs de vision de la camera
|
||
if (sphere_in_cone(¤t_sphere))
|
||
{
|
||
temp_nb_object_on_screen ++;
|
||
current_object->on_screen = true;
|
||
current_object->distance_to_camera = current_sphere.z;
|
||
|
||
for(j=0; j<current_object->modele_size; j++)
|
||
{
|
||
const Modele* current_poly = ¤t_object->modele[j];
|
||
|
||
// creation des vertex a partir du poly
|
||
extract_vertex_from_poly(current_poly, vertex, &vertex_length, &width, &height);
|
||
|
||
// calcul des coordonnees dans le repère monde apres rotation et translation de l objet
|
||
transform_model_to_world(vertex, vertex_length, current_object, cosinus, sinus);
|
||
|
||
// calcul des coordonnees dans le repère camera apres rotation et translation de la camera
|
||
transform_world_to_camera(vertex, vertex_length);
|
||
|
||
// verifie si au moins 1 point peut etre visible
|
||
if (fast_check(vertex, vertex_length))
|
||
{
|
||
// calcul de l'aire du rectangle pour connaitre sa face visible
|
||
int visible = visible_face(&vertex[0], &vertex[1], &vertex[2]);
|
||
|
||
// choisi la texture visible
|
||
const Texture* texture;
|
||
texture = (visible == FRONT) ? current_poly->texture_front : current_poly->texture_back;
|
||
|
||
// si le rectangle est visible
|
||
if (texture != NULL)
|
||
{
|
||
// si le rectangle a une texture
|
||
if (texture != &tex_black && texture != &tex_white)
|
||
{
|
||
texture_coordinates(current_poly, vertex, texture, visible, width, height);
|
||
}
|
||
|
||
// tronque le polygon devant le plan avant de la camera
|
||
clip_depth(vertex, &vertex_length);
|
||
|
||
// calcul des coordonnes apres perspective et decalage au centre de l ecran
|
||
transform_camera_to_screen(vertex, vertex_length);
|
||
|
||
// tronque le polygon sur les bords de l ecran
|
||
clip_viewport(vertex, &vertex_length);
|
||
|
||
// calcul des coordonnees de profondeur
|
||
transform_camera_to_screen2(vertex, vertex_length);
|
||
|
||
// affiche les triangles
|
||
if (visible == FRONT)
|
||
{
|
||
for (int k = 1; k<vertex_length-1; k++)
|
||
{
|
||
render_triangle(&vertex[0], &vertex[k], &vertex[k+1], texture);
|
||
}
|
||
} else {
|
||
for (int k = vertex_length-1; k>1; k--)
|
||
{
|
||
render_triangle(&vertex[0], &vertex[k], &vertex[k-1], texture);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
current_object->on_screen = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
nb_object_on_screen = temp_nb_object_on_screen;
|
||
object_cursor = temp_object_cursor;
|
||
poly_cursor = temp_poly_cursor;
|
||
}
|
||
|
||
|
||
void Windmill::draw_post_treatment()
|
||
{
|
||
char* vram = get_vram_address();
|
||
unsigned char mask;
|
||
int current, right, bottom, left;
|
||
|
||
for (int y = viewport.y1; y<viewport.y2-1; y++)
|
||
{
|
||
for (int x = viewport.x1; x<viewport.x2-1; x++)
|
||
{
|
||
int address = x + y * z_buffer_width + z_buffer_offset;
|
||
current = z_buffer[address];
|
||
right = z_buffer[address + 1];
|
||
bottom = z_buffer[address + z_buffer_width];
|
||
if (current == MAX_DEPTH_Z_BUFFER)
|
||
{
|
||
if (right < MAX_DEPTH_Z_BUFFER)
|
||
{
|
||
mask = 128 >> ((x+1) & 7);
|
||
vram[address<<3] |= mask;
|
||
|
||
//ML_pixel(x+1, y, ML_BLACK);
|
||
}
|
||
if (bottom < MAX_DEPTH_Z_BUFFER)
|
||
{
|
||
dpixel(x, y+1, C_BLACK);
|
||
//ML_pixel(x, y+1, ML_BLACK);
|
||
}
|
||
} else {
|
||
if (right == MAX_DEPTH_Z_BUFFER or bottom == MAX_DEPTH_Z_BUFFER)
|
||
{
|
||
dpixel(x, y+1, C_BLACK);
|
||
//ML_pixel(x, y, ML_BLACK);
|
||
}
|
||
}
|
||
}
|
||
|
||
} // 21 fps 21,5 fps*/
|
||
|
||
/*left = z_buffer[0];
|
||
for (int i = 1; i<z_buffer_size; i++)
|
||
{
|
||
left = current;
|
||
current = z_buffer[i];
|
||
//bottom = z_buffer[i+128];
|
||
if (current < MAX_DEPTH_Z_BUFFER)
|
||
{
|
||
//left = z_buffer[i-1];
|
||
if (left == MAX_DEPTH_Z_BUFFER)
|
||
{
|
||
//ML_pixel((i+1)%128, (i+1)/128, ML_BLACK);
|
||
mask = 128 >> (i & 7);
|
||
vram[(i - z_buffer_offset)>>3] |= mask;
|
||
}
|
||
} else {
|
||
if (left < MAX_DEPTH_Z_BUFFER)
|
||
{
|
||
mask = 128 >> ((i-1) & 7);
|
||
vram[(i - 1 - z_buffer_offset)>>3] |= mask;
|
||
|
||
}
|
||
}
|
||
}
|
||
// sans rien 28 fps
|
||
// avec le i+1 : 24 fps
|
||
// avec le i : 25 fps
|
||
// calculer left = Z_buffer[i-1] dans if : 24 fps
|
||
// avec les deux cote : 24 fps ! */
|
||
|
||
bool flag = false;
|
||
for (int i = 0; i<z_buffer_size; i+=2)
|
||
{
|
||
current = z_buffer[i];
|
||
if (current == MAX_DEPTH_Z_BUFFER)
|
||
{
|
||
if (flag == true)
|
||
{
|
||
if (z_buffer[i-1] == MAX_DEPTH_Z_BUFFER)
|
||
{
|
||
// il y avait rien juste a gauche
|
||
mask = 128 >> ((i-2) & 7);
|
||
vram[(i - 2 - z_buffer_offset)>>3] |= mask;
|
||
flag = false;
|
||
} else {
|
||
// l objet commencait en fait 1 pixel a gauche
|
||
mask = 128 >> ((i-1) & 7);
|
||
vram[(i - 1 - z_buffer_offset)>>3] |= mask;
|
||
flag = false;
|
||
}
|
||
}
|
||
} else {
|
||
if (flag == false)
|
||
{
|
||
if (z_buffer[i-1] == MAX_DEPTH_Z_BUFFER)
|
||
{
|
||
// il y avait rien juste a gauche
|
||
mask = 128 >> (i & 7);
|
||
vram[(i - z_buffer_offset)>>3] |= mask;
|
||
flag = true;
|
||
} else {
|
||
// l objet commencait en fait 1 pixel a gauche
|
||
mask = 128 >> ((i-1) & 7);
|
||
vram[(i - 1 - z_buffer_offset)>>3] |= mask;
|
||
flag = true;
|
||
}
|
||
}
|
||
}
|
||
} // 24 fps
|
||
// avec astuce +=2 : 25 fps
|
||
|
||
/*bool flag = false;
|
||
char i_mod_8;
|
||
for (int i = 0; i<z_buffer_size; i++)
|
||
{
|
||
i_mod_8 = i & 7;
|
||
current = z_buffer[i];
|
||
if (current == MAX_DEPTH_Z_BUFFER)
|
||
{
|
||
if (flag == true)
|
||
{
|
||
mask |= 128 >> i_mod_8;//((i-1) & 7);
|
||
flag = false;
|
||
}
|
||
} else {
|
||
if (flag == false)
|
||
{
|
||
mask |= 128 >> i_mod_8;
|
||
flag = true;
|
||
}
|
||
}
|
||
if (i_mod_8 == 7)
|
||
{
|
||
//if (mask > 0)
|
||
vram[i>>3] |= mask;
|
||
mask = 0;
|
||
}
|
||
}*/
|
||
}
|
||
|
||
|
||
void Windmill::draw_body()
|
||
{
|
||
/*int x = camera.x;
|
||
int y = camera.y;
|
||
int z = camera.z;
|
||
|
||
Vertex v0, v1, v2, v3;
|
||
set_vertex_xyz()
|
||
METTRE DIRECT LES VERTEX DANS LE REPERE SCREEN PUIS RENDER...
|
||
*/
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
//----------------------------------------------------------------------------------------------------
|
||
// TRANSFORMATION 3D
|
||
//----------------------------------------------------------------------------------------------------
|
||
void Windmill::transform_model_to_world(Vertex vertex[], int vertex_length, Object* object, int cosinus, int sinus)
|
||
{
|
||
for (int k = 0; k<vertex_length; k++)
|
||
{
|
||
int vertex_x = vertex[k].x;
|
||
int vertex_y = vertex[k].y;
|
||
int vertex_z = vertex[k].z;
|
||
if (object->axe == N)
|
||
{
|
||
vertex[k].x = vertex_x + object->x;
|
||
vertex[k].y = vertex_y + object->y;
|
||
vertex[k].z = vertex_z + object->z;
|
||
}
|
||
if (object->axe == X)
|
||
{
|
||
vertex[k].x = vertex_x + object->x;
|
||
vertex[k].y = ((vertex_y * cosinus - vertex_z * sinus) >> 10) + object->y;
|
||
vertex[k].z = ((vertex_y * sinus + vertex_z * cosinus) >> 10) + object->z;
|
||
}
|
||
if (object->axe == Y)
|
||
{
|
||
vertex[k].x = ((vertex_x * cosinus - vertex_z * sinus) >> 10) + object->x;
|
||
vertex[k].y = vertex_y + object->y;
|
||
vertex[k].z = ((vertex_x * sinus + vertex_z * cosinus) >> 10) + object->z;
|
||
}
|
||
if (object->axe == Z or object->axe == Z_BILLBOARD)
|
||
{
|
||
vertex[k].x = ((vertex_x * cosinus - vertex_y * sinus) >> 10) + object->x;
|
||
vertex[k].y = ((vertex_x * sinus + vertex_y * cosinus) >> 10) + object->y;
|
||
vertex[k].z = vertex_z + object->z;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::transform_world_to_camera(Vertex vertex[], int vertex_length)
|
||
{
|
||
for (int k = 0; k<vertex_length; k++)
|
||
{
|
||
// translation
|
||
int vertex_x = int(camera.x) - vertex[k].x;
|
||
int vertex_y = int(camera.y) - vertex[k].y;
|
||
int vertex_z = int(camera.z) - vertex[k].z;
|
||
// rotation
|
||
vertex[k].z = -(camera.a1 * vertex_x + camera.a2 * vertex_y + camera.a3 * vertex_z);
|
||
vertex[k].x = camera.a4 * vertex_x + camera.a5 * vertex_y + camera.a6 * vertex_z;
|
||
vertex[k].y = camera.a7 * vertex_x + camera.a8 * vertex_y + camera.a9 * vertex_z;
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::transform_camera_to_screen(Vertex vertex[], int vertex_length)
|
||
{
|
||
for (int k = 0; k<vertex_length; k++)
|
||
{
|
||
// perspective
|
||
vertex[k].x = (vertex[k].x * camera.scale_coef) / vertex[k].z + shift_x;
|
||
vertex[k].y = (vertex[k].y * camera.scale_coef) / vertex[k].z + shift_y;
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::transform_camera_to_screen2(Vertex vertex[], int vertex_length)
|
||
{
|
||
for (int k = 0; k<vertex_length; k++)
|
||
{
|
||
// calcul du z normalise entre les deux plans de clipping
|
||
//vertex[k].z_normalized = (1<<15) * ( float(vertex[k].z * camera.far - SCALE_AI * camera.far * camera.near) / float(vertex[k].z * (camera.far - camera.near)) );
|
||
vertex[k].z_normalized = (1<<15) * ( float(vertex[k].z - SCALE_AI * camera.near) / float(SCALE_AI * camera.far) );
|
||
//vertex[k].z_normalized = vertex[k].z;
|
||
//vertex->z_normalized = (1<<15) * (vertex->z * camera.far - SCALE_AI * camera.far * camera.near) / (vertex->z * (camera.far - camera.near));
|
||
// precalcul de 1/z
|
||
vertex[k].z = (1<<20) / vertex[k].z;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
//----------------------------------------------------------------------------------------------------
|
||
// TEST VISIBILITE
|
||
//----------------------------------------------------------------------------------------------------
|
||
bool Windmill::fast_check(Vertex vertex[], int vertex_length)
|
||
{
|
||
int near = camera.near * SCALE_AI;
|
||
int far = camera.far * SCALE_AI;
|
||
|
||
for (int i = 0; i<vertex_length; i++)
|
||
{
|
||
if (vertex[i].z >= near and vertex[i].z < far) return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
|
||
bool Windmill::inside_viewport(int x, int y)
|
||
{
|
||
return (x < viewport.x2 and y >= viewport.y1 and x >= viewport.x1 and y < viewport.y2);
|
||
}
|
||
|
||
|
||
int Windmill::visible_face(Vertex* a, Vertex* b, Vertex* c)
|
||
{
|
||
int nx = ((b->y - a->y) * (c->z - a->z) - (b->z - a->z) * (c->y - a->y)) >> 15;
|
||
int ny = ((b->z - a->z) * (c->x - a->x) - (b->x - a->x) * (c->z - a->z)) >> 15;
|
||
int nz = ((b->x - a->x) * (c->y - a->y) - (b->y - a->y) * (c->x - a->x)) >> 15;
|
||
return (nx*a->x + ny*a->y + nz*a->z > 0) ? BACK : FRONT;
|
||
}
|
||
|
||
|
||
|
||
// Sutherland–Hodgman algorithm
|
||
void Windmill::clip_depth(Vertex vertex_input[], int* vertex_input_length)
|
||
{
|
||
Vertex vertex_temp;
|
||
Vertex vertex_output[10];
|
||
int vertex_output_length = 0;
|
||
|
||
int S = *vertex_input_length-1;
|
||
|
||
for (int E = 0; E<*vertex_input_length; E++)
|
||
{
|
||
if (clip_depth_inside_edge(&vertex_input[E]) == true)
|
||
{
|
||
if (clip_depth_inside_edge(&vertex_input[S]) == false)
|
||
{
|
||
clip_depth_edge(&vertex_input[E], &vertex_input[S], &vertex_temp);
|
||
copy_vertex(&vertex_temp, &vertex_output[vertex_output_length]);
|
||
vertex_output_length += 1;
|
||
}
|
||
copy_vertex(&vertex_input[E], &vertex_output[vertex_output_length]);
|
||
vertex_output_length += 1;
|
||
|
||
} else if (clip_depth_inside_edge(&vertex_input[S]) == true)
|
||
{
|
||
clip_depth_edge(&vertex_input[S], &vertex_input[E], &vertex_temp);
|
||
copy_vertex(&vertex_temp, &vertex_output[vertex_output_length]);
|
||
vertex_output_length += 1;
|
||
}
|
||
S = E;
|
||
|
||
}
|
||
|
||
*vertex_input_length = vertex_output_length;
|
||
for (int i = 0; i<*vertex_input_length; i++)
|
||
{
|
||
copy_vertex(&vertex_output[i], &vertex_input[i]);
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::clip_depth_edge(Vertex* vertex_in, Vertex* vertex_out, Vertex* vertex_set)
|
||
{
|
||
int near, x_near, y_near, z_near, w_near, h_near;
|
||
float t;
|
||
|
||
near = camera.near * SCALE_AI;
|
||
t = float(near - vertex_in->z) / float(vertex_out->z - vertex_in->z);
|
||
|
||
x_near = (vertex_out->x - vertex_in->x) * t + vertex_in->x;
|
||
y_near = (vertex_out->y - vertex_in->y) * t + vertex_in->y;
|
||
z_near = near;
|
||
|
||
w_near = (vertex_out->w - vertex_in->w) * t + vertex_in->w;
|
||
h_near = (vertex_out->h - vertex_in->h) * t + vertex_in->h;
|
||
|
||
vertex_set->set_xyz(x_near, y_near, z_near);
|
||
vertex_set->set_wh(w_near, h_near);
|
||
}
|
||
|
||
|
||
bool Windmill::clip_depth_inside_edge(Vertex* vertex)
|
||
{
|
||
return (vertex->z >= camera.near * SCALE_AI) ? true : false;
|
||
}
|
||
|
||
|
||
// Sutherland–Hodgman algorithm
|
||
void Windmill::clip_viewport(Vertex vertex_input[], int* vertex_input_length)
|
||
{
|
||
Vertex vertex_temp;
|
||
|
||
Vertex vertex_output[10];
|
||
int vertex_output_length = *vertex_input_length;
|
||
|
||
for (int i = 0; i<*vertex_input_length; i++)
|
||
{
|
||
copy_vertex(&vertex_input[i], &vertex_output[i]);
|
||
}
|
||
|
||
for (int edge = 0; edge < 4; edge++)
|
||
{
|
||
for (int i = 0; i<vertex_output_length; i++)
|
||
{
|
||
copy_vertex(&vertex_output[i], &vertex_input[i]);
|
||
}
|
||
*vertex_input_length = vertex_output_length;
|
||
vertex_output_length = 0;
|
||
|
||
int S = *vertex_input_length-1;
|
||
|
||
for (int E = 0; E<*vertex_input_length; E++)
|
||
{
|
||
if (clip_viewport_inside_edge(&vertex_input[E], edge) == true)
|
||
{
|
||
if (clip_viewport_inside_edge(&vertex_input[S], edge) == false)
|
||
{
|
||
clip_viewport_edge(&vertex_input[E], &vertex_input[S], &vertex_temp, edge);
|
||
copy_vertex(&vertex_temp, &vertex_output[vertex_output_length]);
|
||
vertex_output_length += 1;
|
||
}
|
||
copy_vertex(&vertex_input[E], &vertex_output[vertex_output_length]);
|
||
vertex_output_length += 1;
|
||
|
||
} else if (clip_viewport_inside_edge(&vertex_input[S], edge) == true)
|
||
{
|
||
clip_viewport_edge(&vertex_input[S], &vertex_input[E], &vertex_temp, edge);
|
||
copy_vertex(&vertex_temp, &vertex_output[vertex_output_length]);
|
||
vertex_output_length += 1;
|
||
}
|
||
S = E;
|
||
|
||
}
|
||
}
|
||
|
||
*vertex_input_length = vertex_output_length;
|
||
for (int i = 0; i<*vertex_input_length; i++)
|
||
{
|
||
copy_vertex(&vertex_output[i], &vertex_input[i]);
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::clip_viewport_edge(Vertex* vertex_in, Vertex* vertex_out, Vertex* vertex_set, int edge)
|
||
{
|
||
float x_set, y_set, z_set, w_set, h_set;
|
||
float t; // t = 0 si edge proche de in et = 1 si proche de out
|
||
|
||
if (edge == 0)
|
||
{
|
||
t = float(viewport.x2 - 1 - vertex_in->x) / float(vertex_out->x - vertex_in->x);
|
||
x_set = viewport.x2-1;
|
||
y_set = (vertex_out->y - vertex_in->y) * t + vertex_in->y;
|
||
}
|
||
if (edge == 1)
|
||
{
|
||
t = float(viewport.y1 - vertex_in->y) / float(vertex_out->y - vertex_in->y);
|
||
x_set = (vertex_out->x - vertex_in->x) * t + vertex_in->x;
|
||
y_set = viewport.y1;
|
||
}
|
||
if (edge == 2)
|
||
{
|
||
t = float(viewport.x1 - vertex_in->x) / float(vertex_out->x - vertex_in->x);
|
||
x_set = viewport.x1;
|
||
y_set = (vertex_out->y - vertex_in->y) * t + vertex_in->y;
|
||
}
|
||
if (edge == 3)
|
||
{
|
||
t = float(viewport.y2 - 1 - vertex_in->y) / float(vertex_out->y - vertex_in->y);
|
||
x_set = (vertex_out->x - vertex_in->x) * t + vertex_in->x;
|
||
y_set = viewport.y2-1;
|
||
}
|
||
|
||
z_set = 0.5 + float(1) / (float(1-t)/float(vertex_in->z) + float(t)/float(vertex_out->z));
|
||
w_set = z_set * ( (1.0-t) * vertex_in->w / float(vertex_in->z) + t * vertex_out->w / float(vertex_out->z) );
|
||
h_set = z_set * ( (1.0-t) * vertex_in->h / float(vertex_in->z) + t * vertex_out->h / float(vertex_out->z) );
|
||
|
||
|
||
vertex_set->set_xyz(x_set, y_set, z_set);
|
||
vertex_set->set_wh(w_set, h_set);
|
||
}
|
||
|
||
|
||
bool Windmill::clip_viewport_inside_edge(Vertex* vertex, int edge)
|
||
{
|
||
// 0 : RIGHT 1 : UP 2: LEFT 3 : DOWN
|
||
if (edge == 0 and vertex->x < viewport.x2-1) return true;
|
||
if (edge == 1 and vertex->y > viewport.y1) return true;
|
||
if (edge == 2 and vertex->x > viewport.x1) return true;
|
||
if (edge == 3 and vertex->y < viewport.y2-1) return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
//----------------------------------------------------------------------------------------------------
|
||
// DESSIN DES TRIANGLES
|
||
//----------------------------------------------------------------------------------------------------
|
||
void Windmill::render_triangle(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC, const Texture *texture)//, bool billboard)
|
||
{
|
||
//render_triangle_black(vertexA, vertexB, vertexC);
|
||
if (texture == NULL) return;
|
||
if (texture == &tex_black)
|
||
{
|
||
render_triangle_black(vertexA, vertexB, vertexC);
|
||
}
|
||
else if (texture == &tex_white)
|
||
{
|
||
render_triangle_white(vertexA, vertexB, vertexC);
|
||
}
|
||
else if (texture->transparent == true)
|
||
{
|
||
render_triangle_transparent(vertexA, vertexB, vertexC, texture);
|
||
}
|
||
else
|
||
{
|
||
render_triangle_texture(vertexA, vertexB, vertexC, texture);
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::render_triangle_texture(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC, const Texture* texture)
|
||
{
|
||
// calcul du rectangle circonscrit au triangle
|
||
int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x)));
|
||
int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x)));
|
||
int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y)));
|
||
int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y)));
|
||
|
||
// calcul de l'aire du triangle
|
||
int area = edge(vertexA, vertexB, vertexC);
|
||
// determine si la taille du triangle est trop petite
|
||
if (area <= MIN_AREA_CLIP) return;
|
||
|
||
// pre-calcul des coordonnees de la texture
|
||
int w0 = vertexA->w * vertexA->z; int h0 = vertexA->h * vertexA->z;
|
||
int w1 = vertexB->w * vertexB->z; int h1 = vertexB->h * vertexB->z;
|
||
int w2 = vertexC->w * vertexC->z; int h2 = vertexC->h * vertexC->z;
|
||
|
||
// calcul des produits vectoriels
|
||
int u0_start = edge_start(vertexB, vertexC, min_x, min_y);
|
||
int u0_step_x = edge_step_x(vertexB, vertexC);
|
||
int u0_step_y = edge_step_y(vertexB, vertexC);
|
||
int u1_start = edge_start(vertexC, vertexA, min_x, min_y);
|
||
int u1_step_x = edge_step_x(vertexC, vertexA);
|
||
int u1_step_y = edge_step_y(vertexC, vertexA);
|
||
int u2_start = edge_start(vertexA, vertexB, min_x, min_y);
|
||
int u2_step_x = edge_step_x(vertexA, vertexB);
|
||
int u2_step_y = edge_step_y(vertexA, vertexB);
|
||
|
||
int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area;
|
||
int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area;
|
||
int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area;
|
||
|
||
int z_div_start = u0_start * vertexA->z + u1_start * vertexB->z + u2_start * vertexC->z;
|
||
int z_div_step_x = u0_step_x * vertexA->z + u1_step_x * vertexB->z + u2_step_x * vertexC->z;
|
||
int z_div_step_y = u0_step_y * vertexA->z + u1_step_y * vertexB->z + u2_step_y * vertexC->z;
|
||
|
||
// rapprochement artificiel si texture de type decoration
|
||
int decoration = (texture->decoration ? DECORATION_OFFSET : 0);
|
||
|
||
// acces a la vram
|
||
char* vram = get_vram_address();
|
||
unsigned char mask_vram, mask_w;
|
||
int offset_vram;
|
||
int address;
|
||
|
||
int u0, u1, u2;
|
||
int z_num, z_div;
|
||
int w, h;
|
||
|
||
// pre-calcul largeur en octet des tableaux
|
||
int nbw_tex = ((texture->pixel_width - 1) >> 3) + 1;
|
||
char loop_w_tex = texture->pixel_width-1;
|
||
char loop_h_tex = texture->pixel_height-1;
|
||
|
||
// parcours en ligne
|
||
for(int x=min_x; x<=max_x; x++)
|
||
{
|
||
u0 = u0_start; u1 = u1_start; u2 = u2_start;
|
||
z_num = z_num_start;
|
||
z_div = z_div_start;
|
||
offset_vram = x >> 3;
|
||
mask_vram = 128 >> (x & 7);
|
||
// parcours en colonne
|
||
for(int y=min_y; y<=max_y; y++)
|
||
{
|
||
// si le pixel (x;y) est dans le triangle
|
||
if ((u0 | u1 | u2) > 0)
|
||
{
|
||
// addresse du z-buffer
|
||
address = x + y * z_buffer_width + z_buffer_offset;
|
||
// si le pixel (x;y) est plus proche qu'avant
|
||
if (z_num <= z_buffer[address] + decoration)
|
||
{
|
||
// calcul des coordonnees pour la texture
|
||
w = ((u0 * w0 + u1 * w1 + u2 * w2) / z_div) & loop_w_tex;
|
||
h = ((u0 * h0 + u1 * h1 + u2 * h2) / z_div) & loop_h_tex;
|
||
// calcul du masque pour l'octet
|
||
mask_w = 128 >> (w & 7);
|
||
if (texture->mask == NULL)
|
||
{
|
||
// enregistre la profondeur du pixel dans le z buffer
|
||
z_buffer[address] = z_num;
|
||
if ((texture->sprite[(w >> 3) + (h * nbw_tex)] & mask_w))
|
||
{
|
||
// afficher pixel noir
|
||
vram[(y << 4) + offset_vram] |= mask_vram;
|
||
}else{
|
||
// afficher pixel blanc
|
||
vram[(y << 4) + offset_vram] &= ~mask_vram;
|
||
}
|
||
// curseur
|
||
pixel_on_cursor(x, y);
|
||
} else {
|
||
int alpha = (w >> 3) + (h * nbw_tex);
|
||
if ((texture->mask[alpha] & mask_w))
|
||
{
|
||
// enregistre la profondeur du pixel dans le z buffer
|
||
z_buffer[address] = z_num;
|
||
if ((texture->sprite[alpha] & mask_w))
|
||
{
|
||
// afficher pixel noir
|
||
vram[(y << 4) + offset_vram] |= mask_vram;
|
||
}else{
|
||
// afficher pixel blanc
|
||
vram[(y << 4) + offset_vram] &= ~mask_vram;
|
||
}
|
||
// curseur
|
||
pixel_on_cursor(x, y);
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
|
||
z_num += z_num_step_y;
|
||
z_div += z_div_step_y;
|
||
}
|
||
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
|
||
z_num_start += z_num_step_x;
|
||
z_div_start += z_div_step_x;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
void Windmill::render_triangle_black(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC)
|
||
{
|
||
// calcul du rectangle circonscrit au triangle
|
||
int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x)));
|
||
int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x)));
|
||
int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y)));
|
||
int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y)));
|
||
|
||
// calcul de l'aire du triangle
|
||
int area = edge(vertexA, vertexB, vertexC);
|
||
// termine si la taille du triangle est trop petite
|
||
if (area <= MIN_AREA_CLIP) return;
|
||
|
||
// calcul des produits vectoriels
|
||
int u0_start = edge_start(vertexB, vertexC, min_x, min_y);
|
||
int u0_step_x = edge_step_x(vertexB, vertexC);
|
||
int u0_step_y = edge_step_y(vertexB, vertexC);
|
||
int u1_start = edge_start(vertexC, vertexA, min_x, min_y);
|
||
int u1_step_x = edge_step_x(vertexC, vertexA);
|
||
int u1_step_y = edge_step_y(vertexC, vertexA);
|
||
int u2_start = edge_start(vertexA, vertexB, min_x, min_y);
|
||
int u2_step_x = edge_step_x(vertexA, vertexB);
|
||
int u2_step_y = edge_step_y(vertexA, vertexB);
|
||
|
||
int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area;
|
||
int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area;
|
||
int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area;
|
||
|
||
// acces a la vram
|
||
char* vram = get_vram_address();
|
||
unsigned char mask_vram;
|
||
int offset_vram;
|
||
int address;
|
||
|
||
int u0, u1, u2;
|
||
int z_num;
|
||
|
||
// parcours en ligne
|
||
for(int x=min_x; x<=max_x; x++)
|
||
{
|
||
u0 = u0_start; u1 = u1_start; u2 = u2_start;
|
||
z_num = z_num_start;
|
||
offset_vram = x >> 3;
|
||
mask_vram = 128 >> (x & 7);
|
||
// parcours en colonne
|
||
for(int y=min_y; y<=max_y; y++)
|
||
{
|
||
// si le pixel (x;y) est dans le triangle
|
||
if ((u0 | u1 | u2) > 0)
|
||
{
|
||
// addresse du z-buffer
|
||
address = x + y * z_buffer_width + z_buffer_offset;
|
||
// si le pixel (x;y) est plus proche qu'avant
|
||
if (z_num <= z_buffer[address])
|
||
{
|
||
// enregistre la profondeur du pixel dans le z buffer
|
||
z_buffer[address] = z_num;
|
||
// afficher pixel noir
|
||
vram[(y << 4) + offset_vram] |= mask_vram;
|
||
// curseur
|
||
pixel_on_cursor(x, y);
|
||
}
|
||
}
|
||
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
|
||
z_num += z_num_step_y;
|
||
}
|
||
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
|
||
z_num_start += z_num_step_x;
|
||
}
|
||
}
|
||
|
||
/*
|
||
void Windmill::render_triangle_black(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC)
|
||
{
|
||
// calcul du rectangle circonscrit au triangle
|
||
int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x)));
|
||
int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x)));
|
||
int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y)));
|
||
int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y)));
|
||
|
||
// calcul de l'aire du triangle
|
||
int area = edge(vertexA, vertexB, vertexC);
|
||
// termine si la taille du triangle est trop petite
|
||
if (area <= MIN_AREA_CLIP) return;
|
||
|
||
// calcul des produits vectoriels
|
||
int u0_start = edge_start(vertexB, vertexC, min_x, min_y);
|
||
int u0_step_x = edge_step_x(vertexB, vertexC);
|
||
int u0_step_y = edge_step_y(vertexB, vertexC);
|
||
int u1_start = edge_start(vertexC, vertexA, min_x, min_y);
|
||
int u1_step_x = edge_step_x(vertexC, vertexA);
|
||
int u1_step_y = edge_step_y(vertexC, vertexA);
|
||
int u2_start = edge_start(vertexA, vertexB, min_x, min_y);
|
||
int u2_step_x = edge_step_x(vertexA, vertexB);
|
||
int u2_step_y = edge_step_y(vertexA, vertexB);
|
||
|
||
int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area;
|
||
int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area;
|
||
int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area;
|
||
|
||
// acces a la vram
|
||
// char* vram = get_vram_address();
|
||
unsigned char mask_vram;
|
||
int offset_vram;
|
||
int address;
|
||
|
||
int u0, u1, u2;
|
||
int z_num;
|
||
|
||
// parcours en ligne
|
||
for(int x=min_x; x<=max_x; x++)
|
||
{
|
||
u0 = u0_start; u1 = u1_start; u2 = u2_start;
|
||
z_num = z_num_start;
|
||
offset_vram = x >> 3;
|
||
mask_vram = 128 >> (x & 7);
|
||
// parcours en colonne
|
||
for(int y=min_y; y<=max_y; y++)
|
||
{
|
||
// si le pixel (x;y) est dans le triangle
|
||
if ((u0 | u1 | u2) > 0)
|
||
{
|
||
// addresse du z-buffer
|
||
address = x + y * z_buffer_width + z_buffer_offset;
|
||
// si le pixel (x;y) est plus proche qu'avant
|
||
if (z_num <= z_buffer[address])
|
||
{
|
||
// enregistre la profondeur du pixel dans le z buffer
|
||
z_buffer[address] = z_num;
|
||
// afficher pixel noir
|
||
// vram[(y << 4) + offset_vram] |= mask_vram;
|
||
// curseur
|
||
pixel_on_cursor(x, y);
|
||
}
|
||
}
|
||
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
|
||
z_num += z_num_step_y;
|
||
}
|
||
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
|
||
z_num_start += z_num_step_x;
|
||
}
|
||
}
|
||
*/
|
||
|
||
void Windmill::render_triangle_white(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC)
|
||
{
|
||
// calcul du rectangle circonscrit au triangle
|
||
int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x)));
|
||
int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x)));
|
||
int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y)));
|
||
int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y)));
|
||
|
||
// calcul de l'aire du triangle
|
||
int area = edge(vertexA, vertexB, vertexC);
|
||
// termine si la taille du triangle est trop petite
|
||
if (area <= MIN_AREA_CLIP) return;
|
||
|
||
// calcul des produits vectoriels
|
||
int u0_start = edge_start(vertexB, vertexC, min_x, min_y);
|
||
int u0_step_x = edge_step_x(vertexB, vertexC);
|
||
int u0_step_y = edge_step_y(vertexB, vertexC);
|
||
int u1_start = edge_start(vertexC, vertexA, min_x, min_y);
|
||
int u1_step_x = edge_step_x(vertexC, vertexA);
|
||
int u1_step_y = edge_step_y(vertexC, vertexA);
|
||
int u2_start = edge_start(vertexA, vertexB, min_x, min_y);
|
||
int u2_step_x = edge_step_x(vertexA, vertexB);
|
||
int u2_step_y = edge_step_y(vertexA, vertexB);
|
||
|
||
int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area;
|
||
int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area;
|
||
int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area;
|
||
|
||
// acces a la vram
|
||
char* vram = get_vram_address();
|
||
unsigned char mask_vram;
|
||
int offset_vram;
|
||
int address;
|
||
|
||
int u0, u1, u2;
|
||
int z_num;
|
||
|
||
// parcours en ligne
|
||
for(int x=min_x; x<=max_x; x++)
|
||
{
|
||
u0 = u0_start; u1 = u1_start; u2 = u2_start;
|
||
z_num = z_num_start;
|
||
offset_vram = x >> 3;
|
||
mask_vram = 128 >> (x & 7);
|
||
// parcours en colonne
|
||
for(int y=min_y; y<=max_y; y++)
|
||
{
|
||
// si le pixel (x;y) est dans le triangle
|
||
if ((u0 | u1 | u2) > 0)
|
||
{
|
||
// addresse du z-buffer
|
||
address = x + y * z_buffer_width + z_buffer_offset;
|
||
// si le pixel (x;y) est plus proche qu'avant
|
||
if (z_num <= z_buffer[address])
|
||
{
|
||
// enregistre la profondeur du pixel dans le z buffer
|
||
z_buffer[address] = z_num;
|
||
// afficher pixel blanc
|
||
vram[(y << 4) + offset_vram] &= ~mask_vram;
|
||
// curseur
|
||
pixel_on_cursor(x, y);
|
||
}
|
||
}
|
||
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
|
||
z_num += z_num_step_y;
|
||
}
|
||
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
|
||
z_num_start += z_num_step_x;
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::render_triangle_transparent(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC, const Texture* texture)
|
||
{
|
||
// calcul du rectangle circonscrit au triangle
|
||
int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x)));
|
||
int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x)));
|
||
int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y)));
|
||
int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y)));
|
||
|
||
// calcul de l'aire du triangle
|
||
int area = edge(vertexA, vertexB, vertexC);
|
||
// termine si la taille du triangle est trop petite
|
||
if (area <= MIN_AREA_CLIP) return;
|
||
|
||
// pre-calcul des coordonnees de la texture
|
||
int w0 = vertexA->w * vertexA->z; int h0 = vertexA->h * vertexA->z;
|
||
int w1 = vertexB->w * vertexB->z; int h1 = vertexB->h * vertexB->z;
|
||
int w2 = vertexC->w * vertexC->z; int h2 = vertexC->h * vertexC->z;
|
||
|
||
// calcul des produits vectoriels
|
||
int u0_start = edge_start(vertexB, vertexC, min_x, min_y);
|
||
int u0_step_x = edge_step_x(vertexB, vertexC);
|
||
int u0_step_y = edge_step_y(vertexB, vertexC);
|
||
int u1_start = edge_start(vertexC, vertexA, min_x, min_y);
|
||
int u1_step_x = edge_step_x(vertexC, vertexA);
|
||
int u1_step_y = edge_step_y(vertexC, vertexA);
|
||
int u2_start = edge_start(vertexA, vertexB, min_x, min_y);
|
||
int u2_step_x = edge_step_x(vertexA, vertexB);
|
||
int u2_step_y = edge_step_y(vertexA, vertexB);
|
||
|
||
int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area;
|
||
int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area;
|
||
int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area;
|
||
|
||
int z_div_start = u0_start * vertexA->z + u1_start * vertexB->z + u2_start * vertexC->z;
|
||
int z_div_step_x = u0_step_x * vertexA->z + u1_step_x * vertexB->z + u2_step_x * vertexC->z;
|
||
int z_div_step_y = u0_step_y * vertexA->z + u1_step_y * vertexB->z + u2_step_y * vertexC->z;
|
||
|
||
// acces a la vram
|
||
char* vram = get_vram_address();
|
||
|
||
// pre-calcul largeur en octet des tableaux
|
||
int nbw_tex = ((texture->pixel_width - 1) >> 3) + 1;
|
||
char loop_w_tex = texture->pixel_width-1;
|
||
char loop_h_tex = texture->pixel_height-1;
|
||
|
||
// parcours en ligne
|
||
for(int x=min_x; x<=max_x; x++)
|
||
{
|
||
int u0 = u0_start; int u1 = u1_start; int u2 = u2_start;
|
||
int z_num = z_num_start;
|
||
int z_div = z_div_start;
|
||
int offset_vram = x >> 3;
|
||
char mask_vram = 128 >> (x & 7);
|
||
// parcours en colonne
|
||
for(int y=min_y; y<=max_y; y++)
|
||
{
|
||
// si le pixel (x;y) est dans le triangle
|
||
if ((u0 | u1 | u2) > 0)
|
||
{
|
||
// addresse du z-buffer
|
||
int address = x + y * z_buffer_width + z_buffer_offset;
|
||
// si le pixel (x;y) est plus proche qu'avant
|
||
if (z_num <= z_buffer[address])
|
||
{
|
||
// calcul des coordonnees pour la texture
|
||
unsigned int w = ((u0 * w0 + u1 * w1 + u2 * w2) / z_div) & loop_w_tex;
|
||
unsigned int h = ((u0 * h0 + u1 * h1 + u2 * h2) / z_div) & loop_h_tex;
|
||
// calcul du masque pour l'octet
|
||
unsigned char mask_w = 128 >> (w & 7);
|
||
if ((texture->sprite[(w >> 3) + (h * nbw_tex)] & mask_w))
|
||
{
|
||
// afficher pixel noir
|
||
vram[(y << 4) + offset_vram] |= mask_vram;
|
||
// enregistre la profondeur du pixel dans le z buffer
|
||
z_buffer[address] = z_num;
|
||
}
|
||
}
|
||
}
|
||
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
|
||
z_num += z_num_step_y;
|
||
z_div += z_div_step_y;
|
||
}
|
||
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
|
||
z_num_start += z_num_step_x;
|
||
z_div_start += z_div_step_x;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/*
|
||
//-----------------------------------------------------------------------------
|
||
// load_map
|
||
// Ritter's bounding sphere
|
||
//-----------------------------------------------------------------------------
|
||
void Windmill::load_map(Map* _map)
|
||
{
|
||
if (map != _map)
|
||
{
|
||
map = _map;
|
||
delete[] sphere;
|
||
sphere = new Bounding_Sphere [map->list_object_length];
|
||
for (int i = 0; i<map->list_object_length; i++)
|
||
{
|
||
Object* current_object = map->object[i];
|
||
|
||
int nb_point;
|
||
for (int j = 0; j<current_object->modele_size; j++)
|
||
{
|
||
nb_point += current_object->modele[j].type;
|
||
}
|
||
|
||
Point* point = get_point(current_object, 0);
|
||
int min_x = point->x;
|
||
int min_y = point->y;
|
||
int min_z = point->z;
|
||
int max_x = min_x;
|
||
int max_y = min_y;
|
||
int max_z = min_z;
|
||
|
||
for (int j = 0; j<nb_point)
|
||
{
|
||
point = get_point(j);
|
||
if(point->x < min_x)
|
||
min_x = point->x;
|
||
if(point->y < min_y)
|
||
min_y = point->y;
|
||
if(point->z < min_z)
|
||
min_z = point->z;
|
||
|
||
if(point->x > max_x)
|
||
max_x = point->x;
|
||
if(point->y > max_y)
|
||
max_y = point->y;
|
||
if(point->z > max_z)
|
||
max_z = point->z;
|
||
}
|
||
int xdiff = max_x - min_x;
|
||
int ydiff = max_y - min_y;
|
||
int zdiff = max_z - min_y;
|
||
|
||
int diameter = max(xdiff, max(ydiff, zdiff)); //take max as diameter
|
||
glm::vec3 centre = (vmax+vmin)*(0.5f);
|
||
float radius = diameter/2;
|
||
float sq_radius = radius*radius;
|
||
|
||
for(int i=0; i<num_vertices; i++)
|
||
{
|
||
glm::vec3 point = vertices[i];
|
||
|
||
glm::vec3 direction = point - centre;
|
||
float sq_distance = glm::length2(direction);
|
||
|
||
if(sq_distance > sq_radius)
|
||
{
|
||
float distance = sqrt(sq_distance);
|
||
|
||
float difference = distance - radius;
|
||
|
||
float new_diameter = 2 * radius + difference;
|
||
sq_radius = radius * radius;
|
||
|
||
difference /= 2;
|
||
|
||
centre += difference * direction;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
}
|
||
}
|
||
}*/
|
||
|
||
|
||
|
||
|
||
|
||
//----------------------------------------------------------------------------------------------------
|
||
// MANIPULATION
|
||
//----------------------------------------------------------------------------------------------------
|
||
Point Windmill::get_point(const Modele* poly, int i)
|
||
{
|
||
Point point;
|
||
if (i == 0)
|
||
{
|
||
point.x = poly->x0; point.y = poly->y0; point.z = poly->z0;
|
||
}
|
||
if (i == 1)
|
||
{
|
||
point.x = poly->x1; point.y = poly->y1; point.z = poly->z1;
|
||
}
|
||
if (i == 2)
|
||
{
|
||
point.x = poly->x2; point.y = poly->y2; point.z = poly->z2;
|
||
}
|
||
if (i == 3)
|
||
{
|
||
if (poly->option == PARA)
|
||
{
|
||
point.x = poly->x2 + poly->x1 - poly->x0;
|
||
point.y = poly->y2 + poly->y1 - poly->y0;
|
||
point.z = poly->z2 + poly->z1 - poly->z0;
|
||
} else if (poly->option == TRAP)
|
||
{
|
||
point.x = poly->x2 - poly->x1 + poly->x0;
|
||
point.y = poly->y2 - poly->y1 + poly->y0;
|
||
point.z = poly->z2 - poly->z1 + poly->z0;
|
||
}
|
||
}
|
||
return point;
|
||
}
|
||
|
||
|
||
Point Windmill::get_center_poly(const Modele* poly)
|
||
{
|
||
Point point;
|
||
point.x = 0; point.y = 0; point.z = 0;
|
||
|
||
for (int i = 0; i < poly->type; i++)
|
||
{
|
||
point.x += get_point(poly, i).x;
|
||
point.y += get_point(poly, i).y;
|
||
point.z += get_point(poly, i).z;
|
||
}
|
||
|
||
point.x /= poly->type;
|
||
point.y /= poly->type;
|
||
point.z /= poly->type;
|
||
|
||
return point;
|
||
}
|
||
|
||
|
||
void Windmill::compute_object_angle(Object* object, int* cosinus, int* sinus)
|
||
{
|
||
if (object->axe == Z_BILLBOARD)
|
||
{
|
||
float angle_look_at_camera = atan2f(camera.y - object->y, camera.x - object->x);
|
||
float angle_rad = angle_look_at_camera + 3.1415 * object->angle / 180.0;
|
||
*cosinus = 1024 * cosf(angle_rad);
|
||
*sinus = 1024 * sinf(angle_rad);
|
||
}
|
||
if (object->axe == X or object->axe == Y or object->axe == Z)
|
||
{
|
||
float angle_rad = 3.1415 * object->angle / 180.0;
|
||
*cosinus = 1024 * cosf(angle_rad);
|
||
*sinus = 1024 * sinf(angle_rad);
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::extract_vertex_from_poly(const Modele* poly, Vertex* vertex, int* vertex_length, int* width, int* height)
|
||
{
|
||
int x0, y0, z0, x1, y1, z1, x2, y2, z2, x3, y3, z3;
|
||
|
||
if (poly->type == TRIANGLE)
|
||
{
|
||
*vertex_length = 3;
|
||
x0 = poly->x0; y0 = poly->y0; z0 = poly->z0;
|
||
x1 = poly->x1; y1 = poly->y1; z1 = poly->z1;
|
||
x2 = poly->x2; y2 = poly->y2; z2 = poly->z2;
|
||
vertex[0].set_xyz(x0, y0, z0);
|
||
vertex[1].set_xyz(x1, y1, z1);
|
||
vertex[2].set_xyz(x2, y2, z2);
|
||
*width = distance(x0-x1, y0-y1, z0-z1);
|
||
*height = distance(x0-x2, y0-y2, z0-z2);
|
||
}
|
||
if (poly->type == RECTANGLE)
|
||
{
|
||
*vertex_length = 4;
|
||
x0 = poly->x0; y0 = poly->y0; z0 = poly->z0;
|
||
x1 = poly->x1; y1 = poly->y1; z1 = poly->z1;
|
||
x3 = poly->x2; y3 = poly->y2; z3 = poly->z2;
|
||
if (poly->option == PARA)
|
||
{
|
||
x2 = x3 + x1 - x0; y2 = y3 + y1 - y0; z2 = z3 + z1 - z0;
|
||
} else if (poly->option == TRAP)
|
||
{
|
||
//x2 = x3 - x1 + x0; y2 = y3 - y1 + y0; z2 = z3 - z1 + z0;
|
||
}
|
||
vertex[0].set_xyz(x0, y0, z0);
|
||
vertex[1].set_xyz(x1, y1, z1);
|
||
vertex[2].set_xyz(x2, y2, z2);
|
||
vertex[3].set_xyz(x3, y3, z3);
|
||
*width = distance(x0-x1, y0-y1, z0-z1);
|
||
*height = distance(x0-x3, y0-y3, z0-z3);
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::texture_coordinates(const Modele* poly, Vertex* vertex, const Texture* texture, int visible, int width, int height)
|
||
{
|
||
int w = (texture->real_width > 0) ? width * texture->pixel_width / texture->real_width : texture->pixel_width;
|
||
int h = (texture->real_height > 0) ? height * texture->pixel_height / texture->real_height : texture->pixel_height;
|
||
|
||
if (poly->type == TRIANGLE)
|
||
{
|
||
int offset = w * texture->offset;
|
||
if (visible == FRONT or texture->mirror == true)
|
||
{
|
||
vertex[0].set_wh(0, texture->pixel_height);
|
||
vertex[1].set_wh(w, texture->pixel_height);
|
||
vertex[2].set_wh(offset, texture->pixel_height-h);
|
||
// vertex[0].set_wh(0, h);
|
||
// vertex[1].set_wh(w, h);
|
||
// vertex[2].set_wh(offset, 0);
|
||
} else {
|
||
vertex[0].set_wh(w, h);
|
||
vertex[1].set_wh(0, h);
|
||
vertex[2].set_wh(w-offset, 0);
|
||
}
|
||
}
|
||
else if (poly->type == RECTANGLE)
|
||
{
|
||
if (visible == FRONT or texture->mirror == true)
|
||
{
|
||
vertex[0].set_wh(0, texture->pixel_height);
|
||
vertex[1].set_wh(w, texture->pixel_height);
|
||
vertex[2].set_wh(w, texture->pixel_height-h);
|
||
vertex[3].set_wh(0, texture->pixel_height-h);
|
||
|
||
// vertex[0].set_wh(0, h);
|
||
// vertex[1].set_wh(w, h);
|
||
// vertex[2].set_wh(w, 0);
|
||
// vertex[3].set_wh(0, 0);
|
||
} else {
|
||
vertex[0].set_wh(w, h);
|
||
vertex[1].set_wh(0, h);
|
||
vertex[2].set_wh(0, 0);
|
||
vertex[3].set_wh(w, 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::swap_vertex(Vertex* vertexA, Vertex* vertexB)
|
||
{
|
||
Vertex vertex_temp;
|
||
memcpy(&vertex_temp, vertexA, sizeof(Vertex));
|
||
memcpy(vertexA, vertexB, sizeof(Vertex));
|
||
memcpy(vertexB, &vertex_temp, sizeof(Vertex));
|
||
}
|
||
|
||
|
||
void Windmill::copy_vertex(Vertex* vertex_source, Vertex* vertex_dest)
|
||
{
|
||
memcpy(vertex_dest, vertex_source, sizeof(Vertex));
|
||
}
|
||
|
||
|
||
|
||
//----------------------------------------------------------------------------------------------------
|
||
// SPHERE
|
||
//----------------------------------------------------------------------------------------------------
|
||
Sphere Windmill::transform_sphere_to_world(Sphere* sphere_input, Object* object, int cosinus, int sinus)
|
||
{
|
||
Vertex vertex;
|
||
vertex.set_xyz(sphere_input->x, sphere_input->y, sphere_input->z);
|
||
transform_model_to_world(&vertex, 1, object, cosinus, sinus);
|
||
transform_world_to_camera(&vertex, 1);
|
||
Sphere sphere_output;
|
||
sphere_output.x = vertex.x >> 7;
|
||
sphere_output.y = vertex.y >> 7;
|
||
sphere_output.z = vertex.z >> 7;
|
||
sphere_output.radius = sphere_input->radius;
|
||
|
||
return sphere_output;
|
||
}
|
||
|
||
/*
|
||
bool Windmill::sphere_in_cone(Sphere* sphere)
|
||
{
|
||
//return true;
|
||
int cone_offset = sphere->radius * camera.sin_fov;
|
||
|
||
int nx = camera.nx;
|
||
int ny = camera.ny;
|
||
int nz = camera.nz;
|
||
|
||
Point cone;
|
||
cone.x = int(camera.x) - ((nx * cone_offset) >> 14);
|
||
cone.y = int(camera.y) - ((ny * cone_offset) >> 14);
|
||
cone.z = int(camera.z) - ((nz * cone_offset) >> 14);
|
||
|
||
int sx = sphere->x - cone.x;
|
||
int sy = sphere->y - cone.y;
|
||
int sz = sphere->z - cone.z;
|
||
int ss = sx*sx + sy*sy + sz*sz;
|
||
|
||
// si sommet du cone dans la sphere
|
||
if (ss <= sphere->radius * sphere->radius)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
// si sphere dans le cone
|
||
int ns = ((nx * sx) >> 7) + ((ny * sy) >> 7) + ((nz * sz) >> 7);
|
||
|
||
if (ns > 0 and ns*ns > camera.cos_fov_square * ss)
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}*/
|
||
|
||
bool Windmill::sphere_in_cone(Sphere* sphere)
|
||
{
|
||
//return true;
|
||
sphere->z += sphere->radius;
|
||
if (sphere->z > 0)
|
||
{
|
||
int sphere_z = int(sphere->z * camera.scale_coef) >> 6;
|
||
int xr = 0;
|
||
if (sphere->x > 0) xr = sphere->x - sphere->radius;
|
||
if (sphere->x < 0) xr = - sphere->x - sphere->radius;
|
||
|
||
if (xr <= sphere_z) return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
|
||
//----------------------------------------------------------------------------------------------------
|
||
// DIVERS
|
||
//----------------------------------------------------------------------------------------------------
|
||
void Windmill::copy_camera()
|
||
{
|
||
memcpy(&camera, camera2, sizeof(Camera));
|
||
}
|
||
|
||
|
||
void Windmill::sort_object()
|
||
{
|
||
//qsort(object, list_object_length, sizeof(Object*), compare_object);
|
||
}
|
||
|
||
|
||
int compare_object(void const *a, void const *b)
|
||
{
|
||
Object* object_a = *(Object **) a;
|
||
Object* object_b = *(Object **) b;
|
||
return (object_a->distance_to_camera - object_b->distance_to_camera);
|
||
}
|
||
|
||
|
||
void Windmill::clear_z_buffer()
|
||
{
|
||
memset(z_buffer, MAX_DEPTH_Z_BUFFER, z_buffer_size * sizeof(short));
|
||
}
|
||
|
||
|
||
int Windmill::edge(Vertex* a, Vertex* b, Vertex* c)
|
||
{
|
||
return (c->x - a->x) * (b->y - a->y) - (c->y - a->y) * (b->x - a->x);
|
||
}
|
||
|
||
|
||
int Windmill::edge_start(Vertex* a, Vertex* b, int px, int py)
|
||
{
|
||
return (b->y - a->y) * (px - a->x) - (b->x - a->x) * (py - a->y);
|
||
}
|
||
|
||
|
||
int Windmill::edge_step_x(Vertex* a, Vertex* b)
|
||
{
|
||
return b->y - a->y;
|
||
}
|
||
|
||
|
||
int Windmill::edge_step_y(Vertex* a, Vertex* b)
|
||
{
|
||
return a->x - b->x;
|
||
}
|
||
|
||
|
||
|
||
//----------------------------------------------------------------------------------------------------
|
||
// UTILITAIRE
|
||
//----------------------------------------------------------------------------------------------------
|
||
void Windmill::pixel_on_cursor(int x, int y)
|
||
{
|
||
if (x == cursor_x and y == cursor_y)
|
||
{
|
||
temp_object_cursor = object[i];
|
||
temp_poly_cursor = j;
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::show_coordinates()
|
||
{
|
||
// coordonnees
|
||
float tab_coordinates[5] = {camera.x, camera.y, camera.z, to_deg(camera.yaw), to_deg(camera.pitch)};
|
||
for (int i = 0; i < 5; i++)
|
||
{
|
||
/*
|
||
char str[20];
|
||
sprintf(str, "%f", tab_coordinates[i]);
|
||
int j;
|
||
for(j= 0; j < 16; j++)
|
||
{
|
||
if (str[j] == '.')
|
||
{
|
||
str[j+2] = '\0';
|
||
break;
|
||
}
|
||
}
|
||
PrintMini(127-4*(j+2), 1+6*i, (unsigned char*)str, MINI_OVER);*/
|
||
dprint(0, 1+6*i, C_BLACK, "%f", tab_coordinates[i]); // need Gint
|
||
}
|
||
}
|
||
|
||
|
||
void Windmill::show_repere()
|
||
{/*
|
||
// repere
|
||
int repere_x = 112;
|
||
int repere_y = 55;
|
||
int repere_size = 12;
|
||
|
||
float camera_yaw_rad = -camera.yaw;//- 3.1415 * camera.yaw / 180.0;
|
||
float camera_pitch_rad = camera.pitch;//3.1415 * camera.pitch / 180.0;
|
||
float cos_yaw = cosf(camera_yaw_rad);
|
||
float sin_yaw = sinf(camera_yaw_rad);
|
||
float cos_pitch = cosf(camera_pitch_rad);
|
||
float sin_pitch = sinf(camera_pitch_rad);
|
||
float aa4 = sin_yaw;
|
||
float aa5 = cos_yaw;
|
||
float aa6 = 0;
|
||
float aa7 = -sin_pitch * cos_yaw;
|
||
float aa8 = sin_pitch * sin_yaw;
|
||
float aa9 = cos_pitch;
|
||
// repere
|
||
Vertex v[3];
|
||
//const unsigned char* cx = "x";
|
||
//const unsigned char* cy = "y";
|
||
//const unsigned char* cz = "z";
|
||
const char* letter[] = {"x", "y", "z"};
|
||
v[0].set_xyz(repere_size, 0 , 0 );
|
||
v[1].set_xyz(0 , repere_size, 0 );
|
||
v[2].set_xyz(0 , 0 , repere_size);
|
||
for (int i = 0; i < 3; i++)
|
||
{
|
||
float y = (aa4 * v[i].x + aa5 * v[i].y + aa6 * v[i].z);
|
||
float z = (aa7 * v[i].x + aa8 * v[i].y + aa9 * v[i].z);
|
||
v[i].x = -y;
|
||
v[i].y = -z;
|
||
//ML_line(repere_x, repere_y, v[i].x + repere_x, v[i].y + repere_y, ML_BLACK);
|
||
//PrintMini(v[i].x + repere_x, v[i].y + repere_y-2, letter[i], MINI_OVER);
|
||
}
|
||
*/
|
||
}
|
||
|
||
|
||
/*void Windmill::show_fps()
|
||
{
|
||
char str[20];
|
||
sprintf(str, "%i", time_get_fps());
|
||
PrintMini(1, 58, (unsigned char*)str, MINI_OVER);
|
||
}*/
|
||
|
||
|
||
|
||
|
||
//----------------------------------------------------------------------------------------------------
|
||
// DESTRUCTEUR
|
||
//----------------------------------------------------------------------------------------------------
|
||
Windmill::~Windmill()
|
||
{
|
||
free(z_buffer);
|
||
free(object);
|
||
//delete[] object;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
float distance(float dx, float dy, float dz)
|
||
{
|
||
return sqrtf(dx*dx + dy*dy + dz*dz);
|
||
}
|
||
|
||
Vertex::Vertex(){}
|
||
|
||
void Vertex::set_xyz(int _x, int _y, int _z)
|
||
{
|
||
x = _x;
|
||
y = _y;
|
||
z = _z;
|
||
}
|
||
|
||
void Vertex::set_wh(float _w, float _h)
|
||
{
|
||
w = _w;
|
||
h = _h;
|
||
}
|
||
|
||
float Vertex::length(int x, int y, int z)
|
||
{
|
||
return sqrtf(x*x + y*y + z*z);
|
||
}
|