This commit is contained in:
Wayne Chen 2018-06-18 15:45:03 -07:00
commit 413f08e900
47 changed files with 577 additions and 754 deletions

View file

@ -27,7 +27,8 @@ android {
'-DRELEASE_TYPE=' + RELEASE_TYPE,
'-DSTABLE_BUILD=' + STABLE_BUILD,
'-DDISABLE_QML=OFF',
'-DDISABLE_KTX_CACHE=OFF'
'-DDISABLE_KTX_CACHE=OFF',
'-DUSE_BREAKPAD=' + (project.hasProperty("BACKTRACE_URL") && project.hasProperty("BACKTRACE_TOKEN") ? 'ON' : 'OFF');
}
}
signingConfigs {
@ -46,6 +47,10 @@ android {
}
buildTypes {
debug {
buildConfigField "String", "BACKTRACE_URL", "\"" + (project.hasProperty("BACKTRACE_URL") ? BACKTRACE_URL : '') + "\""
buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (project.hasProperty("BACKTRACE_TOKEN") ? BACKTRACE_TOKEN : '') + "\""
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
@ -53,6 +58,8 @@ android {
project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") &&
project.hasProperty("HIFI_ANDROID_KEY_ALIAS") &&
project.hasProperty("HIFI_ANDROID_KEY_PASSWORD")? signingConfigs.release : null
buildConfigField "String", "BACKTRACE_URL", "\"" + (project.hasProperty("BACKTRACE_URL") ? BACKTRACE_URL : '') + "\""
buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (project.hasProperty("BACKTRACE_TOKEN") ? BACKTRACE_TOKEN : '') + "\""
}
}

View file

@ -67,6 +67,12 @@
android:name=".SplashActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Translucent.NoActionBar" />
<service
android:name=".BreakpadUploaderService"
android:enabled="true"
android:exported="false"
android:process=":breakpad_uploader"/>
</application>
<uses-feature android:name="android.software.vr.mode" android:required="true"/>

View file

@ -0,0 +1,173 @@
package io.highfidelity.hifiinterface;
import android.app.Service;
import android.content.Intent;
import android.os.FileObserver;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Timer;
import java.util.TimerTask;
import javax.net.ssl.HttpsURLConnection;
public class BreakpadUploaderService extends Service {
private static final String ANNOTATIONS_JSON = "annotations.json";
private static final String TAG = "Interface";
public static final String EXT_DMP = "dmp";
private static final long DUMP_DELAY = 5000;
private FileObserver fileObserver;
public BreakpadUploaderService() {
super();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
URL baseUrl;
baseUrl = getUrl();
if (baseUrl == null) {
stopSelf();
return START_NOT_STICKY;
}
new Thread(() -> {
File[] matchingFiles = getFilesByExtension(getObbDir(), EXT_DMP);
for (File file : matchingFiles) {
uploadDumpAndDelete(file, baseUrl);
}
}).start();
fileObserver = new FileObserver(getObbDir().getPath()) {
@Override
public void onEvent(int event, String path) {
if (path == null) {
return;
}
if (FileObserver.CREATE == event && EXT_DMP.equals(getExtension(path))) {
URL baseUrl = getUrl();
if (baseUrl != null) {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
uploadDumpAndDelete(new File(getObbDir(), path), baseUrl);
}
}, DUMP_DELAY);
}
}
}
};
fileObserver.startWatching();
return START_STICKY;
}
private URL getUrl() {
String parameters = getAnnotationsAsUrlEncodedParameters();
try {
return new URL(BuildConfig.BACKTRACE_URL+ "/post?format=minidump&token=" + BuildConfig.BACKTRACE_TOKEN + (parameters.isEmpty() ? "" : ("&" + parameters)));
} catch (MalformedURLException e) {
Log.e(TAG, "Could not initialize Breakpad URL", e);
}
return null;
}
private void uploadDumpAndDelete(File file, URL url) {
int size = (int) file.length();
byte[] bytes = new byte[size];
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
buf.read(bytes, 0, bytes.length);
buf.close();
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
urlConnection.setChunkedStreamingMode(0);
OutputStream ostream = urlConnection.getOutputStream();
OutputStream out = new BufferedOutputStream(ostream);
out.write(bytes, 0, size);
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
in.read();
if (urlConnection.getResponseCode() == 200) {
file.delete();
}
urlConnection.disconnect();
} catch (IOException e) {
Log.e(TAG, "Error uploading file " + file.getAbsolutePath(), e);
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private File[] getFilesByExtension(File dir, final String extension) {
return dir.listFiles(pathName -> getExtension(pathName.getName()).equals(extension));
}
private String getExtension(String fileName) {
String extension = "";
int i = fileName.lastIndexOf('.');
int p = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\'));
if (i > p) {
extension = fileName.substring(i+1);
}
return extension;
}
public String getAnnotationsAsUrlEncodedParameters() {
String parameters = "";
File annotationsFile = new File(getObbDir(), ANNOTATIONS_JSON);
if (annotationsFile.exists()) {
JsonParser parser = new JsonParser();
try {
JsonObject json = (JsonObject) parser.parse(new FileReader(annotationsFile));
for (String k: json.keySet()) {
if (!json.get(k).getAsString().isEmpty()) {
String key = k.contains("/") ? k.substring(k.indexOf("/") + 1) : k;
if (!parameters.isEmpty()) {
parameters += "&";
}
parameters += URLEncoder.encode(key, "UTF-8") + "=" + URLEncoder.encode(json.get(k).getAsString(), "UTF-8");
}
}
} catch (FileNotFoundException e) {
Log.e(TAG, "Error reading annotations file", e);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Error reading annotations file", e);
}
}
return parameters;
}
}

View file

