处理相机旋转的正确方法

Proper way to handle camera rotations

让我们从考虑 2 种类型的摄像机旋转开始:

相机围绕一个点旋转(Rails):

def rotate_around_target(self, target, delta):

  right = (self.target - self.eye).cross(self.up).normalize()

  amount = (right * delta.y + self.up * delta.x)

  self.target = target

  self.up = self.original_up

  self.eye = (

    mat4.rotatez(amount.z) *

    mat4.rotatey(amount.y) *

    mat4.rotatex(amount.x) *

    vec3(self.eye)

  )

def rotate_target(self, delta):

  right = (self.target - self.eye).cross(self.up).normalize()

  self.target = (

    mat4.translate(self.eye) *

    mat4().rotate(delta.y, right) *

    mat4().rotate(delta.x, self.up) *

    mat4.translate(-self.eye) *

    self.target

  )

def update(self, aspect):

  self.view = mat4.lookat(self.eye, self.target, self.up)

  self.projection = mat4.perspective_fovx(

    self.fov, aspect, self.near, self.far

  )

import math

from ctypes import c_void_p



import numpy as np

from OpenGL.GL import *

from OpenGL.GLU import *

from OpenGL.GLUT import *



import glm





class Camera():



  def __init__(

    self,

    eye=None, target=None, up=None,

    fov=None, near=0.1, far=100000

  ):

    self.eye = eye or glm.vec3(0, 0, 1)

    self.target = target or glm.vec3(0, 0, 0)

    self.up = up or glm.vec3(0, 1, 0)

    self.original_up = glm.vec3(self.up)

    self.fov = fov or glm.radians(45)

    self.near = near

    self.far = far



  def update(self, aspect):

    self.view = glm.lookAt(

      self.eye, self.target, self.up

    )

    self.projection = glm.perspective(

      self.fov, aspect, self.near, self.far

    )



  def rotate_target(self, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    M = glm.mat4(1)

    M = glm.translate(M, self.eye)

    M = glm.rotate(M, delta.y, right)

    M = glm.rotate(M, delta.x, self.up)

    M = glm.translate(M, -self.eye)

    self.target = glm.vec3(M * glm.vec4(self.target, 1.0))



  def rotate_around_target(self, target, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    amount = (right * delta.y + self.up * delta.x)

    M = glm.mat4(1)

    M = glm.rotate(M, amount.z, glm.vec3(0, 0, 1))

    M = glm.rotate(M, amount.y, glm.vec3(0, 1, 0))

    M = glm.rotate(M, amount.x, glm.vec3(1, 0, 0))

    self.eye = glm.vec3(M * glm.vec4(self.eye, 1.0))

    self.target = target

    self.up = self.original_up



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)





class GlutController():



  FPS = 0

  ORBIT = 1



  def __init__(self, camera, velocity=100, velocity_wheel=100):

    self.velocity = velocity

    self.velocity_wheel = velocity_wheel

    self.camera = camera



  def glut_mouse(self, button, state, x, y):

    self.mouse_last_pos = glm.vec2(x, y)

    self.mouse_down_pos = glm.vec2(x, y)



    if button == GLUT_LEFT_BUTTON:

      self.mode = self.FPS

    elif button == GLUT_RIGHT_BUTTON:

      self.mode = self.ORBIT



  def glut_motion(self, x, y):

    pos = glm.vec2(x, y)

    move = self.mouse_last_pos - pos

    self.mouse_last_pos = pos



    if self.mode == self.FPS:

      self.camera.rotate_target(move * 0.005)

    elif self.mode == self.ORBIT:

      self.camera.rotate_around_origin(move * 0.005)





class MyWindow:



  def __init__(self, w, h):

    self.width = w

    self.height = h



    glutInit()

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)

    glutInitWindowSize(w, h)

    glutCreateWindow('OpenGL Window')



    self.startup()



    glutReshapeFunc(self.reshape)

    glutDisplayFunc(self.display)

    glutMouseFunc(self.controller.glut_mouse)

    glutMotionFunc(self.controller.glut_motion)

    glutIdleFunc(self.idle_func)



  def startup(self):

    glEnable(GL_DEPTH_TEST)



    aspect = self.width / self.height

    self.camera = Camera(

      eye=glm.vec3(10, 10, 10),

      target=glm.vec3(0, 0, 0),

      up=glm.vec3(0, 1, 0)

    )

    self.model = glm.mat4(1)

    self.controller = GlutController(self.camera)



  def run(self):

    glutMainLoop()



  def idle_func(self):

    glutPostRedisplay()



  def reshape(self, w, h):

    glViewport(0, 0, w, h)

    self.width = w

    self.height = h



  def display(self):

    self.camera.update(self.width / self.height)



    glClearColor(0.2, 0.3, 0.3, 1.0)

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)



    glMatrixMode(GL_PROJECTION)

    glLoadIdentity()

    gluPerspective(glm.degrees(self.camera.fov), self.width / self.height, self.camera.near, self.camera.far)

    glMatrixMode(GL_MODELVIEW)

    glLoadIdentity()

    e = self.camera.eye

    t = self.camera.target

    u = self.camera.up

    gluLookAt(e.x, e.y, e.z, t.x, t.y, t.z, u.x, u.y, u.z)

    glColor3f(1, 1, 1)

    glBegin(GL_LINES)

    for i in range(-5, 6):

      if i == 0:

        continue

      glVertex3f(-5, 0, i)

      glVertex3f(5, 0, i)

      glVertex3f(i, 0, -5)

      glVertex3f(i, 0, 5)

    glEnd()



    glBegin(GL_LINES)

    glColor3f(1, 0, 0)

    glVertex3f(-5, 0, 0)

    glVertex3f(5, 0, 0)

    glColor3f(0, 1, 0)

    glVertex3f(0, -5, 0)

    glVertex3f(0, 5, 0)

    glColor3f(0, 0, 1)

    glVertex3f(0, 0, -5)

    glVertex3f(0, 0, 5)

    glEnd()



    glutSwapBuffers()





if __name__ == '__main__':

  window = MyWindow(800, 600)

  window.run()
V = glm.lookAt(self.eye, self.target, self.up)
pivot = glm.vec3(V * glm.vec4(target.x, target.y, target.z, 1))

axis = glm.vec3(-delta.y, -delta.x, 0)

angle = glm.length(delta)
R = glm.rotate( glm.mat4(1), angle, axis )

RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

NV = RP * VC = glm.inverse(NV)

targetDist = glm.length(self.target - self.eye)

self.eye  = glm.vec3(C[3])

self.target = self.eye - glm.vec3(C[2]) * targetDist 

self.up   = glm.vec3(C[1])

def rotate_around_target_view(self, target, delta):



  V = glm.lookAt(self.eye, self.target, self.up)



  pivot = glm.vec3(V * glm.vec4(target.x, target.y, target.z, 1))

  axis = glm.vec3(-delta.y, -delta.x, 0)

  angle = glm.length(delta)



  R = glm.rotate( glm.mat4(1), angle, axis )

  RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

  NV = RP * V



  C = glm.inverse(NV)

  targetDist = glm.length(self.target - self.eye)

  self.eye  = glm.vec3(C[3])

  self.target = self.eye - glm.vec3(C[2]) * targetDist 

  self.up   = glm.vec3(C[1])

def rotate_around_origin(self, delta):

  return self.rotate_around_target_view(glm.vec3(0), delta)



def rotate_target(self, delta):

  return self.rotate_around_target_view(self.eye, delta)

def rotate_around_target_world(self, target, delta):



  V = glm.lookAt(self.eye, self.target, self.up)



  pivot = target

  axis = glm.vec3(-delta.y, -delta.x, 0)

  angle = glm.length(delta)



  R = glm.rotate( glm.mat4(1), angle, axis )

  RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

  NV = V * RP



  C = glm.inverse(NV)

  targetDist = glm.length(self.target - self.eye)

  self.eye  = glm.vec3(C[3])

  self.target = self.eye - glm.vec3(C[2]) * targetDist 

  self.up   = glm.vec3(C[1]) 



def rotate_around_origin(self, delta):

  return self.rotate_around_target_world(glm.vec3(0), delta)

def rotate_around_target(self, target, delta):



  # get directions

  los  = self.target - self.eye

  losLen = glm.length(los)

  right = glm.normalize(glm.cross(los, self.up))

  up   = glm.cross(right, los)



  # upright up vector (Gram–Schmidt orthogonalization)

  fix_right = glm.normalize(glm.cross(los, self.original_up))

  UPdotX  = glm.dot(fix_right, up)

  up    = glm.normalize(up - UPdotX * fix_right)

  right   = glm.normalize(glm.cross(los, up))

  los    = glm.cross(up, right)



  # tilt around horizontal axis

  RHor = glm.rotate(glm.mat4(1), delta.y, right)

  up  = glm.vec3(RHor * glm.vec4(up, 0.0))

  los = glm.vec3(RHor * glm.vec4(los, 0.0))



  # rotate around up vector

  RUp  = glm.rotate(glm.mat4(1), delta.x, up)

  right = glm.vec3(RUp * glm.vec4(right, 0.0))

  los  = glm.vec3(RUp * glm.vec4(los, 0.0))



  # set eye, target and up

  self.eye  = target - los * losLen 

  self.target = target

  self.up   = up
