mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 08:04:01 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into threaded_voxel_server
This commit is contained in:
commit
38f54a3130
20 changed files with 1665 additions and 1564 deletions
73
README.md
73
README.md
|
@ -1,17 +1,76 @@
|
|||
interface
|
||||
What is Hifi?
|
||||
=========
|
||||
|
||||
Test platform for various render and interface tests for next-gen VR system.
|
||||
High Fidelity (hifi) is an early-stage technology
|
||||
lab experimenting with Virtual Worlds and VR.
|
||||
|
||||
In this repository you'll find the source to many of the components in our
|
||||
alpha-stage virtual world. The project embraces distributed development
|
||||
and if you'd like to help, we'll pay you -- find out more at Worklist.net.
|
||||
If you find a small bug and have a fix, pull requests are welcome. If you'd
|
||||
like to get paid for your work, make sure you report the bug via a job on Worklist.net.
|
||||
|
||||
We're hiring! We're looking for skilled developers;
|
||||
send your resume to hiring@highfidelity.io
|
||||
|
||||
|
||||
Building Interface
|
||||
=========
|
||||
|
||||
Interface is our OS X and Linux build-able
|
||||
client for accessing our virtual world.
|
||||
|
||||
CMake
|
||||
-----
|
||||
Hifi uses CMake to generate build files and project files
|
||||
for your platform. You can download CMake at cmake.org
|
||||
|
||||
This project uses CMake to generate build files and project files for your platform.
|
||||
|
||||
Create a build directory in the root of your checkout and then run the CMake build from there. This will keep the rest of the directory clean, and makes the gitignore a little easier to handle (since we can just ignore build).
|
||||
Create a build directory in the root of your checkout and then run the
|
||||
CMake build from there. This will keep the rest of the directory clean,
|
||||
and makes the gitignore a little easier to handle (since we can just ignore build).
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -GXcode
|
||||
cmake .. -G Xcode
|
||||
|
||||
Those are the commands used on OS X to run CMake from the build folder and generate XCode project files.
|
||||
Those are the commands used on OS X to run CMake from the build folder
|
||||
and generate Xcode project files. If you are building on a *nix system,
|
||||
you'll run something like "cmake .." (this will depend on your exact needs)
|
||||
|
||||
Other dependencies & information
|
||||
----
|
||||
In addition to CMake, Qt 5.1 is required to build all components.
|
||||
|
||||
What can I build on?
|
||||
We have successfully built on OS X 10.8, Ubuntu and a few other modern Linux distributions.
|
||||
A Windows build is planned for the future, but not currently in development.
|
||||
|
||||
I'm in-world, what can I do?
|
||||
----
|
||||
If you don't see anything, make sure your preferences are pointing to root.highfidelity.io,
|
||||
if you still have no luck it's possible our servers are simply down; if you're experiencing
|
||||
a major bug, let us know by suggesting a Job on Worklist.net -- make sure to include details
|
||||
about your operating system and your computer system.
|
||||
|
||||
To move around in-world, use the arrow keys (and Shift + up/down to fly up or down)
|
||||
or W A S D, and E or C to fly up/down. All of the other possible options and features
|
||||
are available via menus in the Interface application.
|
||||
|
||||
|
||||
Other components
|
||||
========
|
||||
|
||||
voxel-server, animation-server, audio-mixer, avatar-mixer, domain-server, pairing-server
|
||||
and space-server are architectural components that will allow you to run the full stack of
|
||||
the virtual world should you choose to.
|
||||
|
||||
|
||||
I want to run my own virtual world!
|
||||
========
|
||||
|
||||
In the voxel-server/src directory you will find a README that explains
|
||||
how to setup and administer a voxel-server.
|
||||
|
||||
Keep in mind that, at a minimum, you must run a domain-server, voxel-server,
|
||||
audio-mixer, and avatar-mixer to have a working virtual world.
|
||||
Basic documentation for the other components is on its way.
|
||||
|
|
|
@ -44,7 +44,8 @@ float texCoordToViewSpaceZ(vec2 texCoord) {
|
|||
// given a texture coordinate, returns the 3D view space coordinate
|
||||
vec3 texCoordToViewSpace(vec2 texCoord) {
|
||||
float z = texCoordToViewSpaceZ(texCoord);
|
||||
return vec3(((texCoord * 2.0 - vec2(1.0, 1.0)) * (rightTop - leftBottom) + rightTop + leftBottom) * z / (-2.0 * near), z);
|
||||
return vec3(((texCoord * 2.0 - vec2(1.0 - gl_ProjectionMatrix[2][0], 1.0)) *
|
||||
(rightTop - leftBottom) + rightTop + leftBottom) * z / (-2.0 * near), z);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <QMenuBar>
|
||||
#include <QMouseEvent>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QOpenGLFramebufferObject>
|
||||
#include <QWheelEvent>
|
||||
#include <QSettings>
|
||||
#include <QShortcut>
|
||||
|
@ -116,7 +117,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_lookatIndicatorScale(1.0f),
|
||||
_perfStatsOn(false),
|
||||
_chatEntryOn(false),
|
||||
_oculusTextureID(0),
|
||||
_oculusProgram(0),
|
||||
_oculusDistortionScale(1.25),
|
||||
#ifndef _WIN32
|
||||
|
@ -378,13 +378,18 @@ void Application::paintGL() {
|
|||
|
||||
if (OculusManager::isConnected()) {
|
||||
displayOculus(whichCamera);
|
||||
|
||||
} else {
|
||||
_glowEffect.prepare();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
displaySide(whichCamera);
|
||||
glPopMatrix();
|
||||
|
||||
_glowEffect.render();
|
||||
|
||||
displayOverlay();
|
||||
}
|
||||
|
||||
|
@ -408,13 +413,6 @@ void Application::resizeGL(int width, int height) {
|
|||
resetCamerasOnResizeGL(_viewFrustumOffsetCamera, width, height);
|
||||
resetCamerasOnResizeGL(_myCamera, width, height);
|
||||
|
||||
// resize the render texture
|
||||
if (OculusManager::isConnected() && _oculusTextureID != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, _oculusTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
// Tell our viewFrustum about this change, using the application camera
|
||||
loadViewFrustum(_myCamera, _viewFrustum);
|
||||
|
||||
|
@ -1923,6 +1921,8 @@ static const char* DISTORTION_FRAGMENT_SHADER =
|
|||
"}";
|
||||
|
||||
void Application::displayOculus(Camera& whichCamera) {
|
||||
_glowEffect.prepare();
|
||||
|
||||
// magic numbers ahoy! in order to avoid pulling in the Oculus utility library that calculates
|
||||
// the rendering parameters from the hardware stats, i just folded their calculations into
|
||||
// constants using the stats for the current-model hardware as contained in the SDK file
|
||||
|
@ -1965,12 +1965,10 @@ void Application::displayOculus(Camera& whichCamera) {
|
|||
// restore our normal viewport
|
||||
glViewport(0, 0, _glWidget->width(), _glWidget->height());
|
||||
|
||||
if (_oculusTextureID == 0) {
|
||||
glGenTextures(1, &_oculusTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _oculusTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _glWidget->width(), _glWidget->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
QOpenGLFramebufferObject* fbo = _glowEffect.render(true);
|
||||
glBindTexture(GL_TEXTURE_2D, fbo->texture());
|
||||
|
||||
if (_oculusProgram == 0) {
|
||||
_oculusProgram = new ProgramObject();
|
||||
_oculusProgram->addShaderFromSourceCode(QGLShader::Fragment, DISTORTION_FRAGMENT_SHADER);
|
||||
_oculusProgram->link();
|
||||
|
@ -1980,18 +1978,13 @@ void Application::displayOculus(Camera& whichCamera) {
|
|||
_screenCenterLocation = _oculusProgram->uniformLocation("screenCenter");
|
||||
_scaleLocation = _oculusProgram->uniformLocation("scale");
|
||||
_scaleInLocation = _oculusProgram->uniformLocation("scaleIn");
|
||||
_hmdWarpParamLocation = _oculusProgram->uniformLocation("hmdWarpParam");
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, _oculusTextureID);
|
||||
_hmdWarpParamLocation = _oculusProgram->uniformLocation("hmdWarpParam");
|
||||
}
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, _glWidget->width(), _glWidget->height());
|
||||
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, _glWidget->width(), 0, _glWidget->height());
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
// for reference on setting these values, see SDK file Samples/OculusRoomTiny/RenderTiny_Device.cpp
|
||||
|
||||
|
@ -1999,7 +1992,6 @@ void Application::displayOculus(Camera& whichCamera) {
|
|||
float aspectRatio = (_glWidget->width() * 0.5) / _glWidget->height();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
_oculusProgram->bind();
|
||||
_oculusProgram->setUniformValue(_textureLocation, 0);
|
||||
_oculusProgram->setUniformValue(_lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
|
||||
|
@ -2035,7 +2027,6 @@ void Application::displayOculus(Camera& whichCamera) {
|
|||
glEnd();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
_oculusProgram->release();
|
||||
|
||||
|
@ -2096,9 +2087,6 @@ void Application::displaySide(Camera& whichCamera) {
|
|||
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
|
||||
setupWorldLight(whichCamera);
|
||||
|
||||
// prepare the glow effect
|
||||
_glowEffect.prepare();
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
|
||||
if (!_stars.getFileLoaded()) {
|
||||
_stars.readInput(STAR_FILE, STAR_CACHE_FILE, 0);
|
||||
|
@ -2256,7 +2244,7 @@ void Application::displaySide(Camera& whichCamera) {
|
|||
_myAvatar.renderScreenTint(SCREEN_TINT_AFTER_AVATARS, whichCamera);
|
||||
|
||||
// Render the world box
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
||||
renderWorldBox();
|
||||
}
|
||||
|
||||
|
@ -2283,9 +2271,6 @@ void Application::displaySide(Camera& whichCamera) {
|
|||
}
|
||||
|
||||
renderFollowIndicator();
|
||||
|
||||
// render the glow effect
|
||||
_glowEffect.render();
|
||||
}
|
||||
|
||||
void Application::displayOverlay() {
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "VoxelImporter.h"
|
||||
#include "Webcam.h"
|
||||
#include "avatar/Avatar.h"
|
||||
#include "avatar/MyAvatar.h"
|
||||
#include "avatar/HandControl.h"
|
||||
#include "renderer/AmbientOcclusionEffect.h"
|
||||
#include "renderer/GeometryCache.h"
|
||||
|
@ -106,7 +107,7 @@ public:
|
|||
const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel);
|
||||
|
||||
QGLWidget* getGLWidget() { return _glWidget; }
|
||||
Avatar* getAvatar() { return &_myAvatar; }
|
||||
MyAvatar* getAvatar() { return &_myAvatar; }
|
||||
Audio* getAudio() { return &_audio; }
|
||||
Camera* getCamera() { return &_myCamera; }
|
||||
ViewFrustum* getViewFrustum() { return &_viewFrustum; }
|
||||
|
@ -249,7 +250,7 @@ private:
|
|||
|
||||
Oscilloscope _audioScope;
|
||||
|
||||
Avatar _myAvatar; // The rendered avatar of oneself
|
||||
MyAvatar _myAvatar; // The rendered avatar of oneself
|
||||
|
||||
Transmitter _myTransmitter; // Gets UDP data from transmitter app used to animate the avatar
|
||||
|
||||
|
@ -302,7 +303,6 @@ private:
|
|||
ChatEntry _chatEntry; // chat entry field
|
||||
bool _chatEntryOn; // Whether to show the chat entry
|
||||
|
||||
GLuint _oculusTextureID; // The texture to which we render for Oculus distortion
|
||||
ProgramObject* _oculusProgram; // The GLSL program containing the distortion shader
|
||||
float _oculusDistortionScale; // Controls the Oculus field of view
|
||||
int _textureLocation;
|
||||
|
|
|
@ -165,7 +165,7 @@ Menu::Menu() :
|
|||
|
||||
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::AmbientOcclusion);
|
||||
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::FrameTimer);
|
||||
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtVectors);
|
||||
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtVectors, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtIndicator, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::FirstPerson, Qt::Key_P, true);
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ void OculusManager::updateYawOffset() {
|
|||
}
|
||||
|
||||
void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {
|
||||
yaw = pitch = roll = 0.0f;
|
||||
#ifdef __APPLE__
|
||||
_sensorFusion.GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,36 +27,41 @@
|
|||
#include "world.h"
|
||||
|
||||
|
||||
static const float MAX_SCALE = 1000.f;
|
||||
static const float MIN_SCALE = .005f;
|
||||
static const float SCALING_RATIO = .05f;
|
||||
static const float SMOOTHING_RATIO = .05f; // 0 < ratio < 1
|
||||
static const float MAX_SCALE = 1000.f;
|
||||
static const float MIN_SCALE = .005f;
|
||||
static const float SCALING_RATIO = .05f;
|
||||
static const float SMOOTHING_RATIO = .05f; // 0 < ratio < 1
|
||||
static const float RESCALING_TOLERANCE = .02f;
|
||||
|
||||
const float BODY_BALL_RADIUS_PELVIS = 0.07;
|
||||
const float BODY_BALL_RADIUS_TORSO = 0.065;
|
||||
const float BODY_BALL_RADIUS_CHEST = 0.08;
|
||||
const float BODY_BALL_RADIUS_NECK_BASE = 0.03;
|
||||
const float BODY_BALL_RADIUS_HEAD_BASE = 0.07;
|
||||
const float BODY_BALL_RADIUS_LEFT_COLLAR = 0.04;
|
||||
const float BODY_BALL_RADIUS_LEFT_SHOULDER = 0.03;
|
||||
const float BODY_BALL_RADIUS_LEFT_ELBOW = 0.02;
|
||||
const float BODY_BALL_RADIUS_LEFT_WRIST = 0.02;
|
||||
const float BODY_BALL_RADIUS_LEFT_FINGERTIPS = 0.01;
|
||||
const float BODY_BALL_RADIUS_RIGHT_COLLAR = 0.04;
|
||||
const float BODY_BALL_RADIUS_RIGHT_SHOULDER = 0.03;
|
||||
const float BODY_BALL_RADIUS_RIGHT_ELBOW = 0.02;
|
||||
const float BODY_BALL_RADIUS_RIGHT_WRIST = 0.02;
|
||||
const float BODY_BALL_RADIUS_PELVIS = 0.07;
|
||||
const float BODY_BALL_RADIUS_TORSO = 0.065;
|
||||
const float BODY_BALL_RADIUS_CHEST = 0.08;
|
||||
const float BODY_BALL_RADIUS_NECK_BASE = 0.03;
|
||||
const float BODY_BALL_RADIUS_HEAD_BASE = 0.07;
|
||||
const float BODY_BALL_RADIUS_LEFT_COLLAR = 0.04;
|
||||
const float BODY_BALL_RADIUS_LEFT_SHOULDER = 0.03;
|
||||
const float BODY_BALL_RADIUS_LEFT_ELBOW = 0.02;
|
||||
const float BODY_BALL_RADIUS_LEFT_WRIST = 0.02;
|
||||
const float BODY_BALL_RADIUS_LEFT_FINGERTIPS = 0.01;
|
||||
const float BODY_BALL_RADIUS_RIGHT_COLLAR = 0.04;
|
||||
const float BODY_BALL_RADIUS_RIGHT_SHOULDER = 0.03;
|
||||
const float BODY_BALL_RADIUS_RIGHT_ELBOW = 0.02;
|
||||
const float BODY_BALL_RADIUS_RIGHT_WRIST = 0.02;
|
||||
const float BODY_BALL_RADIUS_RIGHT_FINGERTIPS = 0.01;
|
||||
const float BODY_BALL_RADIUS_LEFT_HIP = 0.04;
|
||||
const float BODY_BALL_RADIUS_LEFT_MID_THIGH = 0.03;
|
||||
const float BODY_BALL_RADIUS_LEFT_KNEE = 0.025;
|
||||
const float BODY_BALL_RADIUS_LEFT_HEEL = 0.025;
|
||||
const float BODY_BALL_RADIUS_LEFT_TOES = 0.025;
|
||||
const float BODY_BALL_RADIUS_RIGHT_HIP = 0.04;
|
||||
const float BODY_BALL_RADIUS_RIGHT_KNEE = 0.025;
|
||||
const float BODY_BALL_RADIUS_RIGHT_HEEL = 0.025;
|
||||
const float BODY_BALL_RADIUS_RIGHT_TOES = 0.025;
|
||||
const float BODY_BALL_RADIUS_LEFT_HIP = 0.04;
|
||||
const float BODY_BALL_RADIUS_LEFT_MID_THIGH = 0.03;
|
||||
const float BODY_BALL_RADIUS_LEFT_KNEE = 0.025;
|
||||
const float BODY_BALL_RADIUS_LEFT_HEEL = 0.025;
|
||||
const float BODY_BALL_RADIUS_LEFT_TOES = 0.025;
|
||||
const float BODY_BALL_RADIUS_RIGHT_HIP = 0.04;
|
||||
const float BODY_BALL_RADIUS_RIGHT_KNEE = 0.025;
|
||||
const float BODY_BALL_RADIUS_RIGHT_HEEL = 0.025;
|
||||
const float BODY_BALL_RADIUS_RIGHT_TOES = 0.025;
|
||||
|
||||
extern const bool usingBigSphereCollisionTest;
|
||||
|
||||
extern const float chatMessageScale;
|
||||
extern const float chatMessageHeight;
|
||||
|
||||
enum AvatarBodyBallID {
|
||||
BODY_BALL_NULL = -1,
|
||||
|
@ -84,9 +89,6 @@ enum AvatarBodyBallID {
|
|||
BODY_BALL_RIGHT_KNEE,
|
||||
BODY_BALL_RIGHT_HEEL,
|
||||
BODY_BALL_RIGHT_TOES,
|
||||
|
||||
//TEST!
|
||||
//BODY_BALL_LEFT_MID_THIGH,
|
||||
NUM_AVATAR_BODY_BALLS
|
||||
};
|
||||
|
||||
|
@ -117,6 +119,8 @@ enum ScreenTintLayer {
|
|||
NUM_SCREEN_TINT_LAYERS
|
||||
};
|
||||
|
||||
class MyAvatar;
|
||||
|
||||
// Where one's own Avatar begins in the world (will be overwritten if avatar data file is found)
|
||||
// this is basically in the center of the ground plane. Slightly adjusted. This was asked for by
|
||||
// Grayson as he's building a street around here for demo dinner 2
|
||||
|
@ -124,6 +128,7 @@ const glm::vec3 START_LOCATION(0.485f * TREE_SCALE, 0.f, 0.5f * TREE_SCALE);
|
|||
|
||||
class Avatar : public AvatarData {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static void sendAvatarVoxelURLMessage(const QUrl& url);
|
||||
|
||||
|
@ -131,84 +136,32 @@ public:
|
|||
~Avatar();
|
||||
|
||||
void init();
|
||||
void reset();
|
||||
void simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity);
|
||||
void updateThrust(float deltaTime, Transmitter * transmitter);
|
||||
void follow(Avatar* leadingAvatar);
|
||||
void updateFromGyrosAndOrWebcam(bool gyroLook,
|
||||
float pitchFromTouch);
|
||||
void addBodyYaw(float bodyYaw) {_bodyYaw += bodyYaw;};
|
||||
void addBodyYawDelta(float bodyYawDelta) {_bodyYawDelta += bodyYawDelta;}
|
||||
void render(bool lookingInMirror, bool renderAvatarBalls);
|
||||
void renderScreenTint(ScreenTintLayer layer, Camera& whichCamera);
|
||||
|
||||
//setters
|
||||
void setMousePressed(bool mousePressed) { _mousePressed = mousePressed; }
|
||||
void setMovedHandOffset(glm::vec3 movedHandOffset) { _movedHandOffset = movedHandOffset;}
|
||||
void setThrust(glm::vec3 newThrust) { _thrust = newThrust; }
|
||||
void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors); }
|
||||
void setVelocity(const glm::vec3 velocity) { _velocity = velocity; };
|
||||
void setLeanScale(float scale) { _leanScale = scale;}
|
||||
|
||||
void setGravity(glm::vec3 gravity);
|
||||
void setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction);
|
||||
void setOrientation(const glm::quat& orientation);
|
||||
void setNewScale(const float scale);
|
||||
|
||||
//getters
|
||||
bool isInitialized() const { return _initialized;}
|
||||
bool isMyAvatar() const { return _owningNode == NULL; }
|
||||
const Skeleton& getSkeleton() const { return _skeleton;}
|
||||
float getHeadYawRate() const { return _head.yawRate;}
|
||||
float getBodyYaw() const { return _bodyYaw;}
|
||||
bool getIsNearInteractingOther() const { return _avatarTouch.getAbleToReachOtherAvatar();}
|
||||
const glm::vec3& getHeadJointPosition() const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].position;}
|
||||
const glm::vec3& getBallPosition(AvatarJointID j) const { return _bodyBall[j].position;}
|
||||
glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
||||
glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; }
|
||||
glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
||||
float getScale() const { return _scale;}
|
||||
float getNewScale() const { return _newScale;}
|
||||
const glm::vec3& getVelocity() const { return _velocity;}
|
||||
float getSpeed() const { return _speed;}
|
||||
float getHeight() const { return _height;}
|
||||
AvatarMode getMode() const { return _mode;}
|
||||
float getLeanScale() const { return _leanScale;}
|
||||
float getElapsedTimeStopped() const { return _elapsedTimeStopped;}
|
||||
float getElapsedTimeMoving() const { return _elapsedTimeMoving;}
|
||||
float getElapsedTimeSinceCollision() const { return _elapsedTimeSinceCollision;}
|
||||
const glm::vec3& getLastCollisionPosition() const { return _lastCollisionPosition;}
|
||||
float getAbsoluteHeadYaw() const;
|
||||
float getAbsoluteHeadPitch() const;
|
||||
bool isInitialized() const { return _initialized; }
|
||||
const Skeleton& getSkeleton() const { return _skeleton; }
|
||||
float getHeadYawRate() const { return _head.yawRate; }
|
||||
const glm::vec3& getHeadJointPosition() const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].position; }
|
||||
float getScale() const { return _scale; }
|
||||
const glm::vec3& getVelocity() const { return _velocity; }
|
||||
Head& getHead() {return _head; }
|
||||
Hand& getHand() {return _hand; }
|
||||
glm::quat getOrientation() const;
|
||||
glm::quat getWorldAlignedOrientation() const;
|
||||
const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; }
|
||||
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
|
||||
Avatar* getLeadingAvatar() const { return _leadingAvatar; }
|
||||
glm::vec3 getGravity() const { return _gravity; }
|
||||
|
||||
glm::vec3 getUprightHeadPosition() const;
|
||||
glm::vec3 getUprightEyeLevelPosition() const;
|
||||
glm::vec3 getEyePosition();
|
||||
|
||||
AvatarVoxelSystem* getVoxels() { return &_voxels; }
|
||||
|
||||
// Set what driving keys are being pressed to control thrust levels
|
||||
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
|
||||
bool getDriveKeys(int key) { return _driveKeys[key]; };
|
||||
void jump() { _shouldJump = true; };
|
||||
|
||||
// Set/Get update the thrust that will move the avatar around
|
||||
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
||||
glm::vec3 getThrust() { return _thrust; };
|
||||
|
||||
// get/set avatar data
|
||||
void saveData(QSettings* set);
|
||||
void loadData(QSettings* set);
|
||||
|
||||
// Get the position/rotation of a single body ball
|
||||
// Get the position/rotation of a single body ball
|
||||
void getBodyBallTransform(AvatarJointID jointID, glm::vec3& position, glm::quat& rotation) const;
|
||||
|
||||
static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);
|
||||
|
@ -220,96 +173,80 @@ public slots:
|
|||
void decreaseSize();
|
||||
void resetSize();
|
||||
|
||||
friend class MyAvatar;
|
||||
|
||||
|
||||
protected:
|
||||
struct AvatarBall {
|
||||
AvatarJointID parentJoint; /// the skeletal joint that serves as a reference for determining the position
|
||||
glm::vec3 parentOffset; /// a 3D vector in the frame of reference of the parent skeletal joint
|
||||
AvatarBodyBallID parentBall; /// the ball to which this ball is constrained for spring forces
|
||||
glm::vec3 position; /// the actual dynamic position of the ball at any given time
|
||||
glm::quat rotation; /// the rotation of the ball
|
||||
glm::vec3 velocity; /// the velocity of the ball
|
||||
float springLength; /// the ideal length of the spring between this ball and its parentBall
|
||||
float jointTightness; /// how tightly the ball position attempts to stay at its ideal position (determined by parentOffset)
|
||||
float radius; /// the radius of the ball
|
||||
bool isCollidable; /// whether or not the ball responds to collisions
|
||||
float touchForce; /// a scalar determining the amount that the cursor (or hand) is penetrating the ball
|
||||
};
|
||||
|
||||
Head _head;
|
||||
Hand _hand;
|
||||
Skeleton _skeleton;
|
||||
bool _ballSpringsInitialized;
|
||||
float _TEST_bigSphereRadius;
|
||||
glm::vec3 _TEST_bigSpherePosition;
|
||||
float _bodyYawDelta;
|
||||
glm::vec3 _movedHandOffset;
|
||||
AvatarBall _bodyBall[ NUM_AVATAR_BODY_BALLS ];
|
||||
AvatarMode _mode;
|
||||
glm::vec3 _velocity;
|
||||
glm::vec3 _thrust;
|
||||
float _speed;
|
||||
float _leanScale;
|
||||
float _pelvisFloatingHeight;
|
||||
float _pelvisToHeadLength;
|
||||
float _scale;
|
||||
float _height;
|
||||
Balls* _balls;
|
||||
AvatarTouch _avatarTouch;
|
||||
glm::vec3 _worldUpDirection;
|
||||
glm::vec3 _mouseRayOrigin;
|
||||
glm::vec3 _mouseRayDirection;
|
||||
bool _isCollisionsOn;
|
||||
Avatar* _leadingAvatar;
|
||||
float _stringLength;
|
||||
AvatarVoxelSystem _voxels;
|
||||
|
||||
// protected methods...
|
||||
glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
||||
glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; }
|
||||
glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
||||
glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const;
|
||||
void updateCollisionWithSphere(glm::vec3 position, float radius, float deltaTime);
|
||||
void updateBodyBalls(float deltaTime);
|
||||
void updateArmIKAndConstraints(float deltaTime);
|
||||
void setScale(const float scale);
|
||||
|
||||
|
||||
private:
|
||||
// privatize copy constructor and assignment operator to avoid copying
|
||||
Avatar(const Avatar&);
|
||||
Avatar& operator= (const Avatar&);
|
||||
|
||||
struct AvatarBall {
|
||||
AvatarJointID parentJoint; // the skeletal joint that serves as a reference for determining the position
|
||||
glm::vec3 parentOffset; // a 3D vector in the frame of reference of the parent skeletal joint
|
||||
AvatarBodyBallID parentBall; // the ball to which this ball is constrained for spring forces
|
||||
glm::vec3 position; // the actual dynamic position of the ball at any given time
|
||||
glm::quat rotation; // the rotation of the ball
|
||||
glm::vec3 velocity; // the velocity of the ball
|
||||
float springLength; // the ideal length of the spring between this ball and its parentBall
|
||||
float jointTightness; // how tightly the ball position attempts to stay at its ideal position (determined by parentOffset)
|
||||
float radius; // the radius of the ball
|
||||
bool isCollidable; // whether or not the ball responds to collisions
|
||||
float touchForce; // a scalar determining the amount that the cursor (or hand) is penetrating the ball
|
||||
};
|
||||
|
||||
bool _initialized;
|
||||
Head _head;
|
||||
Hand _hand;
|
||||
Skeleton _skeleton;
|
||||
bool _ballSpringsInitialized;
|
||||
float _TEST_bigSphereRadius;
|
||||
glm::vec3 _TEST_bigSpherePosition;
|
||||
bool _mousePressed;
|
||||
float _bodyPitchDelta;
|
||||
float _bodyYawDelta;
|
||||
float _bodyRollDelta;
|
||||
glm::vec3 _movedHandOffset;
|
||||
AvatarBall _bodyBall[ NUM_AVATAR_BODY_BALLS ];
|
||||
AvatarMode _mode;
|
||||
glm::vec3 _handHoldingPosition;
|
||||
glm::vec3 _velocity;
|
||||
glm::vec3 _thrust;
|
||||
bool _shouldJump;
|
||||
float _speed;
|
||||
float _maxArmLength;
|
||||
float _leanScale;
|
||||
int _driveKeys[MAX_DRIVE_KEYS];
|
||||
float _pelvisStandingHeight;
|
||||
float _pelvisFloatingHeight;
|
||||
float _pelvisToHeadLength;
|
||||
float _scale;
|
||||
float _height;
|
||||
Balls* _balls;
|
||||
AvatarTouch _avatarTouch;
|
||||
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
||||
glm::vec3 _gravity;
|
||||
glm::vec3 _worldUpDirection;
|
||||
glm::vec3 _mouseRayOrigin;
|
||||
glm::vec3 _mouseRayDirection;
|
||||
Avatar* _interactingOther;
|
||||
bool _isMouseTurningRight;
|
||||
float _elapsedTimeMoving; // Timers to drive camera transitions when moving
|
||||
float _elapsedTimeStopped;
|
||||
float _elapsedTimeSinceCollision;
|
||||
glm::vec3 _lastCollisionPosition;
|
||||
bool _speedBrakes;
|
||||
bool _isThrustOn;
|
||||
bool _isCollisionsOn;
|
||||
float _collisionRadius;
|
||||
|
||||
Avatar* _leadingAvatar;
|
||||
float _stringLength;
|
||||
|
||||
AvatarVoxelSystem _voxels;
|
||||
bool _initialized;
|
||||
glm::vec3 _handHoldingPosition;
|
||||
float _maxArmLength;
|
||||
float _pelvisStandingHeight;
|
||||
|
||||
// private methods...
|
||||
glm::vec3 calculateAverageEyePosition() { return _head.calculateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat)
|
||||
glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const;
|
||||
float getBallRenderAlpha(int ball, bool lookingInMirror) const;
|
||||
void renderBody(bool lookingInMirror, bool renderAvatarBalls);
|
||||
void initializeBodyBalls();
|
||||
void resetBodyBalls();
|
||||
void updateBodyBalls( float deltaTime );
|
||||
void calculateBoneLengths();
|
||||
void readSensors();
|
||||
void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement);
|
||||
void updateAvatarCollisions(float deltaTime);
|
||||
void updateArmIKAndConstraints( float deltaTime );
|
||||
void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
|
||||
void updateCollisionWithEnvironment(float deltaTime);
|
||||
void updateCollisionWithVoxels(float deltaTime);
|
||||
void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping);
|
||||
void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency);
|
||||
void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );
|
||||
void checkForMouseRayTouching();
|
||||
void setScale (const float scale);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,7 @@ Hand::Hand(Avatar* owningAvatar) :
|
|||
|
||||
void Hand::init() {
|
||||
// Different colors for my hand and others' hands
|
||||
if (_owningAvatar && _owningAvatar->isMyAvatar()) {
|
||||
if (_owningAvatar && _owningAvatar->getOwningNode() == NULL) {
|
||||
_ballColor = glm::vec3(0.0, 0.4, 0.0);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -742,6 +742,8 @@ void Head::renderEyeBalls() {
|
|||
|
||||
void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) {
|
||||
|
||||
Application::getInstance()->getGlowEffect()->begin();
|
||||
|
||||
glLineWidth(2.0);
|
||||
glBegin(GL_LINES);
|
||||
glColor4f(0.2f, 0.2f, 0.2f, 1.f);
|
||||
|
@ -753,6 +755,8 @@ void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosi
|
|||
glColor4f(1.0f, 1.0f, 1.0f, 0.f);
|
||||
glVertex3f(lookatPosition.x, lookatPosition.y, lookatPosition.z);
|
||||
glEnd();
|
||||
|
||||
Application::getInstance()->getGlowEffect()->end();
|
||||
}
|
||||
|
||||
void Head::updateHairPhysics(float deltaTime) {
|
||||
|
|
1035
interface/src/avatar/MyAvatar.cpp
Normal file
1035
interface/src/avatar/MyAvatar.cpp
Normal file
File diff suppressed because it is too large
Load diff
90
interface/src/avatar/MyAvatar.h
Normal file
90
interface/src/avatar/MyAvatar.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
//
|
||||
// MyAvatar.h
|
||||
// interface
|
||||
//
|
||||
// Created by Mark Peng on 8/16/13.
|
||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__myavatar__
|
||||
#define __interface__myavatar__
|
||||
|
||||
#include "Avatar.h"
|
||||
|
||||
class MyAvatar : public Avatar {
|
||||
public:
|
||||
MyAvatar(Node* owningNode = NULL);
|
||||
|
||||
void reset();
|
||||
void simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity);
|
||||
void updateFromGyrosAndOrWebcam(bool gyroLook, float pitchFromTouch);
|
||||
void render(bool lookingInMirror, bool renderAvatarBalls);
|
||||
void renderScreenTint(ScreenTintLayer layer, Camera& whichCamera);
|
||||
|
||||
// setters
|
||||
void setMousePressed(bool mousePressed) { _mousePressed = mousePressed; }
|
||||
void setMovedHandOffset(glm::vec3 movedHandOffset) { _movedHandOffset = movedHandOffset; }
|
||||
void setThrust(glm::vec3 newThrust) { _thrust = newThrust; }
|
||||
void setVelocity(const glm::vec3 velocity) { _velocity = velocity; }
|
||||
void setLeanScale(float scale) { _leanScale = scale; }
|
||||
void setGravity(glm::vec3 gravity);
|
||||
void setOrientation(const glm::quat& orientation);
|
||||
void setNewScale(const float scale);
|
||||
void setWantCollisionsOn(bool wantCollisionsOn) { _isCollisionsOn = wantCollisionsOn; }
|
||||
|
||||
// getters
|
||||
float getNewScale() const { return _newScale; }
|
||||
float getSpeed() const { return _speed; }
|
||||
AvatarMode getMode() const { return _mode; }
|
||||
float getLeanScale() const { return _leanScale; }
|
||||
float getElapsedTimeStopped() const { return _elapsedTimeStopped; }
|
||||
float getElapsedTimeMoving() const { return _elapsedTimeMoving; }
|
||||
float getAbsoluteHeadYaw() const;
|
||||
const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; }
|
||||
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
|
||||
Avatar* getLeadingAvatar() const { return _leadingAvatar; }
|
||||
glm::vec3 getGravity() const { return _gravity; }
|
||||
glm::vec3 getUprightHeadPosition() const;
|
||||
glm::vec3 getUprightEyeLevelPosition() const;
|
||||
|
||||
// Set what driving keys are being pressed to control thrust levels
|
||||
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
|
||||
bool getDriveKeys(int key) { return _driveKeys[key]; };
|
||||
void jump() { _shouldJump = true; };
|
||||
|
||||
// Set/Get update the thrust that will move the avatar around
|
||||
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
||||
glm::vec3 getThrust() { return _thrust; };
|
||||
|
||||
private:
|
||||
bool _mousePressed;
|
||||
float _bodyPitchDelta;
|
||||
float _bodyRollDelta;
|
||||
bool _shouldJump;
|
||||
int _driveKeys[MAX_DRIVE_KEYS];
|
||||
glm::vec3 _gravity;
|
||||
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
||||
Avatar* _interactingOther;
|
||||
float _elapsedTimeMoving; // Timers to drive camera transitions when moving
|
||||
float _elapsedTimeStopped;
|
||||
float _elapsedTimeSinceCollision;
|
||||
glm::vec3 _lastCollisionPosition;
|
||||
bool _speedBrakes;
|
||||
bool _isThrustOn;
|
||||
float _collisionRadius;
|
||||
|
||||
// private methods
|
||||
float getBallRenderAlpha(int ball, bool lookingInMirror) const;
|
||||
void renderBody(bool lookingInMirror, bool renderAvatarBalls);
|
||||
void updateThrust(float deltaTime, Transmitter * transmitter);
|
||||
void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement);
|
||||
void updateAvatarCollisions(float deltaTime);
|
||||
void updateCollisionWithEnvironment(float deltaTime);
|
||||
void updateCollisionWithVoxels(float deltaTime);
|
||||
void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping);
|
||||
void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency);
|
||||
void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );
|
||||
void checkForMouseRayTouching();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -111,11 +111,17 @@ void AmbientOcclusionEffect::render() {
|
|||
_occlusionProgram->setUniformValue(_farLocation, farVal);
|
||||
_occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom);
|
||||
_occlusionProgram->setUniformValue(_rightTopLocation, right, top);
|
||||
QSize size = Application::getInstance()->getGLWidget()->size();
|
||||
_occlusionProgram->setUniformValue(_noiseScaleLocation, size.width() / (float)ROTATION_WIDTH,
|
||||
size.height() / (float)ROTATION_HEIGHT);
|
||||
QSize widgetSize = Application::getInstance()->getGLWidget()->size();
|
||||
_occlusionProgram->setUniformValue(_noiseScaleLocation, widgetSize.width() / (float)ROTATION_WIDTH,
|
||||
widgetSize.height() / (float)ROTATION_HEIGHT);
|
||||
|
||||
renderFullscreenQuad();
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
const int VIEWPORT_X_INDEX = 0;
|
||||
const int VIEWPORT_WIDTH_INDEX = 2;
|
||||
float sMin = viewport[VIEWPORT_X_INDEX] / (float)widgetSize.width();
|
||||
float sMax = (viewport[VIEWPORT_X_INDEX] + viewport[VIEWPORT_WIDTH_INDEX]) / (float)widgetSize.width();
|
||||
renderFullscreenQuad(sMin, sMax);
|
||||
|
||||
_occlusionProgram->release();
|
||||
|
||||
|
@ -133,9 +139,9 @@ void AmbientOcclusionEffect::render() {
|
|||
glBindTexture(GL_TEXTURE_2D, freeFBO->texture());
|
||||
|
||||
_blurProgram->bind();
|
||||
_blurProgram->setUniformValue(_blurScaleLocation, 1.0f / size.width(), 1.0f / size.height());
|
||||
_blurProgram->setUniformValue(_blurScaleLocation, 1.0f / widgetSize.width(), 1.0f / widgetSize.height());
|
||||
|
||||
renderFullscreenQuad();
|
||||
renderFullscreenQuad(sMin, sMax);
|
||||
|
||||
_blurProgram->release();
|
||||
|
||||
|
|
|
@ -78,7 +78,19 @@ void GlowEffect::end() {
|
|||
glBlendColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void GlowEffect::render() {
|
||||
static void maybeBind(QOpenGLFramebufferObject* fbo) {
|
||||
if (fbo != NULL) {
|
||||
fbo->bind();
|
||||
}
|
||||
}
|
||||
|
||||
static void maybeRelease(QOpenGLFramebufferObject* fbo) {
|
||||
if (fbo != NULL) {
|
||||
fbo->release();
|
||||
}
|
||||
}
|
||||
|
||||
QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) {
|
||||
QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();
|
||||
primaryFBO->release();
|
||||
glBindTexture(GL_TEXTURE_2D, primaryFBO->texture());
|
||||
|
@ -94,23 +106,29 @@ void GlowEffect::render() {
|
|||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
QOpenGLFramebufferObject* destFBO = toTexture ?
|
||||
Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject() : NULL;
|
||||
if (_isEmpty) {
|
||||
// copy the primary to the screen
|
||||
if (QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
|
||||
QOpenGLFramebufferObject::blitFramebuffer(NULL, primaryFBO);
|
||||
QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO);
|
||||
|
||||
} else {
|
||||
maybeBind(destFBO);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_LIGHTING);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
renderFullscreenQuad();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_LIGHTING);
|
||||
maybeRelease(destFBO);
|
||||
}
|
||||
} else if (_renderMode == ADD_MODE) {
|
||||
maybeBind(destFBO);
|
||||
_addProgram->bind();
|
||||
renderFullscreenQuad();
|
||||
_addProgram->release();
|
||||
maybeRelease(destFBO);
|
||||
|
||||
} else if (_renderMode == DIFFUSE_ADD_MODE) {
|
||||
// diffuse into the secondary/tertiary (alternating between frames)
|
||||
|
@ -139,9 +157,14 @@ void GlowEffect::render() {
|
|||
// add diffused texture to the primary
|
||||
glBindTexture(GL_TEXTURE_2D, newDiffusedFBO->texture());
|
||||
|
||||
if (toTexture) {
|
||||
destFBO = oldDiffusedFBO;
|
||||
}
|
||||
maybeBind(destFBO);
|
||||
_addSeparateProgram->bind();
|
||||
renderFullscreenQuad();
|
||||
_addSeparateProgram->release();
|
||||
maybeRelease(destFBO);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
@ -163,9 +186,14 @@ void GlowEffect::render() {
|
|||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture());
|
||||
|
||||
if (toTexture) {
|
||||
destFBO = Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject();
|
||||
}
|
||||
maybeBind(destFBO);
|
||||
_verticalBlurAddProgram->bind();
|
||||
renderFullscreenQuad();
|
||||
_verticalBlurAddProgram->release();
|
||||
maybeRelease(destFBO);
|
||||
|
||||
} else { // _renderMode == BLUR_PERSIST_ADD_MODE
|
||||
// render the secondary to the tertiary with horizontal blur and persistence
|
||||
|
@ -196,9 +224,11 @@ void GlowEffect::render() {
|
|||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, tertiaryFBO->texture());
|
||||
|
||||
maybeBind(destFBO);
|
||||
_addSeparateProgram->bind();
|
||||
renderFullscreenQuad();
|
||||
_addSeparateProgram->release();
|
||||
maybeRelease(destFBO);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
@ -214,6 +244,8 @@ void GlowEffect::render() {
|
|||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return destFBO;
|
||||
}
|
||||
|
||||
void GlowEffect::cycleRenderMode() {
|
||||
|
|
|
@ -40,7 +40,9 @@ public:
|
|||
void end();
|
||||
|
||||
/// Renders the glow effect. To be called after rendering the scene.
|
||||
void render();
|
||||
/// \param toTexture whether to render to a texture, rather than to the frame buffer
|
||||
/// \return the framebuffer object to which we rendered, or NULL if to the frame buffer
|
||||
QOpenGLFramebufferObject* render(bool toTexture = false);
|
||||
|
||||
public slots:
|
||||
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
#include "InterfaceConfig.h"
|
||||
#include "RenderUtil.h"
|
||||
|
||||
void renderFullscreenQuad() {
|
||||
void renderFullscreenQuad(float sMin, float sMax) {
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0f, 0.0f);
|
||||
glTexCoord2f(sMin, 0.0f);
|
||||
glVertex2f(-1.0f, -1.0f);
|
||||
glTexCoord2f(1.0f, 0.0f);
|
||||
glTexCoord2f(sMax, 0.0f);
|
||||
glVertex2f(1.0f, -1.0f);
|
||||
glTexCoord2f(1.0f, 1.0f);
|
||||
glTexCoord2f(sMax, 1.0f);
|
||||
glVertex2f(1.0f, 1.0f);
|
||||
glTexCoord2f(0.0f, 1.0f);
|
||||
glTexCoord2f(sMin, 1.0f);
|
||||
glVertex2f(-1.0f, 1.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#ifndef __interface__RenderUtil__
|
||||
#define __interface__RenderUtil__
|
||||
|
||||
/// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (0, 0) to (1, 1).
|
||||
void renderFullscreenQuad();
|
||||
/// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (sMin, 0) to (sMax, 1).
|
||||
void renderFullscreenQuad(float sMin = 0.0f, float sMax = 1.0f);
|
||||
|
||||
#endif /* defined(__interface__RenderUtil__) */
|
||||
|
|
|
@ -1,242 +0,0 @@
|
|||
//
|
||||
// SquarePixelMap.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Tomáš Horáček on 6/25/13.
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SquarePixelMap.h"
|
||||
|
||||
#define CHILD_COORD_X_IS_1 0x1
|
||||
#define CHILD_COORD_Y_IS_1 0x2
|
||||
#define ALPHA_CHANNEL_RANGE_FLOAT 256.f
|
||||
#define ALPHA_CHANNEL_BIT_OFFSET 24
|
||||
#define RED_CHANNEL_BIT_OFFSET 16
|
||||
#define GREEN_CHANNEL_BIT_OFFSET 8
|
||||
|
||||
unsigned int numberOfBitsForSize(unsigned int size) {
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size--;
|
||||
|
||||
unsigned int ans = 1;
|
||||
while (size >>= 1) {
|
||||
ans++;
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
struct PixelQuadTreeCoordinates {
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
class PixelQuadTreeNode {
|
||||
public:
|
||||
PixelQuadTreeCoordinates _coord;
|
||||
uint32_t _color; // undefined value for _allChildrenHasSameColor = false
|
||||
bool _allChildrenHasSameColor;
|
||||
uint8_t _minimumNeighbourhoodAplha;
|
||||
|
||||
// 0 x -> 1
|
||||
// +---+---+
|
||||
// y | 0 | 1 | <- child index
|
||||
// | +---+---+
|
||||
// v | 2 | 3 |
|
||||
// +---+---+
|
||||
// 1
|
||||
PixelQuadTreeNode* _children[4];
|
||||
|
||||
PixelQuadTreeNode(PixelQuadTreeCoordinates coord, SquarePixelMap* pixelMap);
|
||||
~PixelQuadTreeNode() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
delete _children[i];
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void updateChildCoordinates(int i, PixelQuadTreeCoordinates& childCoord) {
|
||||
childCoord.x = _coord.x;
|
||||
childCoord.y = _coord.y;
|
||||
|
||||
if (i & CHILD_COORD_X_IS_1) {
|
||||
childCoord.x += childCoord.size;
|
||||
}
|
||||
if (i & CHILD_COORD_Y_IS_1) {
|
||||
childCoord.y += childCoord.size;
|
||||
}
|
||||
}
|
||||
|
||||
bool hasAllChildrenSameColor() {
|
||||
return false; //turn off import voxel grouping
|
||||
|
||||
for (int i = 1; i < 4; i++) {
|
||||
if (!_children[i]->_allChildrenHasSameColor) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t firstColor = _children[0]->_color;
|
||||
|
||||
for (int i = 1; i < 4; i++) {
|
||||
if (firstColor != _children[i]->_color) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
PixelQuadTreeNode::PixelQuadTreeNode(PixelQuadTreeCoordinates coord, SquarePixelMap* pixelMap) : _coord(coord), _minimumNeighbourhoodAplha(-1) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_children[i] = NULL;
|
||||
}
|
||||
|
||||
if (_coord.size == 1) {
|
||||
_color = pixelMap->getPixelAt(_coord.x, _coord.y);
|
||||
|
||||
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x + 1, _coord.y), _minimumNeighbourhoodAplha);
|
||||
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x - 1, _coord.y), _minimumNeighbourhoodAplha);
|
||||
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x, _coord.y + 1), _minimumNeighbourhoodAplha);
|
||||
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x, _coord.y - 1), _minimumNeighbourhoodAplha);
|
||||
|
||||
_allChildrenHasSameColor = true;
|
||||
} else {
|
||||
PixelQuadTreeCoordinates childCoord = PixelQuadTreeCoordinates();
|
||||
childCoord.size = _coord.size / 2;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
this->updateChildCoordinates(i, childCoord);
|
||||
|
||||
|
||||
if (childCoord.x < pixelMap->dimension() &&
|
||||
childCoord.y < pixelMap->dimension()) {
|
||||
|
||||
_children[i] = new PixelQuadTreeNode(childCoord, pixelMap);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->hasAllChildrenSameColor()) {
|
||||
_allChildrenHasSameColor = true;
|
||||
_color = _children[0]->_color;
|
||||
|
||||
_minimumNeighbourhoodAplha = _children[0]->_minimumNeighbourhoodAplha;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_minimumNeighbourhoodAplha = std::min<uint8_t>(_children[i]->_minimumNeighbourhoodAplha, _minimumNeighbourhoodAplha);
|
||||
delete _children[i];
|
||||
_children[i] = NULL;
|
||||
}
|
||||
} else {
|
||||
_allChildrenHasSameColor = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SquarePixelMap::SquarePixelMap(const uint32_t* pixels, int dimension) : _rootPixelQuadTreeNode(NULL) {
|
||||
_data = new SquarePixelMapData();
|
||||
_data->dimension = dimension;
|
||||
_data->reference_counter = 1;
|
||||
|
||||
size_t pixels_size = dimension * dimension;
|
||||
_data->pixels = new uint32_t[pixels_size];
|
||||
memcpy((void*)_data->pixels, (void*)pixels, sizeof(uint32_t) * pixels_size);
|
||||
}
|
||||
|
||||
SquarePixelMap::SquarePixelMap(const SquarePixelMap& other) {
|
||||
this->_data = other._data;
|
||||
this->_data->reference_counter++;
|
||||
}
|
||||
|
||||
SquarePixelMap::~SquarePixelMap() {
|
||||
delete _rootPixelQuadTreeNode;
|
||||
|
||||
if (--_data->reference_counter == 0) {
|
||||
delete _data->pixels;
|
||||
delete _data;
|
||||
}
|
||||
}
|
||||
|
||||
void SquarePixelMap::addVoxelsToVoxelTree(VoxelTree* voxelTree) {
|
||||
this->generateRootPixelQuadTreeNode();
|
||||
this->createVoxelsFromPixelQuadTreeToVoxelTree(_rootPixelQuadTreeNode, voxelTree);
|
||||
}
|
||||
|
||||
int SquarePixelMap::dimension() {
|
||||
return _data->dimension;
|
||||
}
|
||||
|
||||
uint32_t SquarePixelMap::getPixelAt(unsigned int x, unsigned int y) {
|
||||
return _data->pixels[x + y * _data->dimension];
|
||||
}
|
||||
|
||||
uint8_t SquarePixelMap::getAlphaAt(int x, int y) {
|
||||
int max_coord = this->dimension() - 1;
|
||||
|
||||
if (x < 0 || y < 0 || x > max_coord || y > max_coord) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this->getPixelAt(x, y) >> ALPHA_CHANNEL_BIT_OFFSET;
|
||||
}
|
||||
|
||||
void SquarePixelMap::generateRootPixelQuadTreeNode() {
|
||||
delete _rootPixelQuadTreeNode;
|
||||
|
||||
PixelQuadTreeCoordinates rootNodeCoord = PixelQuadTreeCoordinates();
|
||||
rootNodeCoord.size = 1 << numberOfBitsForSize(_data->dimension);
|
||||
rootNodeCoord.x = rootNodeCoord.y = 0;
|
||||
|
||||
_rootPixelQuadTreeNode = new PixelQuadTreeNode(rootNodeCoord, this);
|
||||
}
|
||||
|
||||
void SquarePixelMap::createVoxelsFromPixelQuadTreeToVoxelTree(PixelQuadTreeNode* pixelQuadTreeNode, VoxelTree* voxelTree) {
|
||||
if (pixelQuadTreeNode->_allChildrenHasSameColor) {
|
||||
VoxelDetail voxel = this->getVoxelDetail(pixelQuadTreeNode);
|
||||
|
||||
unsigned char minimumNeighbourhoodAplha = std::max<int>(0, pixelQuadTreeNode->_minimumNeighbourhoodAplha - 1);
|
||||
|
||||
float minimumNeighbourhoodY = voxel.s * (floor(minimumNeighbourhoodAplha / (ALPHA_CHANNEL_RANGE_FLOAT * voxel.s)) + 0.5);
|
||||
|
||||
do {
|
||||
voxelTree->createVoxel(voxel.x, voxel.y, voxel.z, voxel.s, voxel.red, voxel.green, voxel.blue, true);
|
||||
} while ((voxel.y -= voxel.s) > minimumNeighbourhoodY);
|
||||
} else {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
PixelQuadTreeNode* child = pixelQuadTreeNode->_children[i];
|
||||
if (child) {
|
||||
this->createVoxelsFromPixelQuadTreeToVoxelTree(child, voxelTree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VoxelDetail SquarePixelMap::getVoxelDetail(PixelQuadTreeNode* pixelQuadTreeNode) {
|
||||
VoxelDetail voxel = VoxelDetail();
|
||||
|
||||
uint32_t color = pixelQuadTreeNode->_color;
|
||||
unsigned char alpha = std::max<int>(0, (color >> ALPHA_CHANNEL_BIT_OFFSET) - 1);
|
||||
|
||||
voxel.red = color >> RED_CHANNEL_BIT_OFFSET;
|
||||
voxel.green = color >> GREEN_CHANNEL_BIT_OFFSET;
|
||||
voxel.blue = color;
|
||||
|
||||
|
||||
float rootSize = _rootPixelQuadTreeNode->_coord.size;
|
||||
|
||||
voxel.s = pixelQuadTreeNode->_coord.size / rootSize;
|
||||
voxel.y = voxel.s * (floor(alpha / (ALPHA_CHANNEL_RANGE_FLOAT * voxel.s)) + 0.5);
|
||||
voxel.x = pixelQuadTreeNode->_coord.x / rootSize + voxel.s / 2;
|
||||
voxel.z = pixelQuadTreeNode->_coord.y / rootSize + voxel.s / 2;
|
||||
|
||||
return voxel;
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
//
|
||||
// SquarePixelMap.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Tomáš Horáček on 6/25/13.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __hifi__SquarePixelMap__
|
||||
#define __hifi__SquarePixelMap__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "VoxelTree.h"
|
||||
#include "SharedUtil.h"
|
||||
|
||||
class PixelQuadTreeNode;
|
||||
|
||||
struct SquarePixelMapData {
|
||||
const uint32_t* pixels;
|
||||
int dimension;
|
||||
int reference_counter;
|
||||
};
|
||||
|
||||
class SquarePixelMap {
|
||||
public:
|
||||
SquarePixelMap(const uint32_t* pixels, int dimension);
|
||||
SquarePixelMap(const SquarePixelMap& other);
|
||||
~SquarePixelMap();
|
||||
|
||||
void addVoxelsToVoxelTree(VoxelTree* voxelTree);
|
||||
|
||||
int dimension();
|
||||
uint32_t getPixelAt(unsigned int x, unsigned int y);
|
||||
uint8_t getAlphaAt(int x, int y);
|
||||
private:
|
||||
SquarePixelMapData* _data;
|
||||
PixelQuadTreeNode* _rootPixelQuadTreeNode;
|
||||
|
||||
void generateRootPixelQuadTreeNode();
|
||||
void createVoxelsFromPixelQuadTreeToVoxelTree(PixelQuadTreeNode* pixelQuadTreeNode, VoxelTree* voxelTree);
|
||||
VoxelDetail getVoxelDetail(PixelQuadTreeNode* pixelQuadTreeNode);
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__SquarePixelMap__) */
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QImage>
|
||||
#include <QRgb>
|
||||
|
||||
#include "CoverageMap.h"
|
||||
#include "GeometryUtil.h"
|
||||
#include "OctalCode.h"
|
||||
#include "PacketHeaders.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "SquarePixelMap.h"
|
||||
#include "Tags.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "VoxelConstants.h"
|
||||
|
@ -1607,25 +1607,61 @@ bool VoxelTree::readFromSVOFile(const char* fileName) {
|
|||
}
|
||||
|
||||
bool VoxelTree::readFromSquareARGB32Pixels(const char* filename) {
|
||||
QImage pngImage = QImage(filename);
|
||||
if (pngImage.height() != pngImage.width()) {
|
||||
qDebug("ERROR: Bad PNG size: height != width.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
emit importSize(1.0f, 1.0f, 1.0f);
|
||||
emit importProgress(0);
|
||||
|
||||
const uint32_t* pixels;
|
||||
if (pngImage.format() == QImage::Format_ARGB32) {
|
||||
pixels = reinterpret_cast<const uint32_t*>(pngImage.constBits());
|
||||
} else {
|
||||
QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32);
|
||||
pixels = reinterpret_cast<const uint32_t*>(tmp.constBits());
|
||||
int minAlpha = INT_MAX;
|
||||
|
||||
QImage pngImage = QImage(filename);
|
||||
|
||||
for (int x = 0; x < pngImage.width() * pngImage.height(); ++x) {
|
||||
minAlpha = std::min(qAlpha(pngImage.color(x)) , minAlpha);
|
||||
}
|
||||
|
||||
SquarePixelMap pixelMap = SquarePixelMap(pixels, pngImage.height());
|
||||
pixelMap.addVoxelsToVoxelTree(this);
|
||||
int maxSize = std::max(pngImage.width(), pngImage.height());
|
||||
|
||||
int scale = 1;
|
||||
while (maxSize > scale) {scale *= 2;}
|
||||
float size = 1.0f / scale;
|
||||
|
||||
QRgb pixel;
|
||||
int minNeighborhoodAlpha;
|
||||
|
||||
for (int i = 0; i < pngImage.width(); ++i) {
|
||||
for (int j = 0; j < pngImage.height(); ++j) {
|
||||
emit importProgress((100 * (i * pngImage.height() + j)) /
|
||||
(pngImage.width() * pngImage.height()));
|
||||
|
||||
pixel = pngImage.pixel(i, j);
|
||||
minNeighborhoodAlpha = qAlpha(pixel) - 1;
|
||||
|
||||
if (i != 0) {
|
||||
minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i - 1, j)));
|
||||
}
|
||||
if (j != 0) {
|
||||
minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i, j - 1)));
|
||||
}
|
||||
if (i < pngImage.width() - 1) {
|
||||
minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i + 1, j)));
|
||||
}
|
||||
if (j < pngImage.height() - 1) {
|
||||
minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i, j + 1)));
|
||||
}
|
||||
|
||||
while (qAlpha(pixel) > minNeighborhoodAlpha) {
|
||||
++minNeighborhoodAlpha;
|
||||
createVoxel(i * size,
|
||||
(minNeighborhoodAlpha - minAlpha) * size,
|
||||
j * size,
|
||||
size,
|
||||
qRed(pixel),
|
||||
qGreen(pixel),
|
||||
qBlue(pixel),
|
||||
true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
emit importProgress(100);
|
||||
return true;
|
||||
|
|
Loading…
Reference in a new issue