model-converter-python/d3/controls.py

113 lines
2.8 KiB
Python
Raw Normal View History

2016-11-25 13:56:37 +00:00
from .geometry import Vector
2016-11-25 10:39:34 +00:00
import pygame
2016-11-25 14:03:03 +00:00
import OpenGL.GL as gl
2016-11-25 10:39:34 +00:00
import math
2016-11-25 10:27:05 +00:00
class Controls:
2017-01-18 13:10:16 +00:00
"""Abstract class for controls
"""
2016-11-25 10:27:05 +00:00
def __init__(self):
pass
def apply(self):
2017-01-18 13:10:16 +00:00
"""Apply the controls modification to the model view matrix
"""
2016-11-25 10:27:05 +00:00
pass
def update(self, time = 10):
2017-01-18 13:10:16 +00:00
"""Update according to the user's inputs
"""
2016-11-25 10:27:05 +00:00
pass
class TrackBallControls(Controls):
2017-01-18 13:10:16 +00:00
"""Trackball controls
Simple trackball controls"""
2016-11-25 10:27:05 +00:00
def __init__(self):
2017-01-18 13:10:16 +00:00
"""Creates a TrackBallControls
The trackball is centered at the origin
"""
2016-11-25 10:39:34 +00:00
super().__init__()
2016-11-25 13:56:37 +00:00
self.vertex = Vector()
2016-11-25 10:27:05 +00:00
self.theta = 0
def apply(self):
2017-01-18 13:10:16 +00:00
"""Apply the rotation of the current trackball
"""
2016-11-25 14:03:03 +00:00
gl.glRotatef(self.theta * 180 / math.pi, self.vertex.x, self.vertex.y, self.vertex.z)
2016-11-25 10:27:05 +00:00
def update(self, time = 10):
2017-01-18 13:10:16 +00:00
"""Checks the keyboard inputs and update the angle
"""
2016-11-25 10:27:05 +00:00
if not pygame.mouse.get_pressed()[0]:
return
coeff = 0.001
move = pygame.mouse.get_rel()
2016-11-25 13:56:37 +00:00
dV = Vector(move[1] * time * coeff, move[0] * time * coeff, 0)
2016-11-25 10:27:05 +00:00
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)
2016-11-25 13:56:37 +00:00
A = cosT2 * sinDT2 * dV + cosDT2 * sinT2 * self.vertex + sinDT2 * sinT2 * Vector.cross_product(dV, self.vertex)
2016-11-25 10:27:05 +00:00
2016-11-25 13:56:37 +00:00
self.theta = 2 * math.acos(cosT2 * cosDT2 - sinT2 * sinDT2 * Vector.dot(dV, self.vertex))
2016-11-25 10:27:05 +00:00
self.vertex = A
self.vertex.normalize()
2016-11-25 10:53:35 +00:00
class OrbitControls(Controls):
2017-01-18 13:10:16 +00:00
"""Simple OrbitControls
Similar to TrackBallControls but the up vector is preserved"""
2016-11-25 10:53:35 +00:00
def __init__(self):
2017-01-18 13:10:16 +00:00
"""Creates an OrbitControls with null angles
"""
2016-11-25 10:53:35 +00:00
super().__init__()
self.phi = 0
self.theta = 0
2016-12-01 12:50:04 +00:00
self.scale_log = 0
2016-11-25 10:27:05 +00:00
2016-11-25 14:41:52 +00:00
def apply(self):
2016-12-01 12:50:04 +00:00
scale = math.exp(self.scale_log)
gl.glScalef(scale, scale, scale)
2016-11-25 14:41:52 +00:00
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)
2016-12-01 09:55:41 +00:00
def apply_event(self, event):
2017-01-18 13:10:16 +00:00
"""Manages the wheel event
:param event: a pyevent
"""
2016-12-01 09:55:41 +00:00
if event.type == pygame.MOUSEBUTTONDOWN:
# Wheel up
if event.button == 4:
2016-12-01 12:50:04 +00:00
self.scale_log += 0.1
# Wheel down
2016-12-01 09:55:41 +00:00
elif event.button == 5:
2016-12-01 12:50:04 +00:00
self.scale_log -= 0.1
2016-12-01 09:55:41 +00:00
2016-11-25 14:41:52 +00:00
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)