mirror of
https://github.com/overte-org/overte.git
synced 2025-07-23 06:44:07 +02:00
Fixed merge conflict
This commit is contained in:
commit
c96e01ef51
7 changed files with 728 additions and 621 deletions
|
@ -215,6 +215,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
|
|
||||||
_window->setCentralWidget(_glWidget);
|
_window->setCentralWidget(_glWidget);
|
||||||
|
|
||||||
|
// these are used, for example, to identify the application settings
|
||||||
|
setApplicationName("Interface");
|
||||||
|
setOrganizationDomain("highfidelity.io");
|
||||||
|
setOrganizationName("High Fidelity");
|
||||||
|
|
||||||
initMenu();
|
initMenu();
|
||||||
|
|
||||||
QRect available = desktop()->availableGeometry();
|
QRect available = desktop()->availableGeometry();
|
||||||
|
@ -227,8 +232,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
_glWidget->setMouseTracking(true);
|
_glWidget->setMouseTracking(true);
|
||||||
|
|
||||||
// initialization continues in initializeGL when OpenGL context is ready
|
// initialization continues in initializeGL when OpenGL context is ready
|
||||||
|
|
||||||
QCoreApplication::setOrganizationDomain("highfidelity.io"); // Used by QSettings on OS X
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::initializeGL() {
|
void Application::initializeGL() {
|
||||||
|
@ -289,6 +292,9 @@ void Application::initializeGL() {
|
||||||
printLog("%s", title);
|
printLog("%s", title);
|
||||||
_window->setWindowTitle(title);
|
_window->setWindowTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update before the first render
|
||||||
|
update(0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::paintGL() {
|
void Application::paintGL() {
|
||||||
|
@ -422,6 +428,7 @@ static void sendVoxelServerAddScene() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::keyPressEvent(QKeyEvent* event) {
|
void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
|
if (activeWindow() == _window) {
|
||||||
if (_chatEntryOn) {
|
if (_chatEntryOn) {
|
||||||
if (_chatEntry.keyPressEvent(event)) {
|
if (_chatEntry.keyPressEvent(event)) {
|
||||||
_myAvatar.setKeyState(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete ?
|
_myAvatar.setKeyState(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete ?
|
||||||
|
@ -626,9 +633,11 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
event->ignore();
|
event->ignore();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::keyReleaseEvent(QKeyEvent* event) {
|
void Application::keyReleaseEvent(QKeyEvent* event) {
|
||||||
|
if (activeWindow() == _window) {
|
||||||
if (_chatEntryOn) {
|
if (_chatEntryOn) {
|
||||||
_myAvatar.setKeyState(NO_KEY_DOWN);
|
_myAvatar.setKeyState(NO_KEY_DOWN);
|
||||||
return;
|
return;
|
||||||
|
@ -683,9 +692,11 @@ void Application::keyReleaseEvent(QKeyEvent* event) {
|
||||||
event->ignore();
|
event->ignore();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::mouseMoveEvent(QMouseEvent* event) {
|
void Application::mouseMoveEvent(QMouseEvent* event) {
|
||||||
|
if (activeWindow() == _window) {
|
||||||
_mouseX = event->x();
|
_mouseX = event->x();
|
||||||
_mouseY = event->y();
|
_mouseY = event->y();
|
||||||
|
|
||||||
|
@ -699,9 +710,11 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
|
||||||
deleteVoxelUnderCursor();
|
deleteVoxelUnderCursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::mousePressEvent(QMouseEvent* event) {
|
void Application::mousePressEvent(QMouseEvent* event) {
|
||||||
|
if (activeWindow() == _window) {
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
_mouseX = event->x();
|
_mouseX = event->x();
|
||||||
_mouseY = event->y();
|
_mouseY = event->y();
|
||||||
|
@ -711,17 +724,21 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
||||||
} else if (event->button() == Qt::RightButton && checkedVoxelModeAction() != 0) {
|
} else if (event->button() == Qt::RightButton && checkedVoxelModeAction() != 0) {
|
||||||
deleteVoxelUnderCursor();
|
deleteVoxelUnderCursor();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::mouseReleaseEvent(QMouseEvent* event) {
|
void Application::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
|
if (activeWindow() == _window) {
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
_mouseX = event->x();
|
_mouseX = event->x();
|
||||||
_mouseY = event->y();
|
_mouseY = event->y();
|
||||||
_mousePressed = false;
|
_mousePressed = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::wheelEvent(QWheelEvent* event) {
|
void Application::wheelEvent(QWheelEvent* event) {
|
||||||
|
if (activeWindow() == _window) {
|
||||||
if (checkedVoxelModeAction() == 0) {
|
if (checkedVoxelModeAction() == 0) {
|
||||||
event->ignore();
|
event->ignore();
|
||||||
return;
|
return;
|
||||||
|
@ -731,6 +748,7 @@ void Application::wheelEvent(QWheelEvent* event) {
|
||||||
} else {
|
} else {
|
||||||
decreaseVoxelSize();
|
decreaseVoxelSize();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Every second, check the frame rates and other stuff
|
// Every second, check the frame rates and other stuff
|
||||||
|
@ -780,197 +798,17 @@ void Application::idle() {
|
||||||
// Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran
|
// Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran
|
||||||
|
|
||||||
if (diffclock(&_lastTimeIdle, &check) > IDLE_SIMULATE_MSECS) {
|
if (diffclock(&_lastTimeIdle, &check) > IDLE_SIMULATE_MSECS) {
|
||||||
|
update(1.0f / _fps);
|
||||||
float deltaTime = 1.f/_fps;
|
|
||||||
|
|
||||||
// Use Transmitter Hand to move hand if connected, else use mouse
|
|
||||||
if (_myTransmitter.isConnected()) {
|
|
||||||
const float HAND_FORCE_SCALING = 0.01f;
|
|
||||||
glm::vec3 estimatedRotation = _myTransmitter.getEstimatedRotation();
|
|
||||||
glm::vec3 handForce(-estimatedRotation.z, -estimatedRotation.x, estimatedRotation.y);
|
|
||||||
_myAvatar.setMovedHandOffset(handForce * HAND_FORCE_SCALING);
|
|
||||||
} else {
|
|
||||||
// update behaviors for avatar hand movement: handControl takes mouse values as input,
|
|
||||||
// and gives back 3D values modulated for smooth transitioning between interaction modes.
|
|
||||||
_handControl.update(_mouseX, _mouseY);
|
|
||||||
_myAvatar.setMovedHandOffset(_handControl.getValues());
|
|
||||||
}
|
|
||||||
|
|
||||||
// tell my avatar if the mouse is being pressed...
|
|
||||||
_myAvatar.setMousePressed(_mousePressed);
|
|
||||||
|
|
||||||
// check what's under the mouse and update the mouse voxel
|
|
||||||
glm::vec3 mouseRayOrigin, mouseRayDirection;
|
|
||||||
_viewFrustum.computePickRay(_mouseX / (float)_glWidget->width(),
|
|
||||||
_mouseY / (float)_glWidget->height(), mouseRayOrigin, mouseRayDirection);
|
|
||||||
|
|
||||||
// tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position
|
|
||||||
_myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection);
|
|
||||||
|
|
||||||
_mouseVoxel.s = 0.0f;
|
|
||||||
if (checkedVoxelModeAction() != 0) {
|
|
||||||
float distance;
|
|
||||||
BoxFace face;
|
|
||||||
if (_voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _mouseVoxel, distance, face)) {
|
|
||||||
// find the nearest voxel with the desired scale
|
|
||||||
if (_mouseVoxelScale > _mouseVoxel.s) {
|
|
||||||
// choose the larger voxel that encompasses the one selected
|
|
||||||
_mouseVoxel.x = _mouseVoxelScale * floorf(_mouseVoxel.x / _mouseVoxelScale);
|
|
||||||
_mouseVoxel.y = _mouseVoxelScale * floorf(_mouseVoxel.y / _mouseVoxelScale);
|
|
||||||
_mouseVoxel.z = _mouseVoxelScale * floorf(_mouseVoxel.z / _mouseVoxelScale);
|
|
||||||
_mouseVoxel.s = _mouseVoxelScale;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
glm::vec3 faceVector = getFaceVector(face);
|
|
||||||
if (_mouseVoxelScale < _mouseVoxel.s) {
|
|
||||||
// find the closest contained voxel
|
|
||||||
glm::vec3 pt = (mouseRayOrigin + mouseRayDirection * distance) / (float)TREE_SCALE -
|
|
||||||
faceVector * (_mouseVoxelScale * 0.5f);
|
|
||||||
_mouseVoxel.x = _mouseVoxelScale * floorf(pt.x / _mouseVoxelScale);
|
|
||||||
_mouseVoxel.y = _mouseVoxelScale * floorf(pt.y / _mouseVoxelScale);
|
|
||||||
_mouseVoxel.z = _mouseVoxelScale * floorf(pt.z / _mouseVoxelScale);
|
|
||||||
_mouseVoxel.s = _mouseVoxelScale;
|
|
||||||
}
|
|
||||||
if (_addVoxelMode->isChecked()) {
|
|
||||||
// use the face to determine the side on which to create a neighbor
|
|
||||||
_mouseVoxel.x += faceVector.x * _mouseVoxel.s;
|
|
||||||
_mouseVoxel.y += faceVector.y * _mouseVoxel.s;
|
|
||||||
_mouseVoxel.z += faceVector.z * _mouseVoxel.s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (_addVoxelMode->isChecked() || _selectVoxelMode->isChecked()) {
|
|
||||||
// place the voxel a fixed distance away
|
|
||||||
float worldMouseVoxelScale = _mouseVoxelScale * TREE_SCALE;
|
|
||||||
glm::vec3 pt = mouseRayOrigin + mouseRayDirection * (2.0f + worldMouseVoxelScale * 0.5f);
|
|
||||||
_mouseVoxel.x = _mouseVoxelScale * floorf(pt.x / worldMouseVoxelScale);
|
|
||||||
_mouseVoxel.y = _mouseVoxelScale * floorf(pt.y / worldMouseVoxelScale);
|
|
||||||
_mouseVoxel.z = _mouseVoxelScale * floorf(pt.z / worldMouseVoxelScale);
|
|
||||||
_mouseVoxel.s = _mouseVoxelScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_deleteVoxelMode->isChecked()) {
|
|
||||||
// red indicates deletion
|
|
||||||
_mouseVoxel.red = 255;
|
|
||||||
_mouseVoxel.green = _mouseVoxel.blue = 0;
|
|
||||||
} else if (_selectVoxelMode->isChecked()) {
|
|
||||||
// yellow indicates deletion
|
|
||||||
_mouseVoxel.red = _mouseVoxel.green = 255;
|
|
||||||
_mouseVoxel.blue = 0;
|
|
||||||
} else { // _addVoxelMode->isChecked() || _colorVoxelMode->isChecked()
|
|
||||||
QColor paintColor = _voxelPaintColor->data().value<QColor>();
|
|
||||||
_mouseVoxel.red = paintColor.red();
|
|
||||||
_mouseVoxel.green = paintColor.green();
|
|
||||||
_mouseVoxel.blue = paintColor.blue();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we just edited, use the currently selected voxel as the "last" for drag detection
|
|
||||||
if (_justEditedVoxel) {
|
|
||||||
_lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z);
|
|
||||||
_justEditedVoxel = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// walking triggers the handControl to stop
|
|
||||||
if (_myAvatar.getMode() == AVATAR_MODE_WALKING) {
|
|
||||||
_handControl.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update from Mouse
|
|
||||||
if (_mouseLook->isChecked()) {
|
|
||||||
QPoint mouse = QCursor::pos();
|
|
||||||
_myAvatar.updateFromMouse(_glWidget->mapFromGlobal(mouse).x(),
|
|
||||||
_glWidget->mapFromGlobal(mouse).y(),
|
|
||||||
_glWidget->width(),
|
|
||||||
_glWidget->height());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read serial port interface devices
|
|
||||||
if (_serialHeadSensor.active) {
|
|
||||||
_serialHeadSensor.readData(deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update transmitter
|
|
||||||
|
|
||||||
// Sample hardware, update view frustum if needed, and send avatar data to mixer/agents
|
|
||||||
updateAvatar(deltaTime);
|
|
||||||
|
|
||||||
// read incoming packets from network
|
|
||||||
if (!_enableNetworkThread) {
|
|
||||||
networkReceive(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//loop through all the other avatars and simulate them...
|
|
||||||
AgentList* agentList = AgentList::getInstance();
|
|
||||||
agentList->lock();
|
|
||||||
for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
|
||||||
if (agent->getLinkedData() != NULL) {
|
|
||||||
Avatar *avatar = (Avatar *)agent->getLinkedData();
|
|
||||||
if (!avatar->isInitialized()) {
|
|
||||||
avatar->init();
|
|
||||||
}
|
|
||||||
avatar->simulate(deltaTime, NULL);
|
|
||||||
avatar->setMouseRay(mouseRayOrigin, mouseRayDirection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
agentList->unlock();
|
|
||||||
|
|
||||||
// Simulate myself
|
|
||||||
if (_gravityUse->isChecked()) {
|
|
||||||
_myAvatar.setGravity(_environment.getGravity(_myAvatar.getPosition()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_myAvatar.setGravity(glm::vec3(0.0f, 0.0f, 0.0f));
|
|
||||||
}
|
|
||||||
if (_transmitterDrives->isChecked() && _myTransmitter.isConnected()) {
|
|
||||||
_myAvatar.simulate(deltaTime, &_myTransmitter);
|
|
||||||
} else {
|
|
||||||
_myAvatar.simulate(deltaTime, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TESTING_AVATAR_TOUCH) {
|
|
||||||
if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) {
|
|
||||||
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
|
|
||||||
_myCamera.setModeShiftRate(1.0f);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (_myCamera.getMode() != CAMERA_MODE_MIRROR && !OculusManager::isConnected()) {
|
|
||||||
if (_manualFirstPerson) {
|
|
||||||
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) {
|
|
||||||
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
|
||||||
_myCamera.setModeShiftRate(1.0f);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (_myAvatar.getIsNearInteractingOther()) {
|
|
||||||
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) {
|
|
||||||
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
|
||||||
_myCamera.setModeShiftRate(1.0f);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) {
|
|
||||||
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
|
|
||||||
_myCamera.setModeShiftRate(1.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update audio stats for procedural sounds
|
|
||||||
#ifndef _WIN32
|
|
||||||
_audio.setLastAcceleration(_myAvatar.getThrust());
|
|
||||||
_audio.setLastVelocity(_myAvatar.getVelocity());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_glWidget->updateGL();
|
_glWidget->updateGL();
|
||||||
_lastTimeIdle = check;
|
_lastTimeIdle = check;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::terminate() {
|
void Application::terminate() {
|
||||||
// Close serial port
|
// Close serial port
|
||||||
// close(serial_fd);
|
// close(serial_fd);
|
||||||
|
|
||||||
if (_autosave) {
|
if (_settingsAutosave->isChecked()) {
|
||||||
saveSettings();
|
saveSettings();
|
||||||
_settings->sync();
|
_settings->sync();
|
||||||
}
|
}
|
||||||
|
@ -1028,7 +866,7 @@ void Application::editPreferences() {
|
||||||
QFormLayout* form = new QFormLayout();
|
QFormLayout* form = new QFormLayout();
|
||||||
layout->addLayout(form, 1);
|
layout->addLayout(form, 1);
|
||||||
|
|
||||||
QLineEdit* avatarURL = new QLineEdit(_settings->value("avatarURL").toString());
|
QLineEdit* avatarURL = new QLineEdit(_myAvatar.getVoxels()->getVoxelURL().toString());
|
||||||
avatarURL->setMinimumWidth(400);
|
avatarURL->setMinimumWidth(400);
|
||||||
form->addRow("Avatar URL:", avatarURL);
|
form->addRow("Avatar URL:", avatarURL);
|
||||||
|
|
||||||
|
@ -1045,7 +883,6 @@ void Application::editPreferences() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QUrl url(avatarURL->text());
|
QUrl url(avatarURL->text());
|
||||||
_settings->setValue("avatarURL", url);
|
|
||||||
_myAvatar.getVoxels()->setVoxelURL(url);
|
_myAvatar.getVoxels()->setVoxelURL(url);
|
||||||
sendAvatarVoxelURLMessage(url);
|
sendAvatarVoxelURLMessage(url);
|
||||||
|
|
||||||
|
@ -1477,7 +1314,7 @@ void Application::initMenu() {
|
||||||
debugMenu->addAction("Wants View Delta Sending", this, SLOT(setWantsDelta(bool)))->setCheckable(true);
|
debugMenu->addAction("Wants View Delta Sending", this, SLOT(setWantsDelta(bool)))->setCheckable(true);
|
||||||
|
|
||||||
QMenu* settingsMenu = menuBar->addMenu("Settings");
|
QMenu* settingsMenu = menuBar->addMenu("Settings");
|
||||||
(_settingsAutosave = settingsMenu->addAction("Autosave", this, SLOT(setAutosave(bool))))->setCheckable(true);
|
(_settingsAutosave = settingsMenu->addAction("Autosave"))->setCheckable(true);
|
||||||
_settingsAutosave->setChecked(true);
|
_settingsAutosave->setChecked(true);
|
||||||
settingsMenu->addAction("Load settings", this, SLOT(loadSettings()));
|
settingsMenu->addAction("Load settings", this, SLOT(loadSettings()));
|
||||||
settingsMenu->addAction("Save settings", this, SLOT(saveSettings()));
|
settingsMenu->addAction("Save settings", this, SLOT(saveSettings()));
|
||||||
|
@ -1485,7 +1322,7 @@ void Application::initMenu() {
|
||||||
settingsMenu->addAction("Export settings", this, SLOT(exportSettings()));
|
settingsMenu->addAction("Export settings", this, SLOT(exportSettings()));
|
||||||
|
|
||||||
_networkAccessManager = new QNetworkAccessManager(this);
|
_networkAccessManager = new QNetworkAccessManager(this);
|
||||||
_settings = new QSettings("High Fidelity", "Interface", this);
|
_settings = new QSettings(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateFrustumRenderModeAction() {
|
void Application::updateFrustumRenderModeAction() {
|
||||||
|
@ -1506,6 +1343,9 @@ void Application::updateFrustumRenderModeAction() {
|
||||||
case FRUSTUM_DRAW_MODE_FAR_PLANE:
|
case FRUSTUM_DRAW_MODE_FAR_PLANE:
|
||||||
_frustumRenderModeAction->setText("Render Mode - Far");
|
_frustumRenderModeAction->setText("Render Mode - Far");
|
||||||
break;
|
break;
|
||||||
|
case FRUSTUM_DRAW_MODE_KEYHOLE:
|
||||||
|
_frustumRenderModeAction->setText("Render Mode - Keyhole");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1540,10 +1380,6 @@ void Application::init() {
|
||||||
_myCamera.setModeShiftRate(1.0f);
|
_myCamera.setModeShiftRate(1.0f);
|
||||||
_myAvatar.setDisplayingLookatVectors(false);
|
_myAvatar.setDisplayingLookatVectors(false);
|
||||||
|
|
||||||
QUrl avatarURL = _settings->value("avatarURL").toUrl();
|
|
||||||
_myAvatar.getVoxels()->setVoxelURL(avatarURL);
|
|
||||||
sendAvatarVoxelURLMessage(avatarURL);
|
|
||||||
|
|
||||||
QCursor::setPos(_headMouseX, _headMouseY);
|
QCursor::setPos(_headMouseX, _headMouseY);
|
||||||
|
|
||||||
OculusManager::connect();
|
OculusManager::connect();
|
||||||
|
@ -1555,6 +1391,199 @@ void Application::init() {
|
||||||
gettimeofday(&_lastTimeIdle, NULL);
|
gettimeofday(&_lastTimeIdle, NULL);
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
||||||
|
sendAvatarVoxelURLMessage(_myAvatar.getVoxels()->getVoxelURL());
|
||||||
|
}
|
||||||
|
|
||||||
|
const float MAX_AVATAR_EDIT_VELOCITY = 1.0f;
|
||||||
|
const float MAX_VOXEL_EDIT_DISTANCE = 20.0f;
|
||||||
|
|
||||||
|
void Application::update(float deltaTime) {
|
||||||
|
// Use Transmitter Hand to move hand if connected, else use mouse
|
||||||
|
if (_myTransmitter.isConnected()) {
|
||||||
|
const float HAND_FORCE_SCALING = 0.01f;
|
||||||
|
glm::vec3 estimatedRotation = _myTransmitter.getEstimatedRotation();
|
||||||
|
glm::vec3 handForce(-estimatedRotation.z, -estimatedRotation.x, estimatedRotation.y);
|
||||||
|
_myAvatar.setMovedHandOffset(handForce * HAND_FORCE_SCALING);
|
||||||
|
} else {
|
||||||
|
// update behaviors for avatar hand movement: handControl takes mouse values as input,
|
||||||
|
// and gives back 3D values modulated for smooth transitioning between interaction modes.
|
||||||
|
_handControl.update(_mouseX, _mouseY);
|
||||||
|
_myAvatar.setMovedHandOffset(_handControl.getValues());
|
||||||
|
}
|
||||||
|
|
||||||
|
// tell my avatar if the mouse is being pressed...
|
||||||
|
_myAvatar.setMousePressed(_mousePressed);
|
||||||
|
|
||||||
|
// check what's under the mouse and update the mouse voxel
|
||||||
|
glm::vec3 mouseRayOrigin, mouseRayDirection;
|
||||||
|
_viewFrustum.computePickRay(_mouseX / (float)_glWidget->width(),
|
||||||
|
_mouseY / (float)_glWidget->height(), mouseRayOrigin, mouseRayDirection);
|
||||||
|
|
||||||
|
// tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position
|
||||||
|
_myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection);
|
||||||
|
|
||||||
|
_mouseVoxel.s = 0.0f;
|
||||||
|
if (checkedVoxelModeAction() != 0 &&
|
||||||
|
(fabs(_myAvatar.getVelocity().x) +
|
||||||
|
fabs(_myAvatar.getVelocity().y) +
|
||||||
|
fabs(_myAvatar.getVelocity().z)) / 3 < MAX_AVATAR_EDIT_VELOCITY) {
|
||||||
|
float distance;
|
||||||
|
BoxFace face;
|
||||||
|
if (_voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _mouseVoxel, distance, face)) {
|
||||||
|
if (distance < MAX_VOXEL_EDIT_DISTANCE) {
|
||||||
|
// find the nearest voxel with the desired scale
|
||||||
|
if (_mouseVoxelScale > _mouseVoxel.s) {
|
||||||
|
// choose the larger voxel that encompasses the one selected
|
||||||
|
_mouseVoxel.x = _mouseVoxelScale * floorf(_mouseVoxel.x / _mouseVoxelScale);
|
||||||
|
_mouseVoxel.y = _mouseVoxelScale * floorf(_mouseVoxel.y / _mouseVoxelScale);
|
||||||
|
_mouseVoxel.z = _mouseVoxelScale * floorf(_mouseVoxel.z / _mouseVoxelScale);
|
||||||
|
_mouseVoxel.s = _mouseVoxelScale;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
glm::vec3 faceVector = getFaceVector(face);
|
||||||
|
if (_mouseVoxelScale < _mouseVoxel.s) {
|
||||||
|
// find the closest contained voxel
|
||||||
|
glm::vec3 pt = (mouseRayOrigin + mouseRayDirection * distance) / (float)TREE_SCALE -
|
||||||
|
faceVector * (_mouseVoxelScale * 0.5f);
|
||||||
|
_mouseVoxel.x = _mouseVoxelScale * floorf(pt.x / _mouseVoxelScale);
|
||||||
|
_mouseVoxel.y = _mouseVoxelScale * floorf(pt.y / _mouseVoxelScale);
|
||||||
|
_mouseVoxel.z = _mouseVoxelScale * floorf(pt.z / _mouseVoxelScale);
|
||||||
|
_mouseVoxel.s = _mouseVoxelScale;
|
||||||
|
}
|
||||||
|
if (_addVoxelMode->isChecked()) {
|
||||||
|
// use the face to determine the side on which to create a neighbor
|
||||||
|
_mouseVoxel.x += faceVector.x * _mouseVoxel.s;
|
||||||
|
_mouseVoxel.y += faceVector.y * _mouseVoxel.s;
|
||||||
|
_mouseVoxel.z += faceVector.z * _mouseVoxel.s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_mouseVoxel.s = 0.0f;
|
||||||
|
}
|
||||||
|
} else if (_addVoxelMode->isChecked() || _selectVoxelMode->isChecked()) {
|
||||||
|
// place the voxel a fixed distance away
|
||||||
|
float worldMouseVoxelScale = _mouseVoxelScale * TREE_SCALE;
|
||||||
|
glm::vec3 pt = mouseRayOrigin + mouseRayDirection * (2.0f + worldMouseVoxelScale * 0.5f);
|
||||||
|
_mouseVoxel.x = _mouseVoxelScale * floorf(pt.x / worldMouseVoxelScale);
|
||||||
|
_mouseVoxel.y = _mouseVoxelScale * floorf(pt.y / worldMouseVoxelScale);
|
||||||
|
_mouseVoxel.z = _mouseVoxelScale * floorf(pt.z / worldMouseVoxelScale);
|
||||||
|
_mouseVoxel.s = _mouseVoxelScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_deleteVoxelMode->isChecked()) {
|
||||||
|
// red indicates deletion
|
||||||
|
_mouseVoxel.red = 255;
|
||||||
|
_mouseVoxel.green = _mouseVoxel.blue = 0;
|
||||||
|
} else if (_selectVoxelMode->isChecked()) {
|
||||||
|
// yellow indicates deletion
|
||||||
|
_mouseVoxel.red = _mouseVoxel.green = 255;
|
||||||
|
_mouseVoxel.blue = 0;
|
||||||
|
} else { // _addVoxelMode->isChecked() || _colorVoxelMode->isChecked()
|
||||||
|
QColor paintColor = _voxelPaintColor->data().value<QColor>();
|
||||||
|
_mouseVoxel.red = paintColor.red();
|
||||||
|
_mouseVoxel.green = paintColor.green();
|
||||||
|
_mouseVoxel.blue = paintColor.blue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we just edited, use the currently selected voxel as the "last" for drag detection
|
||||||
|
if (_justEditedVoxel) {
|
||||||
|
_lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z);
|
||||||
|
_justEditedVoxel = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// walking triggers the handControl to stop
|
||||||
|
if (_myAvatar.getMode() == AVATAR_MODE_WALKING) {
|
||||||
|
_handControl.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update from Mouse
|
||||||
|
if (_mouseLook->isChecked()) {
|
||||||
|
QPoint mouse = QCursor::pos();
|
||||||
|
_myAvatar.updateFromMouse(_glWidget->mapFromGlobal(mouse).x(),
|
||||||
|
_glWidget->mapFromGlobal(mouse).y(),
|
||||||
|
_glWidget->width(),
|
||||||
|
_glWidget->height());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read serial port interface devices
|
||||||
|
if (_serialHeadSensor.active) {
|
||||||
|
_serialHeadSensor.readData(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update transmitter
|
||||||
|
|
||||||
|
// Sample hardware, update view frustum if needed, and send avatar data to mixer/agents
|
||||||
|
updateAvatar(deltaTime);
|
||||||
|
|
||||||
|
// read incoming packets from network
|
||||||
|
if (!_enableNetworkThread) {
|
||||||
|
networkReceive(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//loop through all the other avatars and simulate them...
|
||||||
|
AgentList* agentList = AgentList::getInstance();
|
||||||
|
agentList->lock();
|
||||||
|
for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||||
|
if (agent->getLinkedData() != NULL) {
|
||||||
|
Avatar *avatar = (Avatar *)agent->getLinkedData();
|
||||||
|
if (!avatar->isInitialized()) {
|
||||||
|
avatar->init();
|
||||||
|
}
|
||||||
|
avatar->simulate(deltaTime, NULL);
|
||||||
|
avatar->setMouseRay(mouseRayOrigin, mouseRayDirection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
agentList->unlock();
|
||||||
|
|
||||||
|
// Simulate myself
|
||||||
|
if (_gravityUse->isChecked()) {
|
||||||
|
_myAvatar.setGravity(_environment.getGravity(_myAvatar.getPosition()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_myAvatar.setGravity(glm::vec3(0.0f, 0.0f, 0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_transmitterDrives->isChecked() && _myTransmitter.isConnected()) {
|
||||||
|
_myAvatar.simulate(deltaTime, &_myTransmitter);
|
||||||
|
} else {
|
||||||
|
_myAvatar.simulate(deltaTime, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TESTING_AVATAR_TOUCH) {
|
||||||
|
if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) {
|
||||||
|
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
|
||||||
|
_myCamera.setModeShiftRate(1.0f);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_myCamera.getMode() != CAMERA_MODE_MIRROR && !OculusManager::isConnected()) {
|
||||||
|
if (_manualFirstPerson) {
|
||||||
|
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) {
|
||||||
|
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
||||||
|
_myCamera.setModeShiftRate(1.0f);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_myAvatar.getIsNearInteractingOther()) {
|
||||||
|
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) {
|
||||||
|
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
||||||
|
_myCamera.setModeShiftRate(1.0f);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) {
|
||||||
|
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
|
||||||
|
_myCamera.setModeShiftRate(1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update audio stats for procedural sounds
|
||||||
|
#ifndef _WIN32
|
||||||
|
_audio.setLastAcceleration(_myAvatar.getThrust());
|
||||||
|
_audio.setLastVelocity(_myAvatar.getVelocity());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateAvatar(float deltaTime) {
|
void Application::updateAvatar(float deltaTime) {
|
||||||
|
@ -2245,9 +2274,20 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) {
|
||||||
glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z);
|
glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z);
|
||||||
glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z);
|
glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z);
|
||||||
}
|
}
|
||||||
|
|
||||||
glEnd();
|
glEnd();
|
||||||
glEnable(GL_LIGHTING);
|
glEnable(GL_LIGHTING);
|
||||||
|
|
||||||
|
if (_frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || _frustumDrawingMode == FRUSTUM_DRAW_MODE_KEYHOLE) {
|
||||||
|
// Draw the keyhole
|
||||||
|
float keyholeRadius = viewFrustum.getKeyholeRadius();
|
||||||
|
if (keyholeRadius > 0.0f) {
|
||||||
|
glPushMatrix();
|
||||||
|
glColor4f(1, 1, 0, 1);
|
||||||
|
glTranslatef(position.x, position.y, position.z); // where we actually want it!
|
||||||
|
glutWireSphere(keyholeRadius, 20, 20);
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setupPaintingVoxel() {
|
void Application::setupPaintingVoxel() {
|
||||||
|
@ -2529,10 +2569,6 @@ void Application::saveAction(QSettings* set, QAction* action) {
|
||||||
set->setValue(action->text(), action->isChecked());
|
set->setValue(action->text(), action->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setAutosave(bool wantsAutosave) {
|
|
||||||
_autosave = wantsAutosave;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::loadSettings(QSettings* set) {
|
void Application::loadSettings(QSettings* set) {
|
||||||
if (!set) set = getSettings();
|
if (!set) set = getSettings();
|
||||||
|
|
||||||
|
@ -2547,8 +2583,6 @@ void Application::saveSettings(QSettings* set) {
|
||||||
set->setValue("headCameraPitchYawScale", _headCameraPitchYawScale);
|
set->setValue("headCameraPitchYawScale", _headCameraPitchYawScale);
|
||||||
scanMenuBar(&Application::saveAction, set);
|
scanMenuBar(&Application::saveAction, set);
|
||||||
getAvatar()->saveData(set);
|
getAvatar()->saveData(set);
|
||||||
|
|
||||||
set->sync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::importSettings() {
|
void Application::importSettings() {
|
||||||
|
|
|
@ -112,7 +112,6 @@ private slots:
|
||||||
void decreaseVoxelSize();
|
void decreaseVoxelSize();
|
||||||
void increaseVoxelSize();
|
void increaseVoxelSize();
|
||||||
void chooseVoxelPaintColor();
|
void chooseVoxelPaintColor();
|
||||||
void setAutosave(bool wantsAutosave);
|
|
||||||
void loadSettings(QSettings* set = NULL);
|
void loadSettings(QSettings* set = NULL);
|
||||||
void saveSettings(QSettings* set = NULL);
|
void saveSettings(QSettings* set = NULL);
|
||||||
void importSettings();
|
void importSettings();
|
||||||
|
@ -132,6 +131,7 @@ private:
|
||||||
void initDisplay();
|
void initDisplay();
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
void update(float deltaTime);
|
||||||
void updateAvatar(float deltaTime);
|
void updateAvatar(float deltaTime);
|
||||||
void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum);
|
void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum);
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ private:
|
||||||
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
||||||
|
|
||||||
enum FrustumDrawMode { FRUSTUM_DRAW_MODE_ALL, FRUSTUM_DRAW_MODE_VECTORS, FRUSTUM_DRAW_MODE_PLANES,
|
enum FrustumDrawMode { FRUSTUM_DRAW_MODE_ALL, FRUSTUM_DRAW_MODE_VECTORS, FRUSTUM_DRAW_MODE_PLANES,
|
||||||
FRUSTUM_DRAW_MODE_NEAR_PLANE, FRUSTUM_DRAW_MODE_FAR_PLANE, FRUSTUM_DRAW_MODE_COUNT };
|
FRUSTUM_DRAW_MODE_NEAR_PLANE, FRUSTUM_DRAW_MODE_FAR_PLANE, FRUSTUM_DRAW_MODE_KEYHOLE, FRUSTUM_DRAW_MODE_COUNT };
|
||||||
FrustumDrawMode _frustumDrawingMode;
|
FrustumDrawMode _frustumDrawingMode;
|
||||||
|
|
||||||
float _viewFrustumOffsetYaw; // the following variables control yaw, pitch, roll and distance form regular
|
float _viewFrustumOffsetYaw; // the following variables control yaw, pitch, roll and distance form regular
|
||||||
|
@ -294,8 +294,6 @@ private:
|
||||||
int _packetsPerSecond;
|
int _packetsPerSecond;
|
||||||
int _bytesPerSecond;
|
int _bytesPerSecond;
|
||||||
int _bytesCount;
|
int _bytesCount;
|
||||||
|
|
||||||
bool _autosave; // True if the autosave is on.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__interface__Application__) */
|
#endif /* defined(__interface__Application__) */
|
||||||
|
|
|
@ -1225,6 +1225,8 @@ void Avatar::loadData(QSettings* set) {
|
||||||
_position.y = set->value("position_y", _position.y).toFloat();
|
_position.y = set->value("position_y", _position.y).toFloat();
|
||||||
_position.z = set->value("position_z", _position.z).toFloat();
|
_position.z = set->value("position_z", _position.z).toFloat();
|
||||||
|
|
||||||
|
_voxels.setVoxelURL(set->value("voxelURL").toUrl());
|
||||||
|
|
||||||
set->endGroup();
|
set->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1244,6 +1246,8 @@ void Avatar::saveData(QSettings* set) {
|
||||||
set->setValue("position_y", _position.y);
|
set->setValue("position_y", _position.y);
|
||||||
set->setValue("position_z", _position.z);
|
set->setValue("position_z", _position.z);
|
||||||
|
|
||||||
|
set->setValue("voxelURL", _voxels.getVoxelURL());
|
||||||
|
|
||||||
set->endGroup();
|
set->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ void Camera::updateFollowMode(float deltaTime) {
|
||||||
_distance = _previousDistance * (1.0f - _modeShift) + _newDistance * _modeShift;
|
_distance = _previousDistance * (1.0f - _modeShift) + _newDistance * _modeShift;
|
||||||
_tightness = _previousTightness * (1.0f - _modeShift) + _newTightness * _modeShift;
|
_tightness = _previousTightness * (1.0f - _modeShift) + _newTightness * _modeShift;
|
||||||
|
|
||||||
if (_linearModeShift > 1.0f ) {
|
if (_needsToInitialize || _linearModeShift > 1.0f) {
|
||||||
_linearModeShift = 1.0f;
|
_linearModeShift = 1.0f;
|
||||||
_modeShift = 1.0f;
|
_modeShift = 1.0f;
|
||||||
_upShift = _newUpShift;
|
_upShift = _newUpShift;
|
||||||
|
|
|
@ -24,12 +24,13 @@ enum BoxFace {
|
||||||
|
|
||||||
const int FACE_COUNT = 6;
|
const int FACE_COUNT = 6;
|
||||||
|
|
||||||
class AABox
|
class AABox
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(x,y,z) { };
|
AABox(const glm::vec3& corner, float size) : _corner(corner), _size(size, size, size) { };
|
||||||
|
AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(x, y, z) { };
|
||||||
AABox(const glm::vec3& corner, const glm::vec3& size) : _corner(corner), _size(size) { };
|
AABox(const glm::vec3& corner, const glm::vec3& size) : _corner(corner), _size(size) { };
|
||||||
AABox() : _corner(0,0,0), _size(0,0,0) { }
|
AABox() : _corner(0,0,0), _size(0,0,0) { }
|
||||||
~AABox() { }
|
~AABox() { }
|
||||||
|
|
|
@ -29,6 +29,7 @@ ViewFrustum::ViewFrustum() :
|
||||||
_aspectRatio(1.0),
|
_aspectRatio(1.0),
|
||||||
_nearClip(0.1),
|
_nearClip(0.1),
|
||||||
_farClip(500.0),
|
_farClip(500.0),
|
||||||
|
_keyholeRadius(DEFAULT_KEYHOLE_RADIUS),
|
||||||
_farTopLeft(0,0,0),
|
_farTopLeft(0,0,0),
|
||||||
_farTopRight(0,0,0),
|
_farTopRight(0,0,0),
|
||||||
_farBottomLeft(0,0,0),
|
_farBottomLeft(0,0,0),
|
||||||
|
@ -36,7 +37,9 @@ ViewFrustum::ViewFrustum() :
|
||||||
_nearTopLeft(0,0,0),
|
_nearTopLeft(0,0,0),
|
||||||
_nearTopRight(0,0,0),
|
_nearTopRight(0,0,0),
|
||||||
_nearBottomLeft(0,0,0),
|
_nearBottomLeft(0,0,0),
|
||||||
_nearBottomRight(0,0,0) { }
|
_nearBottomRight(0,0,0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) {
|
void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) {
|
||||||
_orientation = orientationAsQuaternion;
|
_orientation = orientationAsQuaternion;
|
||||||
|
@ -114,42 +117,6 @@ void ViewFrustum::calculate() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewFrustum::dump() const {
|
|
||||||
|
|
||||||
printLog("position.x=%f, position.y=%f, position.z=%f\n", _position.x, _position.y, _position.z);
|
|
||||||
printLog("direction.x=%f, direction.y=%f, direction.z=%f\n", _direction.x, _direction.y, _direction.z);
|
|
||||||
printLog("up.x=%f, up.y=%f, up.z=%f\n", _up.x, _up.y, _up.z);
|
|
||||||
printLog("right.x=%f, right.y=%f, right.z=%f\n", _right.x, _right.y, _right.z);
|
|
||||||
|
|
||||||
printLog("farDist=%f\n", _farClip);
|
|
||||||
|
|
||||||
printLog("nearDist=%f\n", _nearClip);
|
|
||||||
|
|
||||||
printLog("eyeOffsetPosition=%f,%f,%f\n", _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z);
|
|
||||||
|
|
||||||
printLog("eyeOffsetOrientation=%f,%f,%f,%f\n", _eyeOffsetOrientation.x, _eyeOffsetOrientation.y,
|
|
||||||
_eyeOffsetOrientation.z, _eyeOffsetOrientation.w);
|
|
||||||
|
|
||||||
printLog("farTopLeft.x=%f, farTopLeft.y=%f, farTopLeft.z=%f\n",
|
|
||||||
_farTopLeft.x, _farTopLeft.y, _farTopLeft.z);
|
|
||||||
printLog("farTopRight.x=%f, farTopRight.y=%f, farTopRight.z=%f\n",
|
|
||||||
_farTopRight.x, _farTopRight.y, _farTopRight.z);
|
|
||||||
printLog("farBottomLeft.x=%f, farBottomLeft.y=%f, farBottomLeft.z=%f\n",
|
|
||||||
_farBottomLeft.x, _farBottomLeft.y, _farBottomLeft.z);
|
|
||||||
printLog("farBottomRight.x=%f, farBottomRight.y=%f, farBottomRight.z=%f\n",
|
|
||||||
_farBottomRight.x, _farBottomRight.y, _farBottomRight.z);
|
|
||||||
|
|
||||||
printLog("nearTopLeft.x=%f, nearTopLeft.y=%f, nearTopLeft.z=%f\n",
|
|
||||||
_nearTopLeft.x, _nearTopLeft.y, _nearTopLeft.z);
|
|
||||||
printLog("nearTopRight.x=%f, nearTopRight.y=%f, nearTopRight.z=%f\n",
|
|
||||||
_nearTopRight.x, _nearTopRight.y, _nearTopRight.z);
|
|
||||||
printLog("nearBottomLeft.x=%f, nearBottomLeft.y=%f, nearBottomLeft.z=%f\n",
|
|
||||||
_nearBottomLeft.x, _nearBottomLeft.y, _nearBottomLeft.z);
|
|
||||||
printLog("nearBottomRight.x=%f, nearBottomRight.y=%f, nearBottomRight.z=%f\n",
|
|
||||||
_nearBottomRight.x, _nearBottomRight.y, _nearBottomRight.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
//enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
||||||
const char* ViewFrustum::debugPlaneName (int plane) const {
|
const char* ViewFrustum::debugPlaneName (int plane) const {
|
||||||
switch (plane) {
|
switch (plane) {
|
||||||
|
@ -163,52 +130,147 @@ const char* ViewFrustum::debugPlaneName (int plane) const {
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ViewFrustum::location ViewFrustum::pointInSphere(const glm::vec3& point, const glm::vec3& center, float radius ) const {
|
||||||
|
|
||||||
|
ViewFrustum::location result = INTERSECT;
|
||||||
|
|
||||||
|
float distance = glm::distance(point, center);
|
||||||
|
if (distance > radius) {
|
||||||
|
result = OUTSIDE;
|
||||||
|
} else if (distance < radius) {
|
||||||
|
result = INSIDE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To determine if two spheres intersect, simply calculate the distance between the centers of the two spheres.
|
||||||
|
// If the distance is greater than the sum of the two sphere radii, they don’t intersect. Otherwise they intersect.
|
||||||
|
// If the distance plus the radius of sphere A is less than the radius of sphere B then, sphere A is inside of sphere B
|
||||||
|
ViewFrustum::location ViewFrustum::sphereInSphere(const glm::vec3& centerA, float radiusA,
|
||||||
|
const glm::vec3& centerB, float radiusB ) const {
|
||||||
|
|
||||||
|
ViewFrustum::location result = INTERSECT;
|
||||||
|
|
||||||
|
float distanceFromAtoB = glm::distance(centerA, centerB);
|
||||||
|
if (distanceFromAtoB > (radiusA + radiusB)) {
|
||||||
|
result = OUTSIDE;
|
||||||
|
} else if ((distanceFromAtoB + radiusA) < radiusB) {
|
||||||
|
result = INSIDE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A box is inside a sphere if all of its corners are inside the sphere
|
||||||
|
// A box intersects a sphere if any of its edges (as rays) interesect the sphere
|
||||||
|
// A box is outside a sphere if none of its edges (as rays) interesect the sphere
|
||||||
|
ViewFrustum::location ViewFrustum::boxInSphere(const AABox& box, const glm::vec3& center, float radius) const {
|
||||||
|
glm::vec3 penetration;
|
||||||
|
bool intersects = box.findSpherePenetration(center, radius, penetration);
|
||||||
|
|
||||||
|
ViewFrustum::location result = OUTSIDE;
|
||||||
|
|
||||||
|
// if the box intersects the sphere, then it may also be inside... calculate further
|
||||||
|
if (intersects) {
|
||||||
|
result = INTERSECT;
|
||||||
|
|
||||||
|
// test all the corners, if they are all inside the sphere, the entire box is in the sphere
|
||||||
|
glm::vec3 testPoint = box.getCorner();
|
||||||
|
glm::vec3 size = box.getSize();
|
||||||
|
if (pointInSphere(testPoint, center, radius)) {
|
||||||
|
testPoint = box.getCorner() + glm::vec3(size.x, 0.0f, 0.0f);
|
||||||
|
if (pointInSphere(testPoint, center, radius)) {
|
||||||
|
testPoint = box.getCorner() + glm::vec3(0.0f, 0.0f, size.z);
|
||||||
|
if (pointInSphere(testPoint, center, radius)) {
|
||||||
|
testPoint = box.getCorner() + glm::vec3(size.x, 0.0f, size.z);
|
||||||
|
if (pointInSphere(testPoint, center, radius)) {
|
||||||
|
testPoint = box.getCorner() + glm::vec3(0.0f, size.y, 0.0f);
|
||||||
|
if (pointInSphere(testPoint, center, radius)) {
|
||||||
|
testPoint = box.getCorner() + glm::vec3(size.x, size.y, 0.0f);
|
||||||
|
if (pointInSphere(testPoint, center, radius)) {
|
||||||
|
testPoint = box.getCorner() + glm::vec3(0.0f, size.y, size.z);
|
||||||
|
if (pointInSphere(testPoint, center, radius)) {
|
||||||
|
testPoint = box.getCorner() + glm::vec3(size.x, size.y, size.z);
|
||||||
|
if (pointInSphere(testPoint, center, radius)) {
|
||||||
|
result = INSIDE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const {
|
ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const {
|
||||||
|
ViewFrustum::location regularResult = INSIDE;
|
||||||
|
ViewFrustum::location keyholeResult = OUTSIDE;
|
||||||
|
|
||||||
//printf("ViewFrustum::pointInFrustum() point=%f,%f,%f\n",point.x,point.y,point.z);
|
// If we have a keyholeRadius, check that first, since it's cheaper
|
||||||
//dump();
|
if (_keyholeRadius >= 0.0f) {
|
||||||
|
keyholeResult = pointInSphere(point, _position, _keyholeRadius);
|
||||||
|
}
|
||||||
|
if (keyholeResult == INSIDE) {
|
||||||
|
return keyholeResult;
|
||||||
|
}
|
||||||
|
|
||||||
ViewFrustum::location result = INSIDE;
|
// If we're not known to be INSIDE the keyhole, then check the regular frustum
|
||||||
for(int i=0; i < 6; i++) {
|
for(int i=0; i < 6; i++) {
|
||||||
float distance = _planes[i].distance(point);
|
float distance = _planes[i].distance(point);
|
||||||
|
|
||||||
//printf("plane[%d] %s -- distance=%f \n",i,debugPlaneName(i),distance);
|
|
||||||
|
|
||||||
if (distance < 0) {
|
if (distance < 0) {
|
||||||
return OUTSIDE;
|
return keyholeResult; // escape early will be the value from checking the keyhole
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(result);
|
|
||||||
|
return regularResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
|
ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
|
||||||
ViewFrustum::location result = INSIDE;
|
ViewFrustum::location regularResult = INSIDE;
|
||||||
|
ViewFrustum::location keyholeResult = OUTSIDE;
|
||||||
|
|
||||||
|
// If we have a keyholeRadius, check that first, since it's cheaper
|
||||||
|
if (_keyholeRadius >= 0.0f) {
|
||||||
|
keyholeResult = sphereInSphere(center, radius, _position, _keyholeRadius);
|
||||||
|
}
|
||||||
|
if (keyholeResult == INSIDE) {
|
||||||
|
return keyholeResult;
|
||||||
|
}
|
||||||
|
|
||||||
float distance;
|
float distance;
|
||||||
for(int i=0; i < 6; i++) {
|
for(int i=0; i < 6; i++) {
|
||||||
distance = _planes[i].distance(center);
|
distance = _planes[i].distance(center);
|
||||||
if (distance < -radius)
|
if (distance < -radius) {
|
||||||
return OUTSIDE;
|
// This is outside the regular frustum, so just return the value from checking the keyhole
|
||||||
else if (distance < radius)
|
return keyholeResult;
|
||||||
result = INTERSECT;
|
} else if (distance < radius) {
|
||||||
|
regularResult = INTERSECT;
|
||||||
}
|
}
|
||||||
return(result);
|
}
|
||||||
|
|
||||||
|
return regularResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
|
ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
|
||||||
|
ViewFrustum::location regularResult = INSIDE;
|
||||||
|
ViewFrustum::location keyholeResult = OUTSIDE;
|
||||||
|
|
||||||
|
// If we have a keyholeRadius, check that first, since it's cheaper
|
||||||
|
if (_keyholeRadius >= 0.0f) {
|
||||||
|
keyholeResult = boxInSphere(box, _position, _keyholeRadius);
|
||||||
|
}
|
||||||
|
if (keyholeResult == INSIDE) {
|
||||||
|
return keyholeResult;
|
||||||
|
}
|
||||||
|
|
||||||
//printf("ViewFrustum::boxInFrustum() box.corner=%f,%f,%f x=%f\n",
|
|
||||||
// box.getCorner().x,box.getCorner().y,box.getCorner().z,box.getSize().x);
|
|
||||||
ViewFrustum::location result = INSIDE;
|
|
||||||
for(int i=0; i < 6; i++) {
|
for(int i=0; i < 6; i++) {
|
||||||
|
|
||||||
//printf("plane[%d] -- point(%f,%f,%f) normal(%f,%f,%f) d=%f \n",i,
|
|
||||||
// _planes[i].getPoint().x, _planes[i].getPoint().y, _planes[i].getPoint().z,
|
|
||||||
// _planes[i].getNormal().x, _planes[i].getNormal().y, _planes[i].getNormal().z,
|
|
||||||
// _planes[i].getDCoefficient()
|
|
||||||
//);
|
|
||||||
|
|
||||||
glm::vec3 normal = _planes[i].getNormal();
|
glm::vec3 normal = _planes[i].getNormal();
|
||||||
glm::vec3 boxVertexP = box.getVertexP(normal);
|
glm::vec3 boxVertexP = box.getVertexP(normal);
|
||||||
float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP);
|
float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP);
|
||||||
|
@ -216,19 +278,14 @@ ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
|
||||||
glm::vec3 boxVertexN = box.getVertexN(normal);
|
glm::vec3 boxVertexN = box.getVertexN(normal);
|
||||||
float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN);
|
float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN);
|
||||||
|
|
||||||
//printf("plane[%d] normal=(%f,%f,%f) bVertexP=(%f,%f,%f) planeToBoxVertexPDistance=%f boxVertexN=(%f,%f,%f) planeToBoxVertexNDistance=%f\n",i,
|
|
||||||
// normal.x,normal.y,normal.z,
|
|
||||||
// boxVertexP.x,boxVertexP.y,boxVertexP.z,planeToBoxVertexPDistance,
|
|
||||||
// boxVertexN.x,boxVertexN.y,boxVertexN.z,planeToBoxVertexNDistance
|
|
||||||
// );
|
|
||||||
|
|
||||||
if (planeToBoxVertexPDistance < 0) {
|
if (planeToBoxVertexPDistance < 0) {
|
||||||
return OUTSIDE;
|
// This is outside the regular frustum, so just return the value from checking the keyhole
|
||||||
|
return keyholeResult;
|
||||||
} else if (planeToBoxVertexNDistance < 0) {
|
} else if (planeToBoxVertexNDistance < 0) {
|
||||||
result = INTERSECT;
|
regularResult = INTERSECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(result);
|
return regularResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool testMatches(glm::quat lhs, glm::quat rhs) {
|
bool testMatches(glm::quat lhs, glm::quat rhs) {
|
||||||
|
|
|
@ -16,44 +16,9 @@
|
||||||
#include "Plane.h"
|
#include "Plane.h"
|
||||||
#include "AABox.h"
|
#include "AABox.h"
|
||||||
|
|
||||||
|
const float DEFAULT_KEYHOLE_RADIUS = 2.0f;
|
||||||
|
|
||||||
class ViewFrustum {
|
class ViewFrustum {
|
||||||
private:
|
|
||||||
|
|
||||||
// camera location/orientation attributes
|
|
||||||
glm::vec3 _position;
|
|
||||||
glm::quat _orientation;
|
|
||||||
|
|
||||||
// calculated for orientation
|
|
||||||
glm::vec3 _direction;
|
|
||||||
glm::vec3 _up;
|
|
||||||
glm::vec3 _right;
|
|
||||||
|
|
||||||
// Lens attributes
|
|
||||||
float _fieldOfView;
|
|
||||||
float _aspectRatio;
|
|
||||||
float _nearClip;
|
|
||||||
float _farClip;
|
|
||||||
glm::vec3 _eyeOffsetPosition;
|
|
||||||
glm::quat _eyeOffsetOrientation;
|
|
||||||
|
|
||||||
// Calculated values
|
|
||||||
glm::vec3 _offsetPosition;
|
|
||||||
glm::vec3 _offsetDirection;
|
|
||||||
glm::vec3 _offsetUp;
|
|
||||||
glm::vec3 _offsetRight;
|
|
||||||
glm::vec3 _farTopLeft;
|
|
||||||
glm::vec3 _farTopRight;
|
|
||||||
glm::vec3 _farBottomLeft;
|
|
||||||
glm::vec3 _farBottomRight;
|
|
||||||
glm::vec3 _nearTopLeft;
|
|
||||||
glm::vec3 _nearTopRight;
|
|
||||||
glm::vec3 _nearBottomLeft;
|
|
||||||
glm::vec3 _nearBottomRight;
|
|
||||||
enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
|
||||||
Plane _planes[6]; // How will this be used?
|
|
||||||
|
|
||||||
const char* debugPlaneName (int plane) const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// setters for camera attributes
|
// setters for camera attributes
|
||||||
void setPosition (const glm::vec3& p) { _position = p; };
|
void setPosition (const glm::vec3& p) { _position = p; };
|
||||||
|
@ -74,7 +39,6 @@ public:
|
||||||
void setEyeOffsetPosition (const glm::vec3& p) { _eyeOffsetPosition = p; };
|
void setEyeOffsetPosition (const glm::vec3& p) { _eyeOffsetPosition = p; };
|
||||||
void setEyeOffsetOrientation (const glm::quat& o) { _eyeOffsetOrientation = o; };
|
void setEyeOffsetOrientation (const glm::quat& o) { _eyeOffsetOrientation = o; };
|
||||||
|
|
||||||
|
|
||||||
// getters for lens attributes
|
// getters for lens attributes
|
||||||
float getFieldOfView() const { return _fieldOfView; };
|
float getFieldOfView() const { return _fieldOfView; };
|
||||||
float getAspectRatio() const { return _aspectRatio; };
|
float getAspectRatio() const { return _aspectRatio; };
|
||||||
|
@ -98,12 +62,14 @@ public:
|
||||||
const glm::vec3& getNearBottomLeft() const { return _nearBottomLeft; };
|
const glm::vec3& getNearBottomLeft() const { return _nearBottomLeft; };
|
||||||
const glm::vec3& getNearBottomRight() const { return _nearBottomRight;};
|
const glm::vec3& getNearBottomRight() const { return _nearBottomRight;};
|
||||||
|
|
||||||
|
// get/set for keyhole attribute
|
||||||
|
void setKeyholeRadius(float keyholdRadius) { _keyholeRadius = keyholdRadius; };
|
||||||
|
float getKeyholeRadius() const { return _keyholeRadius; };
|
||||||
|
|
||||||
void calculate();
|
void calculate();
|
||||||
|
|
||||||
ViewFrustum();
|
ViewFrustum();
|
||||||
|
|
||||||
void dump() const;
|
|
||||||
|
|
||||||
typedef enum {OUTSIDE, INTERSECT, INSIDE} location;
|
typedef enum {OUTSIDE, INTERSECT, INSIDE} location;
|
||||||
|
|
||||||
ViewFrustum::location pointInFrustum(const glm::vec3& point) const;
|
ViewFrustum::location pointInFrustum(const glm::vec3& point) const;
|
||||||
|
@ -120,6 +86,53 @@ public:
|
||||||
glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
|
glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
|
||||||
|
|
||||||
void printDebugDetails() const;
|
void printDebugDetails() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Used for keyhole calculations
|
||||||
|
ViewFrustum::location pointInSphere(const glm::vec3& point, const glm::vec3& center, float radius) const;
|
||||||
|
ViewFrustum::location sphereInSphere(const glm::vec3& centerA, float radiusA, const glm::vec3& centerB, float radiusB) const;
|
||||||
|
ViewFrustum::location boxInSphere(const AABox& box, const glm::vec3& center, float radius) const;
|
||||||
|
|
||||||
|
// camera location/orientation attributes
|
||||||
|
glm::vec3 _position;
|
||||||
|
glm::quat _orientation;
|
||||||
|
|
||||||
|
// calculated for orientation
|
||||||
|
glm::vec3 _direction;
|
||||||
|
glm::vec3 _up;
|
||||||
|
glm::vec3 _right;
|
||||||
|
|
||||||
|
// Lens attributes
|
||||||
|
float _fieldOfView;
|
||||||
|
float _aspectRatio;
|
||||||
|
float _nearClip;
|
||||||
|
float _farClip;
|
||||||
|
glm::vec3 _eyeOffsetPosition;
|
||||||
|
glm::quat _eyeOffsetOrientation;
|
||||||
|
|
||||||
|
// keyhole attributes
|
||||||
|
float _keyholeRadius;
|
||||||
|
|
||||||
|
|
||||||
|
// Calculated values
|
||||||
|
glm::vec3 _offsetPosition;
|
||||||
|
glm::vec3 _offsetDirection;
|
||||||
|
glm::vec3 _offsetUp;
|
||||||
|
glm::vec3 _offsetRight;
|
||||||
|
glm::vec3 _farTopLeft;
|
||||||
|
glm::vec3 _farTopRight;
|
||||||
|
glm::vec3 _farBottomLeft;
|
||||||
|
glm::vec3 _farBottomRight;
|
||||||
|
glm::vec3 _nearTopLeft;
|
||||||
|
glm::vec3 _nearTopRight;
|
||||||
|
glm::vec3 _nearBottomLeft;
|
||||||
|
glm::vec3 _nearBottomRight;
|
||||||
|
enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
||||||
|
Plane _planes[6]; // How will this be used?
|
||||||
|
|
||||||
|
const char* debugPlaneName (int plane) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue