Skin_Vertex :: struct { bone_index: [4] float; bone_weight: [4] float; } Mesh_Vertex_Data_Type :: enum { NONE; POSITION; NORMAL; TEXCOORD; TANGENT; COLOR; BITANGENT; BONE_INDICES; BONE_WEIGHTS; INSTANCED_MAT1; INSTANCED_MAT2; INSTANCED_MAT3; INSTANCED_MAT4; } Mesh_Handle :: #type, distinct u32; Mesh :: struct { name : string; positions : [..] Vector3; normals : [..] Vector3; texcoords : [..] Vector2; tangents : [..] Vector3; bitangents : [..] Vector3; colors : [..] Vector4; skin_data : [..] Skin_Vertex; bone_indices: [..] s32; bone_matrices: [..] Matrix4; num_bones: s32; indices : [..] u32; ib : Buffer_Handle; vbs : Table(u32, Buffer_Handle); //vb : Buffer_Handle; } get_mesh_vb :: (mesh: *Mesh, pipeline_handle: Pipeline_State_Handle = 0) -> Buffer_Handle { handle := ifx pipeline_handle == 0 then engine.renderer.current_state.last_set_pipeline else pipeline_handle; pipeline_state := *engine.renderer.pipeline_states[handle-1]; return get_mesh_vb(mesh, pipeline_state.mesh_data_types); } get_mesh_vb :: (mesh: *Mesh, input: [] Mesh_Vertex_Data_Type) -> Buffer_Handle { hash : u32 = 0; nums : [8] u32 : .[13, 61, 84, 86, 65, 10000, 100000, 126]; for input, i: input { hash += nums[i] * cast(u32)input; } if !table_contains(*mesh.vbs, hash) { final_vertices : [..] float; final_vertices.allocator = temp; stride : u32 = 0; for input: input { if input == { case .POSITION; stride += 3; case .NORMAL; stride += 3; case .TEXCOORD; stride += 2; case .COLOR; stride += 4; case .TANGENT; stride += 3; case .BITANGENT; stride += 3; case .BONE_INDICES; stride += 4; case .BONE_WEIGHTS; stride += 4; } } for 0..mesh.positions.count-1 { for input: input { if input == { case .POSITION; { array_add(*final_vertices, mesh.positions[it].x); array_add(*final_vertices, mesh.positions[it].y); array_add(*final_vertices, mesh.positions[it].z); } case .NORMAL; { if mesh.normals.count > 0 { array_add(*final_vertices, mesh.normals[it].x); array_add(*final_vertices, mesh.normals[it].y); array_add(*final_vertices, mesh.normals[it].z); } else { array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); log_error("Mesh didn't have required normals\n"); } } case .TEXCOORD; { if mesh.texcoords.count > 0 { array_add(*final_vertices, mesh.texcoords[it].x); array_add(*final_vertices, mesh.texcoords[it].y); } else { array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); log_error("Mesh didn't have required texcoords\n"); } } case .COLOR; { if mesh.colors.count > 0 { array_add(*final_vertices, mesh.colors[it].x); array_add(*final_vertices, mesh.colors[it].y); array_add(*final_vertices, mesh.colors[it].z); array_add(*final_vertices, mesh.colors[it].w); } else { array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); log_error("Mesh didn't have required colors\n"); } } case .TANGENT; { if mesh.tangents.count > 0 { array_add(*final_vertices, mesh.tangents[it].x); array_add(*final_vertices, mesh.tangents[it].y); array_add(*final_vertices, mesh.tangents[it].z); } else { array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); log_error("Mesh didn't have required tangents\n"); } } case .BITANGENT; { if mesh.bitangents.count > 0 { array_add(*final_vertices, mesh.bitangents[it].x); array_add(*final_vertices, mesh.bitangents[it].y); array_add(*final_vertices, mesh.bitangents[it].z); } else { array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); log_error("Mesh didn't have required bitangents\n"); } } case .BONE_INDICES; { if mesh.skin_data.count > 0 { for index: 0..3 { array_add(*final_vertices, mesh.skin_data[it].bone_index[index]); } } else { array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); log_error("Mesh didn't have required bone indices\n"); } } case .BONE_WEIGHTS; { if mesh.skin_data.count > 0 { for index: 0..3 { array_add(*final_vertices, mesh.skin_data[it].bone_weight[index]); } } else { array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); array_add(*final_vertices, 0.0); log_error("Mesh didn't have required bone weights\n"); } } } } } vb_size := size_of(float)*stride*mesh.positions.count; vb := create_vertex_buffer(engine.renderer, final_vertices.data, xx vb_size, stride=size_of(float)*stride); table_add(*mesh.vbs, hash, vb); } value, success := table_find(*mesh.vbs, hash); return value; } delete_mesh :: (handle: Mesh_Handle) { mesh := parray_get(*engine.renderer.meshes, handle); for mesh.vbs { destroy_buffer(engine.renderer, it); } deinit(*mesh.vbs); parray_remove(*engine.renderer.meshes, handle); }