from OpenGL.GL import *

from OpenGL.GLU import *

from OpenGL.GLUT import *



import glm





class Camera():



  def __init__(

    self,

    eye=None, target=None, up=None,

    fov=None, near=0.1, far=100000

  ):

    self.eye = eye or glm.vec3(0, 0, 1)

    self.target = target or glm.vec3(0, 0, 0)

    self.up = up or glm.vec3(0, 1, 0)

    self.original_up = glm.vec3(self.up)

    self.fov = fov or glm.radians(45)

    self.near = near

    self.far = far



  def update(self, aspect):

    self.view = glm.lookAt(

      self.eye, self.target, self.up

    )

    self.projection = glm.perspective(

      self.fov, aspect, self.near, self.far

    )



  def zoom(self, *args):

    delta = -args[1] * 0.1

    distance = glm.length(self.target - self.eye)

    self.eye = self.target + (self.eye - self.target) * (delta + 1)



  def load_projection(self):

    width = glutGet(GLUT_WINDOW_WIDTH)

    height = glutGet(GLUT_WINDOW_HEIGHT)



    glMatrixMode(GL_PROJECTION)

    glLoadIdentity()

    gluPerspective(glm.degrees(self.fov), width / height, self.near, self.far)



  def load_modelview(self):

    e = self.eye

    t = self.target

    u = self.up



    glMatrixMode(GL_MODELVIEW)

    glLoadIdentity()

    gluLookAt(e.x, e.y, e.z, t.x, t.y, t.z, u.x, u.y, u.z)





class CameraSkatic(Camera):



  def rotate_around_target(self, target, delta):

    M = glm.mat4(1)

    M = glm.rotate(M, delta.x, glm.vec3(0, 1, 0))

    M = glm.rotate(M, delta.y, glm.vec3(1, 0, 0))



    self.target = target

    T = glm.vec3(0, 0, glm.distance(self.target, self.eye))

    T = glm.vec3(M * glm.vec4(T, 0.0))

    self.eye = self.target + T

    self.up = glm.vec3(M * glm.vec4(self.original_up, 1.0))



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)





class CameraBPL(Camera):



  def rotate_target(self, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    M = glm.mat4(1)

    M = glm.translate(M, self.eye)

    M = glm.rotate(M, delta.y, right)

    M = glm.rotate(M, delta.x, self.up)

    M = glm.translate(M, -self.eye)

    self.target = glm.vec3(M * glm.vec4(self.target, 1.0))



  def rotate_around_target(self, target, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    amount = (right * delta.y + self.up * delta.x)

    M = glm.mat4(1)

    M = glm.rotate(M, amount.z, glm.vec3(0, 0, 1))

    M = glm.rotate(M, amount.y, glm.vec3(0, 1, 0))

    M = glm.rotate(M, amount.x, glm.vec3(1, 0, 0))

    self.eye = glm.vec3(M * glm.vec4(self.eye, 1.0))

    self.target = target

    self.up = self.original_up



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)





class CameraRabbid76_v1(Camera):



  def rotate_around_target_world(self, target, delta):

    V = glm.lookAt(self.eye, self.target, self.up)



    pivot = target

    axis = glm.vec3(-delta.y, -delta.x, 0)

    angle = glm.length(delta)



    R = glm.rotate(glm.mat4(1), angle, axis)

    RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

    NV = V * RP



    C = glm.inverse(NV)

    targetDist = glm.length(self.target - self.eye)

    self.eye = glm.vec3(C[3])

    self.target = self.eye - glm.vec3(C[2]) * targetDist

    self.up = glm.vec3(C[1])



  def rotate_around_target_view(self, target, delta):

    V = glm.lookAt(self.eye, self.target, self.up)



    pivot = glm.vec3(V * glm.vec4(target.x, target.y, target.z, 1))

    axis = glm.vec3(-delta.y, -delta.x, 0)

    angle = glm.length(delta)



    R = glm.rotate(glm.mat4(1), angle, axis)

    RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

    NV = RP * V



    C = glm.inverse(NV)

    targetDist = glm.length(self.target - self.eye)

    self.eye = glm.vec3(C[3])

    self.target = self.eye - glm.vec3(C[2]) * targetDist

    self.up = glm.vec3(C[1])



  def rotate_around_target(self, target, delta):

    if abs(delta.x) > 0:

      self.rotate_around_target_world(target, glm.vec3(delta.x, 0.0, 0.0))

    if abs(delta.y) > 0:

      self.rotate_around_target_view(target, glm.vec3(0.0, delta.y, 0.0))



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)



  def rotate_target(self, delta):

    return self.rotate_around_target(self.eye, delta)





class CameraRabbid76_v2(Camera):



  def rotate_around_target(self, target, delta):



    # get directions

    los = self.target - self.eye

    losLen = glm.length(los)

    right = glm.normalize(glm.cross(los, self.up))

    up = glm.cross(right, los)



    # upright up vector (Gram–Schmidt orthogonalization)

    fix_right = glm.normalize(glm.cross(los, self.original_up))

    UPdotX = glm.dot(fix_right, up)

    up = glm.normalize(up - UPdotX * fix_right)

    right = glm.normalize(glm.cross(los, up))

    los = glm.cross(up, right)



    # tilt around horizontal axis

    RHor = glm.rotate(glm.mat4(1), delta.y, right)

    up = glm.vec3(RHor * glm.vec4(up, 0.0))

    los = glm.vec3(RHor * glm.vec4(los, 0.0))



    # rotate around up vector

    RUp = glm.rotate(glm.mat4(1), delta.x, up)

    right = glm.vec3(RUp * glm.vec4(right, 0.0))

    los = glm.vec3(RUp * glm.vec4(los, 0.0))



    # set eye, target and up

    self.eye = target - los * losLen

    self.target = target

    self.up = up



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)



  def rotate_target(self, delta):

    return self.rotate_around_target(self.eye, delta)





class GlutController():



  FPS = 0

  ORBIT = 1



  def __init__(self, camera, velocity=100, velocity_wheel=100):

    self.velocity = velocity

    self.velocity_wheel = velocity_wheel

    self.camera = camera



  def glut_mouse(self, button, state, x, y):

    self.mouse_last_pos = glm.vec2(x, y)

    self.mouse_down_pos = glm.vec2(x, y)



    if button == GLUT_LEFT_BUTTON:

      self.mode = self.FPS

    elif button == GLUT_RIGHT_BUTTON:

      self.mode = self.ORBIT



  def glut_motion(self, x, y):

    pos = glm.vec2(x, y)

    move = self.mouse_last_pos - pos

    self.mouse_last_pos = pos



    if self.mode == self.FPS:

      self.camera.rotate_target(move * 0.005)

    elif self.mode == self.ORBIT:

      self.camera.rotate_around_origin(move * 0.005)



  def glut_mouse_wheel(self, *args):

    self.camera.zoom(*args)





def render_text(x, y, text):

  glColor3f(1, 1, 1)

  glRasterPos2f(x, y)

  glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, text.encode("utf-8"))





def draw_plane_yup():

  glColor3f(1, 1, 1)

  glBegin(GL_LINES)

  for i in range(-5, 6):

    if i == 0:

      continue

    glVertex3f(-5, 0, i)

    glVertex3f(5, 0, i)

    glVertex3f(i, 0, -5)

    glVertex3f(i, 0, 5)

  glEnd()



  glBegin(GL_LINES)

  glColor3f(1, 1, 1)

  glVertex3f(-5, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 0, -5)

  glVertex3f(0, 0, 0)



  glColor3f(1, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(5, 0, 0)

  glColor3f(0, 1, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 5, 0)

  glColor3f(0, 0, 1)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 0, 5)

  glEnd()





def draw_plane_zup():

  glColor3f(1, 1, 1)

  glBegin(GL_LINES)

  for i in range(-5, 6):

    if i == 0:

      continue

    glVertex3f(-5, 0, i)

    glVertex3f(5, 0, i)

    glVertex3f(i, -5, 0)

    glVertex3f(i, 5, 0)

  glEnd()



  glBegin(GL_LINES)

  glColor3f(1, 1, 1)

  glVertex3f(-5, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, -5, 0)

  glVertex3f(0, 0, 0)



  glColor3f(1, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(5, 0, 0)

  glColor3f(0, 1, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 0, 5)

  glColor3f(0, 0, 1)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 5, 0)

  glEnd()





def line(p0, p1, color=None):

  c = color or glm.vec3(1, 1, 1)

  glColor3f(c.x, c.y, c.z)

  glVertex3f(p0.x, p0.y, p0.z)

  glVertex3f(p1.x, p1.y, p1.z)





def grid(segment_count=10, spacing=1, yup=True):

  size = segment_count * spacing

  right = glm.vec3(1, 0, 0)

  forward = glm.vec3(0, 0, 1) if yup else glm.vec3(0, 1, 0)

  x_axis = right * size

  z_axis = forward * size



  data = []

  i = -segment_count



  glBegin(GL_LINES)

  while i <= segment_count:

    p0 = -x_axis + forward * i * spacing

    p1 = x_axis + forward * i * spacing

    line(p0, p1)

    p0 = -z_axis + right * i * spacing

    p1 = z_axis + right * i * spacing

    line(p0, p1)

    i += 1

  glEnd()





