//---------------------------------------------------------------------------------------------------- // // 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; //---------------------------------------------------------------------------------------------------- // INITIALISATION //---------------------------------------------------------------------------------------------------- Windmill::Windmill() { camera2 = NULL; map = NULL; //object = NULL; z_buffer = NULL; set_viewport(0, 0, 128, 64); sun = {0, 0, 100}; } Windmill::~Windmill() { free(z_buffer); //free(object); } 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(); } void Windmill::set_map(Map* _map) { loading = true; if (map != _map) { // free les anciennes ombres // ... // attribution de la map map = _map; // enregistrement d'une liste triable //set_objects(); // calcul des spheres englobantes de chaque objet compute_bouding_sphere(); // calcul des ombres projetees au sol par chaque objet //compute_shadows(); } loading = false; } /*void Windmill::set_objects() { //objects = new Object* [map->object_length]; objects = (Object**) malloc(map->object_length * sizeof(Object)); if (objects == NULL) debug_pop("ERROR ptr object NULL"); for (int i = 0; iobject_length; i++) { objects[i] = map->object[i]; } }*/ void Windmill::compute_bouding_sphere() { // calcul des spheres englobantes pour chaque objet for (int i = 0; iobject_length; i++) { Object* object = map->object[i]; int nb_point = 0; int barycenter_x = 0; int barycenter_y = 0; int barycenter_z = 0; // calcul du barycentre for (int v = 0; vmesh->v_length; v++) { VertexPoint vp = object->mesh->v[v]; barycenter_x += vp.x; barycenter_y += vp.y; barycenter_z += vp.z; nb_point++; } barycenter_x /= nb_point; barycenter_y /= nb_point; barycenter_z /= nb_point; // recherche du point le plus eloigne du barycentre int square_radius_max = 0; for (int v = 0; vmesh->v_length; v++) { VertexPoint vp = object->mesh->v[v]; int dx = vp.x - barycenter_x; int dy = vp.y - barycenter_y; int dz = vp.z - barycenter_z; int square_radius = dx*dx + dy*dy + dz*dz; if (square_radius > square_radius_max) { square_radius_max = square_radius; } } // enregistrement object->sphere.x = barycenter_x; object->sphere.y = barycenter_y; object->sphere.z = barycenter_z; object->sphere.radius = sqrtf(square_radius_max) + 1; object->sphere.square_radius = square_radius_max + 1; } } /*WMesh Windmill::compute_shadows() { // pout chaque objet for (int i = 0; iobject_length; i++) { Object* object = map->object[i]; list_shadows_length = get_points_size(object; //debug_pop("sh %i", list_shadows_length); shadows = (Point*) malloc(list_shadows_length * sizeof(Point)); int index = 0; // pour chaque poly for (int j = 0; jmodele_size; j++) { const Modele* current_poly = &object->modele[j]; for (int k = 0; ktype; k++) { Point point = get_point(current_poly, k); Point shadow_point = {(sun.x * point.z - sun.z * point.x) / (point.z - sun.z), (sun.y * point.z - sun.z * point.y) / (point.z - sun.z), 0}; shadows[index] = shadow_point; index ++; //debug_pop("p %i %i %i", point.x, point.y, point.z); //debug_pop("s %i %i %i", shadow_point.x, shadow_point.y, shadow_point.z); } } } } // Gift Wrapping algorithme void Windmill::compute_shadows_hull(Point3D* points, int points_size) { if (points_size < 3) return; Point3D* temp_hull = (Point3D*) malloc(list_shadows_length * sizeof(Point3D)); int temp_hull_length = 0; // commencer par le point le plus a gauche int left = 0; for (int i = 1; i 0)? 1 : 2; // clock ou counterclock wise }*/