@ -56,6 +56,8 @@ public class InterfaceActivity extends QtActivity {
private AssetManager assetManager;
private static boolean inVrMode;
private boolean nativeEnterBackgroundCallEnqueued = false;
// private GvrApi gvrApi;
// Opaque native pointer to the Application C++ object.
// This object is owned by the InterfaceActivity instance and passed to the native methods.
@ -121,13 +123,18 @@ public class InterfaceActivity extends QtActivity {
@Override
protected void onPause() {
super.onPause();
nativeEnterBackground();
if (super.isLoading) {
nativeEnterBackgroundCallEnqueued = true;
} else {
nativeEnterBackground();
}
//gvrApi.pauseTracking();
}
@Override
protected void onStart() {
super.onStart();
nativeEnterBackgroundCallEnqueued = false;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
@ -256,6 +263,9 @@ public class InterfaceActivity extends QtActivity {
public void onAppLoadedComplete() {
super.isLoading = false;
if (nativeEnterBackgroundCallEnqueued) {
nativeEnterBackground();
}
}
public void performHapticFeedback(int duration) {

View file

@ -1,13 +1,13 @@
package io.highfidelity.hifiinterface;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.DialogInterface;
import android.app.AlertDialog;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
@ -24,20 +24,31 @@ public class PermissionChecker extends Activity {
private static final int REQUEST_PERMISSIONS = 20;
private static final boolean CHOOSE_AVATAR_ON_STARTUP = false;
private static final String TAG = "Interface";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent myIntent = new Intent(this, BreakpadUploaderService.class);
startService(myIntent);
if (CHOOSE_AVATAR_ON_STARTUP) {
showMenu();
}
this.requestAppPermissions(new
String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA}
,2,REQUEST_PERMISSIONS);
File obbDir = getObbDir();
if (!obbDir.exists()) {
if (obbDir.mkdirs()) {
Log.d(TAG, "Obb dir created");
}
}
requestAppPermissions(new
String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA}
,2,REQUEST_PERMISSIONS);
}
@ -124,6 +135,4 @@ public class PermissionChecker extends Activity {
launchActivityWithPermissions();
}
}
}

View file

@ -149,6 +149,13 @@ def packages = [
file: 'etc2comp-patched-armv8-libcpp.tgz',
versionId: 'bHhGECRAQR1vkpshBcK6ByNc1BQIM8gU',
checksum: '14b02795d774457a33bbc60e00a786bc'
],
breakpad: [
file: 'breakpad.zip',
versionId: '2OwvCCZrF171wnte5T44AnjTYFhhJsGJ',
checksum: 'a46062a3167dfedd4fb4916136e204d2',
sharedLibFolder: 'lib',
includeLibs: ['libbreakpad_client.a','libbreakpad.a']
]
]
@ -367,6 +374,7 @@ task verifyPolyvox(type: Verify) { def p = packages['polyvox']; src new File(bas
task verifyTBB(type: Verify) { def p = packages['tbb']; src new File(baseFolder, p['file']); checksum p['checksum'] }
task verifyHifiAC(type: Verify) { def p = packages['hifiAC']; src new File(baseFolder, p['file']); checksum p['checksum'] }
task verifyEtc2Comp(type: Verify) { def p = packages['etc2comp']; src new File(baseFolder, p['file']); checksum p['checksum'] }
task verifyBreakpad(type: Verify) { def p = packages['breakpad']; src new File(baseFolder, p['file']); checksum p['checksum'] }
task verifyDependencyDownloads(dependsOn: downloadDependencies) { }
verifyDependencyDownloads.dependsOn verifyQt
@ -378,6 +386,7 @@ verifyDependencyDownloads.dependsOn verifyPolyvox
verifyDependencyDownloads.dependsOn verifyTBB
verifyDependencyDownloads.dependsOn verifyHifiAC
verifyDependencyDownloads.dependsOn verifyEtc2Comp
verifyDependencyDownloads.dependsOn verifyBreakpad
task extractDependencies(dependsOn: verifyDependencyDownloads) {
doLast {
@ -615,4 +624,4 @@ task testElf (dependsOn: 'externalNativeBuildDebug') {
}
}
}
*/
*/

View file

@ -40,16 +40,22 @@ if (WIN32)
set(_LIB_FOLDER "$<$<CONFIG:RelWithDebInfo>:build/EtcLib/RelWithDebInfo>")
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<CONFIG:MinSizeRel>:build/EtcLib/MinSizeRel>")
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<OR:$<CONFIG:Release>,$<CONFIG:Debug>>:build/EtcLib/Release>")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/${_LIB_FOLDER}/EtcLib.lib CACHE FILEPATH "Path to Etc2Comp release library")
elseif (APPLE)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/build/EtcLib/Debug/libEtcLib.a CACHE FILEPATH "Path to EtcLib debug library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/build/EtcLib/Release/libEtcLib.a CACHE FILEPATH "Path to EtcLib release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/build/EtcLib/Debug/libEtcLib.a CACHE FILEPATH "Path to EtcLib debug library")
set(_LIB_FOLDER "$<$<CONFIG:RelWithDebInfo>:build/EtcLib/RelWithDebInfo>")
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<CONFIG:MinSizeRel>:build/EtcLib/MinSizeRel>")
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<OR:$<CONFIG:Release>,$<CONFIG:Debug>>:build/EtcLib/Release>")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/${_LIB_FOLDER}/libEtcLib.a CACHE FILEPATH "Path to Etc2Comp release library")
else ()
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Path to EtcLib debug library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/build/EtcLib/libEtcLib.a CACHE FILEPATH "Path to EtcLib release library")
endif ()
set(ETC_INCLUDE_DIR ${SOURCE_DIR}/EtcLib/Etc CACHE FILEPATH "Path to Etc2Comp/Etc include directory")
set(ETCCODEC_INCLUDE_DIR ${SOURCE_DIR}/EtcLib/EtcCodec CACHE FILEPATH "Path to Etc2Comp/EtcCodec include directory")
# ETC2COMP_INCLUDE_DIRS will be set later by FindEtc2Comp
# ETC2COMP_INCLUDE_DIRS will be set later by FindEtc2Comp

View file

@ -0,0 +1,22 @@
#
# Copyright 2018 High Fidelity, Inc.
# Created by Gabriel Calero & Cristian Duarte on 2018/03/13
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(TARGET_BREAKPAD)
if (ANDROID)
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/breakpad)
set(BREAKPAD_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE TYPE INTERNAL)
set(LIB_DIR ${INSTALL_DIR}/lib)
list(APPEND BREAKPAD_LIBRARIES ${LIB_DIR}/libbreakpad_client.a)
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BREAKPAD_INCLUDE_DIRS})
if (USE_BREAKPAD)
add_definitions(-DHAS_BREAKPAD)
endif()
endif()
target_link_libraries(${TARGET_NAME} ${BREAKPAD_LIBRARIES})
endmacro()

View file

@ -226,6 +226,7 @@ target_openssl()
target_bullet()
target_opengl()
add_crashpad()
target_breakpad()
# perform standard include and linking for found externals
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})

View file

@ -87,8 +87,8 @@ Column {
description: description,
online_users: data.details.connections || data.details.concurrency || 0,
// Server currently doesn't give isStacked (undefined). Could give bool.
drillDownToPlace: (data.isStacked === undefined) ? (data.action !== 'concurrency') : data.isStacked,
isStacked: !!data.isStacked
drillDownToPlace: data.is_stacked || (data.action === 'concurrency'),
isStacked: !!data.is_stacked
};
}

View file

