package model import "../image" import "../texture" import "../vertex" import "core:fmt" import glm "core:math/linalg/glsl" import "core:os" import "core:strconv" import "core:strings" Error :: union { os.Error, string, } Index_Range :: struct { first: u32, count: i32, } Material :: struct { name: string, texture: texture.Texture, ranges: [dynamic]Index_Range, // first_index: u32, // index_count: i32, } load_mtl_string :: proc(text: string, texture_map: map[string]string) -> (materials: map[string]Material) { lines := strings.split_lines(text) default, _ := texture.load(image.default_image) current_material: string for line in lines { parts := strings.split(line, " ") switch parts[0] { case "newmtl": current_material = strings.join(parts[1:], " ") materials[current_material] = Material { name = current_material, texture = default, } case "map_Kd": filename := strings.join(parts[1:], " ") img_data := texture_map[filename] fmt.printfln("\"{}\" = #load(\"{}\")", filename, filename) tex, err := texture.load(image.load_string(img_data)) mat := materials[current_material] mat.texture = tex materials[current_material] = mat } } return } load_mtl :: proc(filename: string, texture_map: map[string]string) -> (materials: map[string]Material) { bytes, _ := os.read_entire_file_or_err(filename) lines := strings.split_lines(string(bytes)) default, _ := texture.load(image.default_image) current_material: string for line in lines { parts := strings.split(line, " ") switch parts[0] { case "newmtl": current_material = strings.join(parts[1:], " ") materials[current_material] = Material { name = current_material, texture = default, } case "map_Kd": filename := strings.join(parts[1:], " ") // img_data := texture_map[filename] // fmt.printfln("\"{}\" = #load(\"{}\")", filename, filename) tex, err := texture.load(image.load(filename)) mat := materials[current_material] mat.texture = tex materials[current_material] = mat } } return } load_obj_string :: proc( text: string, mtl: string, textures_map: map[string]string, ) -> ( Maybe(Model), Error, ) { vertices: [dynamic]vertex.Vertex texcoords: [dynamic]glm.vec2 indices: [dynamic]u32 materials: map[string]Material current_material: string current_range := 0 lines := strings.split_lines(text) for line in lines { parts := strings.split(line, " ") switch parts[0] { case "v": vert: vertex.Vertex vert.pos = glm.vec4(1) for part, i in parts[1:] { val, ok := strconv.parse_f32(part) if !ok { return nil, "Failed to parse f32" } vert.pos[i] = val } append(&vertices, vert) case "vt": texcoord: glm.vec2 for part, i in parts[1:] { val, ok := strconv.parse_f32(part) if !ok { return nil, "Failed to parse f32" } texcoord[i] = val } append(&texcoords, texcoord) case "f": for part in parts[1:] { slashes := strings.split(part, "/") v, ok := strconv.parse_u64(slashes[0]) if !ok { return nil, "Failed to parse u64" } v -= 1 if len(slashes) > 1 { vt: u64 vt, ok = strconv.parse_u64(slashes[1]) if !ok { return nil, "Failed to parse u64" } vt -= 1 vertices[v].texcoord = texcoords[vt] } append(&indices, u32(v)) if current_material != "" { mtl := materials[current_material] mtl.ranges[len(mtl.ranges) - 1].count += 1 materials[current_material] = mtl } } case "mtllib": filename := strings.join(parts[1:], " ") mtl_materials := load_mtl_string(mtl, textures_map) for material_name, material in mtl_materials { materials[material_name] = material } case "usemtl": current_material = strings.join(parts[1:], " ") mtl := materials[current_material] append(&mtl.ranges, Index_Range{first = u32(len(indices))}) materials[current_material] = mtl } } model := create(vertices[:], indices[:], materials) return model, nil } // load_obj :: proc(filename: string) -> (Maybe(Model), Error) { // bytes, err := os.read_entire_file_or_err(filename) // if err != nil { // return nil, err // } // // return load_obj_string(string(bytes)) // }