#Current OBJLoader:
Became Hot Network Question
import numpy as np
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import os
import glm
from PIL import Image
class ObjLoader:
def __init__(self):
self.vert_coords: [float] = []
self.text_coords: [float] = []
self.norm_coords: [float] = []
self.object_parts = {}
self.setup_index()
self.obj_shaders()
def setup_index(self):
self.material_index: [int] = []
self.vertex_index: [int] = []
self.texture_index: [int] = []
self.normal_index: [int] = []
self.model = []
self.material_index = []
self.vertex_index = []
self.texture_index = []
self.normal_index = []
def load_model(self, file, *args):
for line in open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'v':
self.vert_coords.append(values[1:4])
if values[0] == 'vt':
self.text_coords.append(values[1:3])
if values[0] == 'vn':
self.norm_coords.append(values[1:4])
if values[0] == 'mtllib':
self.mtl = values[1]
materials=matarials = self.mat_in_file(file)
m_counter = 0
for line in open(file, 'r'): # open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'usemtl':
if values[1] != materials[m_counter][0]matarials[m_counter][0]:
self.define_i_t_u(file, materials[m_counter]matarials[m_counter], args)
m_counter += 1
self.setup_index()
if values[0] == 'f':
partsface_i = [[]
text_i = []
[
norm_i = []
int(w) - 1 for w in v.split('/')
for v in values[1:4]:
for w in= v.split('/')
]
for vface_i.append(int(w[0]) in- values[1:4]1)
]
self.vertex_indextext_i.append([part[0] for partint(w[1]) in- parts]1)
self.texture_index.append([part[1] for part in parts])
self.normal_indexnorm_i.append([part[2] for partint(w[2]) in- parts]1)
self.define_i_t_uvertex_index.append(file,face_i)
materials[m_counter], args self.texture_index.append(text_i)
self.normal_index.append(norm_i)
def get_vertices(values):
for v in values[1:4]:
yield int(vself.splitdefine_i_t_u('/')[0])file, -matarials[m_counter], 1args)
def define_i_t_u(self, file, mat, args):
self.vertex_index = [y for x in self.vertex_index for y in x]
self.texture_index = [y for x in self.texture_index for y in x]
self.normal_index = [y for x in self.normal_index for y in x]
for i in self.vertex_index:
self.model.extend(self.vert_coords[i])
for i in self.texture_index:
self.model.extend(self.text_coords[i])
for i in self.normal_index:
self.model.extend(self.norm_coords[i])
self.model = np.array(self.model, dtype='float32')
glUseProgram(mat[1])
texid = self.texture_materialMTL(file)
l_vao = self.vao_creator(self.vertex_index, self.model, mat[1], mat[2], texid, args)
self.object_parts["{0}".format(mat[0])] = l_vao
def texture_materialMTL(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
filepath = os.path.dirname(filename)
base = os.path.basename(filename)
file_only_name = os.path.splitext(base)[0]
contents = {}
mtl = None
image = None
texid = None
surf = None
values = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
mtl = contents[values[1]] = {}
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'map_Kd':
self.object_shader = self.shader_obj_text
# load the texture referred to by this declaration
mtl[values[0]] = values[1]
texid = mtl['texture_Kd'] = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texid)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR)
image = Image.open(os.path.join(filepath, mtl['map_Kd']))
flipped_image = image.transpose(Image.FLIP_TOP_BOTTOM)
img_data = flipped_image.convert("RGBA").tobytes()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
img_data)
return texid
def vao_creator(self, vertex_index, model, shader, defuse_col, texid, args):
texture_offset = len(vertex_index) * 12
VAO = glGenVertexArrays(1)
glBindVertexArray(VAO)
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, model.itemsize * len(model), model, GL_STATIC_DRAW)
# position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
# texture
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, model.itemsize * 2, ctypes.c_void_p(texture_offset))
glEnableVertexAttribArray(1)
# Normals
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(12))
glEnableVertexAttribArray(2)
# Instancing
if len(args) == 0:
amount = 1
vert_instance = np.array([
[0[[0.0, 0.0, 0.0]
, [1.0, 1.0, ]1.0]])
else:
amount = len(args)
vert_instance = np.array(args)
model_matricesmodelMatrices = []
# Storring the objects in a list
for i in range(0, amount):
mod_list = []
model_o = glm.mat4(1.0)
model_o = glm.translate(model_o, glm.vec3(vert_instance[i][0], vert_instance[i][1], vert_instance[i][2]))
# model_o = glm.scale(model_o, glm.vec3(0.00005, 0.00005, 0.00005))
for i in range(4):
for j in range(4):
mod_list.append(model_o[i][j])
model_matricesmodelMatrices.append(mod_list)
model_matricesmodelMatrices = np.array(model_matricesmodelMatrices, dtype="f")
instanceVBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO)
glBufferData(GL_ARRAY_BUFFER, amount * glm.sizeof(glm.mat4), model_matricesmodelMatrices, GL_STATIC_DRAW)
# Bind each vertex attrib array of matrices (4 vectors in Matrix)
glEnableVertexAttribArray(3)
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(0))
glEnableVertexAttribArray(4)
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(glm.sizeof(glm.vec4)))
glEnableVertexAttribArray(5)
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((2 * glm.sizeof(glm.vec4))))
glEnableVertexAttribArray(6)
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((3 * glm.sizeof(glm.vec4))))
# Set instancing
forglVertexAttribDivisor(3, i1)
in range glVertexAttribDivisor(34, 71):
glVertexAttribDivisor(5, 1)
glVertexAttribDivisor(i6, 1)
glBindVertexArray(0)
return ([VAO, len(vertex_index), shader, defuse_col, texid, len(vert_instance)])
def mat_in_file(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
mtl = None
contents = {}
mat_list = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
object_shader = self.shader_obj
mtl = contents[values[1]] = {}
matname = values[1]
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'Kd':
defuse_col = [float(values[1]), float(values[2]), float(values[3])]
elif values[0] == 'd':
defuse_col = defuse_col + [float(values[1])]
mat_list.append([matname, object_shader, defuse_col])
elif values[0] == 'map_Kd':
object_shader = self.shader_obj_text
mat_list.pop()
mat_list.append([matname, object_shader, defuse_col])
return mat_list
def load_obj(self):
obj_list = [self.object_parts[ind] for ind in self.object_parts]
return obj_list
def draw_call(self, vao_list, view, projection, model, *transf):
if len(transf) == 0:
transform = glm.mat4(1.0)
else:
transform = transf[0]
for key in vao_list:
VAO = key[0]
vertex_len = key[1]
shader = key[2]
d_colour = key[3]
texid = key[4]
len_instanced = key[5]
glUseProgram(shader)
glBindTexture(GL_TEXTURE_2D, texid)
view_loc = glGetUniformLocation(shader, "view")
proj_loc = glGetUniformLocation(shader, "projection")
model_loc = glGetUniformLocation(shader, "model")
col_loc = glGetUniformLocation(shader, "mycolor")
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
glUniform4fv(col_loc, 1, glm.value_ptr(glm.vec4(d_colour)))
transformLoc = glGetUniformLocation(shader, "transform")
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm.value_ptr(transform))
glBindVertexArray(VAO)
glDrawArraysInstanced(GL_TRIANGLES, 0, vertex_len, len_instanced)
glBindVertexArray(0)
def obj_shaders(self):
vertex_obj = """
# version 330
in layout(location = 0) vec3 position;
in layout(location = 1) vec2 textureCoords;
in layout(location = 2) vec3 normalCoords;
in layout (location = 3) mat4 instanceMatrix;
uniform mat4 transform;
uniform mat4 view;
uniform mat4 model;
uniform mat4 projection;
out vec2 newTexture;
out vec3 newNorm;
void main()
{
gl_Position = projection * view *instanceMatrix *model * transform *vec4(position, 1.0f);
newTexture = textureCoords;
newNorm = normalCoords;
}
"""
fragment_obj = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = mycolor;
}
"""
fragment_obj_text = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
in vec3 out_colours;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = texture(samplerTexture, newTexture);
}
"""
self.shader_obj = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj, GL_FRAGMENT_SHADER))
self.shader_obj_text = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj_text, GL_FRAGMENT_SHADER))
import numpy as np
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import os
import glm
from PIL import Image
class ObjLoader:
def __init__(self):
self.vert_coords: [float] = []
self.text_coords: [float] = []
self.norm_coords: [float] = []
self.object_parts = {}
self.setup_index()
self.obj_shaders()
def setup_index(self):
self.material_index: [int] = []
self.vertex_index: [int] = []
self.texture_index: [int] = []
self.normal_index: [int] = []
self.model = []
def load_model(self, file, *args):
for line in open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'v':
self.vert_coords.append(values[1:4])
if values[0] == 'vt':
self.text_coords.append(values[1:3])
if values[0] == 'vn':
self.norm_coords.append(values[1:4])
if values[0] == 'mtllib':
self.mtl = values[1]
materials= self.mat_in_file(file)
m_counter = 0
for line in open(file, 'r'): # open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'usemtl':
if values[1] != materials[m_counter][0]:
self.define_i_t_u(file, materials[m_counter], args)
m_counter += 1
self.setup_index()
if values[0] == 'f':
parts = [
[
int(w) - 1 for w in v.split('/')
for w in v.split('/')
]
for v in values[1:4]
]
self.vertex_index.append([part[0] for part in parts])
self.texture_index.append([part[1] for part in parts])
self.normal_index.append([part[2] for part in parts])
self.define_i_t_u(file, materials[m_counter], args)
def get_vertices(values):
for v in values[1:4]:
yield int(v.split('/')[0]) - 1
def define_i_t_u(self, file, mat, args):
self.vertex_index = [y for x in self.vertex_index for y in x]
self.texture_index = [y for x in self.texture_index for y in x]
self.normal_index = [y for x in self.normal_index for y in x]
for i in self.vertex_index:
self.model.extend(self.vert_coords[i])
for i in self.texture_index:
self.model.extend(self.text_coords[i])
for i in self.normal_index:
self.model.extend(self.norm_coords[i])
self.model = np.array(self.model, dtype='float32')
glUseProgram(mat[1])
texid = self.texture_material(file)
l_vao = self.vao_creator(self.vertex_index, self.model, mat[1], mat[2], texid, args)
self.object_parts["{0}".format(mat[0])] = l_vao
def texture_material(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
filepath = os.path.dirname(filename)
base = os.path.basename(filename)
file_only_name = os.path.splitext(base)[0]
contents = {}
mtl = None
image = None
texid = None
surf = None
values = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
mtl = contents[values[1]] = {}
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'map_Kd':
self.object_shader = self.shader_obj_text
# load the texture referred to by this declaration
mtl[values[0]] = values[1]
texid = mtl['texture_Kd'] = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texid)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR)
image = Image.open(os.path.join(filepath, mtl['map_Kd']))
flipped_image = image.transpose(Image.FLIP_TOP_BOTTOM)
img_data = flipped_image.convert("RGBA").tobytes()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
img_data)
return texid
def vao_creator(self, vertex_index, model, shader, defuse_col, texid, args):
texture_offset = len(vertex_index) * 12
VAO = glGenVertexArrays(1)
glBindVertexArray(VAO)
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, model.itemsize * len(model), model, GL_STATIC_DRAW)
# position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
# texture
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, model.itemsize * 2, ctypes.c_void_p(texture_offset))
glEnableVertexAttribArray(1)
# Normals
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(12))
glEnableVertexAttribArray(2)
# Instancing
if len(args) == 0:
amount = 1
vert_instance = np.array([
[0.0, 0.0, 0.0]
])
else:
amount = len(args)
vert_instance = np.array(args)
model_matrices = []
# Storring the objects in a list
for i in range(0, amount):
mod_list = []
model_o = glm.mat4(1.0)
model_o = glm.translate(model_o, glm.vec3(vert_instance[i][0], vert_instance[i][1], vert_instance[i][2]))
# model_o = glm.scale(model_o, glm.vec3(0.00005, 0.00005, 0.00005))
for i in range(4):
for j in range(4):
mod_list.append(model_o[i][j])
model_matrices.append(mod_list)
model_matrices = np.array(model_matrices, dtype="f")
instanceVBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO)
glBufferData(GL_ARRAY_BUFFER, amount * glm.sizeof(glm.mat4), model_matrices, GL_STATIC_DRAW)
# Bind each vertex attrib array of matrices (4 vectors in Matrix)
glEnableVertexAttribArray(3)
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(0))
glEnableVertexAttribArray(4)
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(glm.sizeof(glm.vec4)))
glEnableVertexAttribArray(5)
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((2 * glm.sizeof(glm.vec4))))
glEnableVertexAttribArray(6)
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((3 * glm.sizeof(glm.vec4))))
# Set instancing
for i in range(3, 7):
glVertexAttribDivisor(i, 1)
glBindVertexArray(0)
return ([VAO, len(vertex_index), shader, defuse_col, texid, len(vert_instance)])
def mat_in_file(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
mtl = None
contents = {}
mat_list = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
object_shader = self.shader_obj
mtl = contents[values[1]] = {}
matname = values[1]
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'Kd':
defuse_col = [float(values[1]), float(values[2]), float(values[3])]
elif values[0] == 'd':
defuse_col = defuse_col + [float(values[1])]
mat_list.append([matname, object_shader, defuse_col])
elif values[0] == 'map_Kd':
object_shader = self.shader_obj_text
mat_list.pop()
mat_list.append([matname, object_shader, defuse_col])
return mat_list
def load_obj(self):
obj_list = [self.object_parts[ind] for ind in self.object_parts]
return obj_list
def draw_call(self, vao_list, view, projection, model, *transf):
if len(transf) == 0:
transform = glm.mat4(1.0)
else:
transform = transf[0]
for key in vao_list:
VAO = key[0]
vertex_len = key[1]
shader = key[2]
d_colour = key[3]
texid = key[4]
len_instanced = key[5]
glUseProgram(shader)
glBindTexture(GL_TEXTURE_2D, texid)
view_loc = glGetUniformLocation(shader, "view")
proj_loc = glGetUniformLocation(shader, "projection")
model_loc = glGetUniformLocation(shader, "model")
col_loc = glGetUniformLocation(shader, "mycolor")
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
glUniform4fv(col_loc, 1, glm.value_ptr(glm.vec4(d_colour)))
transformLoc = glGetUniformLocation(shader, "transform")
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm.value_ptr(transform))
glBindVertexArray(VAO)
glDrawArraysInstanced(GL_TRIANGLES, 0, vertex_len, len_instanced)
glBindVertexArray(0)
def obj_shaders(self):
vertex_obj = """
# version 330
in layout(location = 0) vec3 position;
in layout(location = 1) vec2 textureCoords;
in layout(location = 2) vec3 normalCoords;
in layout (location = 3) mat4 instanceMatrix;
uniform mat4 transform;
uniform mat4 view;
uniform mat4 model;
uniform mat4 projection;
out vec2 newTexture;
out vec3 newNorm;
void main()
{
gl_Position = projection * view *instanceMatrix *model * transform *vec4(position, 1.0f);
newTexture = textureCoords;
newNorm = normalCoords;
}
"""
fragment_obj = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = mycolor;
}
"""
fragment_obj_text = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
in vec3 out_colours;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = texture(samplerTexture, newTexture);
}
"""
self.shader_obj = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj, GL_FRAGMENT_SHADER))
self.shader_obj_text = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj_text, GL_FRAGMENT_SHADER))
import numpy as np
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import os
import glm
from PIL import Image
class ObjLoader:
def __init__(self):
self.vert_coords = []
self.text_coords = []
self.norm_coords = []
self.object_parts = {}
self.setup_index()
self.obj_shaders()
def setup_index(self):
self.material_index = []
self.vertex_index = []
self.texture_index = []
self.normal_index = []
self.model = []
self.material_index = []
self.vertex_index = []
self.texture_index = []
self.normal_index = []
def load_model(self, file, *args):
for line in open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'v':
self.vert_coords.append(values[1:4])
if values[0] == 'vt':
self.text_coords.append(values[1:3])
if values[0] == 'vn':
self.norm_coords.append(values[1:4])
if values[0] == 'mtllib':
self.mtl = values[1]
matarials = self.mat_in_file(file)
m_counter = 0
for line in open(file, 'r'): # open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'usemtl':
if values[1] != matarials[m_counter][0]:
self.define_i_t_u(file, matarials[m_counter], args)
m_counter += 1
self.setup_index()
if values[0] == 'f':
face_i = []
text_i = []
norm_i = []
for v in values[1:4]:
w = v.split('/')
face_i.append(int(w[0]) - 1)
text_i.append(int(w[1]) - 1)
norm_i.append(int(w[2]) - 1)
self.vertex_index.append(face_i)
self.texture_index.append(text_i)
self.normal_index.append(norm_i)
self.define_i_t_u(file, matarials[m_counter], args)
def define_i_t_u(self, file, mat, args):
self.vertex_index = [y for x in self.vertex_index for y in x]
self.texture_index = [y for x in self.texture_index for y in x]
self.normal_index = [y for x in self.normal_index for y in x]
for i in self.vertex_index:
self.model.extend(self.vert_coords[i])
for i in self.texture_index:
self.model.extend(self.text_coords[i])
for i in self.normal_index:
self.model.extend(self.norm_coords[i])
self.model = np.array(self.model, dtype='float32')
glUseProgram(mat[1])
texid = self.MTL(file)
l_vao = self.vao_creator(self.vertex_index, self.model, mat[1], mat[2], texid, args)
self.object_parts["{0}".format(mat[0])] = l_vao
def MTL(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
filepath = os.path.dirname(filename)
base = os.path.basename(filename)
file_only_name = os.path.splitext(base)[0]
contents = {}
mtl = None
image = None
texid = None
surf = None
values = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
mtl = contents[values[1]] = {}
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'map_Kd':
self.object_shader = self.shader_obj_text
# load the texture referred to by this declaration
mtl[values[0]] = values[1]
texid = mtl['texture_Kd'] = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texid)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR)
image = Image.open(os.path.join(filepath, mtl['map_Kd']))
flipped_image = image.transpose(Image.FLIP_TOP_BOTTOM)
img_data = flipped_image.convert("RGBA").tobytes()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
img_data)
return texid
def vao_creator(self, vertex_index, model, shader, defuse_col, texid, args):
texture_offset = len(vertex_index) * 12
VAO = glGenVertexArrays(1)
glBindVertexArray(VAO)
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, model.itemsize * len(model), model, GL_STATIC_DRAW)
# position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
# texture
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, model.itemsize * 2, ctypes.c_void_p(texture_offset))
glEnableVertexAttribArray(1)
# Normals
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(12))
glEnableVertexAttribArray(2)
# Instancing
if len(args) == 0:
amount = 1
vert_instance = np.array([[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]])
else:
amount = len(args)
vert_instance = np.array(args)
modelMatrices = []
# Storring the objects in a list
for i in range(0, amount):
mod_list = []
model_o = glm.mat4(1.0)
model_o = glm.translate(model_o, glm.vec3(vert_instance[i][0], vert_instance[i][1], vert_instance[i][2]))
# model_o = glm.scale(model_o, glm.vec3(0.00005, 0.00005, 0.00005))
for i in range(4):
for j in range(4):
mod_list.append(model_o[i][j])
modelMatrices.append(mod_list)
modelMatrices = np.array(modelMatrices, dtype="f")
instanceVBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO)
glBufferData(GL_ARRAY_BUFFER, amount * glm.sizeof(glm.mat4), modelMatrices, GL_STATIC_DRAW)
# Bind each vertex attrib array of matrices (4 vectors in Matrix)
glEnableVertexAttribArray(3)
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(0))
glEnableVertexAttribArray(4)
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(glm.sizeof(glm.vec4)))
glEnableVertexAttribArray(5)
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((2 * glm.sizeof(glm.vec4))))
glEnableVertexAttribArray(6)
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((3 * glm.sizeof(glm.vec4))))
# Set instancing
glVertexAttribDivisor(3, 1)
glVertexAttribDivisor(4, 1)
glVertexAttribDivisor(5, 1)
glVertexAttribDivisor(6, 1)
glBindVertexArray(0)
return ([VAO, len(vertex_index), shader, defuse_col, texid, len(vert_instance)])
def mat_in_file(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
mtl = None
contents = {}
mat_list = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
object_shader = self.shader_obj
mtl = contents[values[1]] = {}
matname = values[1]
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'Kd':
defuse_col = [float(values[1]), float(values[2]), float(values[3])]
elif values[0] == 'd':
defuse_col = defuse_col + [float(values[1])]
mat_list.append([matname, object_shader, defuse_col])
elif values[0] == 'map_Kd':
object_shader = self.shader_obj_text
mat_list.pop()
mat_list.append([matname, object_shader, defuse_col])
return mat_list
def load_obj(self):
obj_list = [self.object_parts[ind] for ind in self.object_parts]
return obj_list
def draw_call(self, vao_list, view, projection, model, *transf):
if len(transf) == 0:
transform = glm.mat4(1.0)
else:
transform = transf[0]
for key in vao_list:
VAO = key[0]
vertex_len = key[1]
shader = key[2]
d_colour = key[3]
texid = key[4]
len_instanced = key[5]
glUseProgram(shader)
glBindTexture(GL_TEXTURE_2D, texid)
view_loc = glGetUniformLocation(shader, "view")
proj_loc = glGetUniformLocation(shader, "projection")
model_loc = glGetUniformLocation(shader, "model")
col_loc = glGetUniformLocation(shader, "mycolor")
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
glUniform4fv(col_loc, 1, glm.value_ptr(glm.vec4(d_colour)))
transformLoc = glGetUniformLocation(shader, "transform")
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm.value_ptr(transform))
glBindVertexArray(VAO)
glDrawArraysInstanced(GL_TRIANGLES, 0, vertex_len, len_instanced)
glBindVertexArray(0)
def obj_shaders(self):
vertex_obj = """
# version 330
in layout(location = 0) vec3 position;
in layout(location = 1) vec2 textureCoords;
in layout(location = 2) vec3 normalCoords;
in layout (location = 3) mat4 instanceMatrix;
uniform mat4 transform;
uniform mat4 view;
uniform mat4 model;
uniform mat4 projection;
out vec2 newTexture;
out vec3 newNorm;
void main()
{
gl_Position = projection * view *instanceMatrix *model * transform *vec4(position, 1.0f);
newTexture = textureCoords;
newNorm = normalCoords;
}
"""
fragment_obj = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = mycolor;
}
"""
fragment_obj_text = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
in vec3 out_colours;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = texture(samplerTexture, newTexture);
}
"""
self.shader_obj = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj, GL_FRAGMENT_SHADER))
self.shader_obj_text = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj_text, GL_FRAGMENT_SHADER))
import numpy as np
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import os
import glm
from PIL import Image
class ObjLoader:
def __init__(self):
self.vert_coords: [float] = []
self.text_coords: [float] = []
self.norm_coords: [float] = []
self.object_parts = {}
self.setup_index()
self.obj_shaders()
def setup_index(self):
self.material_index: [int] = []
self.vertex_index: [int] = []
self.texture_index: [int] = []
self.normal_index: [int] = []
self.model = []
self.material_index = []
self.vertex_index = []
self.texture_index = []
self.normal_index = []
def load_model(self, file, *args):
for line in open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'v':
self.vert_coords.append(values[1:4])
if values[0] == 'vt':
self.text_coords.append(values[1:3])
if values[0] == 'vn':
self.norm_coords.append(values[1:4])
if values[0] == 'mtllib':
self.mtl = values[1]
matarials =materials= self.mat_in_file(file)
m_counter = 0
for line in open(file, 'r'): # open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'usemtl':
if values[1] != matarials[m_counter][0]materials[m_counter][0]:
self.define_i_t_u(file, matarials[m_counter]materials[m_counter], args)
m_counter += 1
self.setup_index()
if values[0] == 'f':
face_iparts = [][
text_i = []
[
norm_i = []
int(w) - 1 for w in v.split('/')
for v in values[1:4]:
for w =in v.split('/')
face_i.append(int(w[0]) - 1)]
text_i.append(int(w[1]) - 1)
for v in values[1:4]
norm_i.append(int(w[2]) - 1)]
self.vertex_index.append(face_i[part[0] for part in parts])
self.texture_index.append(text_i[part[1] for part in parts])
self.normal_index.append(norm_i[part[2] for part in parts])
self.define_i_t_u(file, matarials[m_counter]materials[m_counter], args)
def get_vertices(values):
for v in values[1:4]:
yield int(v.split('/')[0]) - 1
def define_i_t_u(self, file, mat, args):
self.vertex_index = [y for x in self.vertex_index for y in x]
self.texture_index = [y for x in self.texture_index for y in x]
self.normal_index = [y for x in self.normal_index for y in x]
for i in self.vertex_index:
self.model.extend(self.vert_coords[i])
for i in self.texture_index:
self.model.extend(self.text_coords[i])
for i in self.normal_index:
self.model.extend(self.norm_coords[i])
self.model = np.array(self.model, dtype='float32')
glUseProgram(mat[1])
texid = self.MTLtexture_material(file)
l_vao = self.vao_creator(self.vertex_index, self.model, mat[1], mat[2], texid, args)
self.object_parts["{0}".format(mat[0])] = l_vao
def MTLtexture_material(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
filepath = os.path.dirname(filename)
base = os.path.basename(filename)
file_only_name = os.path.splitext(base)[0]
contents = {}
mtl = None
image = None
texid = None
surf = None
values = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
mtl = contents[values[1]] = {}
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'map_Kd':
self.object_shader = self.shader_obj_text
# load the texture referred to by this declaration
mtl[values[0]] = values[1]
texid = mtl['texture_Kd'] = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texid)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR)
image = Image.open(os.path.join(filepath, mtl['map_Kd']))
flipped_image = image.transpose(Image.FLIP_TOP_BOTTOM)
img_data = flipped_image.convert("RGBA").tobytes()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
img_data)
return texid
def vao_creator(self, vertex_index, model, shader, defuse_col, texid, args):
texture_offset = len(vertex_index) * 12
VAO = glGenVertexArrays(1)
glBindVertexArray(VAO)
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, model.itemsize * len(model), model, GL_STATIC_DRAW)
# position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
# texture
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, model.itemsize * 2, ctypes.c_void_p(texture_offset))
glEnableVertexAttribArray(1)
# Normals
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(12))
glEnableVertexAttribArray(2)
# Instancing
if len(args) == 0:
amount = 1
vert_instance = np.array([[0[
[0.0, 0.0, 0.0],
[1.0, 1.0, 1.0]] ])
else:
amount = len(args)
vert_instance = np.array(args)
modelMatricesmodel_matrices = []
# Storring the objects in a list
for i in range(0, amount):
mod_list = []
model_o = glm.mat4(1.0)
model_o = glm.translate(model_o, glm.vec3(vert_instance[i][0], vert_instance[i][1], vert_instance[i][2]))
# model_o = glm.scale(model_o, glm.vec3(0.00005, 0.00005, 0.00005))
for i in range(4):
for j in range(4):
mod_list.append(model_o[i][j])
modelMatricesmodel_matrices.append(mod_list)
modelMatricesmodel_matrices = np.array(modelMatricesmodel_matrices, dtype="f")
instanceVBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO)
glBufferData(GL_ARRAY_BUFFER, amount * glm.sizeof(glm.mat4), modelMatricesmodel_matrices, GL_STATIC_DRAW)
# Bind each vertex attrib array of matrices (4 vectors in Matrix)
glEnableVertexAttribArray(3)
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(0))
glEnableVertexAttribArray(4)
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(glm.sizeof(glm.vec4)))
glEnableVertexAttribArray(5)
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((2 * glm.sizeof(glm.vec4))))
glEnableVertexAttribArray(6)
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((3 * glm.sizeof(glm.vec4))))
# Set instancing
glVertexAttribDivisor(3, 1)
for i in glVertexAttribDivisorrange(43, 17):
glVertexAttribDivisor(5, 1)
glVertexAttribDivisor(6i, 1)
glBindVertexArray(0)
return ([VAO, len(vertex_index), shader, defuse_col, texid, len(vert_instance)])
def mat_in_file(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
mtl = None
contents = {}
mat_list = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
object_shader = self.shader_obj
mtl = contents[values[1]] = {}
matname = values[1]
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'Kd':
defuse_col = [float(values[1]), float(values[2]), float(values[3])]
elif values[0] == 'd':
defuse_col = defuse_col + [float(values[1])]
mat_list.append([matname, object_shader, defuse_col])
elif values[0] == 'map_Kd':
object_shader = self.shader_obj_text
mat_list.pop()
mat_list.append([matname, object_shader, defuse_col])
return mat_list
def load_obj(self):
obj_list = [self.object_parts[ind] for ind in self.object_parts]
return obj_list
def draw_call(self, vao_list, view, projection, model, *transf):
if len(transf) == 0:
transform = glm.mat4(1.0)
else:
transform = transf[0]
for key in vao_list:
VAO = key[0]
vertex_len = key[1]
shader = key[2]
d_colour = key[3]
texid = key[4]
len_instanced = key[5]
glUseProgram(shader)
glBindTexture(GL_TEXTURE_2D, texid)
view_loc = glGetUniformLocation(shader, "view")
proj_loc = glGetUniformLocation(shader, "projection")
model_loc = glGetUniformLocation(shader, "model")
col_loc = glGetUniformLocation(shader, "mycolor")
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
glUniform4fv(col_loc, 1, glm.value_ptr(glm.vec4(d_colour)))
transformLoc = glGetUniformLocation(shader, "transform")
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm.value_ptr(transform))
glBindVertexArray(VAO)
glDrawArraysInstanced(GL_TRIANGLES, 0, vertex_len, len_instanced)
glBindVertexArray(0)
def obj_shaders(self):
vertex_obj = """
# version 330
in layout(location = 0) vec3 position;
in layout(location = 1) vec2 textureCoords;
in layout(location = 2) vec3 normalCoords;
in layout (location = 3) mat4 instanceMatrix;
uniform mat4 transform;
uniform mat4 view;
uniform mat4 model;
uniform mat4 projection;
out vec2 newTexture;
out vec3 newNorm;
void main()
{
gl_Position = projection * view *instanceMatrix *model * transform *vec4(position, 1.0f);
newTexture = textureCoords;
newNorm = normalCoords;
}
"""
fragment_obj = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = mycolor;
}
"""
fragment_obj_text = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
in vec3 out_colours;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = texture(samplerTexture, newTexture);
}
"""
self.shader_obj = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj, GL_FRAGMENT_SHADER))
self.shader_obj_text = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj_text, GL_FRAGMENT_SHADER))
import numpy as np
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import os
import glm
from PIL import Image
class ObjLoader:
def __init__(self):
self.vert_coords = []
self.text_coords = []
self.norm_coords = []
self.object_parts = {}
self.setup_index()
self.obj_shaders()
def setup_index(self):
self.material_index = []
self.vertex_index = []
self.texture_index = []
self.normal_index = []
self.model = []
self.material_index = []
self.vertex_index = []
self.texture_index = []
self.normal_index = []
def load_model(self, file, *args):
for line in open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'v':
self.vert_coords.append(values[1:4])
if values[0] == 'vt':
self.text_coords.append(values[1:3])
if values[0] == 'vn':
self.norm_coords.append(values[1:4])
if values[0] == 'mtllib':
self.mtl = values[1]
matarials = self.mat_in_file(file)
m_counter = 0
for line in open(file, 'r'): # open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'usemtl':
if values[1] != matarials[m_counter][0]:
self.define_i_t_u(file, matarials[m_counter], args)
m_counter += 1
self.setup_index()
if values[0] == 'f':
face_i = []
text_i = []
norm_i = []
for v in values[1:4]:
w = v.split('/')
face_i.append(int(w[0]) - 1)
text_i.append(int(w[1]) - 1)
norm_i.append(int(w[2]) - 1)
self.vertex_index.append(face_i)
self.texture_index.append(text_i)
self.normal_index.append(norm_i)
self.define_i_t_u(file, matarials[m_counter], args)
def define_i_t_u(self, file, mat, args):
self.vertex_index = [y for x in self.vertex_index for y in x]
self.texture_index = [y for x in self.texture_index for y in x]
self.normal_index = [y for x in self.normal_index for y in x]
for i in self.vertex_index:
self.model.extend(self.vert_coords[i])
for i in self.texture_index:
self.model.extend(self.text_coords[i])
for i in self.normal_index:
self.model.extend(self.norm_coords[i])
self.model = np.array(self.model, dtype='float32')
glUseProgram(mat[1])
texid = self.MTL(file)
l_vao = self.vao_creator(self.vertex_index, self.model, mat[1], mat[2], texid, args)
self.object_parts["{0}".format(mat[0])] = l_vao
def MTL(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
filepath = os.path.dirname(filename)
base = os.path.basename(filename)
file_only_name = os.path.splitext(base)[0]
contents = {}
mtl = None
image = None
texid = None
surf = None
values = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
mtl = contents[values[1]] = {}
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'map_Kd':
self.object_shader = self.shader_obj_text
# load the texture referred to by this declaration
mtl[values[0]] = values[1]
texid = mtl['texture_Kd'] = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texid)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR)
image = Image.open(os.path.join(filepath, mtl['map_Kd']))
flipped_image = image.transpose(Image.FLIP_TOP_BOTTOM)
img_data = flipped_image.convert("RGBA").tobytes()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
img_data)
return texid
def vao_creator(self, vertex_index, model, shader, defuse_col, texid, args):
texture_offset = len(vertex_index) * 12
VAO = glGenVertexArrays(1)
glBindVertexArray(VAO)
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, model.itemsize * len(model), model, GL_STATIC_DRAW)
# position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
# texture
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, model.itemsize * 2, ctypes.c_void_p(texture_offset))
glEnableVertexAttribArray(1)
# Normals
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(12))
glEnableVertexAttribArray(2)
# Instancing
if len(args) == 0:
amount = 1
vert_instance = np.array([[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]])
else:
amount = len(args)
vert_instance = np.array(args)
modelMatrices = []
# Storring the objects in a list
for i in range(0, amount):
mod_list = []
model_o = glm.mat4(1.0)
model_o = glm.translate(model_o, glm.vec3(vert_instance[i][0], vert_instance[i][1], vert_instance[i][2]))
# model_o = glm.scale(model_o, glm.vec3(0.00005, 0.00005, 0.00005))
for i in range(4):
for j in range(4):
mod_list.append(model_o[i][j])
modelMatrices.append(mod_list)
modelMatrices = np.array(modelMatrices, dtype="f")
instanceVBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO)
glBufferData(GL_ARRAY_BUFFER, amount * glm.sizeof(glm.mat4), modelMatrices, GL_STATIC_DRAW)
# Bind each vertex attrib array of matrices (4 vectors in Matrix)
glEnableVertexAttribArray(3)
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(0))
glEnableVertexAttribArray(4)
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(glm.sizeof(glm.vec4)))
glEnableVertexAttribArray(5)
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((2 * glm.sizeof(glm.vec4))))
glEnableVertexAttribArray(6)
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((3 * glm.sizeof(glm.vec4))))
# Set instancing
glVertexAttribDivisor(3, 1)
glVertexAttribDivisor(4, 1)
glVertexAttribDivisor(5, 1)
glVertexAttribDivisor(6, 1)
glBindVertexArray(0)
return ([VAO, len(vertex_index), shader, defuse_col, texid, len(vert_instance)])
def mat_in_file(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
mtl = None
contents = {}
mat_list = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
object_shader = self.shader_obj
mtl = contents[values[1]] = {}
matname = values[1]
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'Kd':
defuse_col = [float(values[1]), float(values[2]), float(values[3])]
elif values[0] == 'd':
defuse_col = defuse_col + [float(values[1])]
mat_list.append([matname, object_shader, defuse_col])
elif values[0] == 'map_Kd':
object_shader = self.shader_obj_text
mat_list.pop()
mat_list.append([matname, object_shader, defuse_col])
return mat_list
def load_obj(self):
obj_list = [self.object_parts[ind] for ind in self.object_parts]
return obj_list
def draw_call(self, vao_list, view, projection, model, *transf):
if len(transf) == 0:
transform = glm.mat4(1.0)
else:
transform = transf[0]
for key in vao_list:
VAO = key[0]
vertex_len = key[1]
shader = key[2]
d_colour = key[3]
texid = key[4]
len_instanced = key[5]
glUseProgram(shader)
glBindTexture(GL_TEXTURE_2D, texid)
view_loc = glGetUniformLocation(shader, "view")
proj_loc = glGetUniformLocation(shader, "projection")
model_loc = glGetUniformLocation(shader, "model")
col_loc = glGetUniformLocation(shader, "mycolor")
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
glUniform4fv(col_loc, 1, glm.value_ptr(glm.vec4(d_colour)))
transformLoc = glGetUniformLocation(shader, "transform")
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm.value_ptr(transform))
glBindVertexArray(VAO)
glDrawArraysInstanced(GL_TRIANGLES, 0, vertex_len, len_instanced)
glBindVertexArray(0)
def obj_shaders(self):
vertex_obj = """
# version 330
in layout(location = 0) vec3 position;
in layout(location = 1) vec2 textureCoords;
in layout(location = 2) vec3 normalCoords;
in layout (location = 3) mat4 instanceMatrix;
uniform mat4 transform;
uniform mat4 view;
uniform mat4 model;
uniform mat4 projection;
out vec2 newTexture;
out vec3 newNorm;
void main()
{
gl_Position = projection * view *instanceMatrix *model * transform *vec4(position, 1.0f);
newTexture = textureCoords;
newNorm = normalCoords;
}
"""
fragment_obj = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = mycolor;
}
"""
fragment_obj_text = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
in vec3 out_colours;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = texture(samplerTexture, newTexture);
}
"""
self.shader_obj = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj, GL_FRAGMENT_SHADER))
self.shader_obj_text = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj_text, GL_FRAGMENT_SHADER))
import numpy as np
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import os
import glm
from PIL import Image
class ObjLoader:
def __init__(self):
self.vert_coords: [float] = []
self.text_coords: [float] = []
self.norm_coords: [float] = []
self.object_parts = {}
self.setup_index()
self.obj_shaders()
def setup_index(self):
self.material_index: [int] = []
self.vertex_index: [int] = []
self.texture_index: [int] = []
self.normal_index: [int] = []
self.model = []
def load_model(self, file, *args):
for line in open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'v':
self.vert_coords.append(values[1:4])
if values[0] == 'vt':
self.text_coords.append(values[1:3])
if values[0] == 'vn':
self.norm_coords.append(values[1:4])
if values[0] == 'mtllib':
self.mtl = values[1]
materials= self.mat_in_file(file)
m_counter = 0
for line in open(file, 'r'): # open(file, 'r'):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'usemtl':
if values[1] != materials[m_counter][0]:
self.define_i_t_u(file, materials[m_counter], args)
m_counter += 1
self.setup_index()
if values[0] == 'f':
parts = [
[
int(w) - 1 for w in v.split('/')
for w in v.split('/')
]
for v in values[1:4]
]
self.vertex_index.append([part[0] for part in parts])
self.texture_index.append([part[1] for part in parts])
self.normal_index.append([part[2] for part in parts])
self.define_i_t_u(file, materials[m_counter], args)
def get_vertices(values):
for v in values[1:4]:
yield int(v.split('/')[0]) - 1
def define_i_t_u(self, file, mat, args):
self.vertex_index = [y for x in self.vertex_index for y in x]
self.texture_index = [y for x in self.texture_index for y in x]
self.normal_index = [y for x in self.normal_index for y in x]
for i in self.vertex_index:
self.model.extend(self.vert_coords[i])
for i in self.texture_index:
self.model.extend(self.text_coords[i])
for i in self.normal_index:
self.model.extend(self.norm_coords[i])
self.model = np.array(self.model, dtype='float32')
glUseProgram(mat[1])
texid = self.texture_material(file)
l_vao = self.vao_creator(self.vertex_index, self.model, mat[1], mat[2], texid, args)
self.object_parts["{0}".format(mat[0])] = l_vao
def texture_material(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
filepath = os.path.dirname(filename)
base = os.path.basename(filename)
file_only_name = os.path.splitext(base)[0]
contents = {}
mtl = None
image = None
texid = None
surf = None
values = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
mtl = contents[values[1]] = {}
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'map_Kd':
self.object_shader = self.shader_obj_text
# load the texture referred to by this declaration
mtl[values[0]] = values[1]
texid = mtl['texture_Kd'] = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texid)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR)
image = Image.open(os.path.join(filepath, mtl['map_Kd']))
flipped_image = image.transpose(Image.FLIP_TOP_BOTTOM)
img_data = flipped_image.convert("RGBA").tobytes()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
img_data)
return texid
def vao_creator(self, vertex_index, model, shader, defuse_col, texid, args):
texture_offset = len(vertex_index) * 12
VAO = glGenVertexArrays(1)
glBindVertexArray(VAO)
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, model.itemsize * len(model), model, GL_STATIC_DRAW)
# position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
# texture
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, model.itemsize * 2, ctypes.c_void_p(texture_offset))
glEnableVertexAttribArray(1)
# Normals
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, model.itemsize * 3, ctypes.c_void_p(12))
glEnableVertexAttribArray(2)
# Instancing
if len(args) == 0:
amount = 1
vert_instance = np.array([
[0.0, 0.0, 0.0]
])
else:
amount = len(args)
vert_instance = np.array(args)
model_matrices = []
# Storring the objects in a list
for i in range(0, amount):
mod_list = []
model_o = glm.mat4(1.0)
model_o = glm.translate(model_o, glm.vec3(vert_instance[i][0], vert_instance[i][1], vert_instance[i][2]))
# model_o = glm.scale(model_o, glm.vec3(0.00005, 0.00005, 0.00005))
for i in range(4):
for j in range(4):
mod_list.append(model_o[i][j])
model_matrices.append(mod_list)
model_matrices = np.array(model_matrices, dtype="f")
instanceVBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO)
glBufferData(GL_ARRAY_BUFFER, amount * glm.sizeof(glm.mat4), model_matrices, GL_STATIC_DRAW)
# Bind each vertex attrib array of matrices (4 vectors in Matrix)
glEnableVertexAttribArray(3)
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(0))
glEnableVertexAttribArray(4)
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4), ctypes.c_void_p(glm.sizeof(glm.vec4)))
glEnableVertexAttribArray(5)
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((2 * glm.sizeof(glm.vec4))))
glEnableVertexAttribArray(6)
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, glm.sizeof(glm.mat4),
ctypes.c_void_p((3 * glm.sizeof(glm.vec4))))
# Set instancing
for i in range(3, 7):
glVertexAttribDivisor(i, 1)
glBindVertexArray(0)
return ([VAO, len(vertex_index), shader, defuse_col, texid, len(vert_instance)])
def mat_in_file(self, filename):
filename = os.path.splitext(filename)[0] + '.mtl'
mtl = None
contents = {}
mat_list = []
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'newmtl':
object_shader = self.shader_obj
mtl = contents[values[1]] = {}
matname = values[1]
elif mtl is None:
raise ValueError("mtl file doesn't start with newmtl stmt")
elif values[0] == 'Kd':
defuse_col = [float(values[1]), float(values[2]), float(values[3])]
elif values[0] == 'd':
defuse_col = defuse_col + [float(values[1])]
mat_list.append([matname, object_shader, defuse_col])
elif values[0] == 'map_Kd':
object_shader = self.shader_obj_text
mat_list.pop()
mat_list.append([matname, object_shader, defuse_col])
return mat_list
def load_obj(self):
obj_list = [self.object_parts[ind] for ind in self.object_parts]
return obj_list
def draw_call(self, vao_list, view, projection, model, *transf):
if len(transf) == 0:
transform = glm.mat4(1.0)
else:
transform = transf[0]
for key in vao_list:
VAO = key[0]
vertex_len = key[1]
shader = key[2]
d_colour = key[3]
texid = key[4]
len_instanced = key[5]
glUseProgram(shader)
glBindTexture(GL_TEXTURE_2D, texid)
view_loc = glGetUniformLocation(shader, "view")
proj_loc = glGetUniformLocation(shader, "projection")
model_loc = glGetUniformLocation(shader, "model")
col_loc = glGetUniformLocation(shader, "mycolor")
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
glUniform4fv(col_loc, 1, glm.value_ptr(glm.vec4(d_colour)))
transformLoc = glGetUniformLocation(shader, "transform")
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm.value_ptr(transform))
glBindVertexArray(VAO)
glDrawArraysInstanced(GL_TRIANGLES, 0, vertex_len, len_instanced)
glBindVertexArray(0)
def obj_shaders(self):
vertex_obj = """
# version 330
in layout(location = 0) vec3 position;
in layout(location = 1) vec2 textureCoords;
in layout(location = 2) vec3 normalCoords;
in layout (location = 3) mat4 instanceMatrix;
uniform mat4 transform;
uniform mat4 view;
uniform mat4 model;
uniform mat4 projection;
out vec2 newTexture;
out vec3 newNorm;
void main()
{
gl_Position = projection * view *instanceMatrix *model * transform *vec4(position, 1.0f);
newTexture = textureCoords;
newNorm = normalCoords;
}
"""
fragment_obj = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = mycolor;
}
"""
fragment_obj_text = """
#version 330
in vec2 newTexture;
in vec3 newNorm;
in vec3 out_colours;
uniform vec4 mycolor;
out vec4 outColor;
uniform sampler2D samplerTexture;
void main()
{
outColor = texture(samplerTexture, newTexture);
}
"""
self.shader_obj = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj, GL_FRAGMENT_SHADER))
self.shader_obj_text = compileProgram(compileShader(vertex_obj, GL_VERTEX_SHADER),
compileShader(fragment_obj_text, GL_FRAGMENT_SHADER))
Loading
Loading
lang-py