def axis(size=1.0, yup=True):

  right = glm.vec3(1, 0, 0)

  forward = glm.vec3(0, 0, 1) if yup else glm.vec3(0, 1, 0)

  x_axis = right * size

  z_axis = forward * size

  y_axis = glm.cross(forward, right) * size

  glBegin(GL_LINES)

  line(x_axis, glm.vec3(0, 0, 0), glm.vec3(1, 0, 0))

  line(y_axis, glm.vec3(0, 0, 0), glm.vec3(0, 1, 0))

  line(z_axis, glm.vec3(0, 0, 0), glm.vec3(0, 0, 1))

  glEnd()





class MyWindow:



  def __init__(self, w, h):

    self.width = w

    self.height = h



    glutInit()

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)

    glutInitWindowSize(w, h)

    glutCreateWindow('OpenGL Window')



    self.startup()



    glutReshapeFunc(self.reshape)

    glutDisplayFunc(self.display)

    glutMouseFunc(self.controller.glut_mouse)

    glutMotionFunc(self.controller.glut_motion)

    glutMouseWheelFunc(self.controller.glut_mouse_wheel)

    glutKeyboardFunc(self.keyboard_func)

    glutIdleFunc(self.idle_func)



  def keyboard_func(self, *args):

    try:

      key = args[0].decode("utf8")



      if key =="\\x1b":

        glutLeaveMainLoop()



      if key in ['1', '2', '3', '4']:

        if key == '1':

          self.index_camera ="Skatic"

        elif key == '2':

          self.index_camera ="BPL"

        elif key == '3':

          self.index_camera ="Rabbid76_v1"

        elif key == '4':

          self.index_camera ="Rabbid76_v2"



        self.camera = self.cameras[self.index_camera]

        self.controller.camera = self.camera



      if key in ['o', 'p']:

        self.camera.eye = glm.vec3(0, 10, 10)

        self.camera.target = glm.vec3(0, 0, 0)



        if key == 'o':

          self.yup = True

          # self.camera.up = glm.vec3(0, 0, 1)

        elif key == 'p':

          self.yup = False

          # self.camera.up = glm.vec3(0, 1, 0)



        self.camera.target = glm.vec3(0, 0, 0)



    except Exception as e:

      import traceback

      traceback.print_exc()



  def startup(self):

    glEnable(GL_DEPTH_TEST)



    aspect = self.width / self.height

    params = {

     "eye": glm.vec3(0, 100, 100),

     "target": glm.vec3(0, 0, 0),

     "up": glm.vec3(0, 1, 0)

    }

    self.cameras = {

     "Skatic": CameraSkatic(**params),

     "BPL": CameraBPL(**params),

     "Rabbid76_v1": CameraRabbid76_v1(**params),

     "Rabbid76_v2": CameraRabbid76_v2(**params)

    }

    self.index_camera ="BPL"

    self.yup = True

    self.camera = self.cameras[self.index_camera]

    self.model = glm.mat4(1)

    self.controller = GlutController(self.camera)



  def run(self):

    glutMainLoop()



  def idle_func(self):

    glutPostRedisplay()



  def reshape(self, w, h):

    glViewport(0, 0, w, h)

    self.width = w

    self.height = h



  def display(self):

    self.camera.update(self.width / self.height)



    glClearColor(0.2, 0.3, 0.3, 1.0)

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)



    self.camera.load_projection()

    self.camera.load_modelview()



    glLineWidth(5)

    axis(size=70, yup=self.yup)

    glLineWidth(1)

    grid(segment_count=7, spacing=10, yup=self.yup)



    glMatrixMode(GL_PROJECTION)

    glLoadIdentity()

    glOrtho(-1, 1, -1, 1, -1, 1)

    glMatrixMode(GL_MODELVIEW)

    glLoadIdentity()



    info ="\

".join([

     "1: Skatic Camera",

     "2: BPL Camera",

     "3: Rabbid76 Camera (version1)",

     "4: Rabbid76 Camera (version2)",

     "o: RHS Scene Y-UP",

     "p: RHS Scene Z-UP",

    ])

    render_text(-1.0, 1.0 - 0.1, info)

    render_text(-1.0, -1.0,"{} camera is active, scene is {}".format(self.index_camera,"Y-UP" if self.yup else"Z-UP"))



    glutSwapBuffers()





if __name__ == '__main__':

  window = MyWindow(800, 600)

  window.run()

# global variables somewhere appropriate (or class variables)

mouseX = 0.0

mouseY = 0.0

def rotate_around_target(self, target, delta):

  global mouseX

  global mouseY

  mouseX += delta.x/5.0

  mouseY += delta.y/5.0

  glm::mat4 M = glm::mat4(1)

  M = glm::rotate(M, delta.z, glm::vec3(0, 0, 1))

  M = glm::rotate(M, mouseX , glm::vec3(0, 1, 0))

  M = glm::rotate(M, mouseY, glm::vec3(1, 0, 0))
  self.target = target

  float distance = glm::distance(self.target, self.eye)

  glm::vec3 T = glm::vec3(0, 0, distance)

  T = glm::vec3(M*glm::vec4(T, 0.0f))
  self.eye = self.target + T  # assuming self.original_up = glm::vec3(0, 1, 0)

  self.up = glm::vec3(M*glm::vec4(self.original_up, 0.0f))

  # or

  self.up = glm::vec3(M*glm::vec4(glm::vec3(0, 1, 0), 0.0f))
  self.view = glm.lookAt( self.eye, self.target, self.up)

相机旋转目标(FPS)

def rotate_around_target(self, target, delta):

  right = (self.target - self.eye).cross(self.up).normalize()

  amount = (right * delta.y + self.up * delta.x)

  self.target = target

  self.up = self.original_up

  self.eye = (

    mat4.rotatez(amount.z) *

    mat4.rotatey(amount.y) *

    mat4.rotatex(amount.x) *

    vec3(self.eye)

  )

def rotate_target(self, delta):

  right = (self.target - self.eye).cross(self.up).normalize()

  self.target = (

    mat4.translate(self.eye) *

    mat4().rotate(delta.y, right) *

    mat4().rotate(delta.x, self.up) *

    mat4.translate(-self.eye) *

    self.target

  )

def update(self, aspect):

  self.view = mat4.lookat(self.eye, self.target, self.up)

  self.projection = mat4.perspective_fovx(

    self.fov, aspect, self.near, self.far

  )

import math

from ctypes import c_void_p



import numpy as np

from OpenGL.GL import *

from OpenGL.GLU import *

from OpenGL.GLUT import *



import glm





class Camera():



  def __init__(

    self,

    eye=None, target=None, up=None,

    fov=None, near=0.1, far=100000

  ):

    self.eye = eye or glm.vec3(0, 0, 1)

    self.target = target or glm.vec3(0, 0, 0)

    self.up = up or glm.vec3(0, 1, 0)

    self.original_up = glm.vec3(self.up)

    self.fov = fov or glm.radians(45)

    self.near = near

    self.far = far



  def update(self, aspect):

    self.view = glm.lookAt(

      self.eye, self.target, self.up

    )

    self.projection = glm.perspective(

      self.fov, aspect, self.near, self.far

    )



  def rotate_target(self, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    M = glm.mat4(1)

    M = glm.translate(M, self.eye)

    M = glm.rotate(M, delta.y, right)

    M = glm.rotate(M, delta.x, self.up)

    M = glm.translate(M, -self.eye)

    self.target = glm.vec3(M * glm.vec4(self.target, 1.0))



  def rotate_around_target(self, target, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    amount = (right * delta.y + self.up * delta.x)

    M = glm.mat4(1)

    M = glm.rotate(M, amount.z, glm.vec3(0, 0, 1))

    M = glm.rotate(M, amount.y, glm.vec3(0, 1, 0))

    M = glm.rotate(M, amount.x, glm.vec3(1, 0, 0))

    self.eye = glm.vec3(M * glm.vec4(self.eye, 1.0))

    self.target = target

    self.up = self.original_up



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)





class GlutController():



  FPS = 0

  ORBIT = 1



  def __init__(self, camera, velocity=100, velocity_wheel=100):

    self.velocity = velocity

    self.velocity_wheel = velocity_wheel

    self.camera = camera



  def glut_mouse(self, button, state, x, y):

    self.mouse_last_pos = glm.vec2(x, y)

    self.mouse_down_pos = glm.vec2(x, y)



    if button == GLUT_LEFT_BUTTON:

      self.mode = self.FPS

    elif button == GLUT_RIGHT_BUTTON:

      self.mode = self.ORBIT



  def glut_motion(self, x, y):

    pos = glm.vec2(x, y)

    move = self.mouse_last_pos - pos

    self.mouse_last_pos = pos



    if self.mode == self.FPS:

      self.camera.rotate_target(move * 0.005)

    elif self.mode == self.ORBIT:

      self.camera.rotate_around_origin(move * 0.005)





class MyWindow:



  def __init__(self, w, h):

    self.width = w

    self.height = h



    glutInit()

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)

    glutInitWindowSize(w, h)

    glutCreateWindow('OpenGL Window')



    self.startup()



    glutReshapeFunc(self.reshape)

    glutDisplayFunc(self.display)

    glutMouseFunc(self.controller.glut_mouse)

    glutMotionFunc(self.controller.glut_motion)

    glutIdleFunc(self.idle_func)



  def startup(self):

    glEnable(GL_DEPTH_TEST)



    aspect = self.width / self.height

    self.camera = Camera(

      eye=glm.vec3(10, 10, 10),

      target=glm.vec3(0, 0, 0),

      up=glm.vec3(0, 1, 0)

    )

    self.model = glm.mat4(1)

    self.controller = GlutController(self.camera)



  def run(self):

    glutMainLoop()



  def idle_func(self):

    glutPostRedisplay()



  def reshape(self, w, h):

    glViewport(0, 0, w, h)

    self.width = w

    self.height = h



  def display(self):

    self.camera.update(self.width / self.height)



    glClearColor(0.2, 0.3, 0.3, 1.0)

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)



    glMatrixMode(GL_PROJECTION)

    glLoadIdentity()

    gluPerspective(glm.degrees(self.camera.fov), self.width / self.height, self.camera.near, self.camera.far)

    glMatrixMode(GL_MODELVIEW)

    glLoadIdentity()

    e = self.camera.eye

    t = self.camera.target

    u = self.camera.up

    gluLookAt(e.x, e.y, e.z, t.x, t.y, t.z, u.x, u.y, u.z)

    glColor3f(1, 1, 1)

    glBegin(GL_LINES)

    for i in range(-5, 6):

      if i == 0:

        continue

      glVertex3f(-5, 0, i)

      glVertex3f(5, 0, i)

      glVertex3f(i, 0, -5)

      glVertex3f(i, 0, 5)

    glEnd()



    glBegin(GL_LINES)

    glColor3f(1, 0, 0)

    glVertex3f(-5, 0, 0)

    glVertex3f(5, 0, 0)

    glColor3f(0, 1, 0)

    glVertex3f(0, -5, 0)

    glVertex3f(0, 5, 0)

    glColor3f(0, 0, 1)

    glVertex3f(0, 0, -5)

    glVertex3f(0, 0, 5)

    glEnd()



    glutSwapBuffers()





