This repository has been archived on 2023-03-25. You can view files and clone it, but cannot push or open issues or pull requests.

113 lines
2.8 KiB
Python

from .geometry import Vector
import pygame
import OpenGL.GL as gl
import math
class Controls:
"""Abstract class for controls
"""
def __init__(self):
pass
def apply(self):
"""Apply the controls modification to the model view matrix
"""
pass
def update(self, time = 10):
"""Update according to the user's inputs
"""
pass
class TrackBallControls(Controls):
"""Trackball controls
Simple trackball controls"""
def __init__(self):
"""Creates a TrackBallControls
The trackball is centered at the origin
"""
super().__init__()
self.vertex = Vector()
self.theta = 0
def apply(self):
"""Apply the rotation of the current trackball
"""
gl.glRotatef(self.theta * 180 / math.pi, self.vertex.x, self.vertex.y, self.vertex.z)
def update(self, time = 10):
"""Checks the keyboard inputs and update the angle
"""
if not pygame.mouse.get_pressed()[0]:
return
coeff = 0.001
move = pygame.mouse.get_rel()
dV = Vector(move[1] * time * coeff, move[0] * time * coeff, 0)
dTheta = dV.norm2()
if abs(dTheta) < 0.00001:
return
dV.normalize()
cosT2 = math.cos(self.theta / 2)
sinT2 = math.sin(self.theta / 2)
cosDT2 = math.cos(dTheta / 2)
sinDT2 = math.sin(dTheta / 2)
A = cosT2 * sinDT2 * dV + cosDT2 * sinT2 * self.vertex + sinDT2 * sinT2 * Vector.cross_product(dV, self.vertex)
self.theta = 2 * math.acos(cosT2 * cosDT2 - sinT2 * sinDT2 * Vector.dot(dV, self.vertex))
self.vertex = A
self.vertex.normalize()
class OrbitControls(Controls):
"""Simple OrbitControls
Similar to TrackBallControls but the up vector is preserved"""
def __init__(self):
"""Creates an OrbitControls with null angles
"""
super().__init__()
self.phi = 0
self.theta = 0
self.scale_log = 0
def apply(self):
scale = math.exp(self.scale_log)
gl.glScalef(scale, scale, scale)
gl.glRotatef(self.theta * 180 / math.pi, 1.0, 0.0, 0.0)
gl.glRotatef(self.phi * 180 / math.pi, 0.0, 1.0, 0.0)
def apply_event(self, event):
"""Manages the wheel event
:param event: a pyevent
"""
if event.type == pygame.MOUSEBUTTONDOWN:
# Wheel up
if event.button == 4:
self.scale_log += 0.1
# Wheel down
elif event.button == 5:
self.scale_log -= 0.1
def update(self, time = 10):
if not pygame.mouse.get_pressed()[0]:
return
move = pygame.mouse.get_rel()
self.theta += move[1] * 0.01
self.phi += move[0] * 0.01
self.theta = max(min(self.theta, math.pi / 2), -math.pi / 2)