Example #1
0
void Stats::resetWidth(int width, int horizontalOffset) {
    QGLWidget* glWidget = Application::getInstance()->getGLWidget();
    int extraSpace = glWidget->width() - horizontalOffset -2
                   - STATS_GENERAL_MIN_WIDTH
                   - (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0)
                   - STATS_GEO_MIN_WIDTH
                   - STATS_VOXEL_MIN_WIDTH;

    int panels = 4;

    _generalStatsWidth = STATS_GENERAL_MIN_WIDTH;
    if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) {
        _pingStatsWidth = STATS_PING_MIN_WIDTH;
    } else {
        _pingStatsWidth = 0;
        panels = 3;
    }
    _geoStatsWidth = STATS_GEO_MIN_WIDTH;
    _voxelStatsWidth = STATS_VOXEL_MIN_WIDTH;

    if (extraSpace > panels) {
        _generalStatsWidth += (int) extraSpace / panels;
        if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) {
            _pingStatsWidth += (int) extraSpace / panels;
        }
        _geoStatsWidth += (int) extraSpace / panels;
        _voxelStatsWidth += glWidget->width() - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3);
    }
}
Example #2
0
// Draws the FBO texture for the screen
void ApplicationOverlay::displayOverlayTexture(Camera& whichCamera) {

    Application* application = Application::getInstance();
    QGLWidget* glWidget = application->getGLWidget();

    glEnable(GL_TEXTURE_2D);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, getFramebufferObject()->texture());

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();

    glLoadIdentity();
    gluOrtho2D(0, glWidget->width(), glWidget->height(), 0);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);

    glBegin(GL_QUADS);
    glTexCoord2f(0, 0); glVertex2i(0, glWidget->height());
    glTexCoord2f(1, 0); glVertex2i(glWidget->width(), glWidget->height());
    glTexCoord2f(1, 1); glVertex2i(glWidget->width(), 0);
    glTexCoord2f(0, 1); glVertex2i(0, 0);
    glEnd();

    glPopMatrix();
    glDisable(GL_TEXTURE_2D);
}
Example #3
0
// Renders the overlays either to a texture or to the screen
void ApplicationOverlay::renderOverlay(bool renderToTexture) {
    PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()");

    Application* application = Application::getInstance();

    Overlays& overlays = application->getOverlays();
    QGLWidget* glWidget = application->getGLWidget();
    MyAvatar* myAvatar = application->getAvatar();

    if (renderToTexture) {
        getFramebufferObject()->bind();
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    // Render 2D overlay
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();

    glLoadIdentity();
    gluOrtho2D(0, glWidget->width(), glWidget->height(), 0);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);

    renderAudioMeter();

    if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) {
        myAvatar->renderHeadMouse(glWidget->width(), glWidget->height());
    }

    renderStatsAndLogs();

    // give external parties a change to hook in
    emit application->renderingOverlay();

    overlays.render2D();

    renderPointers();

    glPopMatrix();

    glMatrixMode(GL_MODELVIEW);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);

    if (renderToTexture) {
        getFramebufferObject()->release();
    }
}
Example #4
0
// called on mouse click release
// check for clicks over stats  in order to expand or contract them
void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset) {
    QGLWidget* glWidget = Application::getInstance()->getGLWidget();

    if (0 != glm::compMax(glm::abs(glm::ivec2(mouseX - mouseDragStartedX, mouseY - mouseDragStartedY)))) {
        // not worried about dragging on stats
        return;
    }

    int statsHeight = 0, 
        statsWidth = 0, 
        statsX = 0, 
        statsY = 0, 
        lines = 0;

    statsX = horizontalOffset;

    // top-left stats click
    lines = _expanded ? 5 : 3;
    statsHeight = lines * STATS_PELS_PER_LINE + 10;
    if (mouseX > statsX && mouseX < statsX + _generalStatsWidth && mouseY > statsY && mouseY < statsY + statsHeight) {
        toggleExpanded();
        return;
    }
    statsX += _generalStatsWidth;

    // ping stats click
    if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) {
        lines = _expanded ? 4 : 3;
        statsHeight = lines * STATS_PELS_PER_LINE + 10;
        if (mouseX > statsX && mouseX < statsX + _pingStatsWidth && mouseY > statsY && mouseY < statsY + statsHeight) {
            toggleExpanded();
            return;
        }
        statsX += _pingStatsWidth;
    }

    // geo stats panel click
    lines = _expanded ? 4 : 3;
    statsHeight = lines * STATS_PELS_PER_LINE + 10;
    if (mouseX > statsX && mouseX < statsX + _geoStatsWidth  && mouseY > statsY && mouseY < statsY + statsHeight) {
        toggleExpanded();
        return;
    }
    statsX += _geoStatsWidth;

    // top-right stats click
    lines = _expanded ? 11 : 3;
    statsHeight = lines * STATS_PELS_PER_LINE + 10;
    statsWidth = glWidget->width() - statsX;
    if (mouseX > statsX && mouseX < statsX + statsWidth  && mouseY > statsY && mouseY < statsY + statsHeight) {
        toggleExpanded();
        return;
    }
}
Example #5
0
void ApplicationOverlay::renderStatsAndLogs() {

    Application* application = Application::getInstance();

    QGLWidget* glWidget = application->getGLWidget();
    const OctreePacketProcessor& octreePacketProcessor = application->getOctreePacketProcessor();
    BandwidthMeter* bandwidthMeter = application->getBandwidthMeter();
    NodeBounds& nodeBoundsDisplay = application->getNodeBoundsDisplay();

    //  Display stats and log text onscreen
    glLineWidth(1.0f);
    glPointSize(1.0f);

    if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
        // let's set horizontal offset to give stats some margin to mirror
        int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2;
        int voxelPacketsToProcess = octreePacketProcessor.packetsToProcessCount();
        //  Onscreen text about position, servers, etc
        Stats::getInstance()->display(WHITE_TEXT, horizontalOffset, application->getFps(), application->getPacketsPerSecond(), application->getBytesPerSecond(), voxelPacketsToProcess);
        //  Bandwidth meter
        if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) {
            Stats::drawBackground(0x33333399, glWidget->width() - 296, glWidget->height() - 68, 296, 68);
            bandwidthMeter->render(glWidget->width(), glWidget->height());
        }
    }

    //  Show on-screen msec timer
    if (Menu::getInstance()->isOptionChecked(MenuOption::FrameTimer)) {
        char frameTimer[10];
        quint64 mSecsNow = floor(usecTimestampNow() / 1000.0 + 0.5);
        sprintf(frameTimer, "%d\n", (int)(mSecsNow % 1000));
        int timerBottom =
            (Menu::getInstance()->isOptionChecked(MenuOption::Stats) &&
            Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth))
            ? 80 : 20;
        drawText(glWidget->width() - 100, glWidget->height() - timerBottom, 0.30f, 0.0f, 0, frameTimer, WHITE_TEXT);
    }
    nodeBoundsDisplay.drawOverlay();
}
Example #6
0
Stats::Stats():
        _expanded(false),
        _recentMaxPackets(0),
        _resetRecentMaxPacketsSoon(true),
        _generalStatsWidth(STATS_GENERAL_MIN_WIDTH),
        _pingStatsWidth(STATS_PING_MIN_WIDTH),
        _geoStatsWidth(STATS_GEO_MIN_WIDTH),
        _voxelStatsWidth(STATS_VOXEL_MIN_WIDTH),
        _lastHorizontalOffset(0)
{
    QGLWidget* glWidget = Application::getInstance()->getGLWidget();
    resetWidth(glWidget->width(), 0);
}
Example #7
0
//Injecting mouse movements and clicks
void SixenseManager::emulateMouse(PalmData* palm, int index) {
    Application* application = Application::getInstance();
    MyAvatar* avatar = application->getAvatar();
    QGLWidget* widget = application->getGLWidget();
    QPoint pos;
    
    Qt::MouseButton bumperButton;
    Qt::MouseButton triggerButton;

    if (Menu::getInstance()->getInvertSixenseButtons()) {
        bumperButton = Qt::LeftButton;
        triggerButton = Qt::RightButton;
    } else {
        bumperButton = Qt::RightButton;
        triggerButton = Qt::LeftButton;
    }

    if (OculusManager::isConnected()) {
        pos = application->getApplicationOverlay().getOculusPalmClickLocation(palm);
    } else {
        // Get directon relative to avatar orientation
        glm::vec3 direction = glm::inverse(avatar->getOrientation()) * palm->getFingerDirection();

        // Get the angles, scaled between (-0.5,0.5)
        float xAngle = (atan2(direction.z, direction.x) + M_PI_2);
        float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2));

        // Get the pixel range over which the xAngle and yAngle are scaled
        float cursorRange = widget->width() * getCursorPixelRangeMult();

        pos.setX(widget->width() / 2.0f + cursorRange * xAngle);
        pos.setY(widget->height() / 2.0f + cursorRange * yAngle);

    }

    //If we are off screen then we should stop processing, and if a trigger or bumper is pressed,
    //we should unpress them.
    if (pos.x() == INT_MAX) {
        if (_bumperPressed[index]) {
            QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, bumperButton, bumperButton, 0);

            application->mouseReleaseEvent(&mouseEvent);

            _bumperPressed[index] = false;
        }
        if (_triggerPressed[index]) {
            QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, triggerButton, triggerButton, 0);

            application->mouseReleaseEvent(&mouseEvent);

            _triggerPressed[index] = false;
        }
        return;
    }

    //If position has changed, emit a mouse move to the application
    if (pos.x() != _oldX[index] || pos.y() != _oldY[index]) {
        QMouseEvent mouseEvent(static_cast<QEvent::Type>(CONTROLLER_MOVE_EVENT), pos, Qt::NoButton, Qt::NoButton, 0);

        //Only send the mouse event if the opposite left button isnt held down.
        //This is specifically for edit voxels
        if (triggerButton == Qt::LeftButton) {
            if (!_triggerPressed[(int)(!index)]) {
                application->mouseMoveEvent(&mouseEvent);
            }
        } else {
            if (!_bumperPressed[(int)(!index)]) {
                application->mouseMoveEvent(&mouseEvent);
            }
        } 
    }
    _oldX[index] = pos.x();
    _oldY[index] = pos.y();
    

    //We need separate coordinates for clicks, since we need to check if
    //a magnification window was clicked on
    int clickX = pos.x();
    int clickY = pos.y();
    //Checks for magnification window click
    application->getApplicationOverlay().getClickLocation(clickX, clickY);
    //Set pos to the new click location, which may be the same if no magnification window is open
    pos.setX(clickX);
    pos.setY(clickY);

    //Check for bumper press ( Right Click )
    if (palm->getControllerButtons() & BUTTON_FWD) {
        if (!_bumperPressed[index]) {
            _bumperPressed[index] = true;
        
            QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, bumperButton, bumperButton, 0);

            application->mousePressEvent(&mouseEvent);
        }
    } else if (_bumperPressed[index]) {
        QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, bumperButton, bumperButton, 0);

        application->mouseReleaseEvent(&mouseEvent);

        _bumperPressed[index] = false;
    }

    //Check for trigger press ( Left Click )
    if (palm->getTrigger() == 1.0f) {
        if (!_triggerPressed[index]) {
            _triggerPressed[index] = true;

            QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, triggerButton, triggerButton, 0);

            application->mousePressEvent(&mouseEvent);
        }
    } else if (_triggerPressed[index]) {
        QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, triggerButton, triggerButton, 0);

        application->mouseReleaseEvent(&mouseEvent);

        _triggerPressed[index] = false;
    }
}
Example #8
0
void ApplicationOverlay::renderAudioMeter() {

    Application* application = Application::getInstance();

    QGLWidget* glWidget = application->getGLWidget();
    Audio* audio = application->getAudio();

    //  Display a single screen-size quad to create an alpha blended 'collision' flash
    if (audio->getCollisionFlashesScreen()) {
        float collisionSoundMagnitude = audio->getCollisionSoundMagnitude();
        const float VISIBLE_COLLISION_SOUND_MAGNITUDE = 0.5f;
        if (collisionSoundMagnitude > VISIBLE_COLLISION_SOUND_MAGNITUDE) {
            renderCollisionOverlay(glWidget->width(), glWidget->height(), audio->getCollisionSoundMagnitude());
        }
    }

    //  Audio VU Meter and Mute Icon
    const int MUTE_ICON_SIZE = 24;
    const int AUDIO_METER_INSET = 2;
    const int MUTE_ICON_PADDING = 10;
    const int AUDIO_METER_WIDTH = MIRROR_VIEW_WIDTH - MUTE_ICON_SIZE - AUDIO_METER_INSET - MUTE_ICON_PADDING;
    const int AUDIO_METER_SCALE_WIDTH = AUDIO_METER_WIDTH - 2 * AUDIO_METER_INSET;
    const int AUDIO_METER_HEIGHT = 8;
    const int AUDIO_METER_GAP = 5;
    const int AUDIO_METER_X = MIRROR_VIEW_LEFT_PADDING + MUTE_ICON_SIZE + AUDIO_METER_INSET + AUDIO_METER_GAP;

    int audioMeterY;
    if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
        audioMeterY = MIRROR_VIEW_HEIGHT + AUDIO_METER_GAP + MUTE_ICON_PADDING;
    } else {
        audioMeterY = AUDIO_METER_GAP + MUTE_ICON_PADDING;
    }

    const float AUDIO_METER_BLUE[] = { 0.0, 0.0, 1.0 };
    const float AUDIO_METER_GREEN[] = { 0.0, 1.0, 0.0 };
    const float AUDIO_METER_RED[] = { 1.0, 0.0, 0.0 };
    const float AUDIO_GREEN_START = 0.25 * AUDIO_METER_SCALE_WIDTH;
    const float AUDIO_RED_START = 0.80 * AUDIO_METER_SCALE_WIDTH;
    const float CLIPPING_INDICATOR_TIME = 1.0f;
    const float AUDIO_METER_AVERAGING = 0.5;
    const float LOG2 = log(2.f);
    const float METER_LOUDNESS_SCALE = 2.8f / 5.f;
    const float LOG2_LOUDNESS_FLOOR = 11.f;
    float audioLevel = 0.f;
    float loudness = audio->getLastInputLoudness() + 1.f;

    _trailingAudioLoudness = AUDIO_METER_AVERAGING * _trailingAudioLoudness + (1.f - AUDIO_METER_AVERAGING) * loudness;
    float log2loudness = log(_trailingAudioLoudness) / LOG2;

    if (log2loudness <= LOG2_LOUDNESS_FLOOR) {
        audioLevel = (log2loudness / LOG2_LOUDNESS_FLOOR) * METER_LOUDNESS_SCALE * AUDIO_METER_SCALE_WIDTH;
    } else {
        audioLevel = (log2loudness - (LOG2_LOUDNESS_FLOOR - 1.f)) * METER_LOUDNESS_SCALE * AUDIO_METER_SCALE_WIDTH;
    }
    if (audioLevel > AUDIO_METER_SCALE_WIDTH) {
        audioLevel = AUDIO_METER_SCALE_WIDTH;
    }
    bool isClipping = ((audio->getTimeSinceLastClip() > 0.f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME));

    if ((audio->getTimeSinceLastClip() > 0.f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) {
        const float MAX_MAGNITUDE = 0.7f;
        float magnitude = MAX_MAGNITUDE * (1 - audio->getTimeSinceLastClip() / CLIPPING_INDICATOR_TIME);
        renderCollisionOverlay(glWidget->width(), glWidget->height(), magnitude, 1.0f);
    }

    audio->renderToolBox(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP,
                         audioMeterY,
                         Menu::getInstance()->isOptionChecked(MenuOption::Mirror));

    audio->renderScope(glWidget->width(), glWidget->height());

    glBegin(GL_QUADS);
    if (isClipping) {
        glColor3f(1, 0, 0);
    } else {
        glColor3f(0.475f, 0.475f, 0.475f);
    }

    audioMeterY += AUDIO_METER_HEIGHT;

    glColor3f(0, 0, 0);
    //  Draw audio meter background Quad
    glVertex2i(AUDIO_METER_X, audioMeterY);
    glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, audioMeterY);
    glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, audioMeterY + AUDIO_METER_HEIGHT);
    glVertex2i(AUDIO_METER_X, audioMeterY + AUDIO_METER_HEIGHT);

    if (audioLevel > AUDIO_RED_START) {
        if (!isClipping) {
            glColor3fv(AUDIO_METER_RED);
        } else {
            glColor3f(1, 1, 1);
        }
        // Draw Red Quad
        glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_RED_START, audioMeterY + AUDIO_METER_INSET);
        glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET);
        glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
        glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_RED_START, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
        audioLevel = AUDIO_RED_START;
    }
    if (audioLevel > AUDIO_GREEN_START) {
        if (!isClipping) {
            glColor3fv(AUDIO_METER_GREEN);
        } else {
            glColor3f(1, 1, 1);
        }
        // Draw Green Quad
        glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_GREEN_START, audioMeterY + AUDIO_METER_INSET);
        glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET);
        glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
        glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_GREEN_START, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
        audioLevel = AUDIO_GREEN_START;
    }
    //   Draw Blue Quad
    if (!isClipping) {
        glColor3fv(AUDIO_METER_BLUE);
    } else {
        glColor3f(1, 1, 1);
    }
    // Draw Blue (low level) quad
    glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_INSET);
    glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET);
    glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
    glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET);
    glEnd();
}
Example #9
0
//Renders a small magnification of the currently bound texture at the coordinates
void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY)
{
    Application* application = Application::getInstance();
    QGLWidget* glWidget = application->getGLWidget();
    MyAvatar* myAvatar = application->getAvatar();
    const glm::vec3& viewMatrixTranslation = application->getViewMatrixTranslation();

    float leftX, rightX, leftZ, rightZ, topZ, bottomZ;

    const int widgetWidth = glWidget->width();
    const int widgetHeight = glWidget->height();
    const float magnification = 4.0f;

    // Get vertical FoV of the displayed overlay texture
    const float halfVerticalAngle = _oculusAngle / 2.0f;
    const float overlayAspectRatio = glWidget->width() / (float)glWidget->height();
    const float halfOverlayHeight = _distance * tan(halfVerticalAngle);

    // Get horizontal angle and angle increment from vertical angle and aspect ratio
    const float horizontalAngle = halfVerticalAngle * 2.0f * overlayAspectRatio;
    const float halfHorizontalAngle = horizontalAngle / 2;


    float magnifyWidth = 80.0f;
    float magnifyHeight = 60.0f;

    mouseX -= magnifyWidth / 2;
    mouseY -= magnifyHeight / 2;

    //clamp the magnification
    if (mouseX < 0) {
        magnifyWidth += mouseX;
        mouseX = 0;
    } else if (mouseX + magnifyWidth > widgetWidth) {
        magnifyWidth = widgetWidth - mouseX;
    }
    if (mouseY < 0) {
        magnifyHeight += mouseY;
        mouseY = 0;
    } else if (mouseY + magnifyHeight > widgetHeight) {
        magnifyHeight = widgetHeight - mouseY;
    }

    const float halfMagnifyHeight = magnifyHeight / 2.0f;

    float newWidth = magnifyWidth * magnification;
    float newHeight = magnifyHeight * magnification;

    // Magnification Texture Coordinates
    float magnifyULeft = mouseX / (float)widgetWidth;
    float magnifyURight = (mouseX + magnifyWidth) / (float)widgetWidth;
    float magnifyVBottom = 1.0f - mouseY / (float)widgetHeight;
    float magnifyVTop = 1.0f - (mouseY + magnifyHeight) / (float)widgetHeight;

    // Coordinates of magnification overlay
    float newMouseX = (mouseX + magnifyWidth / 2) - newWidth / 2.0f;
    float newMouseY = (mouseY + magnifyHeight / 2) + newHeight / 2.0f;

    // Get angle on the UI
    float leftAngle = (newMouseX / (float)widgetWidth) * horizontalAngle - halfHorizontalAngle;
    float rightAngle = ((newMouseX + newWidth) / (float)widgetWidth) * horizontalAngle - halfHorizontalAngle;

    float bottomAngle = (newMouseY / (float)widgetHeight) * _oculusAngle - halfVerticalAngle;
    float topAngle = ((newMouseY - newHeight) / (float)widgetHeight) * _oculusAngle - halfVerticalAngle;

    // Get position on hemisphere using angle
    if (_uiType == HEMISPHERE) {

        //Get new UV coordinates from our magnification window
        float newULeft = newMouseX / widgetWidth;
        float newURight = (newMouseX + newWidth) / widgetWidth;
        float newVBottom = 1.0 - newMouseY / widgetHeight;
        float newVTop = 1.0 - (newMouseY - newHeight) / widgetHeight;

        // Project our position onto the hemisphere using the UV coordinates
        float lX = sin((newULeft - 0.5f) * _textureFov);
        float rX = sin((newURight - 0.5f) * _textureFov);
        float bY = sin((newVBottom - 0.5f) * _textureFov);
        float tY = sin((newVTop - 0.5f) * _textureFov);

        float dist;
        //Bottom Left
        dist = sqrt(lX * lX + bY * bY);
        float blZ = sqrt(1.0f - dist * dist);
        //Top Left
        dist = sqrt(lX * lX + tY * tY);
        float tlZ = sqrt(1.0f - dist * dist);
        //Bottom Right
        dist = sqrt(rX * rX + bY * bY);
        float brZ = sqrt(1.0f - dist * dist);
        //Top Right
        dist = sqrt(rX * rX + tY * tY);
        float trZ = sqrt(1.0f - dist * dist);

        glBegin(GL_QUADS);

        glTexCoord2f(magnifyULeft, magnifyVBottom); glVertex3f(lX, tY, -tlZ);
        glTexCoord2f(magnifyURight, magnifyVBottom); glVertex3f(rX, tY, -trZ);
        glTexCoord2f(magnifyURight, magnifyVTop); glVertex3f(rX, bY, -brZ);
        glTexCoord2f(magnifyULeft, magnifyVTop); glVertex3f(lX, bY, -blZ);

        glEnd();

    } else {
        leftX = sin(leftAngle) * _distance;
        rightX = sin(rightAngle) * _distance;
        leftZ = -cos(leftAngle) * _distance;
        rightZ = -cos(rightAngle) * _distance;
        if (_uiType == CURVED_SEMICIRCLE) {
            topZ = -cos(topAngle * overlayAspectRatio) * _distance;
            bottomZ = -cos(bottomAngle * overlayAspectRatio) * _distance;
        } else {
            // Dont want to use topZ or bottomZ for SEMICIRCLE
            topZ = -99999;
            bottomZ = -99999;
        }

        float bottomY = (1.0 - newMouseY / (float)widgetHeight) * halfOverlayHeight * 2.0f - halfOverlayHeight;
        float topY = bottomY + (newHeight / widgetHeight) * halfOverlayHeight * 2;

        //TODO: Remove immediate mode in favor of VBO
        glBegin(GL_QUADS);

        glTexCoord2f(magnifyULeft, magnifyVBottom); glVertex3f(leftX, topY, max(topZ, leftZ));
        glTexCoord2f(magnifyURight, magnifyVBottom); glVertex3f(rightX, topY, max(topZ, rightZ));
        glTexCoord2f(magnifyURight, magnifyVTop); glVertex3f(rightX, bottomY, max(bottomZ, rightZ));
        glTexCoord2f(magnifyULeft, magnifyVTop); glVertex3f(leftX, bottomY, max(bottomZ, leftZ));

        glEnd();
    }
}
Example #10
0
void ApplicationOverlay::renderControllerPointer() {
    Application* application = Application::getInstance();
    QGLWidget* glWidget = application->getGLWidget();
    MyAvatar* myAvatar = application->getAvatar();

    const HandData* handData = Application::getInstance()->getAvatar()->getHandData();
    int numberOfPalms = handData->getNumPalms();

    for (unsigned int palmIndex = 2; palmIndex < 4; palmIndex++) {
        const PalmData* palmData = NULL;

        if (palmIndex >= handData->getPalms().size()) {
            return;
        }

        if (handData->getPalms()[palmIndex].isActive()) {
            palmData = &handData->getPalms()[palmIndex];
        } else {
            continue;
        }

        // Get directon relative to avatar orientation
        glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection();

        // Get the angles, scaled between 0-1
        float xAngle = (atan2(direction.z, direction.x) + M_PI_2) + 0.5f;
        float yAngle = 1.0f - ((atan2(direction.z, direction.y) + M_PI_2) + 0.5f);

        float cursorRange = glWidget->width();

        int mouseX = cursorRange * xAngle;
        int mouseY = cursorRange * yAngle;

        //If the cursor is out of the screen then don't render it
        if (mouseX < 0 || mouseX >= glWidget->width() || mouseY < 0 || mouseY >= glWidget->height()) {
            continue;
        }

        float pointerWidth = 40;
        float pointerHeight = 40;
        float crossPad = 16;
        //if we have the oculus, we should make the cursor smaller since it will be
        //magnified
        if (OculusManager::isConnected()) {
            pointerWidth /= 4;
            pointerHeight /= 4;
            crossPad /= 4;

            _mouseX[_numMagnifiers] = mouseX;
            _mouseY[_numMagnifiers] = mouseY;
            _numMagnifiers++;

        }

        mouseX -= pointerWidth / 2.0f;
        mouseY += pointerHeight / 2.0f;

        glBegin(GL_QUADS);

        glColor3f(0.0f, 0.0f, 1.0f);

        //Horizontal crosshair
        glVertex2i(mouseX, mouseY - crossPad);
        glVertex2i(mouseX + pointerWidth, mouseY - crossPad);
        glVertex2i(mouseX + pointerWidth, mouseY - pointerHeight + crossPad);
        glVertex2i(mouseX, mouseY - pointerHeight + crossPad);

        //Vertical crosshair
        glVertex2i(mouseX + crossPad, mouseY);
        glVertex2i(mouseX + pointerWidth - crossPad, mouseY);
        glVertex2i(mouseX + pointerWidth - crossPad, mouseY - pointerHeight);
        glVertex2i(mouseX + crossPad, mouseY - pointerHeight);

        glEnd();
    }
}
Example #11
0
// Draws the FBO texture for Oculus rift. TODO: Draw a curved texture instead of plane.
void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {

    Application* application = Application::getInstance();

    QGLWidget* glWidget = application->getGLWidget();
    MyAvatar* myAvatar = application->getAvatar();
    const glm::vec3& viewMatrixTranslation = application->getViewMatrixTranslation();

  

    // Get vertical FoV of the displayed overlay texture
    const float halfVerticalAngle = _oculusAngle / 2.0f;
    const float overlayAspectRatio = glWidget->width() / (float)glWidget->height();
    const float halfOverlayHeight = _distance * tan(halfVerticalAngle);
    const float overlayHeight = halfOverlayHeight * 2.0f;

    // The more vertices, the better the curve
    const int numHorizontalVertices = 20;
    const int numVerticalVertices = 20;
    // U texture coordinate width at each quad
    const float quadTexWidth = 1.0f / (numHorizontalVertices - 1);
    const float quadTexHeight = 1.0f / (numVerticalVertices - 1);

    // Get horizontal angle and angle increment from vertical angle and aspect ratio
    const float horizontalAngle = halfVerticalAngle * 2.0f * overlayAspectRatio;
    const float angleIncrement = horizontalAngle / (numHorizontalVertices - 1);
    const float halfHorizontalAngle = horizontalAngle / 2;

    const float verticalAngleIncrement = _oculusAngle / (numVerticalVertices - 1);

    glActiveTexture(GL_TEXTURE0);
   
    glEnable(GL_BLEND);
    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
    glBindTexture(GL_TEXTURE_2D, getFramebufferObject()->texture());
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glEnable(GL_TEXTURE_2D);

    glMatrixMode(GL_MODELVIEW);

    glPushMatrix();
    glLoadIdentity();
    // Transform to world space
    glm::quat rotation = whichCamera.getRotation();
    glm::vec3 axis2 = glm::axis(rotation);
    glRotatef(-glm::degrees(glm::angle(rotation)), axis2.x, axis2.y, axis2.z);
    glTranslatef(viewMatrixTranslation.x, viewMatrixTranslation.y, viewMatrixTranslation.z);

    // Translate to the front of the camera
    glm::vec3 pos = whichCamera.getPosition();
    glm::quat rot = myAvatar->getOrientation();
    glm::vec3 axis = glm::axis(rot);
   
    glTranslatef(pos.x, pos.y, pos.z);
    glRotatef(glm::degrees(glm::angle(rot)), axis.x, axis.y, axis.z);

    glColor3f(1.0f, 1.0f, 1.0f);

    glDepthMask(GL_TRUE);
    
    glEnable(GL_ALPHA_TEST);
    glAlphaFunc(GL_GREATER, 0.01f);

    float leftX, rightX, leftZ, rightZ, topZ, bottomZ;

    //Draw the magnifiers
    for (int i = 0; i < _numMagnifiers; i++) {
        renderMagnifier(_mouseX[i], _mouseY[i]);
    }

    glDepthMask(GL_FALSE);   
    glDisable(GL_ALPHA_TEST);

    //TODO: Remove immediate mode in favor of VBO
    if (_uiType == HEMISPHERE) {
        renderTexturedHemisphere();
    } else{
        glBegin(GL_QUADS);
        // Place the vertices in a semicircle curve around the camera
        for (int i = 0; i < numHorizontalVertices - 1; i++) {
            for (int j = 0; j < numVerticalVertices - 1; j++) {

                // Calculate the X and Z coordinates from the angles and radius from camera
                leftX = sin(angleIncrement * i - halfHorizontalAngle) * _distance;
                rightX = sin(angleIncrement * (i + 1) - halfHorizontalAngle) * _distance;
                leftZ = -cos(angleIncrement * i - halfHorizontalAngle) * _distance;
                rightZ = -cos(angleIncrement * (i + 1) - halfHorizontalAngle) * _distance;
                if (_uiType == 2) {
                    topZ = -cos((verticalAngleIncrement * (j + 1) - halfVerticalAngle) * overlayAspectRatio) * _distance;
                    bottomZ = -cos((verticalAngleIncrement * j - halfVerticalAngle) * overlayAspectRatio) * _distance;
                } else {
                    topZ = -99999;
                    bottomZ = -99999;
                }

                glTexCoord2f(quadTexWidth * i, (j + 1) * quadTexHeight); 
                glVertex3f(leftX, (j + 1) * quadTexHeight * overlayHeight - halfOverlayHeight, max(topZ, leftZ));
                glTexCoord2f(quadTexWidth * (i + 1), (j + 1) * quadTexHeight); 
                glVertex3f(rightX, (j + 1) * quadTexHeight * overlayHeight - halfOverlayHeight, max(topZ, rightZ));
                glTexCoord2f(quadTexWidth * (i + 1), j * quadTexHeight); 
                glVertex3f(rightX, j * quadTexHeight * overlayHeight - halfOverlayHeight, max(bottomZ, rightZ));
                glTexCoord2f(quadTexWidth * i, j * quadTexHeight); 
                glVertex3f(leftX, j * quadTexHeight * overlayHeight - halfOverlayHeight, max(bottomZ, leftZ));
            }
        }

        glEnd();
    }

    glPopMatrix();

    glDepthMask(GL_TRUE);
    glBindTexture(GL_TEXTURE_2D, 0);
    glDisable(GL_TEXTURE_2D);

    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
    glEnable(GL_LIGHTING);

}
Example #12
0
void NodeBounds::draw() {
    if (!(_showVoxelNodes || _showModelNodes || _showParticleNodes)) {
        _overlayText[0] = '\0';
        return;
    }

    NodeToJurisdictionMap& voxelServerJurisdictions = Application::getInstance()->getVoxelServerJurisdictions();
    NodeToJurisdictionMap& modelServerJurisdictions = Application::getInstance()->getModelServerJurisdictions();
    NodeToJurisdictionMap& particleServerJurisdictions = Application::getInstance()->getParticleServerJurisdictions();
    NodeToJurisdictionMap* serverJurisdictions;

    // Compute ray to find selected nodes later on.  We can't use the pre-computed ray in Application because it centers
    // itself after the cursor disappears.
    Application* application = Application::getInstance();
    QGLWidget* glWidget = application->getGLWidget();
    float mouseX = application->getMouseX() / (float)glWidget->width();
    float mouseY = application->getMouseY() / (float)glWidget->height();
    glm::vec3 mouseRayOrigin;
    glm::vec3 mouseRayDirection;
    application->getViewFrustum()->computePickRay(mouseX, mouseY, mouseRayOrigin, mouseRayDirection);

    // Variables to keep track of the selected node and properties to draw the cube later if needed
    Node* selectedNode = NULL;
    float selectedDistance = FLT_MAX;
    bool selectedIsInside = true;
    glm::vec3 selectedCenter;
    float selectedScale = 0;

    NodeList* nodeList = NodeList::getInstance();

    foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
        NodeType_t nodeType = node->getType();

        if (nodeType == NodeType::VoxelServer && _showVoxelNodes) {
            serverJurisdictions = &voxelServerJurisdictions;
        } else if (nodeType == NodeType::ModelServer && _showModelNodes) {
            serverJurisdictions = &modelServerJurisdictions;
        } else if (nodeType == NodeType::ParticleServer && _showParticleNodes) {
            serverJurisdictions = &particleServerJurisdictions;
        } else {
            continue;
        }

        QUuid nodeUUID = node->getUUID();
        if (serverJurisdictions->find(nodeUUID) != serverJurisdictions->end()) {
            const JurisdictionMap& map = serverJurisdictions->value(nodeUUID);

            unsigned char* rootCode = map.getRootOctalCode();

            if (rootCode) {
                VoxelPositionSize rootDetails;
                voxelDetailsForCode(rootCode, rootDetails);
                glm::vec3 location(rootDetails.x, rootDetails.y, rootDetails.z);
                location *= (float)TREE_SCALE;

                AABox serverBounds(location, rootDetails.s * TREE_SCALE);

                glm::vec3 center = serverBounds.getVertex(BOTTOM_RIGHT_NEAR)
                    + ((serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f);

                const float VOXEL_NODE_SCALE = 1.00f;
                const float MODEL_NODE_SCALE = 0.99f;
                const float PARTICLE_NODE_SCALE = 0.98f;

                float scaleFactor = rootDetails.s * TREE_SCALE;

                // Scale by 0.92 - 1.00 depending on the scale of the node.  This allows smaller nodes to scale in
                // a bit and not overlap larger nodes.
                scaleFactor *= 0.92 + (rootDetails.s * 0.08);

                // Scale different node types slightly differently because it's common for them to overlap.
                if (nodeType == NodeType::VoxelServer) {
                    scaleFactor *= VOXEL_NODE_SCALE;
                } else if (nodeType == NodeType::ModelServer) {
                    scaleFactor *= MODEL_NODE_SCALE;
                } else {
                    scaleFactor *= PARTICLE_NODE_SCALE;
                }

                float red, green, blue;
                getColorForNodeType(nodeType, red, green, blue);
                drawNodeBorder(center, scaleFactor, red, green, blue);

                float distance;
                BoxFace face;
                bool inside = serverBounds.contains(mouseRayOrigin);
                bool colliding = serverBounds.findRayIntersection(mouseRayOrigin, mouseRayDirection, distance, face);

                // If the camera is inside a node it will be "selected" if you don't have your cursor over another node
                // that you aren't inside.
                if (colliding && (!selectedNode || (!inside && (distance < selectedDistance || selectedIsInside)))) {
                    selectedNode = node.data();
                    selectedDistance = distance;
                    selectedIsInside = inside;
                    selectedCenter = center;
                    selectedScale = scaleFactor;
                }
            }
        }
    }

    if (selectedNode) {
        glPushMatrix();

        glTranslatef(selectedCenter.x, selectedCenter.y, selectedCenter.z);
        glScalef(selectedScale, selectedScale, selectedScale);

        NodeType_t selectedNodeType = selectedNode->getType();
        float red, green, blue;
        getColorForNodeType(selectedNode->getType(), red, green, blue);

        glColor4f(red, green, blue, 0.2);
        glutSolidCube(1.0);

        glPopMatrix();

        HifiSockAddr addr = selectedNode->getPublicSocket();
        QString overlay = QString("%1:%2  %3ms")
            .arg(addr.getAddress().toString())
            .arg(addr.getPort())
            .arg(selectedNode->getPingMs())
            .left(MAX_OVERLAY_TEXT_LENGTH);

        // Ideally we'd just use a QString, but I ran into weird blinking issues using
        // constData() directly, as if the data was being overwritten.
        strcpy(_overlayText, overlay.toLocal8Bit().constData());
    } else {
        _overlayText[0] = '\0';
    }
}
glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { 
    QGLWidget* widget = Application::getInstance()->getGLWidget();
    return glm::vec2(widget->width(), widget->height()); 
}
Example #14
0
// display expanded or contracted stats
void Stats::display(
        const float* color, 
        int horizontalOffset, 
        float fps, 
        int packetsPerSecond, 
        int bytesPerSecond, 
        int voxelPacketsToProcess) 
{
    QGLWidget* glWidget = Application::getInstance()->getGLWidget();

    unsigned int backgroundColor = 0x33333399;
    int verticalOffset = 0, lines = 0;

    QLocale locale(QLocale::English);
    std::stringstream voxelStats;

    if (_lastHorizontalOffset != horizontalOffset) {
        resetWidth(glWidget->width(), horizontalOffset);
        _lastHorizontalOffset = horizontalOffset;
    }

    glPointSize(1.0f);

    // we need to take one avatar out so we don't include ourselves
    int totalAvatars = Application::getInstance()->getAvatarManager().size() - 1;
    int totalServers = NodeList::getInstance()->size();

    lines = _expanded ? 5 : 3;
    drawBackground(backgroundColor, horizontalOffset, 0, _generalStatsWidth, lines * STATS_PELS_PER_LINE + 10);
    horizontalOffset += 5;

    char serverNodes[30];
    sprintf(serverNodes, "Servers: %d", totalServers);
    char avatarNodes[30];
    sprintf(avatarNodes, "Avatars: %d", totalAvatars);
    char framesPerSecond[30];
    sprintf(framesPerSecond, "Framerate: %3.0f FPS", fps);
 
    verticalOffset += STATS_PELS_PER_LINE;
    drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, serverNodes, color);
    verticalOffset += STATS_PELS_PER_LINE;
    drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarNodes, color);
    verticalOffset += STATS_PELS_PER_LINE;
    drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, framesPerSecond, color);

    if (_expanded) {
        char packetsPerSecondString[30];
        sprintf(packetsPerSecondString, "Pkts/sec: %d", packetsPerSecond);
        char averageMegabitsPerSecond[30];
        sprintf(averageMegabitsPerSecond, "Mbps: %3.2f", (float)bytesPerSecond * 8.f / 1000000.f);

        verticalOffset += STATS_PELS_PER_LINE;
        drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, packetsPerSecondString, color);
        verticalOffset += STATS_PELS_PER_LINE;
        drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, averageMegabitsPerSecond, color);
    }

    verticalOffset = 0;
    horizontalOffset = _lastHorizontalOffset + _generalStatsWidth +1;

    if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) {
        int pingAudio = 0, pingAvatar = 0, pingVoxel = 0, pingVoxelMax = 0;

        NodeList* nodeList = NodeList::getInstance();
        SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
        SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer);

        pingAudio = audioMixerNode ? audioMixerNode->getPingMs() : 0;
        pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : 0;

        // Now handle voxel servers, since there could be more than one, we average their ping times
        unsigned long totalPingVoxel = 0;
        int voxelServerCount = 0;

        foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
            if (node->getType() == NodeType::VoxelServer) {
                totalPingVoxel += node->getPingMs();
                voxelServerCount++;
                if (pingVoxelMax < node->getPingMs()) {
                    pingVoxelMax = node->getPingMs();
                }
            }
        }

        if (voxelServerCount) {
            pingVoxel = totalPingVoxel/voxelServerCount;
        }

        lines = _expanded ? 4 : 3;
        drawBackground(backgroundColor, horizontalOffset, 0, _pingStatsWidth, lines * STATS_PELS_PER_LINE + 10);
        horizontalOffset += 5;

        Audio* audio = Application::getInstance()->getAudio();

        char audioJitter[30];
        sprintf(audioJitter,
                "Buffer msecs %.1f",
                (float) (audio->getNetworkBufferLengthSamplesPerChannel() + (float) audio->getJitterBufferSamples()) /
                (float) audio->getNetworkSampleRate() * 1000.f);
        drawText(30, glWidget->height() - 22, 0.10f, 0.f, 2.f, audioJitter, color);
        
                 
        char audioPing[30];
        sprintf(audioPing, "Audio ping: %d", pingAudio);
       
                 
        char avatarPing[30];
        sprintf(avatarPing, "Avatar ping: %d", pingAvatar);
        char voxelAvgPing[30];
        sprintf(voxelAvgPing, "Voxel avg ping: %d", pingVoxel);

        verticalOffset += STATS_PELS_PER_LINE;
        drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, audioPing, color);
        verticalOffset += STATS_PELS_PER_LINE;
        drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarPing, color);
        verticalOffset += STATS_PELS_PER_LINE;
        drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, voxelAvgPing, color);

        if (_expanded) {
            char voxelMaxPing[30];
            sprintf(voxelMaxPing, "Voxel max ping: %d", pingVoxelMax);

            verticalOffset += STATS_PELS_PER_LINE;
            drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, voxelMaxPing, color);
        }

        verticalOffset = 0;
        horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _pingStatsWidth + 2;
    }