if __name__ == '__main__':

  window = MyWindow(800, 600)

  window.run()
V = glm.lookAt(self.eye, self.target, self.up)
pivot = glm.vec3(V * glm.vec4(target.x, target.y, target.z, 1))

axis = glm.vec3(-delta.y, -delta.x, 0)

angle = glm.length(delta)
R = glm.rotate( glm.mat4(1), angle, axis )

RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

NV = RP * VC = glm.inverse(NV)

targetDist = glm.length(self.target - self.eye)

self.eye  = glm.vec3(C[3])

self.target = self.eye - glm.vec3(C[2]) * targetDist 

self.up   = glm.vec3(C[1])

def rotate_around_target_view(self, target, delta):



  V = glm.lookAt(self.eye, self.target, self.up)



  pivot = glm.vec3(V * glm.vec4(target.x, target.y, target.z, 1))

  axis = glm.vec3(-delta.y, -delta.x, 0)

  angle = glm.length(delta)



  R = glm.rotate( glm.mat4(1), angle, axis )

  RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

  NV = RP * V



  C = glm.inverse(NV)

  targetDist = glm.length(self.target - self.eye)

  self.eye  = glm.vec3(C[3])

  self.target = self.eye - glm.vec3(C[2]) * targetDist 

  self.up   = glm.vec3(C[1])

def rotate_around_origin(self, delta):

  return self.rotate_around_target_view(glm.vec3(0), delta)



def rotate_target(self, delta):

  return self.rotate_around_target_view(self.eye, delta)

def rotate_around_target_world(self, target, delta):



  V = glm.lookAt(self.eye, self.target, self.up)



  pivot = target

  axis = glm.vec3(-delta.y, -delta.x, 0)

  angle = glm.length(delta)



  R = glm.rotate( glm.mat4(1), angle, axis )

  RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

  NV = V * RP



  C = glm.inverse(NV)

  targetDist = glm.length(self.target - self.eye)

  self.eye  = glm.vec3(C[3])

  self.target = self.eye - glm.vec3(C[2]) * targetDist 

  self.up   = glm.vec3(C[1]) 



def rotate_around_origin(self, delta):

  return self.rotate_around_target_world(glm.vec3(0), delta)

def rotate_around_target(self, target, delta):



  # get directions

  los  = self.target - self.eye

  losLen = glm.length(los)

  right = glm.normalize(glm.cross(los, self.up))

  up   = glm.cross(right, los)



  # upright up vector (Gram–Schmidt orthogonalization)

  fix_right = glm.normalize(glm.cross(los, self.original_up))

  UPdotX  = glm.dot(fix_right, up)

  up    = glm.normalize(up - UPdotX * fix_right)

  right   = glm.normalize(glm.cross(los, up))

  los    = glm.cross(up, right)



  # tilt around horizontal axis

  RHor = glm.rotate(glm.mat4(1), delta.y, right)

  up  = glm.vec3(RHor * glm.vec4(up, 0.0))

  los = glm.vec3(RHor * glm.vec4(los, 0.0))



  # rotate around up vector

  RUp  = glm.rotate(glm.mat4(1), delta.x, up)

  right = glm.vec3(RUp * glm.vec4(right, 0.0))

  los  = glm.vec3(RUp * glm.vec4(los, 0.0))



  # set eye, target and up

  self.eye  = target - los * losLen 

  self.target = target

  self.up   = up
from OpenGL.GL import *

from OpenGL.GLU import *

from OpenGL.GLUT import *



import glm





class Camera():



  def __init__(

    self,

    eye=None, target=None, up=None,

    fov=None, near=0.1, far=100000

  ):

    self.eye = eye or glm.vec3(0, 0, 1)

    self.target = target or glm.vec3(0, 0, 0)

    self.up = up or glm.vec3(0, 1, 0)

    self.original_up = glm.vec3(self.up)

    self.fov = fov or glm.radians(45)

    self.near = near

    self.far = far



  def update(self, aspect):

    self.view = glm.lookAt(

      self.eye, self.target, self.up

    )

    self.projection = glm.perspective(

      self.fov, aspect, self.near, self.far

    )



  def zoom(self, *args):

    delta = -args[1] * 0.1

    distance = glm.length(self.target - self.eye)

    self.eye = self.target + (self.eye - self.target) * (delta + 1)



  def load_projection(self):

    width = glutGet(GLUT_WINDOW_WIDTH)

    height = glutGet(GLUT_WINDOW_HEIGHT)



    glMatrixMode(GL_PROJECTION)

    glLoadIdentity()

    gluPerspective(glm.degrees(self.fov), width / height, self.near, self.far)



  def load_modelview(self):

    e = self.eye

    t = self.target

    u = self.up



    glMatrixMode(GL_MODELVIEW)

    glLoadIdentity()

    gluLookAt(e.x, e.y, e.z, t.x, t.y, t.z, u.x, u.y, u.z)





class CameraSkatic(Camera):



  def rotate_around_target(self, target, delta):

    M = glm.mat4(1)

    M = glm.rotate(M, delta.x, glm.vec3(0, 1, 0))

    M = glm.rotate(M, delta.y, glm.vec3(1, 0, 0))



    self.target = target

    T = glm.vec3(0, 0, glm.distance(self.target, self.eye))

    T = glm.vec3(M * glm.vec4(T, 0.0))

    self.eye = self.target + T

    self.up = glm.vec3(M * glm.vec4(self.original_up, 1.0))



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)





class CameraBPL(Camera):



  def rotate_target(self, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    M = glm.mat4(1)

    M = glm.translate(M, self.eye)

    M = glm.rotate(M, delta.y, right)

    M = glm.rotate(M, delta.x, self.up)

    M = glm.translate(M, -self.eye)

    self.target = glm.vec3(M * glm.vec4(self.target, 1.0))



  def rotate_around_target(self, target, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    amount = (right * delta.y + self.up * delta.x)

    M = glm.mat4(1)

    M = glm.rotate(M, amount.z, glm.vec3(0, 0, 1))

    M = glm.rotate(M, amount.y, glm.vec3(0, 1, 0))

    M = glm.rotate(M, amount.x, glm.vec3(1, 0, 0))

    self.eye = glm.vec3(M * glm.vec4(self.eye, 1.0))

    self.target = target

    self.up = self.original_up



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)





class CameraRabbid76_v1(Camera):



  def rotate_around_target_world(self, target, delta):

    V = glm.lookAt(self.eye, self.target, self.up)



    pivot = target

    axis = glm.vec3(-delta.y, -delta.x, 0)

    angle = glm.length(delta)



    R = glm.rotate(glm.mat4(1), angle, axis)

    RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

    NV = V * RP



    C = glm.inverse(NV)

    targetDist = glm.length(self.target - self.eye)

    self.eye = glm.vec3(C[3])

    self.target = self.eye - glm.vec3(C[2]) * targetDist

    self.up = glm.vec3(C[1])



  def rotate_around_target_view(self, target, delta):

    V = glm.lookAt(self.eye, self.target, self.up)



    pivot = glm.vec3(V * glm.vec4(target.x, target.y, target.z, 1))

    axis = glm.vec3(-delta.y, -delta.x, 0)

    angle = glm.length(delta)



    R = glm.rotate(glm.mat4(1), angle, axis)

    RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

    NV = RP * V



    C = glm.inverse(NV)

    targetDist = glm.length(self.target - self.eye)

    self.eye = glm.vec3(C[3])

    self.target = self.eye - glm.vec3(C[2]) * targetDist

    self.up = glm.vec3(C[1])



  def rotate_around_target(self, target, delta):

    if abs(delta.x) > 0:

      self.rotate_around_target_world(target, glm.vec3(delta.x, 0.0, 0.0))

    if abs(delta.y) > 0:

      self.rotate_around_target_view(target, glm.vec3(0.0, delta.y, 0.0))



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)



  def rotate_target(self, delta):

    return self.rotate_around_target(self.eye, delta)





