Last active
October 17, 2022 03:49
-
-
Save vassvik/bde472fa9daf436c620cf4b693aa93ab to your computer and use it in GitHub Desktop.
odin obj loader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "core:os"; | |
import "core:fmt"; | |
import "core:strconv"; | |
// model data stuff | |
Model_Data :: struct { | |
vertices: [][3]f32, | |
indices: []i32, | |
} | |
free_model_data :: proc(using model_data: Model_Data) { | |
delete(vertices); | |
delete(indices); | |
} | |
// parsing stuff | |
stream: string; | |
is_whitespace :: inline proc(c: u8) -> bool { | |
switch c { | |
case ' ', '\t', '\n', '\v', '\f', '\r': return true; | |
} | |
return false; | |
} | |
skip_whitespace :: inline proc() #no_bounds_check { | |
for stream != "" && is_whitespace(stream[0]) do stream = stream[1:]; | |
} | |
skip_line :: proc() #no_bounds_check { | |
N := len(stream); | |
for i in 0..N-1 { | |
if stream[0] == '\r' || stream[0] == '\n' { | |
skip_whitespace(); | |
return; | |
} | |
stream = stream[1:]; | |
} | |
} | |
next_word :: proc() -> string #no_bounds_check { | |
skip_whitespace(); | |
N := len(stream); | |
for i in 0..N-1 { | |
if is_whitespace(stream[i]) || i == len(stream)-1 { | |
current_word := stream[0:i]; | |
stream = stream[i:]; | |
return current_word; | |
} | |
} | |
return ""; | |
} | |
next_word_slash :: proc() -> string #no_bounds_check { | |
skip_whitespace(); | |
if stream[0] == '/' do stream = stream[1:]; // i/j or i/j/k | |
if stream[0] == '/' do stream = stream[1:]; // i//k | |
N := len(stream); | |
for i in 0..N-1 { | |
if is_whitespace(stream[i]) || stream[i] == '/' || i == len(stream)-1 { | |
current_word := stream[0:i]; | |
stream = stream[i:]; | |
return current_word; | |
} | |
} | |
return ""; | |
} | |
// loader, assumes a well formed file... | |
read_obj :: proc(filename: string) -> (Model_Data, bool) #no_bounds_check { | |
to_f32 :: strconv.parse_f32; | |
to_i32 :: proc(str: string) -> i32 do return cast(i32)strconv.parse_int(str); | |
data, status := os.read_entire_file(filename); | |
if !status do return Model_Data{}, false; | |
defer delete(data); | |
vertices: [dynamic][3]f32; | |
indices: [dynamic]i32; | |
first_face := true; | |
face_type: int; | |
stream = string(data); | |
for stream != "" { | |
current_word := next_word(); | |
switch current_word { | |
case "v": | |
v := append(&vertices, [3]f32{to_f32(next_word()), to_f32(next_word()), to_f32(next_word())}); | |
case "f": | |
if first_face { | |
old_stream := stream; | |
num_slashes := 0; | |
slashes: [2]int; | |
word := next_word(); | |
for c, i in word { | |
if c == '/' { | |
slashes[num_slashes] = i; | |
num_slashes += 1; | |
} | |
} | |
if num_slashes == 0 do face_type = 0; | |
if num_slashes == 1 do face_type = 1; | |
if num_slashes == 2 do face_type = slashes[1] == slashes[0]+1 ? 2 : 3; | |
type_desc := [?]string{"i", "i/j", "i//k", "i/j/k"}; | |
fmt.printf("Identified face formatting of type '%s'\n", type_desc[face_type]); | |
// reset stream to start | |
stream = old_stream; | |
first_face = false; | |
} | |
switch (face_type) { | |
case 0: // i: 0 | |
append(&indices, to_i32(next_word())-1, to_i32(next_word())-1, to_i32(next_word())-1); | |
case 1: // i/j: 1 | |
case 2: // i//k: 2 | |
append(&indices, to_i32(next_word_slash())-1); next_word_slash(); | |
append(&indices, to_i32(next_word_slash())-1); next_word_slash(); | |
append(&indices, to_i32(next_word_slash())-1); next_word_slash(); | |
case 3: // i/j/k: 3 | |
append(&indices, to_i32(next_word_slash())-1); next_word_slash(); next_word_slash(); | |
append(&indices, to_i32(next_word_slash())-1); next_word_slash(); next_word_slash(); | |
append(&indices, to_i32(next_word_slash())-1); next_word_slash(); next_word_slash(); | |
case: | |
fmt.printf("ERROR: should not have reached here. current_word = %v\n", current_word); | |
} | |
} | |
skip_line(); | |
} | |
return Model_Data{vertices[:], indices[:]}, true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment