So i'm trying to a basic opengl program that reads in an .obj
file and then renders it (the obj file contains triangle vertices in the format v 1.000000 2.000000, 3.00000
.
So here's my code to do that (im using GLFW and a Golang binding library for it) (also im currently ignoring normals).
gl.Begin(gl.TRIANGLES)
for scanner.Scan() {
var v0, v1, v2 float32
t := strings.Split(scanner.Text(), " ")
line := scanner.Text()
fmt.Sscanf(line, "v %f %f %f", &v0, &v1, &v2)
if t[0] == "v" {
gl.Vertex3f(v0, v1, v2)
}
}
gl.End()
However when I go to run this the result isnt quite right
I tried it on a few other files I found around the internet and I get similar results. It almost seems like the triangles vertices are offset or something.
You should read all vertices data into array. Obj file contains information about triangles, and how vertices should be indexed. Lines starting with f
contains 3 numbers which describes triangles. So your code should look like this (I don't know go):
var vertices [1000*3] float32
for scanner.Scan() {
var i=0
var v0, v1, v2 float32
var vv byte
t := strings.Split(scanner.Text(), " ")
line := scanner.Text()
fmt.Sscanf(line, "%c %f %f %f", &vv, &v0, &v1, &v2)
if vv == "v" {
vertices[i] = v0
vertices[i+1] = v1
vertices[i+2] = v2
}
i = i+3
}
gl.Begin(gl.TRIANGLES)
for scanner.Scan() {
var v0, v1, v2 int
var vv byte
t := strings.Split(scanner.Text(), " ")
line := scanner.Text()
fmt.Sscanf(line, "%c %d %d %d", &vv, &v0, &v1, &v2)
if vv == "f" {
gl.Vertex3f(vertices[v0], vertices[v1], vertices[v2])
}
}
gl.End()
Obj files store in addition to the vertices (v-lines) also how they have to be combined into faces (f-lines). The vertices themself are stored without a particular ordering, which means that the first triangle is not necessarily composed of the vertices 0-2.
You will have to read all of the vertices into a vector/list/array and then parse the face entries which can be composed (according to here) in four different ways depending on which additional information (normals, texture coordinates) are additionally stored:
f v1 v2 v3 ...
f v1/vt1 v2/vt2 v3/vt3 ...
f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 ....
f v1//vn1 v2//vn2 v3//vn3 ...
where
v ... index into the list of v-entries
vt ... index into the list of vt-entries (texture coordinates)
vn ... index into the list of vn-entries (normals)
For your example, you will have to do something similar to this pseudocode (assuming that all faces are already triangulated)
v-list vertices[];
parse each v-line into v-list
foreach (f-line)
{
parse v-indices -> {v0, v1, v2}
draw triangle {vertices[v0], vertices[v1], vertices[v2]}
}