Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels

This commit is contained in:
Andrzej Kapolka 2014-12-01 16:43:39 -08:00
commit 5b4869f43d
23 changed files with 377 additions and 157 deletions

View file

@ -10,6 +10,7 @@
//
#include <QtCore/QProcess>
#include <QtCore/qsharedmemory.h>
#include <QtCore/QThread>
#include <QtCore/QTimer>
@ -38,7 +39,8 @@ int hifiSockAddrMeta = qRegisterMetaType<HifiSockAddr>("HifiSockAddr");
AssignmentClient::AssignmentClient(int &argc, char **argv) :
QCoreApplication(argc, argv),
_shutdownEventListener(this),
_assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME)
_assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME),
_localASPortSharedMem(NULL)
{
LogUtils::init();
@ -89,13 +91,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
// create a NodeList as an unassigned client
NodeList* nodeList = NodeList::createInstance(NodeType::Unassigned);
unsigned short assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT;
// check for an overriden assignment server port
if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION)) {
assignmentServerPort =
argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toString().toUInt();
}
quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT;
// check for an overriden assignment server hostname
if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION)) {
@ -103,10 +99,16 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
_assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString();
}
HifiSockAddr assignmentServerSocket(_assignmentServerHostname, assignmentServerPort, true);
nodeList->setAssignmentServerSocket(assignmentServerSocket);
// check for an overriden assignment server port
if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION)) {
assignmentServerPort =
argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toString().toUInt();
}
_assignmentServerSocket = HifiSockAddr(_assignmentServerHostname, assignmentServerPort, true);
nodeList->setAssignmentServerSocket(_assignmentServerSocket);
qDebug() << "Assignment server socket is" << assignmentServerSocket;
qDebug() << "Assignment server socket is" << _assignmentServerSocket;
// call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required
qDebug() << "Waiting for assignment -" << _requestAssignment;
@ -129,7 +131,40 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
void AssignmentClient::sendAssignmentRequest() {
if (!_currentAssignment) {
NodeList::getInstance()->sendAssignment(_requestAssignment);
NodeList* nodeList = NodeList::getInstance();
if (_assignmentServerHostname == "localhost") {
// we want to check again for the local domain-server port in case the DS has restarted
if (!_localASPortSharedMem) {
_localASPortSharedMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this);
if (!_localASPortSharedMem->attach(QSharedMemory::ReadOnly)) {
qWarning() << "Could not attach to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY
<< "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort();
}
}
if (_localASPortSharedMem->isAttached()) {
_localASPortSharedMem->lock();
quint16 localAssignmentServerPort;
memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort));
_localASPortSharedMem->unlock();
if (localAssignmentServerPort != _assignmentServerSocket.getPort()) {
qDebug() << "Port for local assignment server read from shared memory is"
<< localAssignmentServerPort;
_assignmentServerSocket.setPort(localAssignmentServerPort);
nodeList->setAssignmentServerSocket(_assignmentServerSocket);
}
}
}
nodeList->sendAssignment(_requestAssignment);
}
}

View file

@ -17,6 +17,8 @@
#include "ShutdownEventListener.h"
#include "ThreadedAssignment.h"
class QSharedMemory;
class AssignmentClient : public QCoreApplication {
Q_OBJECT
public:
@ -34,6 +36,8 @@ private:
static SharedAssignmentPointer _currentAssignment;
ShutdownEventListener _shutdownEventListener;
QString _assignmentServerHostname;
HifiSockAddr _assignmentServerSocket;
QSharedMemory* _localASPortSharedMem;
};
#endif // hifi_AssignmentClient_h

View file

@ -18,6 +18,7 @@
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
#include <QtCore/QProcess>
#include <QtCore/qsharedmemory.h>
#include <QtCore/QStandardPaths>
#include <QtCore/QTimer>
#include <QtCore/QUrlQuery>
@ -228,6 +229,21 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
LimitedNodeList* nodeList = LimitedNodeList::createInstance(domainServerPort, domainServerDTLSPort);
// no matter the local port, save it to shared mem so that local assignment clients can ask what it is
QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this);
quint16 localPort = nodeList->getNodeSocket().localPort();
// attempt to create the shared memory segment
if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) {
sharedPortMem->lock();
memcpy(sharedPortMem->data(), &localPort, sizeof(localPort));
sharedPortMem->unlock();
qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY;
} else {
qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children.";
}
// set our LimitedNodeList UUID to match the UUID from our config
// nodes will currently use this to add resources to data-web that relate to our domain
const QString METAVERSE_DOMAIN_ID_KEY_PATH = "metaverse.id";

View file

@ -0,0 +1,37 @@
//
// developerMenuItems.js
// examples
//
// Created by Brad Hefta-Gaub on 2/24/14
// Copyright 2013 High Fidelity, Inc.
//
// Adds a bunch of developer and debugging menu items
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
function setupMenus() {
if (!Menu.menuExists("Developer")) {
Menu.addMenu("Developer");
}
if (!Menu.menuExists("Developer > Entities")) {
Menu.addMenu("Developer > Entities");
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Bounds", isCheckable: true, isChecked: false });
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Bounds", isCheckable: true, isChecked: false });
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Children", isCheckable: true, isChecked: false });
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false });
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt to Reduce Material Switches", isCheckable: true, isChecked: false });
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt Render Entities as Scene", isCheckable: true, isChecked: false });
Menu.addMenu("Developer > Entities > Culling");
Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Out Of View Mesh Parts", isCheckable: true, isChecked: false });
Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Too Small Mesh Parts", isCheckable: true, isChecked: false });
}
}
function scriptEnding() {
Menu.removeMenu("Developer > Entities");
}
setupMenus();
Script.scriptEnding.connect(scriptEnding);

View file

@ -19,6 +19,7 @@ var warpPosition = { x: 0, y: 0, z: 0 };
var hipsToEyes;
var restoreCountdownTimer;
var headTurningTimer = 0.0;
// Overlays to show target location
@ -168,6 +169,20 @@ function update(deltaTime) {
restoreCountDownTimer = 0.0;
}
}
var HEAD_TURN_TIME = 0.10;
var HEAD_TURN_DEGREES = 4.0;
var HEAD_TURN_START_ANGLE = 45.0;
var currentYaw = MyAvatar.getHeadFinalYaw();
if (Math.abs(currentYaw) > HEAD_TURN_START_ANGLE) {
headTurningTimer += deltaTime;
if (headTurningTimer > HEAD_TURN_TIME) {
headTurningTimer = 0.0;
MyAvatar.orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, (currentYaw > 0) ? HEAD_TURN_DEGREES: -HEAD_TURN_DEGREES, 0),
MyAvatar.orientation);
}
} else {
headTurningTimer = 0.0;
}
}
Controller.keyPressEvent.connect(function(event) {

View file

@ -36,25 +36,36 @@ uniform vec2 depthTexCoordOffset;
uniform vec2 depthTexCoordScale;
void main(void) {
float depthVal = texture2D(depthMap, gl_TexCoord[0].st).r;
vec4 normalVal = texture2D(normalMap, gl_TexCoord[0].st);
vec4 diffuseVal = texture2D(diffuseMap, gl_TexCoord[0].st);
vec4 specularVal = texture2D(specularMap, gl_TexCoord[0].st);
// compute the view space position using the depth
float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0);
float z = near / (depthVal * depthScale - 1.0);
vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 0.0);
// get the normal from the map
vec4 normal = texture2D(normalMap, gl_TexCoord[0].st);
vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0));
// compute the base color based on OpenGL lighting model
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
float facingLight = step(0.0, diffuse);
vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor +
gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
// compute the specular multiplier (sans exponent)
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(position)),
normalizedNormal));
// add specular contribution
vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st);
gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a);
vec4 normal = normalVal;
if ((normalVal.a >= 0.45) && (normalVal.a <= 0.55)) {
normal.a = 1.0;
normalVal.a = 0.0;
gl_FragColor = vec4(diffuseVal.rgb * specularVal.rgb, 1.0);
} else {
vec3 normalizedNormal = normalize(normal.xyz * 2.0 - vec3(1.0));
// compute the base color based on OpenGL lighting model
float diffuse = dot(normalizedNormal, gl_LightSource[0].position.xyz);
float facingLight = step(0.0, diffuse);
vec3 baseColor = diffuseVal.rgb * (gl_FrontLightModelProduct.sceneColor.rgb +
gl_FrontLightProduct[0].ambient.rgb + gl_FrontLightProduct[0].diffuse.rgb * (diffuse * facingLight));
// compute the specular multiplier (sans exponent)
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position.xyz - normalize(position.xyz)),
normalizedNormal));
// add specular contribution
vec4 specularColor = specularVal;
gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a);
}
}

