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

This commit is contained in:
ZappoMan 2013-04-27 14:49:03 -07:00
commit e4c39369aa
17 changed files with 424 additions and 234 deletions

View file

@ -52,11 +52,10 @@ const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SA
const long MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max(); const long MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
const long MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min(); const long MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
const float DISTANCE_RATIO = 3.0/4.2; const float DISTANCE_RATIO = 3.0f / 0.3f;
const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5;
const int PHASE_DELAY_AT_90 = 20; const int PHASE_DELAY_AT_90 = 20;
const int AGENT_LOOPBACK_MODIFIER = 307; const int AGENT_LOOPBACK_MODIFIER = 307;
const int LOOPBACK_SANITY_CHECK = 0; const int LOOPBACK_SANITY_CHECK = 0;
@ -127,7 +126,7 @@ void *sendBuffer(void *args)
for (AgentList::iterator otherAgent = agentList->begin(); otherAgent != agentList->end(); otherAgent++) { for (AgentList::iterator otherAgent = agentList->begin(); otherAgent != agentList->end(); otherAgent++) {
if (otherAgent != agent || ( otherAgent == agent && agentWantsLoopback)) { if (otherAgent != agent || (otherAgent == agent && agentWantsLoopback)) {
AudioRingBuffer* otherAgentBuffer = (AudioRingBuffer*) otherAgent->getLinkedData(); AudioRingBuffer* otherAgentBuffer = (AudioRingBuffer*) otherAgent->getLinkedData();
float *agentPosition = agentRingBuffer->getPosition(); float *agentPosition = agentRingBuffer->getPosition();

View file

@ -151,10 +151,8 @@ int audioCallback (const void *inputBuffer,
unsigned char *currentPacketPtr = dataPacket + 1; unsigned char *currentPacketPtr = dataPacket + 1;
// memcpy the three float positions // memcpy the three float positions
for (int p = 0; p < 3; p++) { memcpy(currentPacketPtr, &data->linkedAvatar->getHeadPosition(), sizeof(float) * 3);
memcpy(currentPacketPtr, &data->linkedAvatar->getPosition()[p], sizeof(float)); currentPacketPtr += (sizeof(float) * 3);
currentPacketPtr += sizeof(float);
}
// tell the mixer not to add additional attenuation to our source // tell the mixer not to add additional attenuation to our source
*(currentPacketPtr++) = 255; *(currentPacketPtr++) = 255;

View file

@ -319,7 +319,7 @@ void Avatar::simulate(float deltaTime) {
// if the avatar being simulated is mine, then loop through // if the avatar being simulated is mine, then loop through
// all the other avatars for potential interactions... // all the other avatars for potential interactions...
if ( _isMine ) if ( _isMine )
{ {
float closestDistance = 10000.0f; float closestDistance = 10000.0f;
AgentList* agentList = AgentList::getInstance(); AgentList* agentList = AgentList::getInstance();
@ -341,7 +341,7 @@ void Avatar::simulate(float deltaTime) {
float distance = glm::length( v ); float distance = glm::length( v );
if ( distance < _maxArmLength + _maxArmLength ) { if ( distance < _maxArmLength + _maxArmLength ) {
//if ( distance < closestDistance ) { // perhaps I don't need this if we want to allow multi-avatar interactions //if ( distance < closestDistance ) { // perhaps I don't need this if we want to allow multi-avatar interactions
{ {
closestDistance = distance; closestDistance = distance;
@ -352,7 +352,7 @@ void Avatar::simulate(float deltaTime) {
if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) { if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) {
glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHolding.position; glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHolding.position;
glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position;
_handHolding.velocity *= 0.7; _handHolding.velocity *= 0.7;
_handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime;
_handHolding.position += _handHolding.velocity; _handHolding.position += _handHolding.velocity;
@ -360,6 +360,9 @@ void Avatar::simulate(float deltaTime) {
_bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position;
} }
} }
_avatarTouch.setMyHandPosition( _bone[ AVATAR_BONE_RIGHT_HAND ].position );
_avatarTouch.setYourPosition( otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ) );
} }
} }
} }
@ -367,7 +370,10 @@ void Avatar::simulate(float deltaTime) {
// Set the vector we send for hand position to other people to be our right hand // Set the vector we send for hand position to other people to be our right hand
setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position); setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position);
} //update the effects of touching another avatar
_avatarTouch.simulate(deltaTime);
}//if ( _isMine )
updateArmIKAndConstraints( deltaTime ); updateArmIKAndConstraints( deltaTime );
@ -400,31 +406,15 @@ void Avatar::simulate(float deltaTime) {
if ( _isMine ) { if ( _isMine ) {
_thrust = glm::vec3( 0.0, 0.0, 0.0 ); _thrust = glm::vec3( 0.0, 0.0, 0.0 );
if (_driveKeys[FWD]) { if (_driveKeys[FWD ]) {_thrust += THRUST_MAG * deltaTime * _orientation.getFront();}
_thrust += _orientation.getFront() * THRUST_MAG; if (_driveKeys[BACK ]) {_thrust -= THRUST_MAG * deltaTime * _orientation.getFront();}
} if (_driveKeys[RIGHT ]) {_thrust += THRUST_MAG * deltaTime * _orientation.getRight();}
if (_driveKeys[BACK]) { if (_driveKeys[LEFT ]) {_thrust -= THRUST_MAG * deltaTime * _orientation.getRight();}
_thrust -= _orientation.getFront() * THRUST_MAG; if (_driveKeys[UP ]) {_thrust += THRUST_MAG * deltaTime * _orientation.getUp();}
} if (_driveKeys[DOWN ]) {_thrust -= THRUST_MAG * deltaTime * _orientation.getUp();}
if (_driveKeys[RIGHT]) { if (_driveKeys[ROT_RIGHT]) {_bodyYawDelta -= YAW_MAG * deltaTime;}
_thrust += _orientation.getRight() * THRUST_MAG; if (_driveKeys[ROT_LEFT ]) {_bodyYawDelta += YAW_MAG * deltaTime;}
}
if (_driveKeys[LEFT]) {
_thrust -= _orientation.getRight() * THRUST_MAG;
}
if (_driveKeys[UP]) {
_thrust += _orientation.getUp() * THRUST_MAG;
}
if (_driveKeys[DOWN]) {
_thrust -= _orientation.getUp() * THRUST_MAG;
}
if (_driveKeys[ROT_RIGHT]) {
_bodyYawDelta -= YAW_MAG * deltaTime;
}
if (_driveKeys[ROT_LEFT]) {
_bodyYawDelta += YAW_MAG * deltaTime;
}
} }
// update body yaw by body yaw delta // update body yaw by body yaw delta
@ -602,6 +592,7 @@ void Avatar::updateAvatarCollisionDetectionAndResponse(glm::vec3 collisionPositi
} }
void Avatar::render(bool lookingInMirror) { void Avatar::render(bool lookingInMirror) {
/* /*
// show avatar position // show avatar position
glColor4f( 0.5f, 0.5f, 0.5f, 0.6 ); glColor4f( 0.5f, 0.5f, 0.5f, 0.6 );
@ -632,17 +623,8 @@ void Avatar::render(bool lookingInMirror) {
// if this is my avatar, then render my interactions with the other avatar // if this is my avatar, then render my interactions with the other avatar
if ( _isMine ) if ( _isMine )
{ {
if ( _interactingOtherIsNearby ) { if ( _interactingOtherIsNearby ) {
_avatarTouch.render();
glm::vec3 v1( _bone[ AVATAR_BONE_RIGHT_HAND ].position );
glm::vec3 v2( _interactingOther->_handPosition );
glLineWidth( 8.0 );
glColor4f( 0.7f, 0.4f, 0.1f, 0.6 );
glBegin( GL_LINE_STRIP );
glVertex3f( v1.x, v1.y, v1.z );
glVertex3f( v2.x, v2.y, v2.z );
glEnd();
} }
} }
@ -674,7 +656,7 @@ void Avatar::render(bool lookingInMirror) {
glTranslatef(width * 0.5, 0, 0); glTranslatef(width * 0.5, 0, 0);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
if (_keyState == NoKeyDown) { if (_keyState == NO_KEY_DOWN) {
drawtext(0, 0, chatMessageScale, 180, 1.0, 0, _chatMessage.c_str(), 0, 1, 0); drawtext(0, 0, chatMessageScale, 180, 1.0, 0, _chatMessage.c_str(), 0, 1, 0);
} else { } else {
@ -855,7 +837,8 @@ void Avatar::renderHead(bool lookingInMirror) {
glPopMatrix(); glPopMatrix();
} }
void Avatar::startHandMovement() { void Avatar::startHandMovement() {
@ -976,11 +959,11 @@ void Avatar::initializeSkeleton() {
calculateBoneLengths(); calculateBoneLengths();
_pelvisStandingHeight = _pelvisStandingHeight =
_bone[ AVATAR_BONE_PELVIS_SPINE ].length + _bone[ AVATAR_BONE_PELVIS_SPINE ].length +
_bone[ AVATAR_BONE_LEFT_THIGH ].length + _bone[ AVATAR_BONE_LEFT_THIGH ].length +
_bone[ AVATAR_BONE_LEFT_SHIN ].length + _bone[ AVATAR_BONE_LEFT_SHIN ].length +
_bone[ AVATAR_BONE_LEFT_FOOT ].length + _bone[ AVATAR_BONE_LEFT_FOOT ].length +
_bone[ AVATAR_BONE_RIGHT_FOOT ].radius; _bone[ AVATAR_BONE_RIGHT_FOOT ].radius;
// generate world positions // generate world positions
updateSkeleton(); updateSkeleton();

View file

@ -14,6 +14,7 @@
#include "Field.h" #include "Field.h"
#include "world.h" #include "world.h"
#include "AvatarTouch.h"
#include "InterfaceConfig.h" #include "InterfaceConfig.h"
#include "SerialInterface.h" #include "SerialInterface.h"
@ -26,7 +27,7 @@
const bool AVATAR_GRAVITY = true; const bool AVATAR_GRAVITY = true;
const float DECAY = 0.1; const float DECAY = 0.1;
const float THRUST_MAG = 10.0; const float THRUST_MAG = 1200.0;
const float YAW_MAG = 500.0; //JJV - changed from 300.0; const float YAW_MAG = 500.0; //JJV - changed from 300.0;
const float TEST_YAW_DECAY = 5.0; const float TEST_YAW_DECAY = 5.0;
const float LIN_VEL_DECAY = 5.0; const float LIN_VEL_DECAY = 5.0;
@ -48,6 +49,8 @@ enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
#define MAX_OTHER_AVATARS 10 // temporary - for testing purposes! #define MAX_OTHER_AVATARS 10 // temporary - for testing purposes!
enum AvatarMode enum AvatarMode
{ {
AVATAR_MODE_STANDING = 0, AVATAR_MODE_STANDING = 0,
@ -257,22 +260,25 @@ private:
Avatar* _interactingOther; Avatar* _interactingOther;
bool _interactingOtherIsNearby; bool _interactingOtherIsNearby;
float _pelvisStandingHeight; float _pelvisStandingHeight;
Balls* _balls; Balls* _balls;
AvatarTouch _avatarTouch;
void initializeSkeleton();
void updateSkeleton(); // private methods...
void initializeBodySprings(); void initializeSkeleton();
void updateBodySprings( float deltaTime ); void updateSkeleton();
void calculateBoneLengths(); void initializeBodySprings();
void readSensors(); void updateBodySprings( float deltaTime );
void renderBoneAsBlock( AvatarBoneID b ); void calculateBoneLengths();
void updateAvatarCollisionDetectionAndResponse(glm::vec3 collisionPosition, void readSensors();
float collisionGirth, void renderBoneAsBlock( AvatarBoneID b );
float collisionHeight, void updateAvatarCollisionDetectionAndResponse
glm::vec3 collisionUpVector, (
float deltaTime); glm::vec3 collisionPosition,
float collisionGirth,
float collisionHeight,
glm::vec3 collisionUpVector,
float deltaTime
);
}; };
#endif #endif

View file

@ -0,0 +1,43 @@
//
// AvatarTouch.cpp
// interface
//
// Created by Jeffrey Ventrella
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#include <iostream>
#include <glm/glm.hpp>
#include "AvatarTouch.h"
#include "InterfaceConfig.h"
AvatarTouch::AvatarTouch() {
_myHandPosition = glm::vec3( 0.0f, 0.0f, 0.0f );
_yourHandPosition = glm::vec3( 0.0f, 0.0f, 0.0f );
}
void AvatarTouch::setMyHandPosition( glm::vec3 position ) {
_myHandPosition = position;
}
void AvatarTouch::setYourPosition( glm::vec3 position ) {
_yourHandPosition = position;
}
void AvatarTouch::render() {
glm::vec3 v1( _myHandPosition );
glm::vec3 v2( _yourHandPosition );
glLineWidth( 8.0 );
glColor4f( 0.7f, 0.4f, 0.1f, 0.6 );
glBegin( GL_LINE_STRIP );
glVertex3f( v1.x, v1.y, v1.z );
glVertex3f( v2.x, v2.y, v2.z );
glEnd();
}
void AvatarTouch::simulate (float deltaTime) {
}

View file

@ -0,0 +1,28 @@
//
// AvatarTouch.h
// interface
//
// Created by Jeffrey Ventrella
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__AvatarTouch__
#define __interface__AvatarTouch__
#include <glm/glm.hpp>
class AvatarTouch {
public:
AvatarTouch();
void setMyHandPosition( glm::vec3 position );
void setYourPosition ( glm::vec3 position );
void simulate(float deltaTime);
void render();
private:
glm::vec3 _myHandPosition;
glm::vec3 _yourHandPosition;
};
#endif

View file

@ -65,25 +65,49 @@ void Camera::updateFollowMode( float deltaTime ) {
} }
// update _yaw (before position!) // update _yaw (before position!)
_yaw += ( _idealYaw - _yaw ) * t; _yaw += (_idealYaw - _yaw) * t;
_orientation.yaw ( _yaw ); _orientation.yaw(_yaw);
float radian = ( _yaw / 180.0 ) * PIE; float radian = (_yaw / 180.0) * PIE;
// update _position // update _position
//these need to be checked to make sure they correspond to the correct coordinate system. //these need to be checked to make sure they correspond to the correct coordinate system.
double x = _distance * -sin( radian ); double x = _distance * -sin(radian);
double z = _distance * cos( radian ); double z = _distance * cos(radian);
double y = _upShift; double y = _upShift;
_idealPosition = _targetPosition + glm::vec3( x, y, z ); _idealPosition = _targetPosition + glm::vec3(x, y, z);
//_idealPosition += _orientation.getRight() * _rightShift;
//_idealPosition += _orientation.getUp () * _upShift;
// pull position towards ideal position // pull position towards ideal position
_position += ( _idealPosition - _position ) * t; _position += (_idealPosition - _position) * t;
} }
void Camera::setMode(CameraMode m) {
_mode = m;
_modeShift = 0.0f;
}
void Camera::setFieldOfView(float f) {
_fieldOfView = f;
_frustumNeedsReshape = true;
}
void Camera::setAspectRatio(float a) {
_aspectRatio = a;
_frustumNeedsReshape = true;
}
void Camera::setNearClip (float n) {
_nearClip = n;
_frustumNeedsReshape = true;
}
void Camera::setFarClip (float f) {
_farClip = f;
_frustumNeedsReshape = true;
}
// call to find out if the view frustum needs to be reshaped // call to find out if the view frustum needs to be reshaped
bool Camera::getFrustumNeedsReshape() { bool Camera::getFrustumNeedsReshape() {

View file

@ -29,7 +29,6 @@ public:
void update( float deltaTime ); void update( float deltaTime );
void setMode ( CameraMode m ) { _mode = m; _modeShift = 0.0f; }
void setYaw ( float y ) { _yaw = y; } void setYaw ( float y ) { _yaw = y; }
void setPitch ( float p ) { _pitch = p; } void setPitch ( float p ) { _pitch = p; }
void setRoll ( float r ) { _roll = r; } void setRoll ( float r ) { _roll = r; }
@ -41,10 +40,12 @@ public:
void setPosition ( glm::vec3 p ) { _position = p; } void setPosition ( glm::vec3 p ) { _position = p; }
void setOrientation ( Orientation o ) { _orientation.set(o); } void setOrientation ( Orientation o ) { _orientation.set(o); }
void setTightness ( float t ) { _tightness = t; } void setTightness ( float t ) { _tightness = t; }
void setFieldOfView ( float f ) { _fieldOfView = f; _frustumNeedsReshape = true; }
void setAspectRatio ( float a ) { _aspectRatio = a; _frustumNeedsReshape = true; } void setMode ( CameraMode m );
void setNearClip ( float n ) { _nearClip = n; _frustumNeedsReshape = true; } void setFieldOfView ( float f );
void setFarClip ( float f ) { _farClip = f; _frustumNeedsReshape = true; } void setAspectRatio ( float a );
void setNearClip ( float n );
void setFarClip ( float f );
float getYaw () { return _yaw; } float getYaw () { return _yaw; }
float getPitch () { return _pitch; } float getPitch () { return _pitch; }

View file

@ -15,8 +15,8 @@ using namespace std;
const int MAX_CONTENT_LENGTH = 140; const int MAX_CONTENT_LENGTH = 140;
void ChatEntry::clear () { void ChatEntry::clear () {
contents.clear(); _contents.clear();
cursorPos = 0; _cursorPos = 0;
} }
bool ChatEntry::key(unsigned char k) { bool ChatEntry::key(unsigned char k) {
@ -25,22 +25,22 @@ bool ChatEntry::key(unsigned char k) {
return false; return false;
case '\b': case '\b':
if (cursorPos != 0) { if (_cursorPos != 0) {
contents.erase(cursorPos - 1, 1); _contents.erase(_cursorPos - 1, 1);
cursorPos--; _cursorPos--;
} }
return true; return true;
case 127: // delete case 127: // delete
if (cursorPos < contents.size()) { if (_cursorPos < _contents.size()) {
contents.erase(cursorPos, 1); _contents.erase(_cursorPos, 1);
} }
return true; return true;
default: default:
if (contents.size() != MAX_CONTENT_LENGTH) { if (_contents.size() != MAX_CONTENT_LENGTH) {
contents.insert(cursorPos, 1, k); _contents.insert(_cursorPos, 1, k);
cursorPos++; _cursorPos++;
} }
return true; return true;
} }
@ -49,24 +49,24 @@ bool ChatEntry::key(unsigned char k) {
void ChatEntry::specialKey(unsigned char k) { void ChatEntry::specialKey(unsigned char k) {
switch (k) { switch (k) {
case GLUT_KEY_LEFT: case GLUT_KEY_LEFT:
if (cursorPos != 0) { if (_cursorPos != 0) {
cursorPos--; _cursorPos--;
} }
break; break;
case GLUT_KEY_RIGHT: case GLUT_KEY_RIGHT:
if (cursorPos != contents.size()) { if (_cursorPos != _contents.size()) {
cursorPos++; _cursorPos++;
} }
break; break;
} }
} }
void ChatEntry::render(int screenWidth, int screenHeight) { void ChatEntry::render(int screenWidth, int screenHeight) {
drawtext(20, screenHeight - 150, 0.10, 0, 1.0, 0, contents.c_str(), 1, 1, 1); drawtext(20, screenHeight - 150, 0.10, 0, 1.0, 0, _contents.c_str(), 1, 1, 1);
float width = 0; float width = 0;
for (string::iterator it = contents.begin(), end = it + cursorPos; it != end; it++) { for (string::iterator it = _contents.begin(), end = it + _cursorPos; it != end; it++) {
width += glutStrokeWidth(GLUT_STROKE_ROMAN, *it)*0.10; width += glutStrokeWidth(GLUT_STROKE_ROMAN, *it)*0.10;
} }
glDisable(GL_LINE_SMOOTH); glDisable(GL_LINE_SMOOTH);

View file

@ -14,7 +14,7 @@
class ChatEntry { class ChatEntry {
public: public:
const std::string& getContents () const { return contents; } const std::string& getContents () const { return _contents; }
void clear (); void clear ();
@ -25,9 +25,8 @@ public:
private: private:
std::string contents; std::string _contents;
int _cursorPos;
int cursorPos;
}; };
#endif /* defined(__interface__ChatEntry__) */ #endif /* defined(__interface__ChatEntry__) */

View file

@ -0,0 +1,93 @@
//
// HandControl.cpp
// interface
//
// Created by Jeffrey Ventrella
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include "HandControl.h"
// this class takes mouse movements normalized within the screen
// dimensions and uses those to determine avatar hand movements, as well
// as states for ramping up and ramping down the amplitude of such movements.
//
// This class might expand to accommodate 3D input devices
//
HandControl::HandControl() {
_enabled = false;
_width = 0;
_height = 0;
_startX = 0;
_startY = 0;
_x = 0;
_y = 0;
_lastX = 0;
_lastY = 0;
_velocityX = 0;
_velocityY = 0;
_rampUpRate = 0.05;
_rampDownRate = 0.02;
_envelope = 0.0f;
}
void HandControl::setScreenDimensions( int width, int height ) {
_width = width;
_height = height;
_startX = _width / 2;
_startY = _height / 2;
}
void HandControl::update( int x, int y ) {
_lastX = _x;
_lastY = _y;
_x = x;
_y = y;
_velocityX = _x - _lastX;
_velocityY = _y - _lastY;
// if the mouse is moving, ramp up the envelope to increase amplitude of hand movement...
if (( _velocityX != 0 )
|| ( _velocityY != 0 )) {
_enabled = true;
if ( _envelope < 1.0 ) {
_envelope += _rampUpRate;
if ( _envelope >= 1.0 ) {
_envelope = 1.0;
}
}
}
// if not enabled ramp down the envelope to decrease amplitude of hand movement...
if ( ! _enabled ) {
if ( _envelope > 0.0 ) {
_envelope -= _rampDownRate;
if ( _envelope <= 0.0 ) {
_startX = _width / 2;
_startY = _height / 2;
_envelope = 0.0;
}
}
}
_leftRight = 0.0;
_downUp = 0.0;
_backFront = 0.0;
// if envelope is greater than zero, apply mouse movement to values to be output
if ( _envelope > 0.0 ) {
_leftRight += ( ( _x - _startX ) / (float)_width ) * _envelope;
_downUp += ( ( _y - _startY ) / (float)_height ) * _envelope;
}
}
glm::vec3 HandControl::getValues() {
return glm::vec3( _leftRight, _downUp, _backFront );
}
void HandControl::stop() {
_enabled = false;
}

View file

@ -0,0 +1,42 @@
//
// HandControl.h
// interface
//
// Created by Jeffrey Ventrella
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__HandControl__
#define __interface__HandControl__
#include <glm/glm.hpp>
class HandControl {
public:
HandControl();
void setScreenDimensions(int width, int height);
void update( int x, int y );
glm::vec3 getValues();
void stop();
private:
bool _enabled;
int _width;
int _height;
int _startX;
int _startY;
int _x;
int _y;
int _lastX;
int _lastY;
int _velocityX;
int _velocityY;
float _rampUpRate;
float _rampDownRate;
float _envelope;
float _leftRight;
float _downUp;
float _backFront;
};
#endif

View file

@ -39,7 +39,7 @@
#include <ifaddrs.h> #include <ifaddrs.h>
#endif #endif
#include <pthread.h> #include <pthread.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
@ -81,16 +81,18 @@
#include <SimpleMovingAverage.h> #include <SimpleMovingAverage.h>
#include "ViewFrustum.h" #include "ViewFrustum.h"
#include "HandControl.h"
using namespace std; using namespace std;
void reshape(int width, int height); // will be defined below void reshape(int width, int height); // will be defined below
void loadViewFrustum(ViewFrustum& viewFrustum); // will be defined below void loadViewFrustum(ViewFrustum& viewFrustum); // will be defined below
bool enableNetworkThread = true;
pthread_t networkReceiveThread; pthread_t networkReceiveThread;
bool stopNetworkReceiveThread = false; bool stopNetworkReceiveThread = false;
unsigned char incomingPacket[MAX_PACKET_SIZE];
int packetCount = 0; int packetCount = 0;
int packetsPerSecond = 0; int packetsPerSecond = 0;
int bytesPerSecond = 0; int bytesPerSecond = 0;
@ -101,6 +103,8 @@ int HEIGHT = 800;
int fullscreen = 0; int fullscreen = 0;
float aspectRatio = 1.0f; float aspectRatio = 1.0f;
bool USING_FIRST_PERSON_EFFECT = false;
bool wantColorRandomizer = true; // for addSphere and load file bool wantColorRandomizer = true; // for addSphere and load file
Oscilloscope audioScope(256,200,true); Oscilloscope audioScope(256,200,true);
@ -163,6 +167,8 @@ int displayField = 0;
int displayHeadMouse = 1; // Display sample mouse pointer controlled by head movement int displayHeadMouse = 1; // Display sample mouse pointer controlled by head movement
int headMouseX, headMouseY; int headMouseX, headMouseY;
HandControl handControl;
int mouseX = 0; int mouseX = 0;
int mouseY = 0; int mouseY = 0;
@ -175,78 +181,6 @@ int menuOn = 1; // Whether to show onscreen menu
ChatEntry chatEntry; // chat entry field ChatEntry chatEntry; // chat entry field
bool chatEntryOn = false; // Whether to show the chat entry bool chatEntryOn = false; // Whether to show the chat entry
struct HandController
{
bool enabled;
int startX;
int startY;
int x;
int y;
int lastX;
int lastY;
int velocityX;
int velocityY;
float rampUpRate;
float rampDownRate;
float envelope;
};
HandController handController;
void initializeHandController() {
handController.enabled = false;
handController.startX = WIDTH / 2;
handController.startY = HEIGHT / 2;
handController.x = 0;
handController.y = 0;
handController.lastX = 0;
handController.lastY = 0;
handController.velocityX = 0;
handController.velocityY = 0;
handController.rampUpRate = 0.05;
handController.rampDownRate = 0.02;
handController.envelope = 0.0f;
}
void updateHandController( int x, int y ) {
handController.lastX = handController.x;
handController.lastY = handController.y;
handController.x = x;
handController.y = y;
handController.velocityX = handController.x - handController.lastX;
handController.velocityY = handController.y - handController.lastY;
if (( handController.velocityX != 0 )
|| ( handController.velocityY != 0 )) {
handController.enabled = true;
myAvatar.startHandMovement();
if ( handController.envelope < 1.0 ) {
handController.envelope += handController.rampUpRate;
if ( handController.envelope >= 1.0 ) {
handController.envelope = 1.0;
}
}
}
if ( ! handController.enabled ) {
if ( handController.envelope > 0.0 ) {
handController.envelope -= handController.rampDownRate;
if ( handController.envelope <= 0.0 ) {
handController.startX = WIDTH / 2;
handController.startY = HEIGHT / 2;
handController.envelope = 0.0;
}
}
}
if ( handController.envelope > 0.0 ) {
float leftRight = ( ( handController.x - handController.startX ) / (float)WIDTH ) * handController.envelope;
float downUp = ( ( handController.y - handController.startY ) / (float)HEIGHT ) * handController.envelope;
float backFront = 0.0;
myAvatar.setHandMovementValues( glm::vec3( leftRight, downUp, backFront ) );
}
}
// //
@ -380,7 +314,7 @@ void init(void)
voxels.setViewerAvatar(&myAvatar); voxels.setViewerAvatar(&myAvatar);
myAvatar.setRenderYaw(startYaw); myAvatar.setRenderYaw(startYaw);
initializeHandController(); handControl.setScreenDimensions(WIDTH, HEIGHT);
headMouseX = WIDTH/2; headMouseX = WIDTH/2;
headMouseY = HEIGHT/2; headMouseY = HEIGHT/2;
@ -420,8 +354,11 @@ void terminate () {
#ifndef _WIN32 #ifndef _WIN32
audio.terminate(); audio.terminate();
#endif #endif
stopNetworkReceiveThread = true;
pthread_join(networkReceiveThread, NULL); if (enableNetworkThread) {
stopNetworkReceiveThread = true;
pthread_join(networkReceiveThread, NULL);
}
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
@ -805,47 +742,48 @@ void display(void)
myCamera.setTightness ( 100.0f ); myCamera.setTightness ( 100.0f );
} else { } else {
// float firstPersonPitch = 20.0f; float firstPersonPitch = 20.0f;
// float firstPersonUpShift = 0.1f; float firstPersonUpShift = 0.1f;
// float firstPersonDistance = 0.0f; float firstPersonDistance = 0.0f;
// float firstPersonT ightness = 100.0f; float firstPersonTightness = 100.0f;
float thirdPersonPitch = 0.0f; float thirdPersonPitch = 0.0f;
float thirdPersonUpShift = -0.1f; float thirdPersonUpShift = -0.1f;
float thirdPersonDistance = 1.f; float thirdPersonDistance = 1.f;
float thirdPersonTightness = 8.0f; float thirdPersonTightness = 8.0f;
myCamera.setPitch (thirdPersonPitch ); if ( USING_FIRST_PERSON_EFFECT ) {
myCamera.setUpShift (thirdPersonUpShift ); if ( myAvatar.getSpeed() < 0.02 ) {
myCamera.setDistance (thirdPersonDistance );
myCamera.setTightness(thirdPersonTightness);
/*
if ( myAvatar.getSpeed() < 0.02 ) {
if (myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) {
myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
}
printf( "myCamera.getModeShift() = %f\n", myCamera.getModeShift()); if (myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) {
myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
}
printf( "myCamera.getModeShift() = %f\n", myCamera.getModeShift());
myCamera.setPitch ( thirdPersonPitch + myCamera.getModeShift() * ( firstPersonPitch - thirdPersonPitch )); myCamera.setPitch ( thirdPersonPitch + myCamera.getModeShift() * ( firstPersonPitch - thirdPersonPitch ));
myCamera.setUpShift ( thirdPersonUpShift + myCamera.getModeShift() * ( firstPersonUpShift - thirdPersonUpShift )); myCamera.setUpShift ( thirdPersonUpShift + myCamera.getModeShift() * ( firstPersonUpShift - thirdPersonUpShift ));
myCamera.setDistance ( thirdPersonDistance + myCamera.getModeShift() * ( firstPersonDistance - thirdPersonDistance )); myCamera.setDistance ( thirdPersonDistance + myCamera.getModeShift() * ( firstPersonDistance - thirdPersonDistance ));
myCamera.setTightness ( thirdPersonTightness + myCamera.getModeShift() * ( firstPersonTightness - thirdPersonTightness )); myCamera.setTightness ( thirdPersonTightness + myCamera.getModeShift() * ( firstPersonTightness - thirdPersonTightness ));
} else { } else {
if (myCamera.getMode() != CAMERA_MODE_THIRD_PERSON ) { if (myCamera.getMode() != CAMERA_MODE_THIRD_PERSON ) {
myCamera.setMode(CAMERA_MODE_THIRD_PERSON); myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
}
printf( "myCamera.getModeShift() = %f\n", myCamera.getModeShift());
myCamera.setPitch ( firstPersonPitch + myCamera.getModeShift() * ( thirdPersonPitch - firstPersonPitch ));
myCamera.setUpShift ( firstPersonUpShift + myCamera.getModeShift() * ( thirdPersonUpShift - firstPersonUpShift ));
myCamera.setDistance ( firstPersonDistance + myCamera.getModeShift() * ( thirdPersonDistance - firstPersonDistance ));
myCamera.setTightness ( firstPersonTightness + myCamera.getModeShift() * ( thirdPersonTightness - firstPersonTightness ));
} }
} else {
printf( "myCamera.getModeShift() = %f\n", myCamera.getModeShift()); myCamera.setPitch (thirdPersonPitch );
myCamera.setUpShift (thirdPersonUpShift );
myCamera.setPitch ( firstPersonPitch + myCamera.getModeShift() * ( thirdPersonPitch - firstPersonPitch )); myCamera.setDistance (thirdPersonDistance );
myCamera.setUpShift ( firstPersonUpShift + myCamera.getModeShift() * ( thirdPersonUpShift - firstPersonUpShift )); myCamera.setTightness(thirdPersonTightness);
myCamera.setDistance ( firstPersonDistance + myCamera.getModeShift() * ( thirdPersonDistance - firstPersonDistance ));
myCamera.setTightness ( firstPersonTightness + myCamera.getModeShift() * ( thirdPersonTightness - firstPersonTightness ));
} }
*/
myCamera.setTargetPosition( myAvatar.getHeadPosition() ); myCamera.setTargetPosition( myAvatar.getHeadPosition() );
myCamera.setTargetYaw ( 180.0 - myAvatar.getBodyYaw() ); myCamera.setTargetYaw ( 180.0 - myAvatar.getBodyYaw() );
myCamera.setRoll ( 0.0 ); myCamera.setRoll ( 0.0 );
@ -1378,7 +1316,7 @@ void specialkey(int k, int x, int y)
void keyUp(unsigned char k, int x, int y) { void keyUp(unsigned char k, int x, int y) {
if (::chatEntryOn) { if (::chatEntryOn) {
myAvatar.setKeyState(AvatarData::NoKeyDown); myAvatar.setKeyState(NO_KEY_DOWN);
return; return;
} }
@ -1396,7 +1334,7 @@ void key(unsigned char k, int x, int y)
if (::chatEntryOn) { if (::chatEntryOn) {
if (chatEntry.key(k)) { if (chatEntry.key(k)) {
myAvatar.setKeyState(k == '\b' || k == 127 ? // backspace or delete myAvatar.setKeyState(k == '\b' || k == 127 ? // backspace or delete
AvatarData::DeleteKeyDown : AvatarData::InsertKeyDown); DELETE_KEY_DOWN : INSERT_KEY_DOWN);
myAvatar.setChatMessage(string(chatEntry.getContents().size(), 'X')); myAvatar.setChatMessage(string(chatEntry.getContents().size(), 'X'));
} else { } else {
@ -1475,18 +1413,17 @@ void key(unsigned char k, int x, int y)
if (k == '\r') { if (k == '\r') {
::chatEntryOn = true; ::chatEntryOn = true;
myAvatar.setKeyState(AvatarData::NoKeyDown); myAvatar.setKeyState(NO_KEY_DOWN);
myAvatar.setChatMessage(string()); myAvatar.setChatMessage(string());
} }
} }
// Receive packets from other agents/servers and decide what to do with them! // Receive packets from other agents/servers and decide what to do with them!
void *networkReceive(void *args) void* networkReceive(void* args)
{ {
sockaddr senderAddress; sockaddr senderAddress;
ssize_t bytesReceived; ssize_t bytesReceived;
unsigned char *incomingPacket = new unsigned char[MAX_PACKET_SIZE];
while (!stopNetworkReceiveThread) { while (!stopNetworkReceiveThread) {
if (AgentList::getInstance()->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) { if (AgentList::getInstance()->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
packetCount++; packetCount++;
@ -1510,12 +1447,15 @@ void *networkReceive(void *args)
AgentList::getInstance()->processAgentData(&senderAddress, incomingPacket, bytesReceived); AgentList::getInstance()->processAgentData(&senderAddress, incomingPacket, bytesReceived);
break; break;
} }
} else if (!enableNetworkThread) {
break;
} }
} }
delete[] incomingPacket; if (enableNetworkThread) {
pthread_exit(0); pthread_exit(0);
return NULL; }
return NULL;
} }
void idle(void) { void idle(void) {
@ -1528,8 +1468,10 @@ void idle(void) {
float deltaTime = 1.f/FPS; float deltaTime = 1.f/FPS;
// update behaviors for avatar hand movement // update behaviors for avatar hand movement: handControl takes mouse values as input,
updateHandController( mouseX, mouseY ); // and gives back 3D values modulated for smooth transitioning between interaction modes.
handControl.update( mouseX, mouseY );
myAvatar.setHandMovementValues( handControl.getValues() );
// tell my avatar if the mouse is being pressed... // tell my avatar if the mouse is being pressed...
if ( mousePressed == 1 ) { if ( mousePressed == 1 ) {
@ -1539,15 +1481,20 @@ void idle(void) {
myAvatar.setMousePressed( false ); myAvatar.setMousePressed( false );
} }
// walking triggers the handController to stop // walking triggers the handControl to stop
if ( myAvatar.getMode() == AVATAR_MODE_WALKING ) { if ( myAvatar.getMode() == AVATAR_MODE_WALKING ) {
handController.enabled = false; handControl.stop();
} }
// //
// Sample hardware, update view frustum if needed, Lsend avatar data to mixer/agents // Sample hardware, update view frustum if needed, Lsend avatar data to mixer/agents
// //
updateAvatar(deltaTime); updateAvatar(deltaTime);
// read incoming packets from network
if (!enableNetworkThread) {
networkReceive(0);
}
//loop through all the other avatars and simulate them... //loop through all the other avatars and simulate them...
AgentList* agentList = AgentList::getInstance(); AgentList* agentList = AgentList::getInstance();
@ -1720,7 +1667,12 @@ int main(int argc, const char * argv[])
listenPort = atoi(portStr); listenPort = atoi(portStr);
} }
AgentList::createInstance(AGENT_TYPE_AVATAR, listenPort); AgentList::createInstance(AGENT_TYPE_AVATAR, listenPort);
enableNetworkThread = !cmdOptionExists(argc, argv, "--nonblocking");
if (!enableNetworkThread) {
AgentList::getInstance()->getAgentSocket().setBlocking(false);
}
gettimeofday(&applicationStartupTime, NULL); gettimeofday(&applicationStartupTime, NULL);
const char* domainIP = getCmdOption(argc, argv, "--domain"); const char* domainIP = getCmdOption(argc, argv, "--domain");
if (domainIP) { if (domainIP) {
@ -1803,8 +1755,10 @@ int main(int argc, const char * argv[])
} }
// create thread for receipt of data via UDP // create thread for receipt of data via UDP
pthread_create(&networkReceiveThread, NULL, networkReceive, NULL); if (enableNetworkThread) {
printLog("Network receive thread created.\n"); pthread_create(&networkReceiveThread, NULL, networkReceive, NULL);
printLog("Network receive thread created.\n");
}
glutTimerFunc(1000, Timer, 0); glutTimerFunc(1000, Timer, 0);
glutMainLoop(); glutMainLoop();

View file

@ -51,7 +51,7 @@ AvatarData::AvatarData() :
_cameraAspectRatio(0.0f), _cameraAspectRatio(0.0f),
_cameraNearClip(0.0f), _cameraNearClip(0.0f),
_cameraFarClip(0.0f), _cameraFarClip(0.0f),
_keyState(NoKeyDown) { _keyState(NO_KEY_DOWN) {
} }

View file

@ -15,6 +15,13 @@
#include <AgentData.h> #include <AgentData.h>
enum KeyState
{
NO_KEY_DOWN,
INSERT_KEY_DOWN,
DELETE_KEY_DOWN
};
class AvatarData : public AgentData { class AvatarData : public AgentData {
public: public:
AvatarData(); AvatarData();
@ -76,8 +83,6 @@ public:
void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; } void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; }
void setCameraFarClip(float farClip) { _cameraFarClip = farClip; } void setCameraFarClip(float farClip) { _cameraFarClip = farClip; }
enum KeyState { NoKeyDown, InsertKeyDown, DeleteKeyDown };
// key state // key state
void setKeyState(KeyState s) { _keyState = s; } void setKeyState(KeyState s) { _keyState = s; }
KeyState keyState() const { return _keyState; } KeyState keyState() const { return _keyState; }
@ -118,7 +123,7 @@ protected:
float _cameraNearClip; float _cameraNearClip;
float _cameraFarClip; float _cameraFarClip;
// key state (nothing, down, up, backspace) // key state
KeyState _keyState; KeyState _keyState;
// chat message // chat message

View file

@ -119,7 +119,7 @@ unsigned short loadBufferWithSocketInfo(char *addressBuffer, sockaddr *socket) {
} }
} }
UDPSocket::UDPSocket(int listeningPort) { UDPSocket::UDPSocket(int listeningPort) : blocking(true) {
init(); init();
// create the socket // create the socket
handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
@ -191,6 +191,18 @@ bool UDPSocket::init() {
return true; return true;
} }
void UDPSocket::setBlocking(bool blocking) {
this->blocking = blocking;
#ifdef _WIN32
u_long mode = blocking ? 0 : 1;
ioctlsocket(handle, FIONBIO, &mode);
#else
int flags = fcntl(handle, F_GETFL, 0);
fcntl(handle, F_SETFL, blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK));
#endif
}
// Receive data on this socket with retrieving address of sender // Receive data on this socket with retrieving address of sender
bool UDPSocket::receive(void *receivedData, ssize_t *receivedBytes) { bool UDPSocket::receive(void *receivedData, ssize_t *receivedBytes) {

View file

@ -23,12 +23,15 @@ class UDPSocket {
UDPSocket(int listening_port); UDPSocket(int listening_port);
~UDPSocket(); ~UDPSocket();
bool init(); bool init();
void setBlocking(bool blocking);
bool isBlocking() { return blocking; }
int send(sockaddr *destAddress, const void *data, size_t byteLength); int send(sockaddr *destAddress, const void *data, size_t byteLength);
int send(char *destAddress, int destPort, const void *data, size_t byteLength); int send(char *destAddress, int destPort, const void *data, size_t byteLength);
bool receive(void *receivedData, ssize_t *receivedBytes); bool receive(void *receivedData, ssize_t *receivedBytes);
bool receive(sockaddr *recvAddress, void *receivedData, ssize_t *receivedBytes); bool receive(sockaddr *recvAddress, void *receivedData, ssize_t *receivedBytes);
private: private:
int handle; int handle;
bool blocking;
}; };
bool socketMatch(sockaddr *first, sockaddr *second); bool socketMatch(sockaddr *first, sockaddr *second);