I have two files, drone2.obj and drone2.mtl. I believe the .mtl file uses RGB color codes for the color instead of using .jpg/.png textures. Here's what drone2.obj looks like when I load it with 3D Builder and PyOpenGL:
I've read several tutorials( Youtube channels sentdex, atibyte, The Cherno). I also tried the website learnopengl.com, opengl-tutorial.org, and codeloop.com. I've also used Udemy. None of these specifically show how to load a model that uses RGB colors defined in the .mtl file. I'm not sure what keywords to use in order to find a tutorial on how to load these .mtl RGB values for the .obj file in OpenGL.
Can someone please help me properly load the .obj/.mtl colors in PyOpenGL? Here is my code and the .mtl values:
import glfw
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import pyrr
from ObjLoader import ObjLoader
vertex_src = """
# version 330
layout(location = 0) in vec3 a_position;
layout(location = 1) in vec2 a_texture;
layout(location = 2) in vec3 a_normal;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
out vec2 v_texture;
void main()
{
gl_Position = projection * view * model * vec4(a_position, 1.0);
v_texture = a_texture;
}
"""
fragment_src = """
# version 330
in vec2 v_texture;
out vec4 out_color;
uniform sampler2D s_texture;
void main()
{
out_color = texture(s_texture, v_texture);
}
"""
# glfw callback functions
def window_resize(window, width, height):
glViewport(0, 0, width, height)
projection = pyrr.matrix44.create_perspective_projection_matrix(45, width / height, 0.1, 100)
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
# initializing glfw library
if not glfw.init():
raise Exception("glfw can not be initialized!")
# creating the window
window = glfw.create_window(640, 480, "My OpenGL window", None, None)
# check if window was created
if not window:
glfw.terminate()
raise Exception("glfw window can not be created!")
# set window's position
glfw.set_window_pos(window, 400, 200)
# set the callback function for window resize
glfw.set_window_size_callback(window, window_resize)
# make the context current
glfw.make_context_current(window)
# load here the 3d meshes
drone_indices, drone_buffer = ObjLoader.load_model("drone2.obj")
shaderObj = compileProgram(compileShader(vertex_src, GL_VERTEX_SHADER), compileShader(fragment_src, GL_FRAGMENT_SHADER))
# VAO and VBO
VAO = glGenVertexArrays(2)
VBO = glGenBuffers(2)
# VAO
glBindVertexArray(VAO[0])
# Vertex Buffer Object
glBindBuffer(GL_ARRAY_BUFFER, VBO[0])
glBufferData(GL_ARRAY_BUFFER, drone_buffer.nbytes, drone_buffer, GL_STATIC_DRAW)
# vertices
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, drone_buffer.itemsize * 8, ctypes.c_void_p(0))
# textures
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, drone_buffer.itemsize * 8, ctypes.c_void_p(12))
# normals
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, drone_buffer.itemsize * 8, ctypes.c_void_p(20))
glEnableVertexAttribArray(2)
glUseProgram(shaderObj)
glClearColor(0, 0.1, 0.1, 1)
glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
projection = pyrr.matrix44.create_perspective_projection_matrix(45, 640 / 480, 0.1, 100)
#drone_pos = pyrr.matrix44.create_from_translation(pyrr.Vector3([0, -5, -10]))
drone_pos = pyrr.matrix44.create_from_translation(pyrr.Vector3([0, 0, 0]))
# eye, target, up
view = pyrr.matrix44.create_look_at(pyrr.Vector3([0, 0, 8]), pyrr.Vector3([0, 0, 0]), pyrr.Vector3([0, 1, 0]))
model_loc = glGetUniformLocation(shaderObj, "model")
proj_loc = glGetUniformLocation(shaderObj, "projection")
view_loc = glGetUniformLocation(shaderObj, "view")
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)
# the main application loop
while not glfw.window_should_close(window):
glfw.poll_events()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
rot_y = pyrr.Matrix44.from_y_rotation(0.8 * glfw.get_time())
model = pyrr.matrix44.multiply(rot_y, drone_pos)
# draw the drone character
glBindVertexArray(VAO[0])
glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
glDrawArrays(GL_TRIANGLES, 0, len(drone_indices))
glfw.swap_buffers(window)
# terminate glfw, free up allocated resources
glfw.terminate()
Here are the .mtl values:
# Blender MTL File: 'drone2.blend'
# Material Count: 6
newmtl drakgray
Ns 225.000000
Ka 0.800000 0.800000 0.800000
Kd 0.067358 0.067358 0.067358
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 3
newmtl flare
Ns 323.999994
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
newmtl gray
Ns 56.250000
Ka 0.200000 0.200000 0.200000
Kd 0.229457 0.229457 0.229457
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 3
newmtl red
Ns 323.999994
Ka 1.000000 1.000000 1.000000
Kd 0.287604 0.005644 0.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
newmtl silver
Ns 506.250000
Ka 1.000000 1.000000 1.000000
Kd 0.815288 0.815288 0.815288
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 3
newmtl white
Ns 81.000006
Ka 0.500000 0.500000 0.500000
Kd 0.668079 0.668079 0.668079
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 3
This is what the beginning of drone2.obj looks like:
# Blender v2.82 (sub 7) OBJ File: 'drone2.blend'
# www.blender.org
mtllib drone2.mtl
o Cylinder
v 0.848355 0.230875 -0.375419
v 0.921437 0.252606 -0.360946
<...>