class CameraRabbid76_v2(Camera):



  def rotate_around_target(self, target, delta):



    # get directions

    los = self.target - self.eye

    losLen = glm.length(los)

    right = glm.normalize(glm.cross(los, self.up))

    up = glm.cross(right, los)



    # upright up vector (Gram–Schmidt orthogonalization)

    fix_right = glm.normalize(glm.cross(los, self.original_up))

    UPdotX = glm.dot(fix_right, up)

    up = glm.normalize(up - UPdotX * fix_right)

    right = glm.normalize(glm.cross(los, up))

    los = glm.cross(up, right)



    # tilt around horizontal axis

    RHor = glm.rotate(glm.mat4(1), delta.y, right)

    up = glm.vec3(RHor * glm.vec4(up, 0.0))

    los = glm.vec3(RHor * glm.vec4(los, 0.0))



    # rotate around up vector

    RUp = glm.rotate(glm.mat4(1), delta.x, up)

    right = glm.vec3(RUp * glm.vec4(right, 0.0))

    los = glm.vec3(RUp * glm.vec4(los, 0.0))



    # set eye, target and up

    self.eye = target - los * losLen

    self.target = target

    self.up = up



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)



  def rotate_target(self, delta):

    return self.rotate_around_target(self.eye, delta)





class GlutController():



  FPS = 0

  ORBIT = 1



  def __init__(self, camera, velocity=100, velocity_wheel=100):

    self.velocity = velocity

    self.velocity_wheel = velocity_wheel

    self.camera = camera



  def glut_mouse(self, button, state, x, y):

    self.mouse_last_pos = glm.vec2(x, y)

    self.mouse_down_pos = glm.vec2(x, y)



    if button == GLUT_LEFT_BUTTON:

      self.mode = self.FPS

    elif button == GLUT_RIGHT_BUTTON:

      self.mode = self.ORBIT



  def glut_motion(self, x, y):

    pos = glm.vec2(x, y)

    move = self.mouse_last_pos - pos

    self.mouse_last_pos = pos



    if self.mode == self.FPS:

      self.camera.rotate_target(move * 0.005)

    elif self.mode == self.ORBIT:

      self.camera.rotate_around_origin(move * 0.005)



  def glut_mouse_wheel(self, *args):

    self.camera.zoom(*args)





def render_text(x, y, text):

  glColor3f(1, 1, 1)

  glRasterPos2f(x, y)

  glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, text.encode("utf-8"))





def draw_plane_yup():

  glColor3f(1, 1, 1)

  glBegin(GL_LINES)

  for i in range(-5, 6):

    if i == 0:

      continue

    glVertex3f(-5, 0, i)

    glVertex3f(5, 0, i)

    glVertex3f(i, 0, -5)

    glVertex3f(i, 0, 5)

  glEnd()



  glBegin(GL_LINES)

  glColor3f(1, 1, 1)

  glVertex3f(-5, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 0, -5)

  glVertex3f(0, 0, 0)



  glColor3f(1, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(5, 0, 0)

  glColor3f(0, 1, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 5, 0)

  glColor3f(0, 0, 1)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 0, 5)

  glEnd()





def draw_plane_zup():

  glColor3f(1, 1, 1)

  glBegin(GL_LINES)

  for i in range(-5, 6):

    if i == 0:

      continue

    glVertex3f(-5, 0, i)

    glVertex3f(5, 0, i)

    glVertex3f(i, -5, 0)

    glVertex3f(i, 5, 0)

  glEnd()



  glBegin(GL_LINES)

  glColor3f(1, 1, 1)

  glVertex3f(-5, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, -5, 0)

  glVertex3f(0, 0, 0)



  glColor3f(1, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(5, 0, 0)

  glColor3f(0, 1, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 0, 5)

  glColor3f(0, 0, 1)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 5, 0)

  glEnd()





def line(p0, p1, color=None):

  c = color or glm.vec3(1, 1, 1)

  glColor3f(c.x, c.y, c.z)

  glVertex3f(p0.x, p0.y, p0.z)

  glVertex3f(p1.x, p1.y, p1.z)





def grid(segment_count=10, spacing=1, yup=True):

  size = segment_count * spacing

  right = glm.vec3(1, 0, 0)

  forward = glm.vec3(0, 0, 1) if yup else glm.vec3(0, 1, 0)

  x_axis = right * size

  z_axis = forward * size



  data = []

  i = -segment_count



  glBegin(GL_LINES)

  while i <= segment_count:

    p0 = -x_axis + forward * i * spacing

    p1 = x_axis + forward * i * spacing

    line(p0, p1)

    p0 = -z_axis + right * i * spacing

    p1 = z_axis + right * i * spacing

    line(p0, p1)

    i += 1

  glEnd()





def axis(size=1.0, yup=True):

  right = glm.vec3(1, 0, 0)

  forward = glm.vec3(0, 0, 1) if yup else glm.vec3(0, 1, 0)

  x_axis = right * size

  z_axis = forward * size

  y_axis = glm.cross(forward, right) * size

  glBegin(GL_LINES)

  line(x_axis, glm.vec3(0, 0, 0), glm.vec3(1, 0, 0))

  line(y_axis, glm.vec3(0, 0, 0), glm.vec3(0, 1, 0))

  line(z_axis, glm.vec3(0, 0, 0), glm.vec3(0, 0, 1))

  glEnd()





class MyWindow:



  def __init__(self, w, h):

    self.width = w

    self.height = h



    glutInit()

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)

    glutInitWindowSize(w, h)

    glutCreateWindow('OpenGL Window')



    self.startup()



    glutReshapeFunc(self.reshape)

    glutDisplayFunc(self.display)

    glutMouseFunc(self.controller.glut_mouse)

    glutMotionFunc(self.controller.glut_motion)

    glutMouseWheelFunc(self.controller.glut_mouse_wheel)

    glutKeyboardFunc(self.keyboard_func)

    glutIdleFunc(self.idle_func)



  def keyboard_func(self, *args):

    try:

      key = args[0].decode("utf8")



      if key =="\\x1b":

        glutLeaveMainLoop()



      if key in ['1', '2', '3', '4']:

        if key == '1':

          self.index_camera ="Skatic"

        elif key == '2':

          self.index_camera ="BPL"

        elif key == '3':

          self.index_camera ="Rabbid76_v1"

        elif key == '4':

          self.index_camera ="Rabbid76_v2"



        self.camera = self.cameras[self.index_camera]

        self.controller.camera = self.camera



      if key in ['o', 'p']:

        self.camera.eye = glm.vec3(0, 10, 10)

        self.camera.target = glm.vec3(0, 0, 0)



        if key == 'o':

          self.yup = True

          # self.camera.up = glm.vec3(0, 0, 1)

        elif key == 'p':

          self.yup = False

          # self.camera.up = glm.vec3(0, 1, 0)



        self.camera.target = glm.vec3(0, 0, 0)



    except Exception as e:

      import traceback

      traceback.print_exc()



  def startup(self):

    glEnable(GL_DEPTH_TEST)



    aspect = self.width / self.height

    params = {

     "eye": glm.vec3(0, 100, 100),

     "target": glm.vec3(0, 0, 0),

     "up": glm.vec3(0, 1, 0)

    }

    self.cameras = {

     "Skatic": CameraSkatic(**params),

     "BPL": CameraBPL(**params),

     "Rabbid76_v1": CameraRabbid76_v1(**params),

     "Rabbid76_v2": CameraRabbid76_v2(**params)

    }

    self.index_camera ="BPL"

    self.yup = True

    self.camera = self.cameras[self.index_camera]

    self.model = glm.mat4(1)

    self.controller = GlutController(self.camera)



  def run(self):

    glutMainLoop()



  def idle_func(self):

    glutPostRedisplay()



  def reshape(self, w, h):

    glViewport(0, 0, w, h)

    self.width = w

    self.height = h



  def display(self):

    self.camera.update(self.width / self.height)



    glClearColor(0.2, 0.3, 0.3, 1.0)

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)



    self.camera.load_projection()

    self.camera.load_modelview()



    glLineWidth(5)

    axis(size=70, yup=self.yup)

    glLineWidth(1)

    grid(segment_count=7, spacing=10, yup=self.yup)



    glMatrixMode(GL_PROJECTION)

    glLoadIdentity()

    glOrtho(-1, 1, -1, 1, -1, 1)

    glMatrixMode(GL_MODELVIEW)

    glLoadIdentity()



    info ="\

