void bsp_select_balanced_divider(const struct BspTree* tree, const struct BspNode* node, size_t num_polygons, const int32_t* polygon_indices, int32_t* selected_divider) { *selected_divider = 0; float node_width = node->bounds.half_width*2.0f; float node_height = node->bounds.half_height*2.0f; float node_depth = node->bounds.half_depth*2.0f; Vec3f normal_comparison_axis = {0}; if( node_width <= node_height && node_width <= node_depth ) { vec_copy3f((Vec4f)X_AXIS, normal_comparison_axis); } else if( node_height <= node_width && node_height <= node_depth ) { vec_copy3f((Vec4f)Y_AXIS, normal_comparison_axis); } else if( node_depth <= node_width && node_depth <= node_height ) { vec_copy3f((Vec4f)Z_AXIS, normal_comparison_axis); } float min_dot = FLT_MAX; Vec3f min_diff_center = {FLT_MAX, FLT_MAX, FLT_MAX}; int32_t best_i = -1; for( size_t polygon_i = 0; polygon_i < num_polygons; polygon_i++ ) { int32_t index_i = polygon_indices[polygon_i]; int32_t start_i = tree->polygons.array[index_i].start; float dot = FLT_MAX; vec_dot(tree->polygons.array[index_i].normal, normal_comparison_axis, &dot); if( fabs(dot) < min_dot ) { min_dot = fabs(dot); best_i = polygon_i; } Vec3f average_vertex = {0.0f, 0.0f, 0.0f}; for( size_t size_i = 0; size_i < tree->polygons.array[index_i].size; size_i++ ) { } } }
int32_t main(int32_t argc, char *argv[]) { if( init_sdl2() ) { return 1; } int width = 1280; int height = 720; SDL_Window* window; sdl2_window("cute3d: " __FILE__, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, &window); SDL_GLContext* context; sdl2_glcontext(3, 2, window, &context); if( init_shader() ) { return 1; } if( init_canvas(width, height) ) { return 1; } canvas_create("global_dynamic_canvas", &global_dynamic_canvas); canvas_create("global_static_canvas", &global_static_canvas); struct Vbo vbo = {0}; vbo_create(&vbo); vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX, 3, GL_FLOAT, GL_STATIC_DRAW); vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX_NORMAL, 3, GL_FLOAT, GL_STATIC_DRAW); vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX_COLOR, 4, GL_UNSIGNED_BYTE, GL_STATIC_DRAW); vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX_NORMAL, NORMAL_SIZE, GL_FLOAT, GL_STATIC_DRAW); struct Ibo ibo = {0}; ibo_create(GL_TRIANGLES, GL_UNSIGNED_INT, GL_STATIC_DRAW, &ibo); struct SolidTetrahedron hard_tetrahedron = {0}; struct SolidBox hard_cube = {0}; struct SolidSphere16 hard_sphere16 = {0}; struct SolidSphere32 hard_sphere32 = {0}; solid_tetrahedron_create(1.0, (Color){255, 0, 0, 255}, &hard_tetrahedron); solid_cube_create(0.5, (Color){0, 255, 0, 255}, &hard_cube); solid_sphere16_create(16, 8, 0.75, (Color){0, 255, 255, 255}, &hard_sphere16); solid_sphere32_create(32, 16, 0.75, (Color){255, 255, 0, 255}, &hard_sphere32); solid_optimize((struct Solid*)&hard_tetrahedron); solid_optimize((struct Solid*)&hard_cube); solid_optimize((struct Solid*)&hard_sphere16); solid_optimize((struct Solid*)&hard_sphere32); struct VboMesh hard_tetrahedron_mesh, hard_box_mesh, hard_cube_mesh, hard_sphere16_mesh, hard_sphere32_mesh; vbo_mesh_create_from_solid((struct Solid*)&hard_tetrahedron, &vbo, &ibo, &hard_tetrahedron_mesh); vbo_mesh_create_from_solid((struct Solid*)&hard_cube, &vbo, &ibo, &hard_cube_mesh); vbo_mesh_create_from_solid((struct Solid*)&hard_sphere16, &vbo, &ibo, &hard_sphere16_mesh); vbo_mesh_create_from_solid((struct Solid*)&hard_sphere32, &vbo, &ibo, &hard_sphere32_mesh); struct SolidTetrahedron smooth_tetrahedron = {0}; struct SolidBox smooth_cube = {0}; struct SolidSphere16 smooth_sphere16 = {0}; struct SolidSphere32 smooth_sphere32 = {0}; solid_tetrahedron_create(1.0, (Color){255, 0, 0, 255}, &smooth_tetrahedron); solid_cube_create(0.5, (Color){0, 255, 0, 255}, &smooth_cube); solid_sphere16_create(16, 8, 0.75, (Color){0, 255, 255, 255}, &smooth_sphere16); solid_sphere32_create(32, 16, 0.75, (Color){255, 255, 0, 255}, &smooth_sphere32); solid_optimize((struct Solid*)&smooth_tetrahedron); solid_optimize((struct Solid*)&smooth_cube); solid_optimize((struct Solid*)&smooth_sphere16); solid_optimize((struct Solid*)&smooth_sphere32); solid_smooth_normals((struct Solid*)&smooth_tetrahedron, smooth_tetrahedron.normals, smooth_tetrahedron.normals); solid_smooth_normals((struct Solid*)&smooth_cube, smooth_cube.normals, smooth_cube.normals); solid_smooth_normals((struct Solid*)&smooth_sphere16, smooth_sphere16.normals, smooth_sphere16.normals); solid_smooth_normals((struct Solid*)&smooth_sphere32, smooth_sphere32.normals, smooth_sphere32.normals); struct VboMesh smooth_tetrahedron_mesh, smooth_box_mesh, smooth_cube_mesh, smooth_sphere16_mesh, smooth_sphere32_mesh; vbo_mesh_create_from_solid((struct Solid*)&smooth_tetrahedron, &vbo, &ibo, &smooth_tetrahedron_mesh); vbo_mesh_create_from_solid((struct Solid*)&smooth_cube, &vbo, &ibo, &smooth_cube_mesh); vbo_mesh_create_from_solid((struct Solid*)&smooth_sphere16, &vbo, &ibo, &smooth_sphere16_mesh); vbo_mesh_create_from_solid((struct Solid*)&smooth_sphere32, &vbo, &ibo, &smooth_sphere32_mesh); struct Arcball arcball = {0}; arcball_create(width, height, (Vec4f){2.5,17.0,17.0,1.0}, (Vec4f){2.5,0.0,0.0,1.0}, 0.1, 100.0, &arcball); float circular_motion_angle = 0.0f; float circular_motion_speed = (2.0f*PI)/30; float circular_motion_radius = 12.0f; Vec3f light_position = { circular_motion_radius, 10.0, circular_motion_radius }; Vec3f light_direction = {0}; vec_sub((Vec3f){0.0f, 0.0f, 0.0f}, light_position, light_direction); vec_normalize(light_direction, light_direction); Vec3f eye_position = {0}; vec_copy3f(arcball.camera.pivot.position, eye_position); Color ambiance = {50, 25, 150, 255}; Color specular = {255, 255, 255, 255}; float material_shininess = 1.0; Vec4f material_coefficients = { 0.8, 0.2, 0.0, 0.0 }; // flat struct Shader flat_shader = {0}; shader_create(&flat_shader); shader_attach(&flat_shader, GL_VERTEX_SHADER, "prefix.vert", 1, "flat_shading.vert"); shader_attach(&flat_shader, GL_FRAGMENT_SHADER, "prefix.frag", 1, "flat_shading.frag"); shader_make_program(&flat_shader, SHADER_DEFAULT_NAMES, "flat_shader"); shader_set_uniform_3f(&flat_shader, flat_shader.program, SHADER_UNIFORM_LIGHT_DIRECTION, 3, GL_FLOAT, light_direction); shader_set_uniform_4f(&flat_shader, flat_shader.program, SHADER_UNIFORM_AMBIENT_LIGHT, 4, GL_UNSIGNED_BYTE, ambiance); // gouraud struct Shader gouraud_shader = {0}; shader_create(&gouraud_shader); shader_attach(&gouraud_shader, GL_VERTEX_SHADER, "prefix.vert", 1, "gouraud_shading.vert"); shader_attach(&gouraud_shader, GL_FRAGMENT_SHADER, "prefix.frag", 1, "gouraud_shading.frag"); shader_make_program(&gouraud_shader, SHADER_DEFAULT_NAMES, "gouraud_shader"); shader_set_uniform_3f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_LIGHT_POSITION, 3, GL_FLOAT, light_position); shader_set_uniform_3f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_EYE_POSITION, 3, GL_FLOAT, eye_position); shader_set_uniform_4f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_AMBIENT_LIGHT, 4, GL_UNSIGNED_BYTE, ambiance); shader_set_uniform_4f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_SPECULAR_LIGHT, 4, GL_UNSIGNED_BYTE, specular); shader_set_uniform_1f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_MATERIAL_SHININESS, 1, GL_FLOAT, &material_shininess); shader_set_uniform_4f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_MATERIAL_COEFFICIENTS, 4, GL_FLOAT, material_coefficients); shader_set_uniform_3f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_EYE_POSITION, 3, GL_FLOAT, &arcball.camera.pivot.position); Mat identity = IDENTITY_MAT; draw_grid(&global_static_canvas, 0, identity, (Color){127, 127, 127, 255}, 0.03f, 12.0f, 12.0f, 12); Mat shading_label_transform = IDENTITY_MAT; Quat text_rotation = IDENTITY_QUAT; quat_from_axis_angle((Vec3f)X_AXIS, -PI/2.0f, text_rotation); mat_rotate(shading_label_transform, text_rotation, shading_label_transform); mat_translate(shading_label_transform, (float[4]){ 6.5, 0.0, -2.5, 1.0 }, shading_label_transform);
void bsp_tree_create_from_solid(struct BspTree* tree, struct Solid* solid) { size_t alloc_attributes_result = bsp_tree_alloc_attributes(tree, solid->attributes_size); log_assert( alloc_attributes_result >= solid->attributes_size ); size_t num_polygons = solid->indices_size/3; size_t alloc_polygons_result = bsp_tree_alloc_polygons(tree, num_polygons); log_assert( alloc_polygons_result >= num_polygons ); size_t alloc_nodes_result = bsp_tree_alloc_nodes(tree, num_polygons); log_assert( alloc_nodes_result >= num_polygons ); int32_t* workset_polygons_front = malloc(alloc_polygons_result * sizeof(int32_t)); log_assert( workset_polygons_front != NULL ); int32_t* workset_polygons_back = malloc(alloc_polygons_result * sizeof(int32_t)); log_assert( workset_polygons_back != NULL ); float min_x = FLT_MAX; float min_y = FLT_MAX; float min_z = FLT_MAX; float max_x = -FLT_MAX; float max_y = -FLT_MAX; float max_z = -FLT_MAX; for( size_t indices_i = 0; indices_i < solid->indices_size+1; indices_i++ ) { uint32_t src_i = solid->indices[indices_i]; if( indices_i < solid->indices_size ) { VecP* src = &solid->vertices[src_i*VERTEX_SIZE]; VecP* dst = &tree->attributes.vertices[indices_i*VERTEX_SIZE]; vec_copy3f(src, dst); tree->attributes.occupied += 1; if( src[0] < min_x ) { min_x = src[0]; } if( src[1] < min_y ) { min_y = src[1]; } if( src[2] < min_z ) { min_z = src[2]; } if( src[0] > max_x ) { max_x = src[0]; } if( src[1] > max_y ) { max_y = src[1]; } if( src[2] > max_z ) { max_z = src[2]; } } if( indices_i > 0 && indices_i % 3 == 0 ) { size_t poly_i = indices_i / 3 - 1; tree->polygons.array[poly_i].start = poly_i*3*VERTEX_SIZE; tree->polygons.array[poly_i].size = 3; polygon_normal(3, VERTEX_SIZE, &tree->attributes.vertices[poly_i*3*VERTEX_SIZE], tree->polygons.array[poly_i].normal); tree->polygons.occupied += 1; workset_polygons_front[poly_i] = poly_i; } } struct BspNode* root = &tree->nodes.array[0]; bsp_node_create(root); tree->nodes.occupied = 1; root->bounds.half_width = (max_x - min_x)/2.0f; root->bounds.half_height = (max_y - min_y)/2.0f; root->bounds.half_depth = (max_z - min_z)/2.0f; root->bounds.center[0] = min_x + root->bounds.half_width; root->bounds.center[1] = min_y + root->bounds.half_height; root->bounds.center[2] = min_z + root->bounds.half_depth; root->divider = 0; bsp_select_balanced_divider(tree, root, num_polygons, workset_polygons_front, &root->divider); struct BspPoly* root_divider = &tree->polygons.array[root->divider]; const float* root_divider_polygon = &tree->attributes.vertices[root_divider->start]; draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 0, 0, 255}, 0.01f, root_divider->size, root_divider_polygon, root_divider->normal); draw_vec(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 0, 0, 255}, 0.01f, root_divider->normal, &root_divider_polygon[3], 1.0f, 0.1f); /* draw_plane(&global_static_canvas, MAX_CANVAS_LAYERS-1, (Mat)IDENTITY_MAT, (Color){120, 120, 150, 127}, root_divider->normal, &root_divider_polygon[3], 10.0f); */ for( size_t polygon_i = 0; polygon_i < num_polygons; polygon_i++ ) { size_t cuts_polygon_size = 3; const float* cuts_polygon = &tree->attributes.vertices[polygon_i*cuts_polygon_size*VERTEX_SIZE]; size_t result_size = cuts_polygon_size; struct PolygonCutPoints result_points[cuts_polygon_size]; enum PolygonCutType result_type = polygon_cut(cuts_polygon_size, VERTEX_SIZE, cuts_polygon, root_divider->normal, root_divider_polygon, result_size, result_points); Vec3f cuts_polygon_normal = {0}; polygon_normal(3, VERTEX_SIZE, cuts_polygon, cuts_polygon_normal); switch(result_type) { case POLYGON_COPLANNAR: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 255, 255, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); break; case POLYGON_FRONT: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 0, 255, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); break; case POLYGON_BACK: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){0, 0, 255, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); break; case POLYGON_SPANNING: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 255, 0, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); if( result_points[0].num_cuts > 0 ) { size_t new_poly_size = cuts_polygon_size+result_points[0].num_cuts+10; size_t front_occupied = 0; float front_vertices[new_poly_size*VERTEX_SIZE]; size_t back_occupied = 0; float back_vertices[new_poly_size*VERTEX_SIZE]; for( size_t result_i = 0; result_i < result_size; result_i++ ) { if( result_points[result_i].type == POLYGON_BACK ) { vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &back_vertices[back_occupied*VERTEX_SIZE]); back_occupied += 1; } else if( result_points[result_i].type == POLYGON_FRONT ) { vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &front_vertices[front_occupied*VERTEX_SIZE]); front_occupied += 1; } else if( result_points[result_i].type == POLYGON_COPLANNAR ) { vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &back_vertices[back_occupied*VERTEX_SIZE]); back_occupied += 1; vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &front_vertices[front_occupied*VERTEX_SIZE]); front_occupied += 1; } if( result_points[result_i].interpolation_index > -1 ) { const VecP* a = &cuts_polygon[result_i*VERTEX_SIZE]; const VecP* b = &cuts_polygon[result_points[result_i].interpolation_index*VERTEX_SIZE]; Vec3f r = {0}; vec_lerp(b, a, result_points[result_i].interpolation_value, r); vec_copy3f(r, &back_vertices[back_occupied*VERTEX_SIZE]); back_occupied += 1; vec_copy3f(r, &front_vertices[front_occupied*VERTEX_SIZE]); front_occupied += 1; } } //printf("front_occupied: %lu\n", front_occupied); //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, red, 0.01f, front_occupied, front_vertices, cuts_polygon_normal); //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, white, 0.01f, back_occupied, back_vertices, cuts_polygon_normal); } break; } } log_fail(__FILE__, __LINE__, "BUILT BSP TREE... OR NOT?\n"); }