Newer
Older
# ############################################################
# Data structs
# ############################################################
def HMD(display_backend, context, error_callback):
"""
return the head mounted display device class
(defined in another file)
:param context: BPY context
:type context: bpy.types.Context
:param error_callback: error handler
:type error_callback: func(message, is_fatal)
from .debug import Debug
displays = {
'OCULUS':Oculus,
'DEBUG':Debug,
}
if display_backend not in displays:
assert False, "Display Backend \"{0}\" not implemented".format(display_backend)
return displays[display_backend](context, error_callback)
# ############################################################
# Base class inherited by HMD devices
# ############################################################
class HMD_Base:
"_head_transformation",
"_eye_pose",
"_offscreen_object",
"_framebuffer_object",
"_color_object",
"_modelview_matrix",
def __init__(self, name, context, error_callback):
self._width = [0, 0]
self._height = [0, 0]
self._projection_matrix = [Matrix.Identity(4), Matrix.Identity(4)]
self._modelview_matrix = [Matrix.Identity(4), Matrix.Identity(4)]
self._framebuffer_object = [0, 0]
self._color_object = [0, 0]
self._offscreen_object = [None, None]
self._eye_orientation_raw = [[i for i in range(4)], [i for i in range(4)]]
self._eye_position_raw = [[i for i in range(3)], [i for i in range(3)]]
self._scale = self._calculateScale(context)
self._updateViewClipping(context)
return self._width[self._current_eye]
@width.setter
def width(self, value):
self._width[self._current_eye] = value
return self._height[self._current_eye]
@height.setter
def height(self, value):
self._height[self._current_eye] = value
def offscreen_object(self):
return self._offscreen_object[self._current_eye]
def framebuffer_object(self):
return self._framebuffer_object[self._current_eye]
def color_object(self):
return self._color_object[self._current_eye]
return self._projection_matrix[self._current_eye]
return self._modelview_matrix[self._current_eye]
def setEye(self, eye):
self._current_eye = int(bool(eye))
def init(self):
"""
Initialize device
:return: return True if the device was properly initialized
:rtype: bool
"""
self._offscreen_object[i] = gpu.offscreen.new(self._width[i], self._height[i])
self._framebuffer_object[i] = self._offscreen_object[i].framebuffer_object
self._color_object[i] = self._offscreen_object[i].color_object
except Exception as E:
print(E)
self._offscreen_object[0] = None
self._offscreen_object[1] = None
return False
else:
return True
self._updateViewClipping(context)
The frame is ready to be sent to the device
assert False, "frameReady() not implemented for the \"{0}\" device".format(self._name)
def reCenter(self):
"""
Re-center the HMD device
:return: return True if success
:rtype: bool
"""
assert False, "reCenter() not implemented for the \"{0}\" device".format(self._name)
def quit(self):
"""
Garbage collection
"""
except Exception as E:
print(E)
def error(self, function, exception, is_fatal):
"""
Handle error messages
"""
if VERBOSE:
print("ADD-ON :: {0}() : {1}".format(function, exception))
import sys
traceback = sys.exc_info()
if traceback and traceback[0]:
print(traceback[0])
if hasattr(exception, "strerror"):
message = exception.strerror
else:
message = str(exception)
# send the error the interface
self._error_callback(message, is_fatal)
def updateMatrices(self, context):
"""
Update OpenGL drawing matrices
"""
view_matrix = self._getViewMatrix(context)
for i in range(2):
rotation_raw = self._eye_orientation_raw[i]
position_raw = self._eye_position_raw[i]
# take scene units into consideration
position_raw = self._scaleMovement(position_raw)
rotation = Quaternion(rotation_raw).to_matrix().to_4x4()
position = Matrix.Translation(position_raw)
transformation = position * rotation
self._modelview_matrix[i] = transformation.inverted() * view_matrix
def _getViewMatrix(self, context):
region = context.region_data
if region.view_perspective == 'CAMERA':
space = context.space_data
camera = space.camera
return camera.matrix_world.copy().inverted()
else:
return region.view_matrix.copy()
def _updateViewClipping(self, context):
space = context.space_data
region = context.region_data
if region.view_perspective == 'CAMERA':
camera_ob = space.camera
camera = camera_ob.data
self._near = camera.clip_start
self._far = camera.clip_end
else:
self._near = space.clip_start
self._far = space.clip_end
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
def _calculateScale(self, context):
"""
if BU != 1 meter, scale the transformations
"""
scene = context.scene
unit_settings = scene.unit_settings
system = unit_settings.system
if system == 'NONE':
return None
elif system == 'METRIC':
return 1.0 / unit_settings.scale_length
elif system == 'IMPERIAL':
return 0.3048 / unit_settings.scale_length
else:
assert('Unit system not supported ({0})'.format(system))
def _scaleMovement(self, position):
"""
if BU != 1 meter, scale the transformations
"""
if self._scale is None:
return position
return [position[0] * self._scale,
position[1] * self._scale,
position[2] * self._scale]
def _convertMatrixTo4x4(self, value):
matrix = Matrix()
matrix[0] = value[0:4]
matrix[1] = value[4:8]
matrix[2] = value[8:12]
matrix[3] = value[12:16]
return matrix.transposed()