1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Refine `EulerCamera` and `App::frame_core_draw` to get a stereoscopic view
16 module stereoscopic_view
19 intrude import cameras
21 redef class EulerCamera
22 redef var mvp_matrix
= new Matrix.identity
(4)
24 # Half of the distance between the eyes
25 var eye_separation
: Float = 0.03125
27 # MVP matrix for the left eye
28 fun mvp_matrix_left
: Matrix do return mvp_matrix_eye
(eye_separation
)
30 # MVP matrix for the right eye
31 fun mvp_matrix_right
: Matrix do return mvp_matrix_eye
(-eye_separation
)
33 # Get an MVP matrix for an eye at `diff` world unit from the center
34 private fun mvp_matrix_eye
(diff
: Float): Matrix
36 var view
= new Matrix.identity
(4)
38 # Translate the world away from the camera
39 view
.translate
(-position
.x
/2.0, -position
.y
/2.0, -position
.z
/2.0)
41 # Rotate the camera, first by looking left or right, then up or down
42 view
= view
* rotation_matrix
44 # Apply eye transformation
45 var translation
= new Matrix.identity
(4)
46 translation
.translate
(diff
, 0.0, 0.0)
47 view
= view
* translation
49 # Use a projection matrix with a depth
50 var projection
= new Matrix.perspective
(pi
*field_of_view_y
/2.0,
51 display
.aspect_ratio
, near
, far
)
53 return view
* projection
57 redef class GamnitDisplay
59 # With stereoscopic view, the aspect ratio (in each eye) is half of the screen
60 redef fun aspect_ratio
do return super / 2.0
64 redef fun frame_core_draw
(display
) do frame_core_stereoscopic display
66 # Split the screen in two, and call `frame_core_depth` for each eyes
67 protected fun frame_core_stereoscopic
(display
: GamnitDisplay)
69 var half_width
= display
.width
/ 2
72 glViewport
(0, 0, half_width
, display
.height
)
73 world_camera
.mvp_matrix
= world_camera
.mvp_matrix_left
74 frame_core_depth display
77 glViewport
(half_width
, 0, half_width
, display
.height
)
78 world_camera
.mvp_matrix
= world_camera
.mvp_matrix_right
79 frame_core_depth display
81 # We reset the viewport for selection
82 glViewport
(0, 0, display
.width
, display
.height
)
85 var gl_error
= glGetError
86 assert gl_error
== gl_NO_ERROR
else print gl_error