mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 19:21:16 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into red
This commit is contained in:
commit
24d712b7b4
14 changed files with 197 additions and 111 deletions
|
@ -4880,7 +4880,10 @@ void Application::updateDisplayMode() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit activeDisplayPluginChanged();
|
emit activeDisplayPluginChanged();
|
||||||
resetSensors();
|
|
||||||
|
// reset the avatar, to set head and hand palms back to a resonable default pose.
|
||||||
|
getMyAvatar()->reset(false);
|
||||||
|
|
||||||
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
|
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -464,6 +464,8 @@ Menu::Menu() {
|
||||||
avatar, SLOT(setUseAnimPreAndPostRotations(bool)));
|
avatar, SLOT(setUseAnimPreAndPostRotations(bool)));
|
||||||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableInverseKinematics, 0, true,
|
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableInverseKinematics, 0, true,
|
||||||
avatar, SLOT(setEnableInverseKinematics(bool)));
|
avatar, SLOT(setEnableInverseKinematics(bool)));
|
||||||
|
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSensorToWorldMatrix, 0, false,
|
||||||
|
avatar, SLOT(setEnableDebugDrawSensorToWorldMatrix(bool)));
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::KeyboardMotorControl,
|
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::KeyboardMotorControl,
|
||||||
Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehaviorFromMenu()),
|
Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehaviorFromMenu()),
|
||||||
|
|
|
@ -144,6 +144,7 @@ namespace MenuOption {
|
||||||
const QString RenderResolutionHalf = "1/2";
|
const QString RenderResolutionHalf = "1/2";
|
||||||
const QString RenderResolutionThird = "1/3";
|
const QString RenderResolutionThird = "1/3";
|
||||||
const QString RenderResolutionQuarter = "1/4";
|
const QString RenderResolutionQuarter = "1/4";
|
||||||
|
const QString RenderSensorToWorldMatrix = "Show SensorToWorld Matrix";
|
||||||
const QString ResetAvatarSize = "Reset Avatar Size";
|
const QString ResetAvatarSize = "Reset Avatar Size";
|
||||||
const QString ResetSensors = "Reset Sensors";
|
const QString ResetSensors = "Reset Sensors";
|
||||||
const QString RunningScripts = "Running Scripts...";
|
const QString RunningScripts = "Running Scripts...";
|
||||||
|
|
|
@ -444,6 +444,10 @@ void MyAvatar::updateSensorToWorldMatrix() {
|
||||||
|
|
||||||
lateUpdatePalms();
|
lateUpdatePalms();
|
||||||
|
|
||||||
|
if (_enableDebugDrawSensorToWorldMatrix) {
|
||||||
|
DebugDraw::getInstance().addMarker("sensorToWorldMatrix", glmExtractRotation(_sensorToWorldMatrix), extractTranslation(_sensorToWorldMatrix), glm::vec4(1));
|
||||||
|
}
|
||||||
|
|
||||||
_sensorToWorldMatrixCache.set(_sensorToWorldMatrix);
|
_sensorToWorldMatrixCache.set(_sensorToWorldMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,6 +702,14 @@ void MyAvatar::setEnableDebugDrawPosition(bool isEnabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::setEnableDebugDrawSensorToWorldMatrix(bool isEnabled) {
|
||||||
|
_enableDebugDrawSensorToWorldMatrix = isEnabled;
|
||||||
|
|
||||||
|
if (!isEnabled) {
|
||||||
|
DebugDraw::getInstance().removeMarker("sensorToWorldMatrix");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MyAvatar::setEnableMeshVisible(bool isEnabled) {
|
void MyAvatar::setEnableMeshVisible(bool isEnabled) {
|
||||||
render::ScenePointer scene = qApp->getMain3DScene();
|
render::ScenePointer scene = qApp->getMain3DScene();
|
||||||
_skeletonModel.setVisibleInScene(isEnabled, scene);
|
_skeletonModel.setVisibleInScene(isEnabled, scene);
|
||||||
|
|
|
@ -271,6 +271,7 @@ public slots:
|
||||||
void setEnableDebugDrawDefaultPose(bool isEnabled);
|
void setEnableDebugDrawDefaultPose(bool isEnabled);
|
||||||
void setEnableDebugDrawAnimPose(bool isEnabled);
|
void setEnableDebugDrawAnimPose(bool isEnabled);
|
||||||
void setEnableDebugDrawPosition(bool isEnabled);
|
void setEnableDebugDrawPosition(bool isEnabled);
|
||||||
|
void setEnableDebugDrawSensorToWorldMatrix(bool isEnabled);
|
||||||
bool getEnableMeshVisible() const { return _skeletonModel.isVisible(); }
|
bool getEnableMeshVisible() const { return _skeletonModel.isVisible(); }
|
||||||
void setEnableMeshVisible(bool isEnabled);
|
void setEnableMeshVisible(bool isEnabled);
|
||||||
void setUseAnimPreAndPostRotations(bool isEnabled);
|
void setUseAnimPreAndPostRotations(bool isEnabled);
|
||||||
|
@ -434,6 +435,7 @@ private:
|
||||||
|
|
||||||
bool _enableDebugDrawDefaultPose { false };
|
bool _enableDebugDrawDefaultPose { false };
|
||||||
bool _enableDebugDrawAnimPose { false };
|
bool _enableDebugDrawAnimPose { false };
|
||||||
|
bool _enableDebugDrawSensorToWorldMatrix { false };
|
||||||
|
|
||||||
AudioListenerMode _audioListenerMode;
|
AudioListenerMode _audioListenerMode;
|
||||||
glm::vec3 _customListenPosition;
|
glm::vec3 _customListenPosition;
|
||||||
|
|
|
@ -341,12 +341,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
|
||||||
static QString userData;
|
static QString userData;
|
||||||
if (userData != zone->getUserData()) {
|
if (userData != zone->getUserData()) {
|
||||||
userData = zone->getUserData();
|
userData = zone->getUserData();
|
||||||
auto procedural = std::make_shared<Procedural>(userData);
|
skybox->parse(userData);
|
||||||
if (procedural->_enabled) {
|
|
||||||
skybox->setProcedural(procedural);
|
|
||||||
} else {
|
|
||||||
skybox->setProcedural(ProceduralPointer());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (zone->getSkyboxProperties().getURL().isEmpty()) {
|
if (zone->getSkyboxProperties().getURL().isEmpty()) {
|
||||||
skybox->setCubemap(gpu::TexturePointer());
|
skybox->setCubemap(gpu::TexturePointer());
|
||||||
|
|
|
@ -31,7 +31,9 @@ EntityItemPointer RenderableBoxEntityItem::factory(const EntityItemID& entityID,
|
||||||
void RenderableBoxEntityItem::setUserData(const QString& value) {
|
void RenderableBoxEntityItem::setUserData(const QString& value) {
|
||||||
if (value != getUserData()) {
|
if (value != getUserData()) {
|
||||||
BoxEntityItem::setUserData(value);
|
BoxEntityItem::setUserData(value);
|
||||||
_procedural.reset();
|
if (_procedural) {
|
||||||
|
_procedural->parse(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +42,6 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
|
||||||
Q_ASSERT(getType() == EntityTypes::Box);
|
Q_ASSERT(getType() == EntityTypes::Box);
|
||||||
Q_ASSERT(args->_batch);
|
Q_ASSERT(args->_batch);
|
||||||
|
|
||||||
|
|
||||||
if (!_procedural) {
|
if (!_procedural) {
|
||||||
_procedural.reset(new Procedural(this->getUserData()));
|
_procedural.reset(new Procedural(this->getUserData()));
|
||||||
_procedural->_vertexSource = simple_vert;
|
_procedural->_vertexSource = simple_vert;
|
||||||
|
@ -62,7 +63,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.setModelTransform(transToCenter); // we want to include the scale as well
|
batch.setModelTransform(transToCenter); // we want to include the scale as well
|
||||||
if (_procedural && _procedural->ready()) {
|
if (_procedural->ready()) {
|
||||||
_procedural->prepare(batch, getPosition(), getDimensions());
|
_procedural->prepare(batch, getPosition(), getDimensions());
|
||||||
auto color = _procedural->getColor(cubeColor);
|
auto color = _procedural->getColor(cubeColor);
|
||||||
batch._glColor4f(color.r, color.g, color.b, color.a);
|
batch._glColor4f(color.r, color.g, color.b, color.a);
|
||||||
|
|
|
@ -36,7 +36,9 @@ EntityItemPointer RenderableSphereEntityItem::factory(const EntityItemID& entity
|
||||||
void RenderableSphereEntityItem::setUserData(const QString& value) {
|
void RenderableSphereEntityItem::setUserData(const QString& value) {
|
||||||
if (value != getUserData()) {
|
if (value != getUserData()) {
|
||||||
SphereEntityItem::setUserData(value);
|
SphereEntityItem::setUserData(value);
|
||||||
_procedural.reset();
|
if (_procedural) {
|
||||||
|
_procedural->parse(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,9 @@ QJsonValue Procedural::getProceduralData(const QString& proceduralJson) {
|
||||||
return doc.object()[PROCEDURAL_USER_DATA_KEY];
|
return doc.object()[PROCEDURAL_USER_DATA_KEY];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Procedural::Procedural() {
|
||||||
|
_state = std::make_shared<gpu::State>();
|
||||||
|
}
|
||||||
|
|
||||||
Procedural::Procedural(const QString& userDataJson) {
|
Procedural::Procedural(const QString& userDataJson) {
|
||||||
parse(userDataJson);
|
parse(userDataJson);
|
||||||
|
@ -69,74 +72,110 @@ Procedural::Procedural(const QString& userDataJson) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Procedural::parse(const QString& userDataJson) {
|
void Procedural::parse(const QString& userDataJson) {
|
||||||
_enabled = false;
|
|
||||||
auto proceduralData = getProceduralData(userDataJson);
|
auto proceduralData = getProceduralData(userDataJson);
|
||||||
if (proceduralData.isObject()) {
|
// Instead of parsing, prep for a parse on the rendering thread
|
||||||
parse(proceduralData.toObject());
|
// This will be called by Procedural::ready
|
||||||
|
std::lock_guard<std::mutex> lock(_proceduralDataMutex);
|
||||||
|
_proceduralData = proceduralData.toObject();
|
||||||
|
_proceduralDataDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Procedural::parseVersion(const QJsonValue& version) {
|
||||||
|
if (version.isDouble()) {
|
||||||
|
_version = (uint8_t)(floor(version.toDouble()));
|
||||||
|
} else {
|
||||||
|
// All unversioned shaders default to V1
|
||||||
|
_version = 1;
|
||||||
}
|
}
|
||||||
|
return (_version == 1 || _version == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Procedural::parseUrl(const QUrl& shaderUrl) {
|
||||||
|
if (!shaderUrl.isValid()) {
|
||||||
|
qWarning() << "Invalid shader URL: " << shaderUrl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_shaderUrl == shaderUrl) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_shaderUrl = shaderUrl;
|
||||||
|
|
||||||
|
if (_shaderUrl.isLocalFile()) {
|
||||||
|
_shaderPath = _shaderUrl.toLocalFile();
|
||||||
|
qDebug() << "Shader path: " << _shaderPath;
|
||||||
|
if (!QFile(_shaderPath).exists()) {
|
||||||
|
return false;;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << "Shader url: " << _shaderUrl;
|
||||||
|
_networkShader = ShaderCache::instance().getShader(_shaderUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Procedural::parseUniforms(const QJsonObject& uniforms) {
|
||||||
|
if (_parsedUniforms != uniforms) {
|
||||||
|
_parsedUniforms = uniforms;
|
||||||
|
_uniformsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Procedural::parseTextures(const QJsonArray& channels) {
|
||||||
|
if (_parsedChannels != channels) {
|
||||||
|
_parsedChannels = channels;
|
||||||
|
|
||||||
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
|
size_t channelCount = std::min(MAX_PROCEDURAL_TEXTURE_CHANNELS, (size_t)_parsedChannels.size());
|
||||||
|
for (size_t i = 0; i < channelCount; ++i) {
|
||||||
|
QString url = _parsedChannels.at((int)i).toString();
|
||||||
|
_channels[i] = textureCache->getTexture(QUrl(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
_channelsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Procedural::parse(const QJsonObject& proceduralData) {
|
void Procedural::parse(const QJsonObject& proceduralData) {
|
||||||
// grab the version number
|
_enabled = false;
|
||||||
{
|
|
||||||
auto version = proceduralData[VERSION_KEY];
|
if (proceduralData.isEmpty()) {
|
||||||
if (version.isDouble()) {
|
return;
|
||||||
_version = (uint8_t)(floor(version.toDouble()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the path to the shader
|
auto version = proceduralData[VERSION_KEY];
|
||||||
{
|
auto shaderUrl = proceduralData[URL_KEY].toString();
|
||||||
QString shaderUrl = proceduralData[URL_KEY].toString();
|
shaderUrl = ResourceManager::normalizeURL(shaderUrl);
|
||||||
shaderUrl = ResourceManager::normalizeURL(shaderUrl);
|
auto uniforms = proceduralData[UNIFORMS_KEY].toObject();
|
||||||
_shaderUrl = QUrl(shaderUrl);
|
auto channels = proceduralData[CHANNELS_KEY].toArray();
|
||||||
if (!_shaderUrl.isValid()) {
|
|
||||||
qWarning() << "Invalid shader URL: " << shaderUrl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_shaderUrl.isLocalFile()) {
|
if (parseVersion(version) &&
|
||||||
_shaderPath = _shaderUrl.toLocalFile();
|
parseUrl(shaderUrl) &&
|
||||||
qDebug() << "Shader path: " << _shaderPath;
|
parseUniforms(uniforms) &&
|
||||||
if (!QFile(_shaderPath).exists()) {
|
parseTextures(channels)) {
|
||||||
return;
|
_enabled = true;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qDebug() << "Shader url: " << _shaderUrl;
|
|
||||||
_networkShader = ShaderCache::instance().getShader(_shaderUrl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab any custom uniforms
|
|
||||||
{
|
|
||||||
auto uniforms = proceduralData[UNIFORMS_KEY];
|
|
||||||
if (uniforms.isObject()) {
|
|
||||||
_parsedUniforms = uniforms.toObject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grab any textures
|
|
||||||
{
|
|
||||||
auto channels = proceduralData[CHANNELS_KEY];
|
|
||||||
if (channels.isArray()) {
|
|
||||||
auto textureCache = DependencyManager::get<TextureCache>();
|
|
||||||
_parsedChannels = channels.toArray();
|
|
||||||
size_t channelCount = std::min(MAX_PROCEDURAL_TEXTURE_CHANNELS, (size_t)_parsedChannels.size());
|
|
||||||
for (size_t i = 0; i < channelCount; ++i) {
|
|
||||||
QString url = _parsedChannels.at((int)i).toString();
|
|
||||||
_channels[i] = textureCache->getTexture(QUrl(url));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_enabled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Procedural::ready() {
|
bool Procedural::ready() {
|
||||||
|
// Load any changes to the procedural
|
||||||
|
if (_proceduralDataDirty) {
|
||||||
|
std::lock_guard<std::mutex> lock(_proceduralDataMutex);
|
||||||
|
parse(_proceduralData);
|
||||||
|
_proceduralDataDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_enabled) {
|
if (!_enabled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do we have a network or local shader
|
// Do we have a network or local shader, and if so, is it loaded?
|
||||||
if (_shaderPath.isEmpty() && (!_networkShader || !_networkShader->isLoaded())) {
|
if (_shaderPath.isEmpty() && (!_networkShader || !_networkShader->isLoaded())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -160,15 +199,14 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm
|
||||||
QFile file(_shaderPath);
|
QFile file(_shaderPath);
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
_shaderSource = QTextStream(&file).readAll();
|
_shaderSource = QTextStream(&file).readAll();
|
||||||
_pipelineDirty = true;
|
_shaderDirty = true;
|
||||||
_shaderModified = lastModified;
|
_shaderModified = lastModified;
|
||||||
}
|
}
|
||||||
} else if (_networkShader && _networkShader->isLoaded()) {
|
} else if (_networkShader && _networkShader->isLoaded()) {
|
||||||
_shaderSource = _networkShader->_source;
|
_shaderSource = _networkShader->_source;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_pipeline || _pipelineDirty) {
|
if (!_pipeline || _shaderDirty) {
|
||||||
_pipelineDirty = true;
|
|
||||||
if (!_vertexShader) {
|
if (!_vertexShader) {
|
||||||
_vertexShader = gpu::Shader::createVertex(_vertexSource);
|
_vertexShader = gpu::Shader::createVertex(_vertexSource);
|
||||||
}
|
}
|
||||||
|
@ -214,11 +252,15 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm
|
||||||
|
|
||||||
batch.setPipeline(_pipeline);
|
batch.setPipeline(_pipeline);
|
||||||
|
|
||||||
if (_pipelineDirty) {
|
if (_shaderDirty || _uniformsDirty) {
|
||||||
_pipelineDirty = false;
|
|
||||||
setupUniforms();
|
setupUniforms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_shaderDirty || _uniformsDirty || _channelsDirty) {
|
||||||
|
setupChannels(_shaderDirty || _uniformsDirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
_shaderDirty = _uniformsDirty = _channelsDirty = false;
|
||||||
|
|
||||||
for (auto lambda : _uniforms) {
|
for (auto lambda : _uniforms) {
|
||||||
lambda(batch);
|
lambda(batch);
|
||||||
|
@ -359,8 +401,14 @@ void Procedural::setupUniforms() {
|
||||||
batch._glUniform(_standardUniformSlots[POSITION], _entityPosition);
|
batch._glUniform(_standardUniformSlots[POSITION], _entityPosition);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Procedural::setupChannels(bool shouldCreate) {
|
||||||
if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[CHANNEL_RESOLUTION]) {
|
if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[CHANNEL_RESOLUTION]) {
|
||||||
|
if (!shouldCreate) {
|
||||||
|
// Instead of modifying the last element, just remove and recreate it.
|
||||||
|
_uniforms.pop_back();
|
||||||
|
}
|
||||||
_uniforms.push_back([=](gpu::Batch& batch) {
|
_uniforms.push_back([=](gpu::Batch& batch) {
|
||||||
vec3 channelSizes[MAX_PROCEDURAL_TEXTURE_CHANNELS];
|
vec3 channelSizes[MAX_PROCEDURAL_TEXTURE_CHANNELS];
|
||||||
for (size_t i = 0; i < MAX_PROCEDURAL_TEXTURE_CHANNELS; ++i) {
|
for (size_t i = 0; i < MAX_PROCEDURAL_TEXTURE_CHANNELS; ++i) {
|
||||||
|
|
|
@ -28,27 +28,24 @@ const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 };
|
||||||
// FIXME better encapsulation
|
// FIXME better encapsulation
|
||||||
// FIXME better mechanism for extending to things rendered using shaders other than simple.slv
|
// FIXME better mechanism for extending to things rendered using shaders other than simple.slv
|
||||||
struct Procedural {
|
struct Procedural {
|
||||||
|
public:
|
||||||
static QJsonValue getProceduralData(const QString& proceduralJson);
|
static QJsonValue getProceduralData(const QString& proceduralJson);
|
||||||
|
|
||||||
|
Procedural();
|
||||||
Procedural(const QString& userDataJson);
|
Procedural(const QString& userDataJson);
|
||||||
void parse(const QString& userDataJson);
|
void parse(const QString& userDataJson);
|
||||||
void parse(const QJsonObject&);
|
|
||||||
bool ready();
|
bool ready();
|
||||||
void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size);
|
void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size);
|
||||||
void setupUniforms();
|
|
||||||
glm::vec4 getColor(const glm::vec4& entityColor);
|
glm::vec4 getColor(const glm::vec4& entityColor);
|
||||||
|
|
||||||
bool _enabled{ false };
|
uint8_t _version { 1 };
|
||||||
uint8_t _version{ 1 };
|
|
||||||
|
|
||||||
std::string _vertexSource;
|
std::string _vertexSource;
|
||||||
std::string _fragmentSource;
|
std::string _fragmentSource;
|
||||||
|
|
||||||
QString _shaderSource;
|
gpu::StatePointer _state;
|
||||||
QString _shaderPath;
|
|
||||||
QUrl _shaderUrl;
|
|
||||||
quint64 _shaderModified{ 0 };
|
|
||||||
bool _pipelineDirty{ true };
|
|
||||||
|
|
||||||
enum StandardUniforms {
|
enum StandardUniforms {
|
||||||
DATE,
|
DATE,
|
||||||
|
@ -60,23 +57,50 @@ struct Procedural {
|
||||||
NUM_STANDARD_UNIFORMS
|
NUM_STANDARD_UNIFORMS
|
||||||
};
|
};
|
||||||
|
|
||||||
int32_t _standardUniformSlots[NUM_STANDARD_UNIFORMS];
|
protected:
|
||||||
|
// Procedural metadata
|
||||||
|
bool _enabled { false };
|
||||||
|
uint64_t _start { 0 };
|
||||||
|
int32_t _frameCount { 0 };
|
||||||
|
|
||||||
uint64_t _start{ 0 };
|
// Rendering object descriptions, from userData
|
||||||
int32_t _frameCount{ 0 };
|
QJsonObject _proceduralData;
|
||||||
|
std::mutex _proceduralDataMutex;
|
||||||
|
QString _shaderSource;
|
||||||
|
QString _shaderPath;
|
||||||
|
QUrl _shaderUrl;
|
||||||
|
quint64 _shaderModified { 0 };
|
||||||
NetworkShaderPointer _networkShader;
|
NetworkShaderPointer _networkShader;
|
||||||
QJsonObject _parsedUniforms;
|
QJsonObject _parsedUniforms;
|
||||||
QJsonArray _parsedChannels;
|
QJsonArray _parsedChannels;
|
||||||
|
bool _proceduralDataDirty { true };
|
||||||
|
bool _shaderDirty { true };
|
||||||
|
bool _uniformsDirty { true };
|
||||||
|
bool _channelsDirty { true };
|
||||||
|
|
||||||
|
// Rendering objects
|
||||||
UniformLambdas _uniforms;
|
UniformLambdas _uniforms;
|
||||||
|
int32_t _standardUniformSlots[NUM_STANDARD_UNIFORMS];
|
||||||
NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS];
|
NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS];
|
||||||
gpu::PipelinePointer _pipeline;
|
gpu::PipelinePointer _pipeline;
|
||||||
gpu::ShaderPointer _vertexShader;
|
gpu::ShaderPointer _vertexShader;
|
||||||
gpu::ShaderPointer _fragmentShader;
|
gpu::ShaderPointer _fragmentShader;
|
||||||
gpu::ShaderPointer _shader;
|
gpu::ShaderPointer _shader;
|
||||||
gpu::StatePointer _state;
|
|
||||||
|
// Entity metadata
|
||||||
glm::vec3 _entityDimensions;
|
glm::vec3 _entityDimensions;
|
||||||
glm::vec3 _entityPosition;
|
glm::vec3 _entityPosition;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This should only be called from the render thread, as it shares data with Procedural::prepare
|
||||||
|
void parse(const QJsonObject&);
|
||||||
|
bool parseVersion(const QJsonValue& version);
|
||||||
|
bool parseUrl(const QUrl& url);
|
||||||
|
bool parseUniforms(const QJsonObject& uniforms);
|
||||||
|
bool parseTextures(const QJsonArray& channels);
|
||||||
|
|
||||||
|
void setupUniforms();
|
||||||
|
void setupChannels(bool shouldCreate);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,22 +19,10 @@
|
||||||
#include "ProceduralSkybox_frag.h"
|
#include "ProceduralSkybox_frag.h"
|
||||||
|
|
||||||
ProceduralSkybox::ProceduralSkybox() : model::Skybox() {
|
ProceduralSkybox::ProceduralSkybox() : model::Skybox() {
|
||||||
}
|
_procedural._vertexSource = ProceduralSkybox_vert;
|
||||||
|
_procedural._fragmentSource = ProceduralSkybox_frag;
|
||||||
ProceduralSkybox::ProceduralSkybox(const ProceduralSkybox& skybox) :
|
// Adjust the pipeline state for background using the stencil test
|
||||||
model::Skybox(skybox),
|
_procedural._state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||||
_procedural(skybox._procedural) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProceduralSkybox::setProcedural(const ProceduralPointer& procedural) {
|
|
||||||
_procedural = procedural;
|
|
||||||
if (_procedural) {
|
|
||||||
_procedural->_vertexSource = ProceduralSkybox_vert;
|
|
||||||
_procedural->_fragmentSource = ProceduralSkybox_frag;
|
|
||||||
// Adjust the pipeline state for background using the stencil test
|
|
||||||
_procedural->_state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const {
|
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const {
|
||||||
|
@ -42,12 +30,10 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) con
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox) {
|
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox) {
|
||||||
if (!(skybox._procedural)) {
|
if (!(skybox._procedural.ready())) {
|
||||||
skybox.updateDataBuffer();
|
skybox.updateDataBuffer();
|
||||||
Skybox::render(batch, viewFrustum, skybox);
|
Skybox::render(batch, viewFrustum, skybox);
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if (skybox._procedural && skybox._procedural->_enabled && skybox._procedural->ready()) {
|
|
||||||
gpu::TexturePointer skymap = skybox.getCubemap();
|
gpu::TexturePointer skymap = skybox.getCubemap();
|
||||||
// FIXME: skymap->isDefined may not be threadsafe
|
// FIXME: skymap->isDefined may not be threadsafe
|
||||||
assert(skymap && skymap->isDefined());
|
assert(skymap && skymap->isDefined());
|
||||||
|
@ -62,8 +48,7 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum,
|
||||||
batch.setModelTransform(Transform()); // only for Mac
|
batch.setModelTransform(Transform()); // only for Mac
|
||||||
batch.setResourceTexture(0, skybox.getCubemap());
|
batch.setResourceTexture(0, skybox.getCubemap());
|
||||||
|
|
||||||
skybox._procedural->prepare(batch, glm::vec3(0), glm::vec3(1));
|
skybox._procedural.prepare(batch, glm::vec3(0), glm::vec3(1));
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,22 +17,18 @@
|
||||||
|
|
||||||
#include "Procedural.h"
|
#include "Procedural.h"
|
||||||
|
|
||||||
typedef std::shared_ptr<Procedural> ProceduralPointer;
|
|
||||||
|
|
||||||
class ProceduralSkybox: public model::Skybox {
|
class ProceduralSkybox: public model::Skybox {
|
||||||
public:
|
public:
|
||||||
ProceduralSkybox();
|
ProceduralSkybox();
|
||||||
ProceduralSkybox(const ProceduralSkybox& skybox);
|
|
||||||
ProceduralSkybox& operator= (const ProceduralSkybox& skybox);
|
|
||||||
virtual ~ProceduralSkybox() {};
|
virtual ~ProceduralSkybox() {};
|
||||||
|
|
||||||
void setProcedural(const ProceduralPointer& procedural);
|
void parse(const QString& userData) { _procedural.parse(userData); }
|
||||||
|
|
||||||
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const;
|
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const;
|
||||||
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox);
|
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ProceduralPointer _procedural;
|
mutable Procedural _procedural;
|
||||||
};
|
};
|
||||||
typedef std::shared_ptr< ProceduralSkybox > ProceduralSkyboxPointer;
|
typedef std::shared_ptr< ProceduralSkybox > ProceduralSkyboxPointer;
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ public:
|
||||||
// WARNING, There is No check on the validity of the ID, so this could return a bad Item
|
// WARNING, There is No check on the validity of the ID, so this could return a bad Item
|
||||||
const Item& getItem(const ItemID& id) const { return _items[id]; }
|
const Item& getItem(const ItemID& id) const { return _items[id]; }
|
||||||
|
|
||||||
// Access the spatialized items
|
// Access the spatialized items
|
||||||
const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; }
|
const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; }
|
||||||
|
|
||||||
// Access non-spatialized items (overlays, backgrounds)
|
// Access non-spatialized items (overlays, backgrounds)
|
||||||
|
|
|
@ -68,6 +68,21 @@ void OpenVrDisplayPlugin::activate() {
|
||||||
_compositor = vr::VRCompositor();
|
_compositor = vr::VRCompositor();
|
||||||
Q_ASSERT(_compositor);
|
Q_ASSERT(_compositor);
|
||||||
HmdDisplayPlugin::activate();
|
HmdDisplayPlugin::activate();
|
||||||
|
|
||||||
|
// set up default sensor space such that the UI overlay will align with the front of the room.
|
||||||
|
auto chaperone = vr::VRChaperone();
|
||||||
|
if (chaperone) {
|
||||||
|
float const UI_RADIUS = 1.0f;
|
||||||
|
float const UI_HEIGHT = 1.6f;
|
||||||
|
float const UI_Z_OFFSET = 0.5;
|
||||||
|
|
||||||
|
float xSize, zSize;
|
||||||
|
chaperone->GetPlayAreaSize(&xSize, &zSize);
|
||||||
|
glm::vec3 uiPos(0.0f, UI_HEIGHT, UI_RADIUS - (0.5f * zSize) - UI_Z_OFFSET);
|
||||||
|
_sensorResetMat = glm::inverse(createMatFromQuatAndPos(glm::quat(), uiPos));
|
||||||
|
} else {
|
||||||
|
qDebug() << "OpenVR: error could not get chaperone pointer";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::deactivate() {
|
void OpenVrDisplayPlugin::deactivate() {
|
||||||
|
@ -115,7 +130,7 @@ glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vr::TrackedDevicePose_t predictedTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
vr::TrackedDevicePose_t predictedTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||||
_system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseSeated, predictedSecondsFromNow, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount);
|
_system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, predictedSecondsFromNow, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount);
|
||||||
|
|
||||||
// copy and process predictedTrackedDevicePoses
|
// copy and process predictedTrackedDevicePoses
|
||||||
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
||||||
|
|
Loading…
Reference in a new issue