".join([

     "1: Skatic Camera",

     "2: BPL Camera",

     "3: Rabbid76 Camera (version1)",

     "4: Rabbid76 Camera (version2)",

     "o: RHS Scene Y-UP",

     "p: RHS Scene Z-UP",

    ])

    render_text(-1.0, 1.0 - 0.1, info)

    render_text(-1.0, -1.0,"{} camera is active, scene is {}".format(self.index_camera,"Y-UP" if self.yup else"Z-UP"))



    glutSwapBuffers()





if __name__ == '__main__':

  window = MyWindow(800, 600)

  window.run()

# global variables somewhere appropriate (or class variables)

mouseX = 0.0

mouseY = 0.0

def rotate_around_target(self, target, delta):

  global mouseX

  global mouseY

  mouseX += delta.x/5.0

  mouseY += delta.y/5.0

  glm::mat4 M = glm::mat4(1)

  M = glm::rotate(M, delta.z, glm::vec3(0, 0, 1))

  M = glm::rotate(M, mouseX , glm::vec3(0, 1, 0))

  M = glm::rotate(M, mouseY, glm::vec3(1, 0, 0))
  self.target = target

  float distance = glm::distance(self.target, self.eye)

  glm::vec3 T = glm::vec3(0, 0, distance)

  T = glm::vec3(M*glm::vec4(T, 0.0f))
  self.eye = self.target + T  # assuming self.original_up = glm::vec3(0, 1, 0)

  self.up = glm::vec3(M*glm::vec4(self.original_up, 0.0f))

  # or

  self.up = glm::vec3(M*glm::vec4(glm::vec3(0, 1, 0), 0.0f))
  self.view = glm.lookAt( self.eye, self.target, self.up)

然后只是一个更新函数,其中投影/视图矩阵是从眼睛/目标/向上相机向量中计算出来的:

def rotate_around_target(self, target, delta):

  right = (self.target - self.eye).cross(self.up).normalize()

  amount = (right * delta.y + self.up * delta.x)

  self.target = target

  self.up = self.original_up

  self.eye = (

    mat4.rotatez(amount.z) *

    mat4.rotatey(amount.y) *

    mat4.rotatex(amount.x) *

    vec3(self.eye)

  )

def rotate_target(self, delta):

  right = (self.target - self.eye).cross(self.up).normalize()

  self.target = (

    mat4.translate(self.eye) *

    mat4().rotate(delta.y, right) *

    mat4().rotate(delta.x, self.up) *

    mat4.translate(-self.eye) *

    self.target

  )

def update(self, aspect):

  self.view = mat4.lookat(self.eye, self.target, self.up)

  self.projection = mat4.perspective_fovx(

    self.fov, aspect, self.near, self.far

  )

import math

from ctypes import c_void_p



import numpy as np

from OpenGL.GL import *

from OpenGL.GLU import *

from OpenGL.GLUT import *



import glm





class Camera():



  def __init__(

    self,

    eye=None, target=None, up=None,

    fov=None, near=0.1, far=100000

  ):

    self.eye = eye or glm.vec3(0, 0, 1)

    self.target = target or glm.vec3(0, 0, 0)

    self.up = up or glm.vec3(0, 1, 0)

    self.original_up = glm.vec3(self.up)

    self.fov = fov or glm.radians(45)

    self.near = near

    self.far = far



  def update(self, aspect):

    self.view = glm.lookAt(

      self.eye, self.target, self.up

    )

    self.projection = glm.perspective(

      self.fov, aspect, self.near, self.far

    )



  def rotate_target(self, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    M = glm.mat4(1)

    M = glm.translate(M, self.eye)

    M = glm.rotate(M, delta.y, right)

    M = glm.rotate(M, delta.x, self.up)

    M = glm.translate(M, -self.eye)

    self.target = glm.vec3(M * glm.vec4(self.target, 1.0))



  def rotate_around_target(self, target, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    amount = (right * delta.y + self.up * delta.x)

    M = glm.mat4(1)

    M = glm.rotate(M, amount.z, glm.vec3(0, 0, 1))

    M = glm.rotate(M, amount.y, glm.vec3(0, 1, 0))

    M = glm.rotate(M, amount.x, glm.vec3(1, 0, 0))

    self.eye = glm.vec3(M * glm.vec4(self.eye, 1.0))

    self.target = target

    self.up = self.original_up



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)





class GlutController():



  FPS = 0

  ORBIT = 1



  def __init__(self, camera, velocity=100, velocity_wheel=100):

    self.velocity = velocity

    self.velocity_wheel = velocity_wheel

    self.camera = camera



  def glut_mouse(self, button, state, x, y):

    self.mouse_last_pos = glm.vec2(x, y)

    self.mouse_down_pos = glm.vec2(x, y)



    if button == GLUT_LEFT_BUTTON:

      self.mode = self.FPS

    elif button == GLUT_RIGHT_BUTTON:

      self.mode = self.ORBIT



  def glut_motion(self, x, y):

    pos = glm.vec2(x, y)

    move = self.mouse_last_pos - pos

    self.mouse_last_pos = pos



    if self.mode == self.FPS:

      self.camera.rotate_target(move * 0.005)

    elif self.mode == self.ORBIT:

      self.camera.rotate_around_origin(move * 0.005)





class MyWindow:



  def __init__(self, w, h):

    self.width = w

    self.height = h



    glutInit()

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)

    glutInitWindowSize(w, h)

    glutCreateWindow('OpenGL Window')



    self.startup()



    glutReshapeFunc(self.reshape)

    glutDisplayFunc(self.display)

    glutMouseFunc(self.controller.glut_mouse)

    glutMotionFunc(self.controller.glut_motion)

    glutIdleFunc(self.idle_func)



  def startup(self):

    glEnable(GL_DEPTH_TEST)



    aspect = self.width / self.height

    self.camera = Camera(

      eye=glm.vec3(10, 10, 10),

      target=glm.vec3(0, 0, 0),

      up=glm.vec3(0, 1, 0)

    )

    self.model = glm.mat4(1)

    self.controller = GlutController(self.camera)



  def run(self):

    glutMainLoop()



  def idle_func(self):

    glutPostRedisplay()



  def reshape(self, w, h):

    glViewport(0, 0, w, h)

    self.width = w

    self.height = h



  def display(self):

    self.camera.update(self.width / self.height)



    glClearColor(0.2, 0.3, 0.3, 1.0)

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)



    glMatrixMode(GL_PROJECTION)

    glLoadIdentity()

    gluPerspective(glm.degrees(self.camera.fov), self.width / self.height, self.camera.near, self.camera.far)

    glMatrixMode(GL_MODELVIEW)

    glLoadIdentity()

    e = self.camera.eye

    t = self.camera.target

    u = self.camera.up

    gluLookAt(e.x, e.y, e.z, t.x, t.y, t.z, u.x, u.y, u.z)

    glColor3f(1, 1, 1)

    glBegin(GL_LINES)

    for i in range(-5, 6):

      if i == 0:

        continue

      glVertex3f(-5, 0, i)

      glVertex3f(5, 0, i)

      glVertex3f(i, 0, -5)

      glVertex3f(i, 0, 5)

    glEnd()



    glBegin(GL_LINES)

    glColor3f(1, 0, 0)

    glVertex3f(-5, 0, 0)

    glVertex3f(5, 0, 0)

    glColor3f(0, 1, 0)

    glVertex3f(0, -5, 0)

    glVertex3f(0, 5, 0)

    glColor3f(0, 0, 1)

    glVertex3f(0, 0, -5)

    glVertex3f(0, 0, 5)

    glEnd()



    glutSwapBuffers()





if __name__ == '__main__':

  window = MyWindow(800, 600)

  window.run()
V = glm.lookAt(self.eye, self.target, self.up)
pivot = glm.vec3(V * glm.vec4(target.x, target.y, target.z, 1))

axis = glm.vec3(-delta.y, -delta.x, 0)

angle = glm.length(delta)
R = glm.rotate( glm.mat4(1), angle, axis )

RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

NV = RP * VC = glm.inverse(NV)

targetDist = glm.length(self.target - self.eye)

self.eye  = glm.vec3(C[3])

self.target = self.eye - glm.vec3(C[2]) * targetDist 

self.up   = glm.vec3(C[1])

def rotate_around_target_view(self, target, delta):



  V = glm.lookAt(self.eye, self.target, self.up)



  pivot = glm.vec3(V * glm.vec4(target.x, target.y, target.z, 1))

  axis = glm.vec3(-delta.y, -delta.x, 0)

  angle = glm.length(delta)



  R = glm.rotate( glm.mat4(1), angle, axis )

  RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

  NV = RP * V



  C = glm.inverse(NV)

  targetDist = glm.length(self.target - self.eye)

  self.eye  = glm.vec3(C[3])

  self.target = self.eye - glm.vec3(C[2]) * targetDist 

  self.up   = glm.vec3(C[1])

def rotate_around_origin(self, delta):

  return self.rotate_around_target_view(glm.vec3(0), delta)



def rotate_target(self, delta):

  return self.rotate_around_target_view(self.eye, delta)

def rotate_around_target_world(self, target, delta):



  V = glm.lookAt(self.eye, self.target, self.up)



  pivot = target

  axis = glm.vec3(-delta.y, -delta.x, 0)

  angle = glm.length(delta)



  R = glm.rotate( glm.mat4(1), angle, axis )

  RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

  NV = V * RP



  C = glm.inverse(NV)

  targetDist = glm.length(self.target - self.eye)

  self.eye  = glm.vec3(C[3])

  self.target = self.eye - glm.vec3(C[2]) * targetDist 

  self.up   = glm.vec3(C[1]) 



