diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 20d2065a75..8261ad9585 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -439,7 +439,7 @@ void Application::paintGL() { // myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera Camera whichCamera = _myCamera; - if (_frustumOn->isChecked()) { + if (_viewFrustumFromOffset->isChecked() && _frustumOn->isChecked()) { // set the camera to third-person view but offset so we can see the frustum _viewFrustumOffsetCamera.setTargetPosition(_myCamera.getTargetPosition()); @@ -467,42 +467,32 @@ void Application::paintGL() { _frameCount++; } -void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) { +void Application::resizeGL(int width, int height) { float aspectRatio = ((float)width/(float)height); // based on screen resize // reset the camera FOV to our preference... - camera.setFieldOfView(_horizontalFieldOfView); + _myCamera.setFieldOfView(_fieldOfView); + + // get the lens details from the current camera + Camera& camera = _viewFrustumFromOffset->isChecked() ? _viewFrustumOffsetCamera : _myCamera; + float nearClip = camera.getNearClip(); + float farClip = camera.getFarClip(); + float fov; if (OculusManager::isConnected()) { // more magic numbers; see Oculus SDK docs, p. 32 camera.setAspectRatio(aspectRatio *= 0.5); - camera.setFieldOfView(2 * atan((0.0468 * _oculusDistortionScale) / 0.041) * (180 / PIf)); - } else { - camera.setAspectRatio(aspectRatio); - camera.setFieldOfView(_horizontalFieldOfView); - } -} - -void Application::resizeGL(int width, int height) { - - // tell both cameras about our new size - resetCamerasOnResizeGL(_myCamera, width, height); - resetCamerasOnResizeGL(_viewFrustumOffsetCamera, width, height); - - float aspectRatio = ((float)width/(float)height); // based on screen resize - - // get the lens details from the current camera - Camera& camera = _frustumOn->isChecked() ? _viewFrustumOffsetCamera : _myCamera; - float nearClip = camera.getNearClip(); - float farClip = camera.getFarClip(); - - if (OculusManager::isConnected()) { + camera.setFieldOfView(fov = 2 * atan((0.0468 * _oculusDistortionScale) / 0.041) * (180 / PIf)); + // resize the render texture if (_oculusTextureID != 0) { glBindTexture(GL_TEXTURE_2D, _oculusTextureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, 0); } + } else { + camera.setAspectRatio(aspectRatio); + camera.setFieldOfView(fov = _fieldOfView); } // Tell our viewFrustum about this change @@ -829,7 +819,11 @@ void Application::keyPressEvent(QKeyEvent* event) { _colorVoxelMode->trigger(); break; case Qt::Key_O: - _selectVoxelMode->trigger(); + if (isShifted) { + _viewFrustumFromOffset->trigger(); + } else { + _selectVoxelMode->trigger(); + } break; case Qt::Key_Slash: _renderStatsOn->trigger(); @@ -1301,11 +1295,11 @@ void Application::editPreferences() { avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH); form->addRow("Avatar URL:", avatarURL); - QSpinBox* horizontalFieldOfView = new QSpinBox(); - horizontalFieldOfView->setMaximum(180); - horizontalFieldOfView->setMinimum(1); - horizontalFieldOfView->setValue(_horizontalFieldOfView); - form->addRow("Horizontal field of view (degrees):", horizontalFieldOfView); + QSpinBox* fieldOfView = new QSpinBox(); + fieldOfView->setMaximum(180); + fieldOfView->setMinimum(1); + fieldOfView->setValue(_fieldOfView); + form->addRow("Vertical Field of View (Degrees):", fieldOfView); QDoubleSpinBox* gyroCameraSensitivity = new QDoubleSpinBox(); gyroCameraSensitivity->setValue(_gyroCameraSensitivity); @@ -1365,7 +1359,7 @@ void Application::editPreferences() { if (!shouldDynamicallySetJitterBuffer()) { _audio.setJitterBufferSamples(_audioJitterBufferSamples); } - _horizontalFieldOfView = horizontalFieldOfView->value(); + _fieldOfView = fieldOfView->value(); resizeGL(_glWidget->width(), _glWidget->height()); } @@ -2066,6 +2060,8 @@ void Application::initMenu() { QMenu* frustumMenu = debugMenu->addMenu("View Frustum Debugging Tools"); (_frustumOn = frustumMenu->addAction("Display Frustum"))->setCheckable(true); _frustumOn->setShortcut(Qt::SHIFT | Qt::Key_F); + (_viewFrustumFromOffset = frustumMenu->addAction( + "Use Offset Camera", this, SLOT(setFrustumOffset(bool)), Qt::SHIFT | Qt::Key_O))->setCheckable(true); _frustumRenderModeAction = frustumMenu->addAction( "Render Mode", this, SLOT(cycleFrustumRenderMode()), Qt::SHIFT | Qt::Key_R); updateFrustumRenderModeAction(); @@ -4145,7 +4141,7 @@ void Application::loadSettings(QSettings* settings) { _gyroCameraSensitivity = loadSetting(settings, "gyroCameraSensitivity", 0.5f); _audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0); - _horizontalFieldOfView = loadSetting(settings, "horizontalFieldOfView", HORIZONTAL_FIELD_OF_VIEW_DEGREES); + _fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES); settings->beginGroup("View Frustum Offset Camera"); // in case settings is corrupt or missing loadSetting() will check for NaN @@ -4169,7 +4165,7 @@ void Application::saveSettings(QSettings* settings) { settings->setValue("gyroCameraSensitivity", _gyroCameraSensitivity); settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples); - settings->setValue("horizontalFieldOfView", _horizontalFieldOfView); + settings->setValue("fieldOfView", _fieldOfView); settings->beginGroup("View Frustum Offset Camera"); settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffsetYaw); settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffsetPitch); diff --git a/interface/src/Application.h b/interface/src/Application.h index 8de73edeb5..c49050ba8c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -384,7 +384,7 @@ private: int _audioJitterBufferSamples; // Number of extra samples to wait before starting audio playback - float _horizontalFieldOfView; // In Degrees, doesn't apply to HMD like Oculus + float _fieldOfView; // In Degrees, doesn't apply to HMD like Oculus HandControl _handControl; diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 29449e63b5..6b99f9db2e 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -37,7 +37,8 @@ Camera::Camera() { _linearModeShift = 0.0f; _mode = CAMERA_MODE_THIRD_PERSON; _tightness = 10.0f; // default - _fieldOfView = HORIZONTAL_FIELD_OF_VIEW_DEGREES; + _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES; + _aspectRatio = 16.f/9.f; _nearClip = 0.08f; // default _farClip = 50.0f * TREE_SCALE; // default _upShift = 0.0f; diff --git a/interface/src/Camera.h b/interface/src/Camera.h index de4553b6dc..615135bc80 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -11,7 +11,7 @@ #include #include -const float HORIZONTAL_FIELD_OF_VIEW_DEGREES = 90.0f; +const float DEFAULT_FIELD_OF_VIEW_DEGREES = 90.0f; enum CameraMode { diff --git a/interface/src/avatar/Face.cpp b/interface/src/avatar/Face.cpp index 22ce3c0727..1949fa6c8c 100644 --- a/interface/src/avatar/Face.cpp +++ b/interface/src/avatar/Face.cpp @@ -63,7 +63,6 @@ void Face::setFrameFromWebcam() { _textureSize = webcam->getTextureSize(); _textureRect = webcam->getFaceRect(); _aspectRatio = webcam->getAspectRatio(); - } else { clearFrame(); } @@ -262,6 +261,11 @@ bool Face::render(float alpha) { xScale = FULL_FRAME_SCALE * _owningHead->getScale(); zScale = xScale * 0.3f; + glPushMatrix(); + glColor4f(1.0f, 1.0f, 1.0f, alpha); + glScalef(xScale / 12, xScale / (aspect * 3), zScale / 2); + Application::getInstance()->getGeometryCache()->renderHalfCylinder(25, 20); + glPopMatrix(); } else { aspect = _aspectRatio; xScale = BODY_BALL_RADIUS_HEAD_BASE * _owningHead->getScale(); @@ -308,7 +312,7 @@ bool Face::render(float alpha) { glGenBuffers(1, &_iboID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboID); int* indices = new int[INDEX_COUNT]; - int* indexPosition = indices; + int* indexPosition = indices; for (int i = 0; i < QUAD_HEIGHT; i++) { for (int j = 0; j < QUAD_WIDTH; j++) { *indexPosition++ = i * VERTEX_WIDTH + j; diff --git a/interface/src/avatar/Face.h b/interface/src/avatar/Face.h index f3e681ff72..1a68f8173e 100644 --- a/interface/src/avatar/Face.h +++ b/interface/src/avatar/Face.h @@ -61,7 +61,7 @@ private: cv::Size2f _textureSize; cv::RotatedRect _textureRect; float _aspectRatio; - + vpx_codec_ctx_t _colorCodec; vpx_codec_ctx_t _depthCodec; bool _lastFullFrame; diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 8331a5deb9..adc4d98361 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -163,3 +163,77 @@ void GeometryCache::renderSquare(int xDivisions, int yDivisions) { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } + +void GeometryCache::renderHalfCylinder(int slices, int stacks) { + VerticesIndices& vbo = _halfCylinderVBOs[IntPair(slices, stacks)]; + int vertices = (slices + 1) * stacks; + int indices = 2 * 3 * slices * (stacks - 1); + if (vbo.first == 0) { + GLfloat* vertexData = new GLfloat[vertices * 2 * 3]; + GLfloat* vertex = vertexData; + for (int i = 0; i <= (stacks - 1); i++) { + float y = (float)i / (stacks - 1); + + for (int j = 0; j <= slices; j++) { + float theta = 3 * PIf / 2 + PIf * j / slices; + + //normals + *(vertex++) = sinf(theta); + *(vertex++) = 0; + *(vertex++) = cosf(theta); + + // vertices + *(vertex++) = sinf(theta); + *(vertex++) = y; + *(vertex++) = cosf(theta); + } + } + + glGenBuffers(1, &vbo.first); + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + const int BYTES_PER_VERTEX = 3 * sizeof(GLfloat); + glBufferData(GL_ARRAY_BUFFER, 2 * vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + delete[] vertexData; + + GLushort* indexData = new GLushort[indices]; + GLushort* index = indexData; + for (int i = 0; i < stacks - 1; i++) { + GLushort bottom = i * (slices + 1); + GLushort top = bottom + slices + 1; + for (int j = 0; j < slices; j++) { + int next = j + 1; + + *(index++) = bottom + j; + *(index++) = top + next; + *(index++) = top + j; + + *(index++) = bottom + j; + *(index++) = bottom + next; + *(index++) = top + next; + } + } + + glGenBuffers(1, &vbo.second); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + const int BYTES_PER_INDEX = sizeof(GLushort); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + delete[] indexData; + + } else { + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + } + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + glNormalPointer(GL_FLOAT, 6 * sizeof(float), 0); + glVertexPointer(3, GL_FLOAT, (6 * sizeof(float)), (const void *)(3 * sizeof(float))); + + glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} \ No newline at end of file diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index bfce642554..f1e1ec4e34 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -20,6 +20,7 @@ public: void renderHemisphere(int slices, int stacks); void renderSquare(int xDivisions, int yDivisions); + void renderHalfCylinder(int slices, int stacks); private: @@ -28,6 +29,7 @@ private: QHash _hemisphereVBOs; QHash _squareVBOs; + QHash _halfCylinderVBOs; }; #endif /* defined(__interface__GeometryCache__) */