View file

@ -31,7 +31,7 @@ void main(void) {
// set the diffuse, normal, specular data
vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st);
vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st);
gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)));
gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0);
gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)));
gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);
gl_FragData[2] = vec4((vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), gl_FrontMaterial.shininess / 128.0);
}

View file

@ -4,7 +4,7 @@
// model_normal_map.frag
// fragment shader
//
// Created by Andrzej Kapolka on 10/14/13.
// Created by Andrzej Kapolka on 10/29/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.

View file

@ -438,6 +438,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
void Application::aboutToQuit() {
_aboutToQuit = true;
setFullscreen(false); // if you exit while in full screen, you'll get bad behavior when you restart.
}
Application::~Application() {
@ -650,20 +651,11 @@ void Application::paintGL() {
}
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
//Only behave like a true mirror when in the OR
if (OculusManager::isConnected()) {
_myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
_myCamera.setPosition(_myAvatar->getHead()->getEyePosition() +
glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) +
(_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
} else {
_myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
_myCamera.setPosition(_myAvatar->getHead()->getEyePosition() +
glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) +
(_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
}
_myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
_myCamera.setPosition(_myAvatar->getDefaultEyePosition() +
glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) +
(_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
}
// Update camera position

View file

@ -445,23 +445,7 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderBoundingCollisionShapes);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderLookAtVectors, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false);
QMenu* entitiesDebugMenu = developerMenu->addMenu("Entities");
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelBounds, 0, false);
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelElementProxy, 0, false);
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelElementChildProxies, 0, false);
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisableLightEntities, 0, false);
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DontReduceMaterialSwitches, 0, false);
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DontRenderEntitiesAsScene, 0, false);
QMenu* entityCullingMenu = entitiesDebugMenu->addMenu("Culling");
addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontCullOutOfViewMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontCullTooSmallMeshParts, 0, false);
QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxels");
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion);

View file

@ -367,6 +367,15 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
const float TORSO_LENGTH = 0.5f;
glm::vec3 relativePosition = estimatedPosition - glm::vec3(0.0f, -TORSO_LENGTH, 0.0f);
const float MAX_LEAN = 45.0f;
// Invert left/right lean when in mirror mode
// NOTE: this is kinda a hack, it's the same hack we use to make the head tilt. But it's not really a mirror
// it just makes you feel like you're looking in a mirror because the body movements of the avatar appear to
// match your body movements.
if (OculusManager::isConnected() && Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) {
relativePosition.x = -relativePosition.x;
}
head->setLeanSideways(glm::clamp(glm::degrees(atanf(relativePosition.x * _leanScale / TORSO_LENGTH)),
-MAX_LEAN, MAX_LEAN));
head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)),

View file