def rotate_around_origin(self, delta):

  return self.rotate_around_target_world(glm.vec3(0), delta)

def rotate_around_target(self, target, delta):



  # get directions

  los  = self.target - self.eye

  losLen = glm.length(los)

  right = glm.normalize(glm.cross(los, self.up))

  up   = glm.cross(right, los)



  # upright up vector (Gram–Schmidt orthogonalization)

  fix_right = glm.normalize(glm.cross(los, self.original_up))

  UPdotX  = glm.dot(fix_right, up)

  up    = glm.normalize(up - UPdotX * fix_right)

  right   = glm.normalize(glm.cross(los, up))

  los    = glm.cross(up, right)



  # tilt around horizontal axis

  RHor = glm.rotate(glm.mat4(1), delta.y, right)

  up  = glm.vec3(RHor * glm.vec4(up, 0.0))

  los = glm.vec3(RHor * glm.vec4(los, 0.0))



  # rotate around up vector

  RUp  = glm.rotate(glm.mat4(1), delta.x, up)

  right = glm.vec3(RUp * glm.vec4(right, 0.0))

  los  = glm.vec3(RUp * glm.vec4(los, 0.0))



  # set eye, target and up

  self.eye  = target - los * losLen 

  self.target = target

  self.up   = up
from OpenGL.GL import *

from OpenGL.GLU import *

from OpenGL.GLUT import *



import glm





class Camera():



  def __init__(

    self,

    eye=None, target=None, up=None,

    fov=None, near=0.1, far=100000

  ):

    self.eye = eye or glm.vec3(0, 0, 1)

    self.target = target or glm.vec3(0, 0, 0)

    self.up = up or glm.vec3(0, 1, 0)

    self.original_up = glm.vec3(self.up)

    self.fov = fov or glm.radians(45)

    self.near = near

    self.far = far



  def update(self, aspect):

    self.view = glm.lookAt(

      self.eye, self.target, self.up

    )

    self.projection = glm.perspective(

      self.fov, aspect, self.near, self.far

    )



  def zoom(self, *args):

    delta = -args[1] * 0.1

    distance = glm.length(self.target - self.eye)

    self.eye = self.target + (self.eye - self.target) * (delta + 1)



  def load_projection(self):

    width = glutGet(GLUT_WINDOW_WIDTH)

    height = glutGet(GLUT_WINDOW_HEIGHT)



    glMatrixMode(GL_PROJECTION)

    glLoadIdentity()

    gluPerspective(glm.degrees(self.fov), width / height, self.near, self.far)



  def load_modelview(self):

    e = self.eye

    t = self.target

    u = self.up



    glMatrixMode(GL_MODELVIEW)

    glLoadIdentity()

    gluLookAt(e.x, e.y, e.z, t.x, t.y, t.z, u.x, u.y, u.z)





class CameraSkatic(Camera):



  def rotate_around_target(self, target, delta):

    M = glm.mat4(1)

    M = glm.rotate(M, delta.x, glm.vec3(0, 1, 0))

    M = glm.rotate(M, delta.y, glm.vec3(1, 0, 0))



    self.target = target

    T = glm.vec3(0, 0, glm.distance(self.target, self.eye))

    T = glm.vec3(M * glm.vec4(T, 0.0))

    self.eye = self.target + T

    self.up = glm.vec3(M * glm.vec4(self.original_up, 1.0))



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)





class CameraBPL(Camera):



  def rotate_target(self, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    M = glm.mat4(1)

    M = glm.translate(M, self.eye)

    M = glm.rotate(M, delta.y, right)

    M = glm.rotate(M, delta.x, self.up)

    M = glm.translate(M, -self.eye)

    self.target = glm.vec3(M * glm.vec4(self.target, 1.0))



  def rotate_around_target(self, target, delta):

    right = glm.normalize(glm.cross(self.target - self.eye, self.up))

    amount = (right * delta.y + self.up * delta.x)

    M = glm.mat4(1)

    M = glm.rotate(M, amount.z, glm.vec3(0, 0, 1))

    M = glm.rotate(M, amount.y, glm.vec3(0, 1, 0))

    M = glm.rotate(M, amount.x, glm.vec3(1, 0, 0))

    self.eye = glm.vec3(M * glm.vec4(self.eye, 1.0))

    self.target = target

    self.up = self.original_up



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)





class CameraRabbid76_v1(Camera):



  def rotate_around_target_world(self, target, delta):

    V = glm.lookAt(self.eye, self.target, self.up)



    pivot = target

    axis = glm.vec3(-delta.y, -delta.x, 0)

    angle = glm.length(delta)



    R = glm.rotate(glm.mat4(1), angle, axis)

    RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

    NV = V * RP



    C = glm.inverse(NV)

    targetDist = glm.length(self.target - self.eye)

    self.eye = glm.vec3(C[3])

    self.target = self.eye - glm.vec3(C[2]) * targetDist

    self.up = glm.vec3(C[1])



  def rotate_around_target_view(self, target, delta):

    V = glm.lookAt(self.eye, self.target, self.up)



    pivot = glm.vec3(V * glm.vec4(target.x, target.y, target.z, 1))

    axis = glm.vec3(-delta.y, -delta.x, 0)

    angle = glm.length(delta)



    R = glm.rotate(glm.mat4(1), angle, axis)

    RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)

    NV = RP * V



    C = glm.inverse(NV)

    targetDist = glm.length(self.target - self.eye)

    self.eye = glm.vec3(C[3])

    self.target = self.eye - glm.vec3(C[2]) * targetDist

    self.up = glm.vec3(C[1])



  def rotate_around_target(self, target, delta):

    if abs(delta.x) > 0:

      self.rotate_around_target_world(target, glm.vec3(delta.x, 0.0, 0.0))

    if abs(delta.y) > 0:

      self.rotate_around_target_view(target, glm.vec3(0.0, delta.y, 0.0))



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)



  def rotate_target(self, delta):

    return self.rotate_around_target(self.eye, delta)





class CameraRabbid76_v2(Camera):



  def rotate_around_target(self, target, delta):



    # get directions

    los = self.target - self.eye

    losLen = glm.length(los)

    right = glm.normalize(glm.cross(los, self.up))

    up = glm.cross(right, los)



    # upright up vector (Gram–Schmidt orthogonalization)

    fix_right = glm.normalize(glm.cross(los, self.original_up))

    UPdotX = glm.dot(fix_right, up)

    up = glm.normalize(up - UPdotX * fix_right)

    right = glm.normalize(glm.cross(los, up))

    los = glm.cross(up, right)



    # tilt around horizontal axis

    RHor = glm.rotate(glm.mat4(1), delta.y, right)

    up = glm.vec3(RHor * glm.vec4(up, 0.0))

    los = glm.vec3(RHor * glm.vec4(los, 0.0))



    # rotate around up vector

    RUp = glm.rotate(glm.mat4(1), delta.x, up)

    right = glm.vec3(RUp * glm.vec4(right, 0.0))

    los = glm.vec3(RUp * glm.vec4(los, 0.0))



    # set eye, target and up

    self.eye = target - los * losLen

    self.target = target

    self.up = up



  def rotate_around_origin(self, delta):

    return self.rotate_around_target(glm.vec3(0), delta)



  def rotate_target(self, delta):

    return self.rotate_around_target(self.eye, delta)





class GlutController():



  FPS = 0

  ORBIT = 1



  def __init__(self, camera, velocity=100, velocity_wheel=100):

    self.velocity = velocity

    self.velocity_wheel = velocity_wheel

    self.camera = camera



  def glut_mouse(self, button, state, x, y):

    self.mouse_last_pos = glm.vec2(x, y)

    self.mouse_down_pos = glm.vec2(x, y)



    if button == GLUT_LEFT_BUTTON:

      self.mode = self.FPS

    elif button == GLUT_RIGHT_BUTTON:

      self.mode = self.ORBIT



  def glut_motion(self, x, y):

    pos = glm.vec2(x, y)

    move = self.mouse_last_pos - pos

    self.mouse_last_pos = pos



    if self.mode == self.FPS:

      self.camera.rotate_target(move * 0.005)

    elif self.mode == self.ORBIT:

      self.camera.rotate_around_origin(move * 0.005)



  def glut_mouse_wheel(self, *args):

    self.camera.zoom(*args)





def render_text(x, y, text):

  glColor3f(1, 1, 1)

  glRasterPos2f(x, y)

  glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, text.encode("utf-8"))





def draw_plane_yup():

  glColor3f(1, 1, 1)

  glBegin(GL_LINES)

  for i in range(-5, 6):

    if i == 0:

      continue

    glVertex3f(-5, 0, i)

    glVertex3f(5, 0, i)

    glVertex3f(i, 0, -5)

    glVertex3f(i, 0, 5)

  glEnd()



  glBegin(GL_LINES)

  glColor3f(1, 1, 1)

  glVertex3f(-5, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 0, -5)

  glVertex3f(0, 0, 0)



  glColor3f(1, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(5, 0, 0)

  glColor3f(0, 1, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 5, 0)

  glColor3f(0, 0, 1)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 0, 5)

  glEnd()