@ -150,8 +150,8 @@
#include "audio/AudioScope.h"
#include "avatar/AvatarManager.h"
#include "avatar/MyHead.h"
#include "CrashRecoveryHandler.h"
#include "CrashHandler.h"
#include "Crashpad.h"
#include "devices/DdeFaceTracker.h"
#include "DiscoverabilityManager.h"
#include "GLCanvas.h"
@ -282,7 +282,9 @@ public:
private:
void initialize() {
setObjectName("Render");
PROFILE_SET_THREAD_NAME("Render");
setCrashAnnotation("render_thread_id", std::to_string((size_t)QThread::currentThreadId()));
if (!_renderContext->makeCurrent()) {
qFatal("Unable to make rendering context current on render thread");
}
@ -791,7 +793,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
bool previousSessionCrashed { false };
if (!inTestMode) {
previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);
previousSessionCrashed = CrashRecoveryHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);
}
// get dir to use for cache
@ -1096,6 +1098,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
_logger->setSessionID(accountManager->getSessionID());
setCrashAnnotation("metaverse_session_id", accountManager->getSessionID().toString().toStdString());
setCrashAnnotation("main_thread_id", std::to_string((size_t)QThread::currentThreadId()));
if (steamClient) {
qCDebug(interfaceapp) << "[VERSION] SteamVR buildID:" << steamClient->getSteamVRBuildID();
@ -1241,9 +1244,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
connect(accountManager.data(), &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog);
#endif
connect(accountManager.data(), &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
connect(accountManager.data(), &AccountManager::usernameChanged, [](QString username){
setCrashAnnotation("username", username.toStdString());
});
// set the account manager's root URL and trigger a login request if we don't have the access token
accountManager->setIsAgent(true);
@ -6165,6 +6165,8 @@ void Application::updateWindowTitle() const {
QString connectionStatus = nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED)";
QString username = accountManager->getAccountInfo().getUsername();
setCrashAnnotation("username", username.toStdString());
QString currentPlaceName;
if (isServerlessMode()) {
currentPlaceName = "serverless: " + DependencyManager::get<AddressManager>()->getDomainURL().toString();

View file

@ -2,8 +2,8 @@
// CrashHandler.h
// interface/src
//
// Created by David Rowe on 24 Aug 2015.
// Copyright 2015 High Fidelity, Inc.
// Created by Clement Brisset on 01/19/18.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -12,22 +12,10 @@
#ifndef hifi_CrashHandler_h
#define hifi_CrashHandler_h
#include <QString>
#include <string>
class CrashHandler {
bool startCrashHandler();
void setCrashAnnotation(std::string name, std::string value);
public:
static bool checkForResetSettings(bool wasLikelyCrash, bool suppressPrompt = false);
private:
enum Action {
DELETE_INTERFACE_INI,
RETAIN_IMPORTANT_INFO,
DO_NOTHING
};
static Action promptUserForAction(bool showCrashMessage);
static void handleCrash(Action action);
};
#endif // hifi_CrashHandler_h
#endif

View file

@ -0,0 +1,70 @@
//
// CrashHandler_Breakpad.cpp
// interface/src
//
// Created by Clement Brisset on 01/19/18.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "CrashHandler.h"
#if HAS_BREAKPAD
#include <mutex>
#include <client/linux/handler/exception_handler.h>
#include <client/linux/handler/minidump_descriptor.h>
#include <QDebug>
#include <QMap>
#include <QtCore/QFileInfo>
#include <QtAndroidExtras/QAndroidJniObject>
#include <SettingHelpers.h>
google_breakpad::ExceptionHandler* gBreakpadHandler;
std::mutex annotationMutex;
QMap<QString, QString> annotations;
static bool breakpad_dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) {
return succeeded;
}
QString obbDir() {
QAndroidJniObject mediaDir = QAndroidJniObject::callStaticObjectMethod("android/os/Environment", "getExternalStorageDirectory", "()Ljava/io/File;");
QAndroidJniObject mediaPath = mediaDir.callObjectMethod( "getAbsolutePath", "()Ljava/lang/String;" );
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
QAndroidJniObject package = activity.callObjectMethod("getPackageName", "()Ljava/lang/String;");
QString dataAbsPath = mediaPath.toString()+"/Android/obb/" + package.toString();
return dataAbsPath;
}
bool startCrashHandler() {
gBreakpadHandler = new google_breakpad::ExceptionHandler(
google_breakpad::MinidumpDescriptor(obbDir().toStdString()),
nullptr, breakpad_dumpCallback, nullptr, true, -1);
return true;
}
void setCrashAnnotation(std::string name, std::string value) {
std::lock_guard<std::mutex> guard(annotationMutex);
QString qName = QString::fromStdString(name);
QString qValue = QString::fromStdString(value);
annotations[qName] = qValue;
QSettings settings(obbDir() + "/annotations.json", JSON_FORMAT);
settings.clear();
settings.beginGroup("Annotations");
for (auto k : annotations.keys()) {
settings.setValue(k, annotations.value(k));
}
settings.endGroup();
settings.sync();
}
#endif

View file

@ -1,5 +1,5 @@
//
// Crashpad.cpp
// CrashHandler_Crashpad.cpp
// interface/src
//
// Created by Clement Brisset on 01/19/18.
@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Crashpad.h"
#include "CrashHandler.h"
#include <assert.h>
@ -117,14 +117,4 @@ void setCrashAnnotation(std::string name, std::string value) {
crashpadAnnotations->SetKeyValue(name, value);
}
#else
bool startCrashHandler() {
qDebug() << "No crash handler available.";
return false;
}
void setCrashAnnotation(std::string name, std::string value) {
}
#endif

View file

@ -0,0 +1,27 @@
//
// CrashHandler_None.cpp
// interface/src
//
// Created by Clement Brisset on 01/19/18.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "CrashHandler.h"
#include <assert.h>
#include <QDebug>
#if !defined(HAS_CRASHPAD) && !defined(HAS_BREAKPAD)
bool startCrashHandler() {
qDebug() << "No crash handler available.";
return false;
}
void setCrashAnnotation(std::string name, std::string value) {
}
#endif

View file

@ -1,5 +1,5 @@
//
// CrashHandler.cpp
// CrashRecoveryHandler.cpp
// interface/src
//
// Created by David Rowe on 24 Aug 2015.
@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "CrashHandler.h"
#include "CrashRecoveryHandler.h"
#include <QCoreApplication>
#include <QDialog>
@ -30,7 +30,7 @@
#include <SettingHelpers.h>
bool CrashHandler::checkForResetSettings(bool wasLikelyCrash, bool suppressPrompt) {
bool CrashRecoveryHandler::checkForResetSettings(bool wasLikelyCrash, bool suppressPrompt) {
QSettings::setDefaultFormat(JSON_FORMAT);
QSettings settings;
settings.beginGroup("Developer");
@ -59,7 +59,7 @@ bool CrashHandler::checkForResetSettings(bool wasLikelyCrash, bool suppressPromp
return wasLikelyCrash;
}
CrashHandler::Action CrashHandler::promptUserForAction(bool showCrashMessage) {
CrashRecoveryHandler::Action CrashRecoveryHandler::promptUserForAction(bool showCrashMessage) {
QDialog crashDialog;
QLabel* label;
if (showCrashMessage) {
@ -94,20 +94,20 @@ CrashHandler::Action CrashHandler::promptUserForAction(bool showCrashMessage) {
if (result == QDialog::Accepted) {
if (option1->isChecked()) {
return CrashHandler::DELETE_INTERFACE_INI;
return CrashRecoveryHandler::DELETE_INTERFACE_INI;
}
if (option2->isChecked()) {
return CrashHandler::RETAIN_IMPORTANT_INFO;
return CrashRecoveryHandler::RETAIN_IMPORTANT_INFO;
}
}
// Dialog cancelled or "do nothing" option chosen
return CrashHandler::DO_NOTHING;
return CrashRecoveryHandler::DO_NOTHING;
}
void CrashHandler::handleCrash(CrashHandler::Action action) {
if (action != CrashHandler::DELETE_INTERFACE_INI && action != CrashHandler::RETAIN_IMPORTANT_INFO) {
// CrashHandler::DO_NOTHING or unexpected value
void CrashRecoveryHandler::handleCrash(CrashRecoveryHandler::Action action) {
if (action != CrashRecoveryHandler::DELETE_INTERFACE_INI && action != CrashRecoveryHandler::RETAIN_IMPORTANT_INFO) {
// CrashRecoveryHandler::DO_NOTHING or unexpected value
return;
}
@ -126,7 +126,7 @@ void CrashHandler::handleCrash(CrashHandler::Action action) {
QUrl address;
bool tutorialComplete = false;
if (action == CrashHandler::RETAIN_IMPORTANT_INFO) {
if (action == CrashRecoveryHandler::RETAIN_IMPORTANT_INFO) {
// Read avatar info
// Location and orientation
@ -151,7 +151,7 @@ void CrashHandler::handleCrash(CrashHandler::Action action) {
settingsFile.remove();
}
if (action == CrashHandler::RETAIN_IMPORTANT_INFO) {
if (action == CrashRecoveryHandler::RETAIN_IMPORTANT_INFO) {
// Write avatar info
// Location and orientation

View file

@ -0,0 +1,33 @@
//
// CrashRecoveryHandler.h
// interface/src
//
// Created by David Rowe on 24 Aug 2015.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_CrashRecoveryHandler_h
#define hifi_CrashRecoveryHandler_h
#include <QString>
class CrashRecoveryHandler {
public:
static bool checkForResetSettings(bool wasLikelyCrash, bool suppressPrompt = false);
private:
enum Action {
DELETE_INTERFACE_INI,
RETAIN_IMPORTANT_INFO,
DO_NOTHING
};
static Action promptUserForAction(bool showCrashMessage);
static void handleCrash(Action action);
};
#endif // hifi_CrashRecoveryHandler_h

View file

@ -1,20 +0,0 @@
//
// Crashpad.h
// interface/src
//
// Created by Clement Brisset on 01/19/18.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Crashpad_h
#define hifi_Crashpad_h
#include <string>
bool startCrashHandler();
void setCrashAnnotation(std::string name, std::string value);
#endif // hifi_Crashpad_h

View file

@ -23,7 +23,7 @@
#include <UserActivityLogger.h>
#include <UUID.h>
#include "Crashpad.h"
#include "CrashHandler.h"
#include "Menu.h"
const Discoverability::Mode DEFAULT_DISCOVERABILITY_MODE = Discoverability::Connections;

View file

@ -21,6 +21,17 @@ AvatarMotionState::AvatarMotionState(AvatarSharedPointer avatar, const btCollisi
_type = MOTIONSTATE_TYPE_AVATAR;
}
void AvatarMotionState::handleEasyChanges(uint32_t& flags) {
ObjectMotionState::handleEasyChanges(flags);
if (flags & Simulation::DIRTY_PHYSICS_ACTIVATION && !_body->isActive()) {
_body->activate();
}
}
bool AvatarMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
return ObjectMotionState::handleHardAndEasyChanges(flags, engine);
}
AvatarMotionState::~AvatarMotionState() {
assert(_avatar);
_avatar = nullptr;
@ -46,6 +57,9 @@ PhysicsMotionType AvatarMotionState::computePhysicsMotionType() const {
const btCollisionShape* AvatarMotionState::computeNewShape() {
ShapeInfo shapeInfo;
std::static_pointer_cast<Avatar>(_avatar)->computeShapeInfo(shapeInfo);
glm::vec3 halfExtents = shapeInfo.getHalfExtents();
halfExtents.y = 0.0f;
_diameter = 2.0f * glm::length(halfExtents);
return getShapeManager()->getShape(shapeInfo);
}
@ -60,25 +74,31 @@ void AvatarMotionState::getWorldTransform(btTransform& worldTrans) const {
worldTrans.setRotation(glmToBullet(getObjectRotation()));
if (_body) {
_body->setLinearVelocity(glmToBullet(getObjectLinearVelocity()));
_body->setAngularVelocity(glmToBullet(getObjectLinearVelocity()));
_body->setAngularVelocity(glmToBullet(getObjectAngularVelocity()));
}
}
// virtual
void AvatarMotionState::setWorldTransform(const btTransform& worldTrans) {
// HACK: The PhysicsEngine does not actually move OTHER avatars -- instead it slaves their local RigidBody to the transform
// as specified by a remote simulation. However, to give the remote simulation time to respond to our own objects we tie
// the other avatar's body to its true position with a simple spring. This is a HACK that will have to be improved later.
const float SPRING_TIMESCALE = 0.5f;
float tau = PHYSICS_ENGINE_FIXED_SUBSTEP / SPRING_TIMESCALE;
btVector3 currentPosition = worldTrans.getOrigin();
btVector3 targetPosition = glmToBullet(getObjectPosition());
btTransform newTransform;
newTransform.setOrigin((1.0f - tau) * currentPosition + tau * targetPosition);
newTransform.setRotation(glmToBullet(getObjectRotation()));
_body->setWorldTransform(newTransform);
_body->setLinearVelocity(glmToBullet(getObjectLinearVelocity()));
_body->setAngularVelocity(glmToBullet(getObjectLinearVelocity()));
btVector3 offsetToTarget = glmToBullet(getObjectPosition()) - currentPosition;
float distance = offsetToTarget.length();
if ((1.0f - tau) * distance > _diameter) {
// the avatar body is far from its target --> slam position
btTransform newTransform;
newTransform.setOrigin(currentPosition + offsetToTarget);
newTransform.setRotation(glmToBullet(getObjectRotation()));
_body->setWorldTransform(newTransform);
_body->setLinearVelocity(glmToBullet(getObjectLinearVelocity()));
_body->setAngularVelocity(glmToBullet(getObjectAngularVelocity()));
} else {
// the avatar body is near its target --> slam velocity
btVector3 velocity = glmToBullet(getObjectLinearVelocity()) + (1.0f / SPRING_TIMESCALE) * offsetToTarget;
_body->setLinearVelocity(velocity);
_body->setAngularVelocity(glmToBullet(getObjectAngularVelocity()));
}
}
// These pure virtual methods must be implemented for each MotionState type
@ -145,3 +165,8 @@ void AvatarMotionState::computeCollisionGroupAndMask(int32_t& group, int32_t& ma
mask = Physics::getDefaultCollisionMask(group);
}
// virtual
float AvatarMotionState::getMass() const {
return std::static_pointer_cast<Avatar>(_avatar)->computeMass();
}

View file

@ -23,6 +23,9 @@ class AvatarMotionState : public ObjectMotionState {
public:
AvatarMotionState(AvatarSharedPointer avatar, const btCollisionShape* shape);
virtual void handleEasyChanges(uint32_t& flags) override;
virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) override;
virtual PhysicsMotionType getMotionType() const override { return _motionType; }
virtual uint32_t getIncomingDirtyFlags() override;
@ -64,6 +67,8 @@ public:
virtual void computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const override;
virtual float getMass() const override;
friend class AvatarManager;
friend class Avatar;
@ -76,6 +81,7 @@ protected:
virtual const btCollisionShape* computeNewShape() override;
AvatarSharedPointer _avatar;
float _diameter { 0.0f };
uint32_t _dirtyFlags;
};

View file

@ -26,7 +26,7 @@
#include "AddressManager.h"
#include "Application.h"
#include "Crashpad.h"
#include "CrashHandler.h"
#include "InterfaceLogging.h"
#include "UserActivityLogger.h"
#include "MainWindow.h"

View file

@ -319,6 +319,15 @@ public slots:
* {@link Window.processingGifStarted|processingGifStarted} and {@link Window.processingGifCompleted|processingGifCompleted}
* are emitted. The path to store the snapshots and the length of the animated GIF to capture are specified in Settings >
* General > Snapshots.
*
* If user has supplied a specific filename for the snapshot:
* If the user's requested filename has a suffix that's contained within SUPPORTED_IMAGE_FORMATS,
* DON'T append ".jpg" to the filename. QT will save the image in the format associated with the
* filename's suffix.
* If you want lossless Snapshots, supply a `.png` filename. Otherwise, use `.jpeg` or `.jpg`.
* Otherwise, ".jpg" is appended to the user's requested filename so that the image is saved in JPG format.
* If the user hasn't supplied a specific filename for the snapshot:
* Save the snapshot in JPG format according to FILENAME_PATH_FORMAT
* @function Window.takeSnapshot
* @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken}
* signal.

View file

@ -50,6 +50,7 @@ const QString DATETIME_FORMAT = "yyyy-MM-dd_hh-mm-ss";
const QString SNAPSHOTS_DIRECTORY = "Snapshots";
const QString URL = "highfidelity_url";
static const int SNAPSHOT_360_TIMER_INTERVAL = 350;
static const QList<QString> SUPPORTED_IMAGE_FORMATS = { "jpg", "jpeg", "png" };
Snapshot::Snapshot() {
_snapshotTimer.setSingleShot(false);
@ -67,7 +68,6 @@ Snapshot::Snapshot() {
}
SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) {
if (!QFile(snapshotPath).exists()) {
return NULL;
}
@ -95,7 +95,6 @@ SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) {
}
QString Snapshot::saveSnapshot(QImage image, const QString& filename, const QString& pathname) {
QFile* snapshotFile = savedFileForSnapshot(image, false, filename, pathname);
if (snapshotFile) {
@ -122,11 +121,15 @@ static const glm::quat CAMERA_ORIENTATION_LEFT(glm::quat(glm::radians(glm::vec3(
static const glm::quat CAMERA_ORIENTATION_BACK(glm::quat(glm::radians(glm::vec3(0.0f, 180.0f, 0.0f))));
static const glm::quat CAMERA_ORIENTATION_RIGHT(glm::quat(glm::radians(glm::vec3(0.0f, 270.0f, 0.0f))));
static const glm::quat CAMERA_ORIENTATION_UP(glm::quat(glm::radians(glm::vec3(90.0f, 0.0f, 0.0f))));
void Snapshot::save360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat, const bool& notify, const QString& filename) {
void Snapshot::save360Snapshot(const glm::vec3& cameraPosition,
const bool& cubemapOutputFormat,
const bool& notify,
const QString& filename) {
_snapshotFilename = filename;
_notify360 = notify;
_cubemapOutputFormat = cubemapOutputFormat;
SecondaryCameraJobConfig* secondaryCameraRenderConfig = static_cast<SecondaryCameraJobConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera"));
SecondaryCameraJobConfig* secondaryCameraRenderConfig =
static_cast<SecondaryCameraJobConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera"));
// Save initial values of secondary camera render config
_oldEnabled = secondaryCameraRenderConfig->isEnabled();
@ -141,9 +144,11 @@ void Snapshot::save360Snapshot(const glm::vec3& cameraPosition, const bool& cube
}
// Initialize some secondary camera render config options for 360 snapshot capture
static_cast<ToneMappingConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping"))->setCurve(0);
static_cast<ToneMappingConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping"))
->setCurve(0);
secondaryCameraRenderConfig->resetSizeSpectatorCamera(static_cast<int>(CUBEMAP_SIDE_PIXEL_DIMENSION), static_cast<int>(CUBEMAP_SIDE_PIXEL_DIMENSION));
secondaryCameraRenderConfig->resetSizeSpectatorCamera(static_cast<int>(CUBEMAP_SIDE_PIXEL_DIMENSION),
static_cast<int>(CUBEMAP_SIDE_PIXEL_DIMENSION));
secondaryCameraRenderConfig->setProperty("attachedEntityId", "");
secondaryCameraRenderConfig->setPosition(cameraPosition);
secondaryCameraRenderConfig->setProperty("vFoV", SNAPSHOT_360_FOV);
@ -159,7 +164,8 @@ void Snapshot::save360Snapshot(const glm::vec3& cameraPosition, const bool& cube
}
void Snapshot::takeNextSnapshot() {
SecondaryCameraJobConfig* config = static_cast<SecondaryCameraJobConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera"));
SecondaryCameraJobConfig* config =
static_cast<SecondaryCameraJobConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera"));
// Order is:
// 0. Down
@ -191,7 +197,9 @@ void Snapshot::takeNextSnapshot() {
_snapshotTimer.stop();
// Reset secondary camera render config
static_cast<ToneMappingConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping"))->setCurve(1);
static_cast<ToneMappingConfig*>(
qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping"))
->setCurve(1);
config->resetSizeSpectatorCamera(qApp->getWindow()->geometry().width(), qApp->getWindow()->geometry().height());
config->setProperty("attachedEntityId", _oldAttachedEntityId);
config->setProperty("vFoV", _oldvFoV);
@ -338,8 +346,10 @@ QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) {
return static_cast<QTemporaryFile*>(savedFileForSnapshot(image, true));
}
QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname) {
QFile* Snapshot::savedFileForSnapshot(QImage& shot,
bool isTemporary,
const QString& userSelectedFilename,
const QString& userSelectedPathname) {
// adding URL to snapshot
QUrl currentURL = DependencyManager::get<AddressManager>()->currentPublicAddress();
shot.setText(URL, currentURL.toString());
@ -350,12 +360,23 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QSt
QDateTime now = QDateTime::currentDateTime();
// If user has requested specific filename then use it, else create the filename
// 'jpg" is appended, as the image is saved in jpg format. This is the case for all snapshots
// (see definition of FILENAME_PATH_FORMAT)
// If user has supplied a specific filename for the snapshot:
// If the user's requested filename has a suffix that's contained within SUPPORTED_IMAGE_FORMATS,
// DON'T append ".jpg" to the filename. QT will save the image in the format associated with the
// filename's suffix.
// If you want lossless Snapshots, supply a `.png` filename. Otherwise, use `.jpeg` or `.jpg`.
// Otherwise, ".jpg" is appended to the user's requested filename so that the image is saved in JPG format.
// If the user hasn't supplied a specific filename for the snapshot:
// Save the snapshot in JPG format according to FILENAME_PATH_FORMAT
QString filename;
if (!userSelectedFilename.isNull()) {
filename = userSelectedFilename + ".jpg";
QFileInfo snapshotFileInfo(userSelectedFilename);
QString userSelectedFilenameSuffix = snapshotFileInfo.suffix();
if (SUPPORTED_IMAGE_FORMATS.contains(userSelectedFilenameSuffix)) {
filename = userSelectedFilename;
} else {
filename = userSelectedFilename + ".jpg";
}
} else {
filename = FILENAME_PATH_FORMAT.arg(username, now.toString(DATETIME_FORMAT));
}
@ -372,11 +393,13 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QSt
}
if (snapshotFullPath.isEmpty()) {
snapshotFullPath = OffscreenUi::getExistingDirectory(nullptr, "Choose Snapshots Directory", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
snapshotFullPath =
OffscreenUi::getExistingDirectory(nullptr, "Choose Snapshots Directory",
QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
_snapshotsLocation.set(snapshotFullPath);
}
if (!snapshotFullPath.isEmpty()) { // not cancelled
if (!snapshotFullPath.isEmpty()) { // not cancelled
if (!snapshotFullPath.endsWith(QDir::separator())) {
snapshotFullPath.append(QDir::separator());
@ -393,7 +416,9 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QSt
qApp->getApplicationCompositor().getReticleInterface()->setVisible(true);
qApp->getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(true);
snapshotFullPath = OffscreenUi::getExistingDirectory(nullptr, "Write Error - Choose New Snapshots Directory", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
snapshotFullPath =
OffscreenUi::getExistingDirectory(nullptr, "Write Error - Choose New Snapshots Directory",
QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
if (snapshotFullPath.isEmpty()) {
return NULL;
}
@ -412,7 +437,6 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QSt
return imageFile;
}
}
// Either we were asked for a tempororary, or the user didn't set a directory.
QTemporaryFile* imageTempFile = new QTemporaryFile(QDir::tempPath() + "/XXXXXX-" + filename);
@ -430,11 +454,10 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QSt
}
void Snapshot::uploadSnapshot(const QString& filename, const QUrl& href) {
const QString SNAPSHOT_UPLOAD_URL = "/api/v1/snapshots";
QUrl url = href;
if (url.isEmpty()) {
SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(filename);
SnapshotMetaData* snapshotData = parseSnapshotData(filename);
if (snapshotData) {
url = snapshotData->getURL();
}
@ -444,7 +467,7 @@ void Snapshot::uploadSnapshot(const QString& filename, const QUrl& href) {
url = QUrl(DependencyManager::get<AddressManager>()->currentShareableAddress());
}
SnapshotUploader* uploader = new SnapshotUploader(url, filename);
QFile* file = new QFile(filename);
Q_ASSERT(file->exists());
file->open(QIODevice::ReadOnly);
@ -458,20 +481,16 @@ void Snapshot::uploadSnapshot(const QString& filename, const QUrl& href) {
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader,
QVariant("form-data; name=\"image\"; filename=\"" + file->fileName() + "\""));
imagePart.setBodyDevice(file);
QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
multiPart->append(imagePart);
auto accountManager = DependencyManager::get<AccountManager>();
JSONCallbackParameters callbackParams(uploader, "uploadSuccess", uploader, "uploadFailure");
accountManager->sendRequest(SNAPSHOT_UPLOAD_URL,
AccountManagerAuth::Required,
QNetworkAccessManager::PostOperation,
callbackParams,
nullptr,
multiPart);
accountManager->sendRequest(SNAPSHOT_UPLOAD_URL, AccountManagerAuth::Required, QNetworkAccessManager::PostOperation,
callbackParams, nullptr, multiPart);
}
QString Snapshot::getSnapshotsLocation() {

View file

@ -41,8 +41,6 @@
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false);
Overlays::Overlays() {
auto pointerManager = DependencyManager::get<PointerManager>();
connect(pointerManager.data(), &PointerManager::hoverBeginOverlay, this, &Overlays::hoverEnterPointerEvent);

View file

@ -861,7 +861,6 @@ bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const {
return true;
}
// virtual
void Avatar::simulateAttachments(float deltaTime) {
assert(_attachmentModels.size() == _attachmentModelsTexturesLoaded.size());
PerformanceTimer perfTimer("attachments");
@ -1544,12 +1543,13 @@ void Avatar::updateDisplayNameAlpha(bool showDisplayName) {
}
}
// virtual
void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) {
float uniformScale = getModelScale();
shapeInfo.setCapsuleY(uniformScale * _skeletonModel->getBoundingCapsuleRadius(),
0.5f * uniformScale * _skeletonModel->getBoundingCapsuleHeight());
shapeInfo.setOffset(uniformScale * _skeletonModel->getBoundingCapsuleOffset());
float radius = glm::max(MIN_AVATAR_RADIUS, uniformScale * _skeletonModel->getBoundingCapsuleRadius());
float height = glm::max(MIN_AVATAR_HEIGHT, uniformScale * _skeletonModel->getBoundingCapsuleHeight());
shapeInfo.setCapsuleY(radius, 0.5f * height);
glm::vec3 offset = uniformScale * _skeletonModel->getBoundingCapsuleOffset();
shapeInfo.setOffset(offset);
}
void Avatar::getCapsule(glm::vec3& start, glm::vec3& end, float& radius) {
@ -1572,9 +1572,8 @@ float Avatar::computeMass() {
return _density * TWO_PI * radius * radius * (glm::length(end - start) + 2.0f * radius / 3.0f);
}
// virtual
void Avatar::rebuildCollisionShape() {
addPhysicsFlags(Simulation::DIRTY_SHAPE);
addPhysicsFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
}
void Avatar::setPhysicsCallback(AvatarPhysicsCallback cb) {

View file

@ -83,6 +83,7 @@ public:
connect(qApp, &QCoreApplication::aboutToQuit, [this] {
shutdown();
});
setObjectName("Present");
}
~PresentThread() {

View file

@ -110,8 +110,8 @@ public:
MotionStateType getType() const { return _type; }
virtual PhysicsMotionType getMotionType() const { return _motionType; }
void setMass(float mass);
float getMass() const;
virtual void setMass(float mass);
virtual float getMass() const;
void setBodyLinearVelocity(const glm::vec3& velocity) const;
void setBodyAngularVelocity(const glm::vec3& velocity) const;

View file

@ -105,9 +105,9 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) {
}
case MOTION_TYPE_DYNAMIC: {
mass = motionState->getMass();
if (mass != mass || mass < 1.0f) {
qCDebug(physics) << "mass is too low, setting to 1.0 Kg --" << mass;
mass = 1.0f;
const float MIN_DYNAMIC_MASS = 0.01f;
if (mass != mass || mass < MIN_DYNAMIC_MASS) {
mass = MIN_DYNAMIC_MASS;
}
btCollisionShape* shape = const_cast<btCollisionShape*>(motionState->getShape());
assert(shape);

View file

@ -286,6 +286,7 @@ void DrawHighlight::run(const render::RenderContextPointer& renderContext, const
shaderParameters._size.y = size;
}
auto primaryFramebuffer = inputs.get4();
gpu::doInBatch("DrawHighlight::run", args->_context, [&](gpu::Batch& batch) {
batch.enableStereo(false);
batch.setFramebuffer(destinationFrameBuffer);
@ -301,6 +302,9 @@ void DrawHighlight::run(const render::RenderContextPointer& renderContext, const
batch.setResourceTexture(SCENE_DEPTH_MAP_SLOT, sceneDepthBuffer->getPrimaryDepthTexture());
batch.setResourceTexture(HIGHLIGHTED_DEPTH_MAP_SLOT, highlightedDepthTexture);
batch.draw(gpu::TRIANGLE_STRIP, 4);
// Reset the framebuffer for overlay drawing
batch.setFramebuffer(primaryFramebuffer);
});
}
}
@ -360,6 +364,7 @@ void DebugHighlight::run(const render::RenderContextPointer& renderContext, cons
RenderArgs* args = renderContext->args;
const auto jitter = input.get2();
auto primaryFramebuffer = input.get3();
gpu::doInBatch("DebugHighlight::run", args->_context, [&](gpu::Batch& batch) {
batch.setViewportTransform(args->_viewport);
batch.setFramebuffer(highlightRessources->getColorFramebuffer());
@ -384,6 +389,9 @@ void DebugHighlight::run(const render::RenderContextPointer& renderContext, cons
geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryDepthId);
batch.setResourceTexture(0, nullptr);
// Reset the framebuffer for overlay drawing
batch.setFramebuffer(primaryFramebuffer);
});
}
}
@ -532,12 +540,12 @@ void DrawHighlightTask::build(JobModel& task, const render::Varying& inputs, ren
stream << "HighlightEffect" << i;
name = stream.str();
}
const auto drawHighlightInputs = DrawHighlight::Inputs(deferredFrameTransform, highlightRessources, sceneFrameBuffer, highlightedRect).asVarying();
const auto drawHighlightInputs = DrawHighlight::Inputs(deferredFrameTransform, highlightRessources, sceneFrameBuffer, highlightedRect, primaryFramebuffer).asVarying();
task.addJob<DrawHighlight>(name, drawHighlightInputs, i, sharedParameters);
}
// Debug highlight
const auto debugInputs = DebugHighlight::Inputs(highlightRessources, const_cast<const render::Varying&>(highlight0Rect), jitter).asVarying();
const auto debugInputs = DebugHighlight::Inputs(highlightRessources, const_cast<const render::Varying&>(highlight0Rect), jitter, primaryFramebuffer).asVarying();
task.addJob<DebugHighlight>("HighlightDebug", debugInputs);
}

View file

@ -135,7 +135,7 @@ protected:
class DrawHighlight {
public:
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, HighlightRessourcesPointer, DeferredFramebufferPointer, glm::ivec4>;
using Inputs = render::VaryingSet5<DeferredFrameTransformPointer, HighlightRessourcesPointer, DeferredFramebufferPointer, glm::ivec4, gpu::FramebufferPointer>;
using Config = render::Job::Config;
using JobModel = render::Job::ModelI<DrawHighlight, Inputs, Config>;
@ -182,7 +182,7 @@ signals:
class DebugHighlight {
public:
using Inputs = render::VaryingSet3<HighlightRessourcesPointer, glm::ivec4, glm::vec2>;
using Inputs = render::VaryingSet4<HighlightRessourcesPointer, glm::ivec4, glm::vec2, gpu::FramebufferPointer>;
using Config = DebugHighlightConfig;
using JobModel = render::Job::ModelI<DebugHighlight, Inputs, Config>;

View file

@ -14,7 +14,7 @@
#include "RenderUtilsLogging.h"
using namespace render;
extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false);
extern void initForwardPipelines(ShapePlumber& plumber);
void BeginGPURangeTimer::run(const render::RenderContextPointer& renderContext, gpu::RangeTimerPointer& timer) {
timer = _gpuTimer;
@ -35,7 +35,7 @@ void EndGPURangeTimer::run(const render::RenderContextPointer& renderContext, co
DrawOverlay3D::DrawOverlay3D(bool opaque) :
_shapePlumber(std::make_shared<ShapePlumber>()),
_opaquePass(opaque) {
initOverlay3DPipelines(*_shapePlumber);
initForwardPipelines(*_shapePlumber);
}
void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs& inputs) {
@ -60,7 +60,7 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs&
if (_opaquePass) {
gpu::doInBatch("DrawOverlay3D::run::clear", args->_context, [&](gpu::Batch& batch){
batch.enableStereo(false);
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0, false);
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTHSTENCIL, glm::vec4(), 1.f, 0, false);
});
}

View file

@ -53,7 +53,6 @@
#include <sstream>
using namespace render;
extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false);
extern void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
RenderDeferredTask::RenderDeferredTask()

View file

@ -37,10 +37,7 @@
#include "nop_frag.h"
using namespace render;
extern void initForwardPipelines(ShapePlumber& plumber,
const render::ShapePipeline::BatchSetter& batchSetter,
const render::ShapePipeline::ItemSetter& itemSetter);
extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false);
extern void initForwardPipelines(ShapePlumber& plumber);
void RenderForwardTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
auto items = input.get<Input>();
@ -48,8 +45,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
// Prepare the ShapePipelines
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
initForwardPipelines(*shapePlumber, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
initOverlay3DPipelines(*shapePlumber);
initForwardPipelines(*shapePlumber);
// Extract opaques / transparents / lights / metas / overlays / background
const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE];

View file

@ -80,16 +80,6 @@
#include "model_translucent_unlit_fade_frag.h"
#include "model_translucent_normal_map_fade_frag.h"
#include "overlay3D_vert.h"
#include "overlay3D_frag.h"
#include "overlay3D_model_frag.h"
#include "overlay3D_model_translucent_frag.h"
#include "overlay3D_translucent_frag.h"
#include "overlay3D_unlit_frag.h"
#include "overlay3D_translucent_unlit_frag.h"
#include "overlay3D_model_unlit_frag.h"
#include "overlay3D_model_translucent_unlit_frag.h"
#include "model_shadow_vert.h"
#include "skin_model_shadow_vert.h"
#include "skin_model_shadow_dq_vert.h"
@ -104,12 +94,16 @@
#include "model_shadow_fade_frag.h"
#include "skin_model_shadow_fade_frag.h"
#include "simple_vert.h"
#include "forward_simple_textured_frag.h"
#include "forward_simple_textured_transparent_frag.h"
#include "forward_simple_textured_unlit_frag.h"
using namespace render;
using namespace std::placeholders;
void initOverlay3DPipelines(ShapePlumber& plumber, bool depthTest = false);
void initDeferredPipelines(ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
void initForwardPipelines(ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
void initForwardPipelines(ShapePlumber& plumber);
void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state);
void addPlumberPipeline(ShapePlumber& plumber,
@ -120,71 +114,6 @@ void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* a
void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);
static bool forceLightBatchSetter{ false };
void initOverlay3DPipelines(ShapePlumber& plumber, bool depthTest) {
auto vertex = overlay3D_vert::getShader();
auto vertexModel = model_vert::getShader();
auto pixel = overlay3D_frag::getShader();
auto pixelTranslucent = overlay3D_translucent_frag::getShader();
auto pixelUnlit = overlay3D_unlit_frag::getShader();
auto pixelTranslucentUnlit = overlay3D_translucent_unlit_frag::getShader();
auto pixelModel = overlay3D_model_frag::getShader();
auto pixelModelTranslucent = overlay3D_model_translucent_frag::getShader();
auto pixelModelUnlit = overlay3D_model_unlit_frag::getShader();
auto pixelModelTranslucentUnlit = overlay3D_model_translucent_unlit_frag::getShader();
auto opaqueProgram = gpu::Shader::createProgram(vertex, pixel);
auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent);
auto unlitOpaqueProgram = gpu::Shader::createProgram(vertex, pixelUnlit);
auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit);
auto materialOpaqueProgram = gpu::Shader::createProgram(vertexModel, pixelModel);
auto materialTranslucentProgram = gpu::Shader::createProgram(vertexModel, pixelModelTranslucent);
auto materialUnlitOpaqueProgram = gpu::Shader::createProgram(vertexModel, pixelModel);
auto materialUnlitTranslucentProgram = gpu::Shader::createProgram(vertexModel, pixelModelTranslucent);
for (int i = 0; i < 8; i++) {
bool isCulled = (i & 1);
bool isBiased = (i & 2);
bool isOpaque = (i & 4);
auto state = std::make_shared<gpu::State>();
if (depthTest) {
state->setDepthTest(true, true, gpu::LESS_EQUAL);
} else {
state->setDepthTest(false);
}
state->setCullMode(isCulled ? gpu::State::CULL_BACK : gpu::State::CULL_NONE);
if (isBiased) {
state->setDepthBias(1.0f);
state->setDepthBiasSlopeScale(1.0f);
}
if (isOpaque) {
// Soft edges
state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
} else {
state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
}
ShapeKey::Filter::Builder builder;
isCulled ? builder.withCullFace() : builder.withoutCullFace();
isBiased ? builder.withDepthBias() : builder.withoutDepthBias();
isOpaque ? builder.withOpaque() : builder.withTranslucent();
auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram;
auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram;
auto materialProgram = isOpaque ? materialOpaqueProgram : materialTranslucentProgram;
auto materialUnlitProgram = isOpaque ? materialUnlitOpaqueProgram : materialUnlitTranslucentProgram;
plumber.addPipeline(builder.withMaterial().build().key(), materialProgram, state, &lightBatchSetter);
plumber.addPipeline(builder.withMaterial().withUnlit().build().key(), materialUnlitProgram, state, &batchSetter);
plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build().key(), simpleProgram, state, &lightBatchSetter);
plumber.addPipeline(builder.withUnlit().withoutMaterial().build().key(), unlitProgram, state, &batchSetter);
}
}
void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter) {
// Vertex shaders
auto simpleVertex = simple_vert::getShader();
@ -432,8 +361,9 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
skinModelShadowFadeDualQuatVertex, modelShadowFadePixel, batchSetter, itemSetter);
}
void initForwardPipelines(ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter) {
void initForwardPipelines(ShapePlumber& plumber) {
// Vertex shaders
auto simpleVertex = simple_vert::getShader();
auto modelVertex = model_vert::getShader();
auto modelNormalMapVertex = model_normal_map_vert::getShader();
auto skinModelVertex = skin_model_vert::getShader();
@ -443,6 +373,10 @@ void initForwardPipelines(ShapePlumber& plumber, const render::ShapePipeline::Ba
auto skinModelNormalMapDualQuatVertex = skin_model_normal_map_dq_vert::getShader();
// Pixel shaders
auto simplePixel = forward_simple_textured_frag::getShader();
auto simpleTranslucentPixel = forward_simple_textured_transparent_frag::getShader();
auto simpleUnlitPixel = forward_simple_textured_unlit_frag::getShader();
auto simpleTranslucentUnlitPixel = simple_transparent_textured_unlit_frag::getShader();
auto modelPixel = forward_model_frag::getShader();
auto modelUnlitPixel = forward_model_unlit_frag::getShader();
auto modelNormalMapPixel = forward_model_normal_map_frag::getShader();
@ -458,8 +392,15 @@ void initForwardPipelines(ShapePlumber& plumber, const render::ShapePipeline::Ba
};
// Forward pipelines need the lightBatchSetter for opaques and transparents
// forceLightBatchSetter = true;
forceLightBatchSetter = false;
forceLightBatchSetter = true;
// Simple Opaques
addPipeline(Key::Builder(), simpleVertex, simplePixel);
addPipeline(Key::Builder().withUnlit(), simpleVertex, simpleUnlitPixel);
// Simple Translucents
addPipeline(Key::Builder().withTranslucent(), simpleVertex, simpleTranslucentPixel);
addPipeline(Key::Builder().withTranslucent().withUnlit(), simpleVertex, simpleTranslucentUnlitPixel);
// Opaques
addPipeline(Key::Builder().withMaterial(), modelVertex, modelPixel);
@ -501,7 +442,7 @@ void addPlumberPipeline(ShapePlumber& plumber,
bool isWireframed = (i & 4);
auto state = std::make_shared<gpu::State>();
PrepareStencil::testMaskDrawShape(*state);
key.isTranslucent() ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state);
// Depth test depends on transparency
state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);

View file

@ -1,92 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// overlay3D.slf
// fragment shader
//
// Created by Sam Gateau on 6/16/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include graphics/Light.slh@>
<$declareLightBuffer()$>
<$declareLightAmbientBuffer()$>
<@include LightingModel.slh@>
<@include LightDirectional.slh@>
<$declareLightingDirectional()$>
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) {
// Need the light now
Light light = getKeyLight();
vec3 lightDirection = getLightDirection(light);
vec3 lightIrradiance = getLightIrradiance(light);
LightAmbient ambient = getLightAmbient();
TransformCamera cam = getTransformCamera();
vec3 fragEyeVectorView = normalize(-position);
vec3 fragEyeDir;
<$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$>
SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir);
vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient);
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse * isDiffuseEnabled() * isDirectionalEnabled();
color += directionalSpecular * isSpecularEnabled() * isDirectionalEnabled();
return vec4(color, opacity);
}
uniform sampler2D originalTexture;
in vec2 _texCoord0;
in vec4 _positionES;
in vec3 _normalWS;
in vec3 _color;
in float _alpha;
out vec4 _fragColor;
void main(void) {
vec4 albedo = texture(originalTexture, _texCoord0);
vec3 fragPosition = _positionES.xyz;
vec3 fragNormal = normalize(_normalWS);
vec3 fragAlbedo = albedo.rgb * _color;
float fragMetallic = 0.0;
vec3 fragSpecular = vec3(0.1);
float fragRoughness = 0.9;
float fragOpacity = albedo.a;
if (fragOpacity <= 0.1) {
discard;
}
vec4 color = evalGlobalColor(1.0,
fragPosition,
fragNormal,
fragAlbedo,
fragMetallic,
fragSpecular,
fragRoughness,
fragOpacity);
// Apply standard tone mapping
_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);
}

View file

@ -1,36 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// overlay3D.slv
// vertex shader
//
// Created by Sam Gateau on 6/16/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include gpu/Inputs.slh@>
<@include gpu/Color.slh@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
out vec3 _color;
out float _alpha;
out vec2 _texCoord0;
out vec4 _positionES;
out vec3 _normalWS;
void main(void) {
_color = color_sRGBToLinear(inColor.xyz);
_alpha = inColor.w;
_texCoord0 = inTexCoord0.st;
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$>
}

View file

@ -1,79 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// overlay3D.slf
// fragment shader
//
// Created by Sam Gateau on 6/16/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include DeferredGlobalLight.slh@>
<$declareEvalSkyboxGlobalColor()$>
<@include graphics/Material.slh@>
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec4 _positionES;
in vec3 _normalWS;
in vec3 _color;
in float _alpha;
out vec4 _fragColor;
void main(void) {
Material mat = getMaterial();
BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
float opacity = 1.0;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color;
float metallic = getMaterialMetallic(mat);
vec3 fresnel = getFresnelF0(metallic, albedo);
float roughness = getMaterialRoughness(mat);
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 fragPosition = _positionES.xyz;
TransformCamera cam = getTransformCamera();
vec4 color = vec4(evalSkyboxGlobalColor(
cam._viewInverse,
1.0,
occlusionTex,
fragPosition,
normalize(_normalWS),
albedo,
fresnel,
metallic,
roughness),
opacity);
// And emissive
color.rgb += emissive * isEmissiveEnabled();
// Apply standard tone mapping
_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);
}

View file

@ -1,72 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// overlay3D_model_transparent.slf
//
// Created by Sam Gateau on 2/27/2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include DeferredGlobalLight.slh@>
<$declareEvalGlobalLightingAlphaBlendedWithHaze()$>
<@include graphics/Material.slh@>
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec4 _positionES;
in vec3 _normalWS;
in vec3 _color;
out vec4 _fragColor;
void main(void) {
Material mat = getMaterial();
BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
float opacity = 1.0;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color;
float metallic = getMaterialMetallic(mat);
vec3 fresnel = getFresnelF0(metallic, albedo);
float roughness = getMaterialRoughness(mat);
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 fragPosition = _positionES.xyz;
TransformCamera cam = getTransformCamera();
vec4 color = vec4(evalGlobalLightingAlphaBlendedWithHaze(
cam._viewInverse,
1.0,
occlusionTex,
fragPosition,
normalize(_normalWS),
albedo,
fresnel,
metallic,
emissive,
roughness, opacity),
opacity);
// Apply standard tone mapping
_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);
}

View file

@ -1,41 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// overlay3D-model_transparent_unlit.slf
// fragment shader
//
// Created by Sam Gateau on 2/28/2017.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include LightingModel.slh@>
<@include graphics/Material.slh@>
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO)$>
in vec2 _texCoord0;
in vec3 _color;
out vec4 _fragColor;
void main(void) {
Material mat = getMaterial();
BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
float opacity = 1.0;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color;
vec4 color = vec4(albedo * isUnlitEnabled(), opacity);
_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);
}

View file

@ -1,42 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// overlay3D-model_unlit.slf
// fragment shader
//
// Created by Sam Gateau on 2/28/2017.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include LightingModel.slh@>
<@include graphics/Material.slh@>
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO)$>
in vec2 _texCoord0;
in vec3 _color;
out vec4 _fragColor;
void main(void) {
Material mat = getMaterial();
BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
float opacity = 1.0;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color;
vec4 color = vec4(albedo * isUnlitEnabled(), opacity);
_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);
}

View file

@ -1,87 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// overlay3D_translucent.slf
// fragment shader
//
// Created by Sam Gateau on 6/16/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include graphics/Light.slh@>
<$declareLightBuffer()$>
<$declareLightAmbientBuffer()$>
<@include LightingModel.slh@>
<@include LightDirectional.slh@>
<$declareLightingDirectional()$>
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) {
// Need the light now
Light light = getKeyLight();
vec3 lightDirection = getLightDirection(light);
vec3 lightIrradiance = getLightIrradiance(light);
LightAmbient ambient = getLightAmbient();
TransformCamera cam = getTransformCamera();
vec3 fragEyeVectorView = normalize(-position);
vec3 fragEyeDir;
<$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$>
SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir);
vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient);
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse;
color += directionalSpecular / opacity;
return vec4(color, opacity);
}
uniform sampler2D originalTexture;
in vec2 _texCoord0;
in vec4 _positionES;
in vec3 _normalWS;
in vec3 _color;
in float _alpha;
out vec4 _fragColor;
void main(void) {
vec4 albedo = texture(originalTexture, _texCoord0);
vec3 fragPosition = _positionES.xyz;
vec3 fragNormal = normalize(_normalWS);
vec3 fragAlbedo = albedo.rgb * _color;
float fragMetallic = 0.0;
vec3 fragSpecular = vec3(0.1);
float fragRoughness = 0.9;
float fragOpacity = albedo.a * _alpha;
vec4 color = evalGlobalColor(1.0,
fragPosition,
fragNormal,
fragAlbedo,
fragMetallic,
fragSpecular,
fragRoughness,
fragOpacity);
// Apply standard tone mapping
_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);
}

View file

@ -1,27 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// overlay3D_translucent_unlit.frag
// fragment shader
//
// Created by Zach Pomerantz on 2/2/2016.
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
uniform sampler2D originalTexture;
in vec2 _texCoord0;
in vec3 _color;
in float _alpha;
out vec4 _fragColor;
void main(void) {
vec4 albedo = texture(originalTexture, _texCoord0);
_fragColor = vec4(albedo.rgb * _color, albedo.a * _alpha);
}

View file

@ -1,32 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// overlay3D_unlit.frag
// fragment shader
//
// Created by Zach Pomerantz on 2/2/2016.
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
uniform sampler2D originalTexture;
in vec2 _texCoord0;
in vec3 _color;
out vec4 _fragColor;
void main(void) {
vec4 albedo = texture(originalTexture, _texCoord0);
if (albedo.a <= 0.1) {
discard;
}
vec4 color = vec4(albedo.rgb * _color, albedo.a);
// Apply standard tone mapping
_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);
}

View file

@ -69,6 +69,7 @@ static const float MIN_AVATAR_SCALE = 0.005f;
static const float MAX_AVATAR_HEIGHT = 1000.0f * DEFAULT_AVATAR_HEIGHT; // meters
static const float MIN_AVATAR_HEIGHT = 0.005f * DEFAULT_AVATAR_HEIGHT; // meters
static const float MIN_AVATAR_RADIUS = 0.5f * MIN_AVATAR_HEIGHT;
static const float AVATAR_WALK_SPEED_SCALAR = 1.0f;
static const float AVATAR_SPRINT_SPEED_SCALAR = 3.0f;

View file

@ -46,6 +46,7 @@ function init() {
function onMuteClicked() {
Audio.muted = !Audio.muted;
Menu.triggerOption("Out of Bounds Vector Access");
}
function onMutePressed() {

View file

@ -57,9 +57,6 @@
#include <entities-renderer/textured_particle_frag.h>
#include <entities-renderer/textured_particle_vert.h>
#include <render-utils/overlay3D_vert.h>
#include <render-utils/overlay3D_frag.h>
#include <graphics/skybox_vert.h>
#include <graphics/skybox_frag.h>
@ -195,8 +192,6 @@ void QTestWindow::draw() {
testShaderBuild(ambient_occlusion_vert::getSource(), occlusion_blend_frag::getSource());
*/
testShaderBuild(overlay3D_vert::getSource(), overlay3D_frag::getSource());
testShaderBuild(paintStroke_vert::getSource(),paintStroke_frag::getSource());
testShaderBuild(polyvox_vert::getSource(), polyvox_frag::getSource());