//---------------------------------------------------------------------------------------------------- // // 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" void debug_pop(char const *fmt, ...); void debug_display(char const *fmt, ...); extern Texture tex_white; extern Texture tex_light; extern Texture tex_dark; extern Texture tex_black; //---------------------------------------------------------------------------------------------------- // 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 les ombres // draw_shadows(); // 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 debug if (log) { //show_fps(); //show_coordinates(); show_repere(); } } void Windmill::draw_horizon() { int distance = 1000; int hx = camera.x + distance * camera.cos_yaw; int hy = camera.y + distance * camera.sin_yaw; Vertex horizon = Vertex(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); } } void Windmill::draw_ground() { 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 0) { transform_camera_to_screen(&ground, 1); if (inside_viewport(ground.x, ground.y) == true) { dpixel(ground.x, ground.y, C_BLACK); } } } } } } void Windmill::draw_objects() { for(i=0; iobject_length; i++) { // récupère l'objet en cours Object* object = map->object[i]; //Object* object = objects[i]; //int f_visible = 0; // si l'objet est totalement ou partie dans le frustrum if (object-> visible && object_in_frustrum(object)) { // copie le mesh avec plus de memoires disponible pour possiblement ajouter des points au clipping WMesh mesh; mesh.from_mesh(object->mesh, 20); // calcul des coordonnees dans le repère monde apres rotation et translation de l objet transform_model_to_world(object, mesh.v, mesh.v_length); // calcul des coordonnees dans le repère camera apres rotation et translation de la camera transform_world_to_camera(mesh.v, mesh.v_length); // coupe 3D selon le frustrum de la camera clip_frustrum(&mesh); // SI OBJECT IN FRUSTRUM DIT QUE L'OBJET EST PARTEILLEMENT DANS FRUSTRUM // calcul des coordonnes apres perspective et decalage au centre de l ecran transform_camera_to_screen(mesh.v, mesh.v_length); if (log) { for (int v = 0; v> ((x+1) & 7); vram[(y << 4) + ((x+1) >> 3)] |= mask; } if (bottom < MAX_DEPTH_Z_BUFFER) { mask = 128 >> (x & 7); vram[(y << 4) + (x >> 3) + 16] |= mask; } } else { if (right == MAX_DEPTH_Z_BUFFER or bottom == MAX_DEPTH_Z_BUFFER) { mask = 128 >> (x & 7); vram[(y << 4) + (x >> 3) + 16] |= mask; } } } } // 21 fps 21,5 fps*/ /*left = z_buffer[0]; for (int i = 1; i> (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> ((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> 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... */ } //---------------------------------------------------------------------------------------------------- // DESSIN DES TRIANGLES //---------------------------------------------------------------------------------------------------- void Windmill::render_triangles(WMesh mesh) { for (int f = 0; fx, 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))); // ajustement des coordonnees des textures a la taille en pixel vertexA->u *= texture->pixel_width; vertexA->v *= texture->pixel_height; vertexB->u *= texture->pixel_width; vertexB->v *= texture->pixel_height; vertexC->u *= texture->pixel_width; vertexC->v *= texture->pixel_height; // pre-calcul des coordonnees de la texture << 13 => tex_w * 8192 / x int w0 = vertexA->u * vertexA->inv_z; int h0 = vertexA->v * vertexA->inv_z; int w1 = vertexB->u * vertexB->inv_z; int h1 = vertexB->v * vertexB->inv_z; int w2 = vertexC->u * vertexC->inv_z; int h2 = vertexC->v * vertexC->inv_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); // << 15 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; // << 13 int z_div_start = u0_start * vertexA->inv_z + u1_start * vertexB->inv_z + u2_start * vertexC->inv_z; int z_div_step_x = u0_step_x * vertexA->inv_z + u1_step_x * vertexB->inv_z + u2_step_x * vertexC->inv_z; int z_div_step_y = u0_step_y * vertexA->inv_z + u1_step_y * vertexB->inv_z + u2_step_y * vertexC->inv_z; // rapprochement artificiel si texture de type decoration int decoration = 0;//(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 dpixel(x, y, C_BLACK); //vram[(y << 4) + offset_vram] |= mask_vram; }else{ // afficher pixel blanc dpixel(x, y, C_WHITE); //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_color(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC, color_t color) { // calcul de l'aire du triangle int area = edge(vertexA, vertexB, vertexC); if (area <= MIN_AREA_CLIP) return; // 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 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 dpixel(x, y, color); } } 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_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; } }*/ //---------------------------------------------------------------------------------------------------- // UTILITAIRES //---------------------------------------------------------------------------------------------------- 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; }