"""Binding strategies that upload CPU meshes to GPU representations."""
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any
from picogl.backend.geometry.legacy_mesh import LegacyMesh
from picogl.backend.geometry.mesh import GPUMesh
from picogl.backend.geometry.modern_mesh import ModernMesh
from picogl.backend.state import gl_value
if TYPE_CHECKING:
from picogl.renderer.meshdata import MeshData
[docs]
class GLBindingStrategy(ABC):
"""Upload CPU mesh data to a reusable :class:`GPUMesh`."""
def __init__(self):
[docs]
self._last_gpu_mesh: GPUMesh | None = None
@abstractmethod
[docs]
def upload(self, mesh: "MeshData") -> GPUMesh: ...
[docs]
def bind_mesh(self, mesh) -> None:
"""Deprecated: upload, bind, and remember mesh for the next draw."""
self._last_gpu_mesh = self.upload(mesh)
self._last_gpu_mesh.bind()
[docs]
def draw(self, mesh, mode) -> None:
"""Deprecated: draw the last bound mesh, or upload on demand."""
gpu_mesh = self._last_gpu_mesh
if gpu_mesh is None:
gpu_mesh = self.upload(mesh)
gpu_mesh.draw(gl_value(mode))
[docs]
class LegacyBinding(GLBindingStrategy):
"""Upload ``MeshData`` to a client-state :class:`LegacyMesh`."""
[docs]
def upload(self, mesh: "MeshData") -> GPUMesh:
return LegacyMesh(mesh)
[docs]
class ModernBinding(GLBindingStrategy):
"""Upload ``MeshData`` to a VAO-backed :class:`ModernMesh`."""
[docs]
def upload(self, mesh: "MeshData") -> GPUMesh:
from picogl.renderer.glmesh import GLMesh
gl_mesh = GLMesh.from_mesh_data(mesh)
gl_mesh.upload()
return ModernMesh(gl_mesh=gl_mesh)
[docs]
def upload_gpu_object(self, mesh: Any) -> GPUMesh:
"""Wrap an object that already has ``vao`` / ``ebo`` / ``index_count``."""
if hasattr(mesh, "vao") and mesh.vao is not None:
return ModernMesh(vao=mesh.vao, index_count=int(mesh.index_count))
if hasattr(mesh, "ebo") and mesh.ebo is not None:
return ModernMesh(vao=mesh, index_count=int(mesh.index_count))
return self.upload(mesh)
[docs]
def bind_mesh(self, mesh) -> None:
self._last_gpu_mesh = self.upload_gpu_object(mesh)
self._last_gpu_mesh.bind()