@ -477,7 +477,8 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) {
triggerButton = Qt::LeftButton;
}
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)
|| Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) {
pos = application->getApplicationOverlay().getPalmClickLocation(palm);
} else {
// Get directon relative to avatar orientation

View file

@ -138,11 +138,9 @@ void AnimationHandle::simulate(float deltaTime) {
return;
}
// TODO: When moving the loop/frame calculations to AnimationLoop class, we changed this behavior
// see AnimationLoop class for more details. Do we need to support clamping the endFrameIndex to
// the max number of frames in the geometry???
//
// float endFrameIndex = qMin(_lastFrame, animationGeometry.animationFrames.size() - (_loop ? 0.0f : 1.0f));
if (_animationLoop.getMaxFrameIndexHint() != animationGeometry.animationFrames.size()) {
_animationLoop.setMaxFrameIndexHint(animationGeometry.animationFrames.size());
}
// blend between the closest two frames
applyFrame(getFrameIndex());

View file

@ -829,10 +829,25 @@ void GeometryReader::run() {
return;
}
try {
QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&,
std::string urlname = _url.path().toLower().toStdString();
FBXGeometry fbxgeo;
if (_url.path().toLower().endsWith(".svo")) {
fbxgeo = readSVO(_reply->readAll());
} else {
bool grabLightmaps = true;
float lightmapLevel = 1.0f;
// HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber...
if (_url.path().toLower().endsWith("loungev4_11-18.fbx")) {
grabLightmaps = false;
} else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) {
lightmapLevel = 4.0f;
}
fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps, lightmapLevel);
}
QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo));
_url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping)));
// _url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping)));
} catch (const QString& error) {
qDebug() << "Error reading " << _url << ": " << error;

View file

@ -2347,8 +2347,12 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
diffuseMap = (_dilatedTextures[i][j] =
static_cast<DilatableNetworkTexture*>(diffuseMap)->getDilatedTexture(_pupilDilation)).data();
}
GLBATCH(glBindTexture)(GL_TEXTURE_2D, !diffuseMap ?
Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID());
static bool showDiffuse = true;
if (showDiffuse && diffuseMap) {
GLBATCH(glBindTexture)(GL_TEXTURE_2D, diffuseMap->getID());
} else {
GLBATCH(glBindTexture)(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getWhiteTextureID());
}
if (locations->texcoordMatrices >= 0) {
glm::mat4 texcoordTransform[2];
@ -2377,22 +2381,27 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
GLBATCH(glActiveTexture)(GL_TEXTURE0);
}
if (locations->emissiveTextureUnit >= 0) {
assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader
GLBATCH(glUniform2f)(locations->emissiveParams, 0.1f, 4.0f);
GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit);
Texture* emissiveMap = networkPart.emissiveTexture.data();
GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ?
Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID());
GLBATCH(glActiveTexture)(GL_TEXTURE0);
}
if (args) {
args->_materialSwitches++;
}
}
// HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every
// drawcall with an emissive, so let's do it for now.
if (locations->emissiveTextureUnit >= 0) {
// assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader
float emissiveOffset = part.emissiveParams.x;
float emissiveScale = part.emissiveParams.y;
GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale);
GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit);
Texture* emissiveMap = networkPart.emissiveTexture.data();
GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ?
Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID());
GLBATCH(glActiveTexture)(GL_TEXTURE0);
}
lastMaterialID = part.materialID;
}

View file

