mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 09:44:21 +02:00
Merge pull request #1297 from PhilipRosedale/master
Voxel editing with hands, flying by pointing hands
This commit is contained in:
commit
44f92fb47c
9 changed files with 202 additions and 50 deletions
|
@ -1480,6 +1480,54 @@ void Application::doKillLocalVoxels() {
|
|||
_wantToKillLocalVoxels = true;
|
||||
}
|
||||
|
||||
void Application::removeVoxel(glm::vec3 position,
|
||||
float scale) {
|
||||
VoxelDetail voxel;
|
||||
voxel.x = position.x / TREE_SCALE;
|
||||
voxel.y = position.y / TREE_SCALE;
|
||||
voxel.z = position.z / TREE_SCALE;
|
||||
voxel.s = scale / TREE_SCALE;
|
||||
_voxelEditSender.sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, voxel);
|
||||
|
||||
// delete it locally to see the effect immediately (and in case no voxel server is present)
|
||||
_voxels.deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s);
|
||||
}
|
||||
|
||||
void Application::makeVoxel(glm::vec3 position,
|
||||
float scale,
|
||||
unsigned char red,
|
||||
unsigned char green,
|
||||
unsigned char blue,
|
||||
bool isDestructive) {
|
||||
VoxelDetail voxel;
|
||||
voxel.x = position.x / TREE_SCALE;
|
||||
voxel.y = position.y / TREE_SCALE;
|
||||
voxel.z = position.z / TREE_SCALE;
|
||||
voxel.s = scale / TREE_SCALE;
|
||||
voxel.red = red;
|
||||
voxel.green = green;
|
||||
voxel.blue = blue;
|
||||
PACKET_TYPE message = isDestructive ? PACKET_TYPE_SET_VOXEL_DESTRUCTIVE : PACKET_TYPE_SET_VOXEL;
|
||||
_voxelEditSender.sendVoxelEditMessage(message, voxel);
|
||||
|
||||
// create the voxel locally so it appears immediately
|
||||
|
||||
_voxels.createVoxel(voxel.x, voxel.y, voxel.z, voxel.s,
|
||||
voxel.red, voxel.green, voxel.blue,
|
||||
isDestructive);
|
||||
|
||||
// Implement voxel fade effect
|
||||
VoxelFade fade(VoxelFade::FADE_OUT, 1.0f, 1.0f, 1.0f);
|
||||
const float VOXEL_BOUNDS_ADJUST = 0.01f;
|
||||
float slightlyBigger = voxel.s * VOXEL_BOUNDS_ADJUST;
|
||||
fade.voxelDetails.x = voxel.x - slightlyBigger;
|
||||
fade.voxelDetails.y = voxel.y - slightlyBigger;
|
||||
fade.voxelDetails.z = voxel.z - slightlyBigger;
|
||||
fade.voxelDetails.s = voxel.s + slightlyBigger + slightlyBigger;
|
||||
_voxelFades.push_back(fade);
|
||||
|
||||
}
|
||||
|
||||
const glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel) {
|
||||
return glm::vec3((_mouseVoxel.x + _mouseVoxel.s / 2.f) * TREE_SCALE,
|
||||
(_mouseVoxel.y + _mouseVoxel.s / 2.f) * TREE_SCALE,
|
||||
|
@ -2214,11 +2262,11 @@ void Application::updateLeap(float deltaTime) {
|
|||
LeapManager::nextFrame();
|
||||
}
|
||||
|
||||
void Application::updateSixense() {
|
||||
void Application::updateSixense(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateSixense()");
|
||||
|
||||
_sixenseManager.update();
|
||||
_sixenseManager.update(deltaTime);
|
||||
}
|
||||
|
||||
void Application::updateSerialDevices(float deltaTime) {
|
||||
|
@ -2428,7 +2476,7 @@ void Application::update(float deltaTime) {
|
|||
updateMouseVoxels(deltaTime, mouseRayOrigin, mouseRayDirection, distance, face); // UI/UX related to voxels
|
||||
updateHandAndTouch(deltaTime); // Update state for touch sensors
|
||||
updateLeap(deltaTime); // Leap finger-sensing device
|
||||
updateSixense(); // Razer Hydra controllers
|
||||
updateSixense(deltaTime); // Razer Hydra controllers
|
||||
updateSerialDevices(deltaTime); // Read serial port interface devices
|
||||
updateAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
||||
|
@ -3945,29 +3993,18 @@ bool Application::maybeEditVoxelUnderCursor() {
|
|||
if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode)
|
||||
|| Menu::getInstance()->isOptionChecked(MenuOption::VoxelColorMode)) {
|
||||
if (_mouseVoxel.s != 0) {
|
||||
PACKET_TYPE message = Menu::getInstance()->isOptionChecked(MenuOption::DestructiveAddVoxel)
|
||||
? PACKET_TYPE_SET_VOXEL_DESTRUCTIVE
|
||||
: PACKET_TYPE_SET_VOXEL;
|
||||
_voxelEditSender.sendVoxelEditMessage(message, _mouseVoxel);
|
||||
|
||||
// create the voxel locally so it appears immediately
|
||||
_voxels.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s,
|
||||
_mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue,
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::DestructiveAddVoxel));
|
||||
|
||||
// Implement voxel fade effect
|
||||
VoxelFade fade(VoxelFade::FADE_OUT, 1.0f, 1.0f, 1.0f);
|
||||
const float VOXEL_BOUNDS_ADJUST = 0.01f;
|
||||
float slightlyBigger = _mouseVoxel.s * VOXEL_BOUNDS_ADJUST;
|
||||
fade.voxelDetails.x = _mouseVoxel.x - slightlyBigger;
|
||||
fade.voxelDetails.y = _mouseVoxel.y - slightlyBigger;
|
||||
fade.voxelDetails.z = _mouseVoxel.z - slightlyBigger;
|
||||
fade.voxelDetails.s = _mouseVoxel.s + slightlyBigger + slightlyBigger;
|
||||
_voxelFades.push_back(fade);
|
||||
|
||||
makeVoxel(glm::vec3(_mouseVoxel.x * TREE_SCALE,
|
||||
_mouseVoxel.y * TREE_SCALE,
|
||||
_mouseVoxel.z * TREE_SCALE),
|
||||
_mouseVoxel.s * TREE_SCALE,
|
||||
_mouseVoxel.red,
|
||||
_mouseVoxel.green,
|
||||
_mouseVoxel.blue,
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::DestructiveAddVoxel));
|
||||
|
||||
// inject a sound effect
|
||||
injectVoxelAddedSoundEffect();
|
||||
|
||||
|
||||
// remember the position for drag detection
|
||||
_justEditedVoxel = true;
|
||||
|
||||
|
|
|
@ -117,6 +117,15 @@ public:
|
|||
|
||||
void wheelEvent(QWheelEvent* event);
|
||||
|
||||
void makeVoxel(glm::vec3 position,
|
||||
float scale,
|
||||
unsigned char red,
|
||||
unsigned char green,
|
||||
unsigned char blue,
|
||||
bool isDestructive);
|
||||
|
||||
void removeVoxel(glm::vec3 position, float scale);
|
||||
|
||||
const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel);
|
||||
|
||||
QGLWidget* getGLWidget() { return _glWidget; }
|
||||
|
@ -249,7 +258,7 @@ private:
|
|||
glm::vec3& eyePosition);
|
||||
void updateHandAndTouch(float deltaTime);
|
||||
void updateLeap(float deltaTime);
|
||||
void updateSixense();
|
||||
void updateSixense(float deltaTime);
|
||||
void updateSerialDevices(float deltaTime);
|
||||
void updateThreads(float deltaTime);
|
||||
void updateMyAvatarSimulation(float deltaTime);
|
||||
|
|
|
@ -61,6 +61,33 @@ void Hand::simulate(float deltaTime, bool isMine) {
|
|||
|
||||
updateRaveGloveParticles(deltaTime);
|
||||
}
|
||||
|
||||
// Create a voxel at fingertip if controller button is pressed
|
||||
const float FINGERTIP_VOXEL_SIZE = 0.0125;
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
FingerData& finger = palm.getFingers()[0];
|
||||
glm::vec3 newVoxelPosition = finger.getTipPosition();
|
||||
if (palm.getControllerButtons() & BUTTON_1) {
|
||||
if (glm::length(newVoxelPosition - _lastFingerAddVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) {
|
||||
QColor paintColor = Menu::getInstance()->getActionForOption(MenuOption::VoxelPaintColor)->data().value<QColor>();
|
||||
Application::getInstance()->makeVoxel(newVoxelPosition,
|
||||
FINGERTIP_VOXEL_SIZE,
|
||||
paintColor.red(),
|
||||
paintColor.green(),
|
||||
paintColor.blue(),
|
||||
true);
|
||||
_lastFingerAddVoxel = newVoxelPosition;
|
||||
}
|
||||
} else if (palm.getControllerButtons() & BUTTON_2) {
|
||||
if (glm::length(newVoxelPosition - _lastFingerDeleteVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) {
|
||||
Application::getInstance()->removeVoxel(newVoxelPosition, FINGERTIP_VOXEL_SIZE);
|
||||
_lastFingerDeleteVoxel = newVoxelPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Hand::calculateGeometry() {
|
||||
|
@ -157,6 +184,45 @@ void Hand::render() {
|
|||
}
|
||||
}
|
||||
|
||||
// If hand controller buttons pressed, render stuff as needed
|
||||
if (getPalms().size() > 0) {
|
||||
for (size_t i = 0; i < getPalms().size(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
// If trigger pulled, thrust in that direction and draw beam
|
||||
const float MAX_THRUSTER_BEAM_LENGTH = 5.f;
|
||||
const float THRUSTER_MARKER_SIZE = 0.0125f;
|
||||
if (palm.getJoystickY() != 0.f) {
|
||||
FingerData& finger = palm.getFingers()[0];
|
||||
if (finger.isActive()) {
|
||||
if (palm.getJoystickY() > 0.f) {
|
||||
glColor3f(0, 1, 0);
|
||||
} else {
|
||||
glColor3f(1, 0, 0);
|
||||
}
|
||||
glm::vec3 palmPosition = palm.getPosition();
|
||||
glm::vec3 pointerPosition = palmPosition +
|
||||
glm::normalize(finger.getTipPosition() - palmPosition) *
|
||||
MAX_THRUSTER_BEAM_LENGTH;
|
||||
glPushMatrix();
|
||||
glm::vec3 markerPosition = palmPosition +
|
||||
glm::normalize(finger.getTipPosition() - palmPosition) *
|
||||
MAX_THRUSTER_BEAM_LENGTH *
|
||||
(0.5f + palm.getJoystickY() / 2.f);
|
||||
|
||||
glTranslatef(markerPosition.x, markerPosition.y, markerPosition.z);
|
||||
glutSolidSphere(THRUSTER_MARKER_SIZE, 10, 10);
|
||||
glPopMatrix();
|
||||
glLineWidth(2.0);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(palmPosition.x, palmPosition.y, palmPosition.z);
|
||||
glVertex3f(pointerPosition.x, pointerPosition.y, pointerPosition.z);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_RESCALE_NORMAL);
|
||||
|
||||
|
@ -227,8 +293,8 @@ void Hand::renderLeapHands() {
|
|||
//const glm::vec3 handColor = _ballColor;
|
||||
const glm::vec3 handColor(1.0, 0.84, 0.66); // use the skin color
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glPushMatrix();
|
||||
// Draw the leap balls
|
||||
for (size_t i = 0; i < _leapFingerTipBalls.size(); i++) {
|
||||
|
|
|
@ -30,6 +30,7 @@ enum RaveLightsSetting {
|
|||
RAVE_LIGHTS_PARTICLES
|
||||
};
|
||||
|
||||
|
||||
class Avatar;
|
||||
class ProgramObject;
|
||||
|
||||
|
@ -46,7 +47,7 @@ public:
|
|||
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
|
||||
};
|
||||
|
||||
|
||||
void init();
|
||||
void reset();
|
||||
void simulate(float deltaTime, bool isMine);
|
||||
|
@ -62,7 +63,7 @@ public:
|
|||
// getters
|
||||
const glm::vec3& getLeapFingerTipBallPosition (int ball) const { return _leapFingerTipBalls [ball].position;}
|
||||
const glm::vec3& getLeapFingerRootBallPosition(int ball) const { return _leapFingerRootBalls[ball].position;}
|
||||
|
||||
|
||||
private:
|
||||
// disallow copies of the Hand, copy of owning Avatar is disallowed too
|
||||
Hand(const Hand&);
|
||||
|
@ -72,6 +73,8 @@ private:
|
|||
float _raveGloveClock;
|
||||
bool _raveGloveInitialized;
|
||||
int _raveGloveEmitter[NUM_FINGERS];
|
||||
|
||||
int _controllerButtons; /// Button states read from hand-held controllers
|
||||
|
||||
Avatar* _owningAvatar;
|
||||
float _renderAlpha;
|
||||
|
@ -79,6 +82,8 @@ private:
|
|||
std::vector<HandBall> _leapFingerTipBalls;
|
||||
std::vector<HandBall> _leapFingerRootBalls;
|
||||
|
||||
glm::vec3 _lastFingerAddVoxel, _lastFingerDeleteVoxel;
|
||||
|
||||
// private methods
|
||||
void setLeapHands(const std::vector<glm::vec3>& handPositions,
|
||||
const std::vector<glm::vec3>& handNormals);
|
||||
|
|
|
@ -848,7 +848,25 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) {
|
|||
up;
|
||||
}
|
||||
}
|
||||
|
||||
// Add thrust and rotation from hand controllers
|
||||
const float THRUST_MAG_HAND_JETS = THRUST_MAG_FWD;
|
||||
const float JOYSTICK_YAW_MAG = YAW_MAG;
|
||||
for (size_t i = 0; i < getHand().getPalms().size(); ++i) {
|
||||
PalmData& palm = getHand().getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
if (palm.getJoystickY() != 0.f) {
|
||||
FingerData& finger = palm.getFingers()[0];
|
||||
if (finger.isActive()) {
|
||||
}
|
||||
glm::vec3 thrustDirection = glm::normalize(finger.getTipPosition() - palm.getPosition());
|
||||
_thrust += thrustDirection * _scale * THRUST_MAG_HAND_JETS * palm.getJoystickY() * _thrustMultiplier * deltaTime;
|
||||
}
|
||||
if (palm.getJoystickX() != 0.f) {
|
||||
_bodyYawDelta -= palm.getJoystickX() * JOYSTICK_YAW_MAG * deltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update speed brake status
|
||||
const float MIN_SPEED_BRAKE_VELOCITY = _scale * 0.4f;
|
||||
if ((glm::length(_thrust) == 0.0f) && _isThrustOn && (glm::length(_velocity) > MIN_SPEED_BRAKE_VELOCITY)) {
|
||||
|
|
|
@ -25,7 +25,7 @@ SixenseManager::~SixenseManager() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void SixenseManager::update() {
|
||||
void SixenseManager::update(float deltaTime) {
|
||||
#ifdef HAVE_SIXENSE
|
||||
if (sixenseGetNumActiveControllers() == 0) {
|
||||
return;
|
||||
|
@ -42,27 +42,19 @@ void SixenseManager::update() {
|
|||
sixenseControllerData data;
|
||||
sixenseGetNewestData(i, &data);
|
||||
|
||||
// drive avatar with joystick and triggers
|
||||
if (data.controller_index) {
|
||||
avatar->setDriveKeys(ROT_LEFT, qMax(0.0f, -data.joystick_x));
|
||||
avatar->setDriveKeys(ROT_RIGHT, qMax(0.0f, data.joystick_x));
|
||||
avatar->setDriveKeys(ROT_UP, qMax(0.0f, data.joystick_y));
|
||||
avatar->setDriveKeys(ROT_DOWN, qMax(0.0f, -data.joystick_y));
|
||||
avatar->setDriveKeys(UP, data.trigger);
|
||||
|
||||
} else {
|
||||
avatar->setDriveKeys(FWD, qMax(0.0f, data.joystick_y));
|
||||
avatar->setDriveKeys(BACK, qMax(0.0f, -data.joystick_y));
|
||||
avatar->setDriveKeys(LEFT, qMax(0.0f, -data.joystick_x));
|
||||
avatar->setDriveKeys(RIGHT, qMax(0.0f, data.joystick_x));
|
||||
avatar->setDriveKeys(DOWN, data.trigger);
|
||||
}
|
||||
|
||||
// Set palm position and normal based on Hydra position/orientation
|
||||
PalmData palm(&hand);
|
||||
palm.setActive(true);
|
||||
glm::vec3 position(data.pos[0], data.pos[1], data.pos[2]);
|
||||
|
||||
// Compute current velocity from position change
|
||||
palm.setVelocity((position - palm.getPosition()) / deltaTime);
|
||||
|
||||
// Read controller buttons and joystick into the hand
|
||||
palm.setControllerButtons(data.buttons);
|
||||
palm.setTrigger(data.trigger);
|
||||
palm.setJoystick(data.joystick_x, data.joystick_y);
|
||||
|
||||
// Adjust for distance between acquisition 'orb' and the user's torso
|
||||
// (distance to the right of body center, distance below torso, distance behind torso)
|
||||
const glm::vec3 SPHERE_TO_TORSO(-250.f, -300.f, -300.f);
|
||||
|
|
|
@ -16,7 +16,7 @@ public:
|
|||
SixenseManager();
|
||||
~SixenseManager();
|
||||
|
||||
void update();
|
||||
void update(float deltaTime);
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__SixenseManager__) */
|
||||
|
|
|
@ -37,6 +37,8 @@ PalmData& HandData::addNewPalm() {
|
|||
PalmData::PalmData(HandData* owningHandData) :
|
||||
_rawPosition(0, 0, 0),
|
||||
_rawNormal(0, 1, 0),
|
||||
_velocity(0, 0, 0),
|
||||
_controllerButtons(0),
|
||||
_isActive(false),
|
||||
_leapID(LEAPID_INVALID),
|
||||
_numFramesWithoutData(0),
|
||||
|
|
|
@ -41,6 +41,12 @@ enum RaveGloveEffectsMode
|
|||
NUM_RAVE_GLOVE_EFFECTS_MODES
|
||||
};
|
||||
|
||||
const int BUTTON_1 = 32;
|
||||
const int BUTTON_2 = 64;
|
||||
const int BUTTON_3 = 8;
|
||||
const int BUTTON_4 = 16;
|
||||
const int BUTTON_FWD = 128;
|
||||
|
||||
class HandData {
|
||||
public:
|
||||
HandData(AvatarData* owningAvatar);
|
||||
|
@ -144,17 +150,34 @@ public:
|
|||
void setLeapID(int id) { _leapID = id; }
|
||||
void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; }
|
||||
void setRawNormal(const glm::vec3& normal) { _rawNormal = normal; }
|
||||
void setVelocity(const glm::vec3& velocity) { _velocity = velocity; }
|
||||
const glm::vec3& getVelocity() const { return _velocity; }
|
||||
|
||||
void incrementFramesWithoutData() { _numFramesWithoutData++; }
|
||||
void resetFramesWithoutData() { _numFramesWithoutData = 0; }
|
||||
int getFramesWithoutData() const { return _numFramesWithoutData; }
|
||||
|
||||
// Controller buttons
|
||||
void setControllerButtons(int controllerButtons) { _controllerButtons = controllerButtons; }
|
||||
int getControllerButtons() { return _controllerButtons; }
|
||||
|
||||
void setTrigger(float trigger) { _trigger = trigger; }
|
||||
float getTrigger() { return _trigger; }
|
||||
void setJoystick(float joystickX, float joystickY) { _joystickX = joystickX; _joystickY = joystickY; }
|
||||
float getJoystickX() { return _joystickX; }
|
||||
float getJoystickY() { return _joystickY; }
|
||||
|
||||
private:
|
||||
std::vector<FingerData> _fingers;
|
||||
glm::vec3 _rawPosition;
|
||||
glm::vec3 _rawNormal;
|
||||
bool _isActive; // This has current valid data
|
||||
int _leapID; // the Leap's serial id for this tracked object
|
||||
glm::vec3 _velocity;
|
||||
int _controllerButtons;
|
||||
float _trigger;
|
||||
float _joystickX, _joystickY;
|
||||
|
||||
bool _isActive; // This has current valid data
|
||||
int _leapID; // the Leap's serial id for this tracked object
|
||||
int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost.
|
||||
HandData* _owningHandData;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue