Engine Code

This commit is contained in:
Exil Productions
2025-04-07 22:07:52 +02:00
committed by GitHub
parent b940113bf2
commit fb3b098299
16 changed files with 1147 additions and 0 deletions

128
engine/mesh.py Normal file
View File

@@ -0,0 +1,128 @@
from OpenGL.GL import *
import numpy as np
import open3d as o3d
import ctypes
class Mesh:
def __init__(self, o3d_mesh=None, vertices=None, indices=None, textures=None):
self.textures = textures if textures else []
self.VAO = glGenVertexArrays(1)
self.VBO = glGenBuffers(1)
self.EBO = glGenBuffers(1)
#if we use a mesh from open3d we should use vertices and indices
if o3d_mesh is not None:
self._init_from_open3d(o3d_mesh)
#if not just use the vertices and indices
elif vertices is not None and indices is not None:
self._init_from_arrays(vertices, indices)
else:
raise ValueError("Either an Open3D mesh or vertices and indices must be provided")
def _init_from_open3d(self, o3d_mesh):
if not o3d_mesh.has_vertex_normals():
o3d_mesh.compute_vertex_normals()
vertices = np.asarray(o3d_mesh.vertices)
normals = np.asarray(o3d_mesh.vertex_normals)
if o3d_mesh.has_triangle_uvs():
uvs = np.asarray(o3d_mesh.triangle_uvs)
#this is only some workaround though, still need to implement this right
if len(uvs) > 0:
tex_coords = np.zeros((len(vertices), 2), dtype=np.float32)
for i, triangle in enumerate(o3d_mesh.triangles):
for j in range(3):
tex_coords[triangle[j]] = uvs[i * 3 + j]
else:
tex_coords = np.zeros((len(vertices), 2), dtype=np.float32)
else:
tex_coords = np.zeros((len(vertices), 2), dtype=np.float32)
vertex_data = np.zeros((len(vertices), 8), dtype=np.float32)
vertex_data[:, 0:3] = vertices
vertex_data[:, 3:6] = normals
vertex_data[:, 6:8] = tex_coords
indices = np.asarray(o3d_mesh.triangles).flatten()
self._init_from_arrays(vertex_data, indices)
self.o3d_mesh = o3d_mesh
def _init_from_arrays(self, vertices, indices):
self.vertices = vertices
self.indices = indices
glBindVertexArray(self.VAO)
glBindBuffer(GL_ARRAY_BUFFER, self.VBO)
glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, GL_STATIC_DRAW)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.EBO)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.indices.nbytes, self.indices, GL_STATIC_DRAW)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * 4, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * 4, ctypes.c_void_p(3 * 4))
glEnableVertexAttribArray(1)
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * 4, ctypes.c_void_p(6 * 4))
glEnableVertexAttribArray(2)
glBindVertexArray(0)
@staticmethod
def create_box(width=1.0, height=1.0, depth=1.0):
box = o3d.geometry.TriangleMesh.create_box(width=width, height=height, depth=depth)
box.compute_vertex_normals()
return Mesh(o3d_mesh=box)
@staticmethod
def create_sphere(radius=1.0, resolution=20):
sphere = o3d.geometry.TriangleMesh.create_sphere(radius=radius, resolution=resolution)
sphere.compute_vertex_normals()
return Mesh(o3d_mesh=sphere)
@staticmethod
def create_cylinder(radius=1.0, height=2.0, resolution=20, split=4):
cylinder = o3d.geometry.TriangleMesh.create_cylinder(radius=radius, height=height, resolution=resolution,
split=split)
cylinder.compute_vertex_normals()
return Mesh(o3d_mesh=cylinder)
@staticmethod
def create_cone(radius=1.0, height=2.0, resolution=20, split=1):
cone = o3d.geometry.TriangleMesh.create_cone(radius=radius, height=height, resolution=resolution, split=split)
cone.compute_vertex_normals()
return Mesh(o3d_mesh=cone)
@staticmethod
def create_torus(torus_radius=1.0, tube_radius=0.2, radial_resolution=30, tubular_resolution=20):
torus = o3d.geometry.TriangleMesh.create_torus(torus_radius=torus_radius, tube_radius=tube_radius,
radial_resolution=radial_resolution,
tubular_resolution=tubular_resolution)
torus.compute_vertex_normals()
return Mesh(o3d_mesh=torus)
def draw(self, shader):
diffuse_nr = 1
specular_nr = 1
for i, texture in enumerate(self.textures):
glActiveTexture(GL_TEXTURE0 + i)
number = ""
name = texture.type
if name == "texture_diffuse":
number = str(diffuse_nr)
diffuse_nr += 1
elif name == "texture_specular":
number = str(specular_nr)
specular_nr += 1
shader.set_int(f"material.{name}{number}", i)
glBindTexture(GL_TEXTURE_2D, texture.id)
glBindVertexArray(self.VAO)
glDrawElements(GL_TRIANGLES, len(self.indices), GL_UNSIGNED_INT, None)
glBindVertexArray(0)
glActiveTexture(GL_TEXTURE0)