Merge branch 'master' of https://github.com/worklist/hifi into threaded_voxel_server

This commit is contained in:
ZappoMan 2013-08-21 17:03:34 -07:00
commit 38f54a3130
20 changed files with 1665 additions and 1564 deletions

View file

@ -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.

View file

@ -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) {

View file

@ -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() {

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

@ -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) {

File diff suppressed because it is too large Load diff

View 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

View file

@ -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();

View file

@ -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() {

View file

@ -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:

View file

@ -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();
}

View file

@ -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__) */

View file

@ -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;
}

View file

@ -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__) */

View file

@ -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;