class ObjectManager: def __init__(self): self.console = None self.__objTemplatesWatingVertices_l = [] self.__objTemplatesWatingTextrue_l = [] self.__objectTemplates_d = {} self.bufferManager = BufferManager() self.texMan = TextureManager() self.__toHereQueue = Queue() self.__toProcessQueue = Queue() self.objectLoader = ObjectLoader(self.__toHereQueue, self.__toProcessQueue) self.__haveThingsToGetFromProcess_i = 0 def update(self) -> None: self.__fillObjectTemplateWithTexture() if self.__haveThingsToGetFromProcess_i: self.__popObjectBlueprintFromProcess() def terminate(self): try: self.objectLoader.terminate() except AttributeError: pass try: self.texMan.terminate() except AssertionError: pass def runProcesses(self): self.objectLoader.start() def requestObject(self, objInitInfo:"ObjectInitInfo") -> Optional[ds.Object]: self.update() if objInitInfo.objTemplateName_s in self.__objectTemplates_d.keys(): if self.__objectTemplates_d[objInitInfo.objTemplateName_s] is None: return None else: objTemplate = self.__objectTemplates_d[objInitInfo.objTemplateName_s] obj = objTemplate.makeObject( objInitInfo.name_s, objInitInfo.level, objInitInfo.initPos_t, objInitInfo.static_b, objInitInfo.colliders_l, objInitInfo.colGroupTargets_l ) self.console.appendLogs("Instancing object: {} ({})".format(objTemplate.templateName_s, objTemplate.refCount_i)) return obj else: print("Object never created:", objInitInfo.objTemplateName_s) raise FileNotFoundError def dumpObjects(self, objTempNames_l:list) -> None: for objTempName_s in objTempNames_l: objTemplate = self.__objectTemplates_d[objTempName_s] objTemplate.refCount_i -= 1 tempName_s = objTemplate.templateName_s self.console.appendLogs("Deleted an object instance: '{}' ({})".format(objTemplate.templateName_s, objTemplate.refCount_i)) if objTemplate.refCount_i <= 0: trashes_l = objTemplate.terminate() for trash_t in trashes_l: self.bufferManager.dumpVertexArray(trash_t[0]) self.bufferManager.dumpBuffer(trash_t[1]) self.bufferManager.dumpBuffer(trash_t[2]) self.bufferManager.dumpBuffer(trash_t[3]) self.texMan.dump(trash_t[4]) del self.__objectTemplates_d[objTempName_s], objTemplate self.console.appendLogs( "Deleted ObjectTemplate: '{}'".format(tempName_s) ) def giveObjectDefineBlueprint(self, objBprint:ObjectDefineBlueprint) -> None: if objBprint.name_s in self.__objectTemplates_d.keys(): if self.__objectTemplates_d[objBprint.name_s] is not None: raise FileExistsError(objBprint.name_s) else: self.__objectTemplates_d[objBprint.name_s] = None objTemp = ObjectTemplate( objBprint.name_s, [self.__makeRendererFromBprint(xx) for xx in objBprint.rendererBlueprints_l], objBprint.colliders_l, objBprint.boundingBox ) self.console.appendLogs("Created an object template: '{}'".format(objTemp.templateName_s)) self.__objTemplatesWatingTextrue_l.append(objTemp) def giveObjectObjStaticBlueprint(self, objBprint:ObjectObjStaticBlueprint) -> None: if objBprint.objFileName_s in self.__objectTemplates_d.keys(): return self.__objectTemplates_d[objBprint.objFileName_s] = None a = self.__findObjMtlDir(objBprint.objFileName_s) if a is None: self.console.appendLogs( "Failed to obj file: '{}'".format(objBprint.objFileName_s) ) else: self.__toProcessQueue.put( (objBprint.objFileName_s, *a) ) self.__haveThingsToGetFromProcess_i += 1 def __fillObjectTemplateWithTexture(self): for x in range(len(self.__objTemplatesWatingTextrue_l) - 1, -1, -1): failedCount_i = 0 objTemplate = self.__objTemplatesWatingTextrue_l[x] # ObjectTemplate for y in range(len(objTemplate.renderers_l) - 1, -1, -1): aRenderer = objTemplate.renderers_l[y] if aRenderer.diffuseMap_i is None: result = self.texMan.request(aRenderer.diffuseMapName_s) if result is None: failedCount_i += 1 continue else: aRenderer.diffuseMap_i = result continue else: pass if failedCount_i <= 0: self.__objectTemplates_d[objTemplate.templateName_s] = objTemplate del self.__objTemplatesWatingTextrue_l[x] def __popObjectBlueprintFromProcess(self): try: objBprint = self.__toHereQueue.get_nowait() except Empty: return None else: self.giveObjectDefineBlueprint(objBprint) def __makeRendererFromBprint(self, renBprint:RendererBlueprint) -> ds.Renderer: newRenderer = ds.Renderer(renBprint.name_s, renBprint.initPos_t, renBprint.static_b); vramUsage_i = 0; ######## VAO ######## newRenderer.vao_i = self.bufferManager.requestVertexArray(); gl.glBindVertexArray(newRenderer.vao_i); ######## Vertex buffer ######## size = renBprint.vertexNdarray.size * renBprint.vertexNdarray.itemsize; newRenderer.vertexSize_i = renBprint.vertexNdarray.size // 3; vramUsage_i += size; newRenderer.vertexArrayBuffer_i = self.bufferManager.requestBuffer(); gl.glBindBuffer(gl.GL_ARRAY_BUFFER, newRenderer.vertexArrayBuffer_i); gl.glBufferData(gl.GL_ARRAY_BUFFER, size, renBprint.vertexNdarray, gl.GL_STATIC_DRAW); gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, None) gl.glEnableVertexAttribArray(0); ######## Texture coord buffer ######## size = renBprint.texCoordNdarray.size * renBprint.texCoordNdarray.itemsize; vramUsage_i += size; newRenderer.textureArrayBuffer_i = self.bufferManager.requestBuffer(); gl.glBindBuffer(gl.GL_ARRAY_BUFFER, newRenderer.textureArrayBuffer_i); # Bind the buffer. gl.glBufferData(gl.GL_ARRAY_BUFFER, size, renBprint.texCoordNdarray, gl.GL_STATIC_DRAW); # Allocate memory. gl.glVertexAttribPointer(1, 2, gl.GL_FLOAT, gl.GL_FALSE, 0, None); # Defines vertex attributes. What are those? gl.glEnableVertexAttribArray(1); ######## ######## size = renBprint.normalNdarray.size * renBprint.normalNdarray.itemsize; vramUsage_i += size; newRenderer.normalArrayBuffe_i = self.bufferManager.requestBuffer(); gl.glBindBuffer(gl.GL_ARRAY_BUFFER, newRenderer.normalArrayBuffe_i); # Bind the buffer. gl.glBufferData(gl.GL_ARRAY_BUFFER, size, renBprint.normalNdarray, gl.GL_STATIC_DRAW); # Allocate memory. gl.glVertexAttribPointer(2, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, None); # Defines vertex attributes. What are those? gl.glEnableVertexAttribArray(2); ######## ######## newRenderer.diffuseMapName_s = renBprint.textureDir_s; newRenderer.textureVerNum_f = renBprint.textureVerNum_f; newRenderer.textureHorNum_f = renBprint.textureHorNum_f; newRenderer.shininess_f = renBprint.shininess_f; newRenderer.specularStrength_f = renBprint.specularStrength_f; newRenderer.vramUsage_i = vramUsage_i; return newRenderer; @staticmethod def __findObjMtlDir(objFileName_s:str) -> Optional[ Tuple[str, str] ]: objFileDir_s = "" mtlFileDir_s = "" for folderDir_s, _, files_l in os.walk(const.MODEL_DIR_s): for file_s in files_l: if objFileDir_s and mtlFileDir_s: break if file_s == objFileName_s + ".obj": if objFileDir_s: raise FileExistsError("There are multiple '{}' files.".format(objFileName_s)) else: objFileDir_s = "{}\\{}".format(folderDir_s, file_s) continue elif file_s == objFileName_s + ".mtl": if mtlFileDir_s: raise FileExistsError("There are multiple '{}' files.".format(mtlFileDir_s)) else: mtlFileDir_s = "{}\\{}".format(folderDir_s, file_s) continue if objFileDir_s and mtlFileDir_s: return objFileDir_s, mtlFileDir_s else: return None