@ -30,27 +30,27 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) :
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) ,
_previousScreen(NULL),
_hmdScreen(NULL),
_previousDialogScreen(NULL)
_hmdScreenNumber(-1),
_switchModeButton(NULL),
_debugDetails(NULL),
_previousDialogScreen(NULL),
_inHDMMode(false)
{
this->setWindowTitle("HMD Tools");
// Create layouter
QFormLayout* form = new QFormLayout();
const int WIDTH = 350;
// Add a button to enter
QPushButton* enterModeButton = new QPushButton("Enter HMD Mode");
form->addRow("", enterModeButton);
connect(enterModeButton,SIGNAL(clicked(bool)),this,SLOT(enterModeClicked(bool)));
// Add a button to leave
QPushButton* leaveModeButton = new QPushButton("Leave HMD Mode");
form->addRow("", leaveModeButton);
connect(leaveModeButton,SIGNAL(clicked(bool)),this,SLOT(leaveModeClicked(bool)));
_switchModeButton = new QPushButton("Enter HMD Mode");
_switchModeButton->setFixedWidth(WIDTH);
form->addRow("", _switchModeButton);
connect(_switchModeButton,SIGNAL(clicked(bool)),this,SLOT(switchModeClicked(bool)));
// Create a label with debug details...
_debugDetails = new QLabel();
_debugDetails->setText(getDebugDetails());
const int WIDTH = 350;
const int HEIGHT = 100;
_debugDetails->setFixedSize(WIDTH, HEIGHT);
form->addRow("", _debugDetails);
@ -65,14 +65,21 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) :
QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle();
connect(mainWindow, &QWindow::screenChanged, this, &HMDToolsDialog::applicationWindowScreenChanged);
// watch for our dialog window moving screens. If it does we want to enforce our rules about what screens we're
// allowed on
// watch for our dialog window moving screens. If it does we want to enforce our rules about
// what screens we're allowed on
QWindow* dialogWindow = windowHandle();
connect(dialogWindow, &QWindow::screenChanged, this, &HMDToolsDialog::dialogWindowScreenChanged);
connect(dialogWindow, &QWindow::xChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged);
connect(dialogWindow, &QWindow::yChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged);
connect(dialogWindow, &QWindow::widthChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged);
connect(dialogWindow, &QWindow::heightChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged);
// when the application is about to quit, leave HDM mode
connect(Application::getInstance(), SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
// keep track of changes to the number of screens
connect(QApplication::desktop(), &QDesktopWidget::screenCountChanged, this, &HMDToolsDialog::screenCountChanged);
}
HMDToolsDialog::~HMDToolsDialog() {
@ -96,11 +103,11 @@ void HMDToolsDialog::dialogWindowScreenChanged(QScreen* screen) {
// if we have more than one screen, and a known hmdScreen then try to
// keep our dialog off of the hmdScreen
if (QApplication::desktop()->screenCount() > 1) {
int hmdScreenNumber = OculusManager::getHMDScreen();
if (hmdScreenNumber >= 0) {
QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber];
// we want to use a local variable here because we are not necesarily in HMD mode
int hmdScreenNumber = OculusManager::getHMDScreen();
if (_hmdScreenNumber >= 0) {
QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber];
if (screen == hmdScreen) {
qDebug() << "HMD Tools: Whoa! What are you doing? You don't want to move me to the HMD Screen!";
QWindow* dialogWindow = windowHandle();
@ -154,42 +161,55 @@ QString HMDToolsDialog::getDebugDetails() const {
results += "Application Primary Screen: " + QGuiApplication::primaryScreen()->name() + "\n";
QScreen* mainWindowScreen = Application::getInstance()->getWindow()->windowHandle()->screen();
results += "Application Main Window Screen: " + mainWindowScreen->name() + "\n";
results += "Total Screens: " + QString::number(QApplication::desktop()->screenCount()) + "\n";
return results;
}
void HMDToolsDialog::enterModeClicked(bool checked) {
_debugDetails->setText(getDebugDetails());
void HMDToolsDialog::switchModeClicked(bool checked) {
if (!_inHDMMode) {
enterHDMMode();
} else {
leaveHDMMode();
}
}
int hmdScreen = OculusManager::getHMDScreen();
qDebug() << "enterModeClicked().... hmdScreen:" << hmdScreen;
void HMDToolsDialog::enterHDMMode() {
if (!_inHDMMode) {
_switchModeButton->setText("Leave HMD Mode");
_debugDetails->setText(getDebugDetails());
_hmdScreenNumber = OculusManager::getHMDScreen();
if (hmdScreen >= 0) {
QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle();
_hmdScreen = QGuiApplication::screens()[hmdScreen];
if (_hmdScreenNumber >= 0) {
QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle();
_hmdScreen = QGuiApplication::screens()[_hmdScreenNumber];
_previousRect = Application::getInstance()->getWindow()->rect();
_previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()),
mainWindow->mapToGlobal(_previousRect.bottomRight()));
_previousScreen = mainWindow->screen();
QRect rect = QApplication::desktop()->screenGeometry(hmdScreen);
mainWindow->setScreen(_hmdScreen);
mainWindow->setGeometry(rect);
_previousRect = Application::getInstance()->getWindow()->rect();
_previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()),
mainWindow->mapToGlobal(_previousRect.bottomRight()));
_previousScreen = mainWindow->screen();
QRect rect = QApplication::desktop()->screenGeometry(_hmdScreenNumber);
mainWindow->setScreen(_hmdScreen);
mainWindow->setGeometry(rect);
_wasMoved = true;
}
_wasMoved = true;
}
// if we're on a single screen setup, then hide our tools window when entering HMD mode
if (QApplication::desktop()->screenCount() == 1) {
close();
}
// if we're on a single screen setup, then hide our tools window when entering HMD mode
if (QApplication::desktop()->screenCount() == 1) {
close();
}
Application::getInstance()->setFullscreen(true);
Application::getInstance()->setEnableVRMode(true);
Application::getInstance()->setFullscreen(true);
Application::getInstance()->setEnableVRMode(true);
const int SLIGHT_DELAY = 500;
QTimer::singleShot(SLIGHT_DELAY, this, SLOT(activateWindowAfterEnterMode()));
const int SLIGHT_DELAY = 500;
QTimer::singleShot(SLIGHT_DELAY, this, SLOT(activateWindowAfterEnterMode()));
_inHDMMode = true;
}
}
void HMDToolsDialog::activateWindowAfterEnterMode() {
@ -199,23 +219,26 @@ void HMDToolsDialog::activateWindowAfterEnterMode() {
centerCursorOnWidget(Application::getInstance()->getWindow());
}
void HMDToolsDialog::leaveHDMMode() {
if (_inHDMMode) {
_switchModeButton->setText("Enter HMD Mode");
_debugDetails->setText(getDebugDetails());
void HMDToolsDialog::leaveModeClicked(bool checked) {
_debugDetails->setText(getDebugDetails());
Application::getInstance()->setFullscreen(false);
Application::getInstance()->setEnableVRMode(false);
Application::getInstance()->getWindow()->activateWindow();
Application::getInstance()->setFullscreen(false);
Application::getInstance()->setEnableVRMode(false);
Application::getInstance()->getWindow()->activateWindow();
if (_wasMoved) {
QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle();
mainWindow->setScreen(_previousScreen);
mainWindow->setGeometry(_previousRect);
if (_wasMoved) {
QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle();
mainWindow->setScreen(_previousScreen);
mainWindow->setGeometry(_previousRect);
const int SLIGHT_DELAY = 1500;
QTimer::singleShot(SLIGHT_DELAY, this, SLOT(moveWindowAfterLeaveMode()));
const int SLIGHT_DELAY = 1500;
QTimer::singleShot(SLIGHT_DELAY, this, SLOT(moveWindowAfterLeaveMode()));
}
_wasMoved = false;
_inHDMMode = false;
}
_wasMoved = false;
}
void HMDToolsDialog::moveWindowAfterLeaveMode() {
@ -256,3 +279,31 @@ void HMDToolsDialog::hideEvent(QHideEvent* event) {
}
void HMDToolsDialog::aboutToQuit() {
if (_inHDMMode) {
leaveHDMMode();
}
}
void HMDToolsDialog::screenCountChanged(int newCount) {
if (!OculusManager::isConnected()) {
OculusManager::connect();
}
int hmdScreenNumber = OculusManager::getHMDScreen();
if (_inHDMMode && _hmdScreenNumber != hmdScreenNumber) {
qDebug() << "HMD Display changed WHILE IN HMD MODE";
leaveHDMMode();
// if there is a new best HDM screen then go back into HDM mode after done leaving
if (hmdScreenNumber >= 0) {
qDebug() << "Trying to go back into HDM Mode";
const int SLIGHT_DELAY = 2000;
QTimer::singleShot(SLIGHT_DELAY, this, SLOT(enterHDMMode()));
}
}
_debugDetails->setText(getDebugDetails());
}

View file

@ -28,14 +28,15 @@ signals:
public slots:
void reject();
void enterModeClicked(bool checked);
void leaveModeClicked(bool checked);
void switchModeClicked(bool checked);
void activateWindowAfterEnterMode();
void moveWindowAfterLeaveMode();
void applicationWindowScreenChanged(QScreen* screen);
void dialogWindowScreenChanged(QScreen* screen);
void dialogWindowGeometryChanged(int arg);
void aboutToQuit();
void screenCountChanged(int newCount);
protected:
virtual void closeEvent(QCloseEvent*); // Emits a 'closed' signal when this dialog is closed.
virtual void showEvent(QShowEvent* event);
@ -43,15 +44,20 @@ protected:
private:
void centerCursorOnWidget(QWidget* widget);
void enterHDMMode();
void leaveHDMMode();
bool _wasMoved;
QRect _previousRect;
QScreen* _previousScreen;
QScreen* _hmdScreen;
int _hmdScreenNumber;
QPushButton* _switchModeButton;
QLabel* _debugDetails;
QRect _previousDialogRect;
QScreen* _previousDialogScreen;
bool _inHDMMode;
};
#endif // hifi_HMDToolsDialog_h

View file

@ -20,7 +20,8 @@ AnimationLoop::AnimationLoop() :
_firstFrame(0.0f),
_lastFrame(FLT_MAX),
_running(false),
_frameIndex(0.0f)
_frameIndex(0.0f),
_maxFrameIndexHint(FLT_MAX)
{
}
@ -55,7 +56,7 @@ void AnimationLoop::simulate(float deltaTime) {
// If we knew the number of frames from the animation, we'd consider using it here
// animationGeometry.animationFrames.size()
float maxFrame = _lastFrame;
float maxFrame = _maxFrameIndexHint;
float endFrameIndex = qMin(_lastFrame, maxFrame - (_loop ? 0.0f : 1.0f));
float startFrameIndex = qMin(_firstFrame, endFrameIndex);
if ((!_loop && (_frameIndex < startFrameIndex || _frameIndex > endFrameIndex)) || startFrameIndex == endFrameIndex) {

View file

@ -44,6 +44,9 @@ public:
void setFrameIndex(float frameIndex) { _frameIndex = glm::clamp(frameIndex, _firstFrame, _lastFrame); }
float getFrameIndex() const { return _frameIndex; }
void setMaxFrameIndexHint(float value) { _maxFrameIndexHint = value; }
float getMaxFrameIndexHint() const { return _maxFrameIndexHint; }
void start() { setRunning(true); }
void stop() { setRunning(false); }
@ -58,6 +61,7 @@ private:
float _lastFrame;
bool _running;
float _frameIndex;
float _maxFrameIndexHint;
};
#endif // hifi_AnimationLoop_h

View file

@ -344,7 +344,9 @@ QVector<glm::quat> ModelEntityItem::getAnimationFrame() {
Animation* myAnimation = getAnimation(_animationURL);
QVector<FBXAnimationFrame> frames = myAnimation->getFrames();
int frameCount = frames.size();
if (_animationLoop.getMaxFrameIndexHint() != frameCount) {
_animationLoop.setMaxFrameIndexHint(frameCount);
}
if (frameCount > 0) {
int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount;
if (animationFrameIndex < 0 || animationFrameIndex > frameCount) {

View file

@ -1194,7 +1194,7 @@ int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const Q
}
}
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) {
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) {
QHash<QString, ExtractedMesh> meshes;
QHash<QString, QString> modelIDsToNames;
QHash<QString, int> meshIDsToMeshIndices;
@ -1216,6 +1216,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
QHash<QString, QString> bumpTextures;
QHash<QString, QString> specularTextures;
QHash<QString, QString> emissiveTextures;
QHash<QString, QString> ambientTextures;
QHash<QString, QString> localRotations;
QHash<QString, QString> xComponents;
QHash<QString, QString> yComponents;
@ -1597,9 +1598,28 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
} else if (property.properties.at(0) == "Opacity") {
material.opacity = property.properties.at(index).value<double>();
}
#if defined(DEBUG_FBXREADER)
else {
const std::string propname = property.properties.at(0).toString().toStdString();
if (propname == "EmissiveFactor") {
}
}
#endif
}
}
}
#if defined(DEBUG_FBXREADER)
else {
std::string propname = subobject.name.data();
int unknown = 0;
if ( (propname == "Version")
||(propname == "ShadingModel")
||(propname == "Multilayer")) {
} else {
unknown++;
}
}
#endif
}
material.id = getID(object.properties);
materials.insert(material.id, material);
@ -1684,10 +1704,13 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
} else if (type.contains("shininess")) {
counter++;
} else if (type.contains("emissive")) {
} else if (loadLightmaps && type.contains("emissive")) {
emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (loadLightmaps && type.contains("ambient")) {
ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else {
std::string typenam = type.data();
counter++;
}
}
@ -1930,19 +1953,21 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
}
FBXTexture emissiveTexture;
glm::vec2 emissiveParams(0.f, 1.f);
emissiveParams.y = lightmapLevel;
QString emissiveTextureID = emissiveTextures.value(childID);
if (!emissiveTextureID.isNull()) {
emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams);
// FBX files generated by 3DSMax have an intermediate texture parent, apparently
foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) {
if (textureFilenames.contains(childTextureID)) {
emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams);
}
QString ambientTextureID = ambientTextures.value(childID);
if (!emissiveTextureID.isNull() || !ambientTextureID.isNull()) {
if (!emissiveTextureID.isNull()) {
emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams);
emissiveParams.y = 4.0f;
} else if (!ambientTextureID.isNull()) {
emissiveTexture = getTexture(ambientTextureID, textureNames, textureFilenames, textureContent, textureParams);
}
emissiveTexture.texcoordSet = matchTextureUVSetToAttributeChannel(emissiveTexture.texcoordSetName, extracted.texcoordSetMap);
detectDifferentUVs |= (emissiveTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity());
}
@ -1970,6 +1995,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
if (!emissiveTexture.filename.isNull()) {
part.emissiveTexture = emissiveTexture;
}
part.emissiveParams = emissiveParams;
part.materialID = material.id;
}
}
@ -2346,10 +2373,10 @@ QByteArray writeMapping(const QVariantHash& mapping) {
return buffer.data();
}
FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping) {
FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) {
QBuffer buffer(const_cast<QByteArray*>(&model));
buffer.open(QIODevice::ReadOnly);
return extractFBXGeometry(parseFBX(&buffer), mapping);
return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps, lightmapLevel);
}
bool addMeshVoxelsOperation(OctreeElement* element, void* extraData) {

View file

@ -119,6 +119,7 @@ public:
glm::vec3 diffuseColor;
glm::vec3 specularColor;
glm::vec3 emissiveColor;
glm::vec2 emissiveParams;
float shininess;
float opacity;
@ -252,7 +253,7 @@ QByteArray writeMapping(const QVariantHash& mapping);
/// Reads FBX geometry from the supplied model and mapping data.
/// \exception QString if an error occurs in parsing
FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping);
FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f);
/// Reads SVO geometry from the supplied model data.
FBXGeometry readSVO(const QByteArray& model);

View file

@ -44,6 +44,8 @@ const char DEFAULT_ASSIGNMENT_SERVER_HOSTNAME[] = "localhost";
const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io";
const unsigned short STUN_SERVER_PORT = 3478;
const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port";
class HifiSockAddr;
typedef QSet<NodeType_t> NodeSet;