def draw_plane_zup():

  glColor3f(1, 1, 1)

  glBegin(GL_LINES)

  for i in range(-5, 6):

    if i == 0:

      continue

    glVertex3f(-5, 0, i)

    glVertex3f(5, 0, i)

    glVertex3f(i, -5, 0)

    glVertex3f(i, 5, 0)

  glEnd()



  glBegin(GL_LINES)

  glColor3f(1, 1, 1)

  glVertex3f(-5, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, -5, 0)

  glVertex3f(0, 0, 0)



  glColor3f(1, 0, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(5, 0, 0)

  glColor3f(0, 1, 0)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 0, 5)

  glColor3f(0, 0, 1)

  glVertex3f(0, 0, 0)

  glVertex3f(0, 5, 0)

  glEnd()





def line(p0, p1, color=None):

  c = color or glm.vec3(1, 1, 1)

  glColor3f(c.x, c.y, c.z)

  glVertex3f(p0.x, p0.y, p0.z)

  glVertex3f(p1.x, p1.y, p1.z)





def grid(segment_count=10, spacing=1, yup=True):

  size = segment_count * spacing

  right = glm.vec3(1, 0, 0)

  forward = glm.vec3(0, 0, 1) if yup else glm.vec3(0, 1, 0)

  x_axis = right * size

  z_axis = forward * size



  data = []

  i = -segment_count



  glBegin(GL_LINES)

  while i <= segment_count:

    p0 = -x_axis + forward * i * spacing

    p1 = x_axis + forward * i * spacing

    line(p0, p1)

    p0 = -z_axis + right * i * spacing

    p1 = z_axis + right * i * spacing

    line(p0, p1)

    i += 1

  glEnd()





def axis(size=1.0, yup=True):

  right = glm.vec3(1, 0, 0)

  forward = glm.vec3(0, 0, 1) if yup else glm.vec3(0, 1, 0)

  x_axis = right * size

  z_axis = forward * size

  y_axis = glm.cross(forward, right) * size

  glBegin(GL_LINES)

  line(x_axis, glm.vec3(0, 0, 0), glm.vec3(1, 0, 0))

  line(y_axis, glm.vec3(0, 0, 0), glm.vec3(0, 1, 0))

  line(z_axis, glm.vec3(0, 0, 0), glm.vec3(0, 0, 1))

  glEnd()





class MyWindow:



  def __init__(self, w, h):

    self.width = w

    self.height = h



    glutInit()

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)

    glutInitWindowSize(w, h)

    glutCreateWindow('OpenGL Window')



    self.startup()



    glutReshapeFunc(self.reshape)

    glutDisplayFunc(self.display)

    glutMouseFunc(self.controller.glut_mouse)

    glutMotionFunc(self.controller.glut_motion)

    glutMouseWheelFunc(self.controller.glut_mouse_wheel)

    glutKeyboardFunc(self.keyboard_func)

    glutIdleFunc(self.idle_func)



  def keyboard_func(self, *args):

    try:

      key = args[0].decode("utf8")



      if key =="\\x1b":

        glutLeaveMainLoop()



      if key in ['1', '2', '3', '4']:

        if key == '1':

          self.index_camera ="Skatic"

        elif key == '2':

          self.index_camera ="BPL"

        elif key == '3':

          self.index_camera ="Rabbid76_v1"

        elif key == '4':

          self.index_camera ="Rabbid76_v2"



        self.camera = self.cameras[self.index_camera]

        self.controller.camera = self.camera



      if key in ['o', 'p']:

        self.camera.eye = glm.vec3(0, 10, 10)

        self.camera.target = glm.vec3(0, 0, 0)



        if key == 'o':

          self.yup = True

          # self.camera.up = glm.vec3(0, 0, 1)

        elif key == 'p':

          self.yup = False

          # self.camera.up = glm.vec3(0, 1, 0)



        self.camera.target = glm.vec3(0, 0, 0)



    except Exception as e:

      import traceback

      traceback.print_exc()



  def startup(self):

    glEnable(GL_DEPTH_TEST)



    aspect = self.width / self.height

    params = {

     "eye": glm.vec3(0, 100, 100),

     "target": glm.vec3(0, 0, 0),

     "up": glm.vec3(0, 1, 0)

    }

    self.cameras = {

     "Skatic": CameraSkatic(**params),

     "BPL": CameraBPL(**params),

     "Rabbid76_v1": CameraRabbid76_v1(**params),

     "Rabbid76_v2": CameraRabbid76_v2(**params)

    }

    self.index_camera ="BPL"

    self.yup = True

    self.camera = self.cameras[self.index_camera]

    self.model = glm.mat4(1)

    self.controller = GlutController(self.camera)



  def run(self):

    glutMainLoop()



  def idle_func(self):

    glutPostRedisplay()



  def reshape(self, w, h):

    glViewport(0, 0, w, h)

    self.width = w

    self.height = h



  def display(self):

    self.camera.update(self.width / self.height)



    glClearColor(0.2, 0.3, 0.3, 1.0)

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)



    self.camera.load_projection()

    self.camera.load_modelview()



    glLineWidth(5)

    axis(size=70, yup=self.yup)

    glLineWidth(1)

    grid(segment_count=7, spacing=10, yup=self.yup)



    glMatrixMode(GL_PROJECTION)

    glLoadIdentity()

    glOrtho(-1, 1, -1, 1, -1, 1)

    glMatrixMode(GL_MODELVIEW)

    glLoadIdentity()



    info ="\

".join([

     "1: Skatic Camera",

     "2: BPL Camera",

     "3: Rabbid76 Camera (version1)",

     "4: Rabbid76 Camera (version2)",

     "o: RHS Scene Y-UP",

     "p: RHS Scene Z-UP",

    ])

    render_text(-1.0, 1.0 - 0.1				

相关推荐

  • Spring部署设置openshift

    Springdeploymentsettingsopenshift我有一个问题让我抓狂了三天。我根据OpenShift帐户上的教程部署了spring-eap6-quickstart代码。我已配置调试选项,并且已将Eclipse工作区与OpehShift服务器同步-服务器上的一切工作正常,但在Eclipse中出现无法消除的错误。我有这个错误:cvc-complex-type.2.4.a:Invali…
    2025-04-161
  • 检查Java中正则表达式中模式的第n次出现

    CheckfornthoccurrenceofpatterninregularexpressioninJava本问题已经有最佳答案,请猛点这里访问。我想使用Java正则表达式检查输入字符串中特定模式的第n次出现。你能建议怎么做吗?这应该可以工作:MatchResultfindNthOccurance(intn,Patternp,CharSequencesrc){Matcherm=p.matcher…
    2025-04-161
  • 如何让 JTable 停留在已编辑的单元格上

    HowtohaveJTablestayingontheeditedcell如果有人编辑JTable的单元格内容并按Enter,则内容会被修改并且表格选择会移动到下一行。是否可以禁止JTable在单元格编辑后转到下一行?原因是我的程序使用ListSelectionListener在单元格选择上同步了其他一些小部件,并且我不想在编辑当前单元格后选择下一行。Enter的默认绑定是名为selectNext…
    2025-04-161
  • Weblogic 12c 部署

    Weblogic12cdeploy我正在尝试将我的应用程序从Tomcat迁移到Weblogic12.2.1.3.0。我能够毫无错误地部署应用程序,但我遇到了与持久性提供程序相关的运行时错误。这是堆栈跟踪:javax.validation.ValidationException:CalltoTraversableResolver.isReachable()threwanexceptionatorg.…
    2025-04-161
  • Resteasy Content-Type 默认值

    ResteasyContent-Typedefaults我正在使用Resteasy编写一个可以返回JSON和XML的应用程序,但可以选择默认为XML。这是我的方法:@GET@Path("/content")@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})publicStringcontentListRequestXm…
    2025-04-161
  • 代码不会停止运行,在 Java 中

    thecodedoesn'tstoprunning,inJava我正在用Java解决项目Euler中的问题10,即"Thesumoftheprimesbelow10is2+3+5+7=17.Findthesumofalltheprimesbelowtwomillion."我的代码是packageprojecteuler_1;importjava.math.BigInteger;importjava…
    2025-04-161
  • Out of memory java heap space

    Outofmemoryjavaheapspace我正在尝试将大量文件从服务器发送到多个客户端。当我尝试发送大小为700mb的文件时,它显示了"OutOfMemoryjavaheapspace"错误。我正在使用Netbeans7.1.2版本。我还在属性中尝试了VMoption。但仍然发生同样的错误。我认为阅读整个文件存在一些问题。下面的代码最多可用于300mb。请给我一些建议。提前致谢publicc…
    2025-04-161
  • Log4j 记录到共享日志文件

    Log4jLoggingtoaSharedLogFile有没有办法将log4j日志记录事件写入也被其他应用程序写入的日志文件。其他应用程序可以是非Java应用程序。有什么缺点?锁定问题?格式化?Log4j有一个SocketAppender,它将向服务发送事件,您可以自己实现或使用与Log4j捆绑的简单实现。它还支持syslogd和Windows事件日志,这对于尝试将日志输出与来自非Java应用程序…
    2025-04-161