From 1e58f6fd40f1395b585d17cf52ee0d9f6f73cd33 Mon Sep 17 00:00:00 2001 From: tosh Date: Thu, 18 Apr 2013 20:02:24 +0200 Subject: [PATCH 01/52] fixes upside down aspect ratio --- interface/src/starfield/renderer/Renderer.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/starfield/renderer/Renderer.h b/interface/src/starfield/renderer/Renderer.h index a09226ed85..5148c5fa01 100644 --- a/interface/src/starfield/renderer/Renderer.h +++ b/interface/src/starfield/renderer/Renderer.h @@ -133,14 +133,14 @@ namespace starfield { // determine dimensions based on a sought screen diagonal // // ww + hh = dd - // a = h / w => h = wa - // ww + ww aa = dd - // ww = dd / (1 + aa) + // a = w / h => w = ha + // hh + hh aa = dd + // hh = dd / (1 + aa) float diag = 2.0f * std::sin(halfPersp); float nearClip = std::cos(halfPersp); - float hw = 0.5f * sqrt(diag * diag / (1.0f + aspect * aspect)); - float hh = hw * aspect; + float hh = 0.5f * sqrt(diag * diag / (1.0f + aspect * aspect)); + float hw = hh * aspect; // cancel all translation mat4 matrix = orientation; From 715534154e02ab5f7567f2bbef0b70a87ec5c577 Mon Sep 17 00:00:00 2001 From: tosh Date: Fri, 19 Apr 2013 02:46:34 +0200 Subject: [PATCH 02/52] numerous starfield fixes --- interface/src/Stars.cpp | 12 ++- interface/src/Stars.h | 80 +++++++-------- interface/src/main.cpp | 7 +- interface/src/starfield/renderer/Renderer.h | 105 ++++++++++++-------- interface/src/starfield/renderer/Tiling.h | 3 +- libraries/shared/src/FloodFill.h | 101 ++++++++----------- 6 files changed, 164 insertions(+), 144 deletions(-) diff --git a/interface/src/Stars.cpp b/interface/src/Stars.cpp index 97d68bc61d..a049269305 100644 --- a/interface/src/Stars.cpp +++ b/interface/src/Stars.cpp @@ -34,7 +34,17 @@ float Stars::changeLOD(float fraction, float overalloc, float realloc) { return float(_ptrController->changeLOD(fraction, overalloc, realloc)); } -void Stars::render(float fovDiagonal, float aspect, glm::mat4 const& view) { +void Stars::render(float fovY, float aspect, float nearZ) { + + // determine length of screen diagonal from quadrant height and aspect ratio + float quadrantHeight = nearZ * tan(angleConvert(fovY) * 0.5f); + float halfDiagonal = sqrt(quadrantHeight * quadrantHeight * (1.0f + aspect * aspect)); + + // determine fov angle in respect to the diagonal + float fovDiagonal = atan(halfDiagonal / nearZ) * 2.0f; + + // pull the modelview matrix off the GL stack + glm::mat4 view; glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(view)); _ptrController->render(fovDiagonal, aspect, glm::affineInverse(view)); } diff --git a/interface/src/Stars.h b/interface/src/Stars.h index 92c7b0f806..caca215444 100644 --- a/interface/src/Stars.h +++ b/interface/src/Stars.h @@ -13,9 +13,9 @@ namespace starfield { class Controller; } -/** - * Starfield rendering component. - */ +// +// Starfield rendering component. +// class Stars { starfield::Controller* _ptrController; @@ -25,49 +25,49 @@ class Stars { Stars(); ~Stars(); - /** - * Reads input file from URL. Returns true upon success. - * - * The limit parameter allows to reduce the number of stars - * that are loaded, keeping the brightest ones. - */ + // + // Reads input file from URL. Returns true upon success. + // + // The limit parameter allows to reduce the number of stars + // that are loaded, keeping the brightest ones. + // bool readInput(const char* url, const char* cacheFile = 0l, unsigned limit = 200000); - /** - * Renders the starfield from a local viewer's perspective. - * The parameter specifies the field of view. - */ - void render(float fovDiagonal, float aspect, glm::mat4 const& view); + // + // Renders the starfield from a local viewer's perspective. + // The parameters specifiy the field of view. + // + void render(float fovY, float aspect, float nearZ); - /** - * Sets the resolution for FOV culling. - * - * The parameter determines the number of tiles in azimuthal - * and altitudinal directions. - * - * GPU resources are updated upon change in which case 'true' - * is returned. - */ + // + // Sets the resolution for FOV culling. + // + // The parameter determines the number of tiles in azimuthal + // and altitudinal directions. + // + // GPU resources are updated upon change in which case 'true' + // is returned. + // bool setResolution(unsigned k); - /** - * Allows to alter the number of stars to be rendered given a - * factor. The least brightest ones are omitted first. - * - * The further parameters determine when GPU resources should - * be reallocated. Its value is fractional in respect to the - * last number of stars 'n' that caused 'n * (1+overalloc)' to - * be allocated. When the next call to setLOD causes the total - * number of stars that could be rendered to drop below 'n * - * (1-realloc)' or rises above 'n * (1+realloc)' GPU resources - * are updated. Note that all parameters must be fractions, - * that is within the range [0;1] and that 'overalloc' must be - * greater than or equal to 'realloc'. - * - * The current level of detail is returned as a float in [0;1]. - */ + // + // Allows to alter the number of stars to be rendered given a + // factor. The least brightest ones are omitted first. + // + // The further parameters determine when GPU resources should + // be reallocated. Its value is fractional in respect to the + // last number of stars 'n' that caused 'n * (1+overalloc)' to + // be allocated. When the next call to setLOD causes the total + // number of stars that could be rendered to drop below 'n * + // (1-realloc)' or rises above 'n * (1+realloc)' GPU resources + // are updated. Note that all parameters must be fractions, + // that is within the range [0;1] and that 'overalloc' must be + // greater than or equal to 'realloc'. + // + // The current level of detail is returned as a float in [0;1]. + // float changeLOD(float factor, - float overalloc = 0.25, float realloc = 0.15); + float overalloc = 0.25, float realloc = 0.15); private: // don't copy/assign diff --git a/interface/src/main.cpp b/interface/src/main.cpp index c44aeea168..a413a0cedf 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -762,9 +762,10 @@ void display(void) if (::starsOn) { // should be the first rendering pass - w/o depth buffer / lighting - glm::mat4 view; - glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(view)); - stars.render(angleConvert(whichCamera.getFieldOfView()), aspectRatio, view); + + // finally render the starfield + stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip()); + } glEnable(GL_LIGHTING); diff --git a/interface/src/starfield/renderer/Renderer.h b/interface/src/starfield/renderer/Renderer.h index 5148c5fa01..c0ffff2ce2 100644 --- a/interface/src/starfield/renderer/Renderer.h +++ b/interface/src/starfield/renderer/Renderer.h @@ -130,16 +130,17 @@ namespace starfield { float halfPersp = perspective * 0.5f; - // determine dimensions based on a sought screen diagonal + // define diagonal and near distance + float halfDiag = std::sin(halfPersp); + float nearClip = std::cos(halfPersp); + + // determine half dimensions based on the screen diagonal // // ww + hh = dd // a = w / h => w = ha // hh + hh aa = dd // hh = dd / (1 + aa) - float diag = 2.0f * std::sin(halfPersp); - float nearClip = std::cos(halfPersp); - - float hh = 0.5f * sqrt(diag * diag / (1.0f + aspect * aspect)); + float hh = sqrt(halfDiag * halfDiag / (1.0f + aspect * aspect)); float hw = hh * aspect; // cancel all translation @@ -154,32 +155,34 @@ namespace starfield { float azimuth = atan2(ahead.x,-ahead.z) + Radians::pi(); float altitude = atan2(-ahead.y, hypotf(ahead.x, ahead.z)); angleHorizontalPolar(azimuth, altitude); + float const eps = 0.002f; + altitude = glm::clamp(altitude, + -Radians::halfPi() + eps, Radians::halfPi() - eps); #if STARFIELD_HEMISPHERE_ONLY altitude = std::max(0.0f, altitude); #endif - unsigned tileIndex = - _objTiling.getTileIndex(azimuth, altitude); - // fprintf(stderr, "Stars.cpp: starting on tile #%d\n", tileIndex); #if STARFIELD_DEBUG_CULLING - mat4 matrix_debug = glm::translate( - glm::frustum(-hw, hw, -hh, hh, nearClip, 10.0f), - vec3(0.0f, 0.0f, -4.0f)) * glm::affineInverse(matrix); + mat4 matrix_debug = glm::translate(glm::frustum(-hw, hw, -hh, hh, nearClip, 10.0f), + vec3(0.0f, 0.0f, -4.0f)) * + glm::affineInverse(matrix); #endif - matrix = glm::frustum(-hw,hw, -hh,hh, nearClip,10.0f) - * glm::affineInverse(matrix); + matrix = glm::frustum(-hw,hw, -hh,hh, nearClip,10.0f) * glm::affineInverse(matrix); this->_itrOutIndex = (unsigned*) _arrBatchOffs; this->_vecWxform = vec3(row(matrix, 3)); this->_valHalfPersp = halfPersp; this->_valMinBright = minBright; - floodFill(_arrTile + tileIndex, TileSelection(*this, - _arrTile, _arrTile + _objTiling.getTileCount(), - (Tile**) _arrBatchCount)); + TileSelection::Cursor cursor; + cursor.current = _arrTile + _objTiling.getTileIndex(azimuth, altitude); + cursor.firstInRow = _arrTile + _objTiling.getTileIndex(0.0f, altitude); + + floodFill(cursor, TileSelection(*this, _arrTile, _arrTile + _objTiling.getTileCount(), + (TileSelection::Cursor*) _arrBatchCount)); #if STARFIELD_DEBUG_CULLING # define matrix matrix_debug @@ -269,31 +272,35 @@ namespace starfield { class TileSelection { + public: + struct Cursor { Tile* current, * firstInRow; }; + private: Renderer& _refRenderer; - Tile** const _arrStack; - Tile** _itrStack; + Cursor* const _arrStack; + Cursor* _itrStack; Tile const* const _arrTile; - Tile const* const _itrTilesEnd; + Tile const* const _ptrTilesEnd; public: TileSelection(Renderer& renderer, Tile const* tiles, - Tile const* tiles_end, Tile** stack) : + Tile const* tiles_end, Cursor* stack) : _refRenderer(renderer), _arrStack(stack), _itrStack(stack), _arrTile(tiles), - _itrTilesEnd(tiles_end) { + _ptrTilesEnd(tiles_end) { } protected: // flood fill strategy - bool select(Tile* t) { + bool select(Cursor const& c) { + Tile* t = c.current; - if (t < _arrTile || t >= _itrTilesEnd || + if (t < _arrTile || t >= _ptrTilesEnd || !! (t->flags & Tile::checked)) { // out of bounds or been here already @@ -311,7 +318,8 @@ namespace starfield { return false; } - bool process(Tile* t) { + bool process(Cursor const& c) { + Tile* t = c.current; if (! (t->flags & Tile::visited)) { @@ -321,14 +329,39 @@ namespace starfield { return false; } - void right(Tile*& cursor) const { cursor += 1; } - void left(Tile*& cursor) const { cursor -= 1; } - void up(Tile*& cursor) const { cursor += yStride(); } - void down(Tile*& cursor) const { cursor -= yStride(); } + void right(Cursor& c) const { - void defer(Tile* t) { *_itrStack++ = t; } + c.current += 1; + if (c.current == c.firstInRow + _refRenderer._objTiling.getAzimuthalTiles()) { + c.current = c.firstInRow; + } + } + void left(Cursor& c) const { + + if (c.current == c.firstInRow) { + c.current = c.firstInRow + _refRenderer._objTiling.getAzimuthalTiles(); + } + c.current -= 1; + } + void up(Cursor& c) const { - bool deferred(Tile*& cursor) { + unsigned d = _refRenderer._objTiling.getAzimuthalTiles(); + c.current += d; + c.firstInRow += d; + } + void down(Cursor& c) const { + + unsigned d = _refRenderer._objTiling.getAzimuthalTiles(); + c.current -= d; + c.firstInRow -= d; + } + + void defer(Cursor const& t) { + + *_itrStack++ = t; + } + + bool deferred(Cursor& cursor) { if (_itrStack != _arrStack) { cursor = *--_itrStack; @@ -336,12 +369,6 @@ namespace starfield { } return false; } - - private: - unsigned yStride() const { - - return _refRenderer._objTiling.getAzimuthalTiles(); - } }; bool visitTile(Tile* t) { @@ -362,6 +389,7 @@ namespace starfield { bool tileVisible(Tile* t, unsigned i) { float slice = _objTiling.getSliceAngle(); + float halfSlice = 0.5f * slice; unsigned stride = _objTiling.getAzimuthalTiles(); float azimuth = (i % stride) * slice; float altitude = (i / stride) * slice - Radians::halfPi(); @@ -371,14 +399,13 @@ namespace starfield { vec3 tileCenter = vec3(gx * exz, sin(altitude), gz * exz); float w = dot(_vecWxform, tileCenter); - float halfSlice = 0.5f * slice; - float daz = halfSlice * cos(abs(altitude) - halfSlice); + float daz = halfSlice * cos(std::max(0.0f, abs(altitude) - halfSlice)); float dal = halfSlice; float adjustedNear = cos(_valHalfPersp + sqrt(daz * daz + dal * dal)); // fprintf(stderr, "Stars.cpp: checking tile #%d, w = %f, near = %f\n", i, w, nearClip); - return w > adjustedNear; + return w >= adjustedNear; } void updateVertexCount(Tile* t, BrightnessLevel minBright) { diff --git a/interface/src/starfield/renderer/Tiling.h b/interface/src/starfield/renderer/Tiling.h index 1df4dd1956..56df23f30c 100644 --- a/interface/src/starfield/renderer/Tiling.h +++ b/interface/src/starfield/renderer/Tiling.h @@ -1,5 +1,5 @@ // -// starfield/renderer/ +// starfield/renderer/Tiling.h // interface // // Created by Tobias Schwinger on 3/22/13. @@ -51,6 +51,7 @@ namespace starfield { private: unsigned discreteAngle(float unsigned_angle) const { + return unsigned(floor(unsigned_angle * _valRcpSlice + 0.5f)); } diff --git a/libraries/shared/src/FloodFill.h b/libraries/shared/src/FloodFill.h index 273c1c4f6e..40a89bfd1b 100644 --- a/libraries/shared/src/FloodFill.h +++ b/libraries/shared/src/FloodFill.h @@ -9,32 +9,31 @@ #ifndef __hifi__FloodFill__ #define __hifi__FloodFill__ -/** - * Line scanning, iterative flood fill algorithm. - * - * The strategy must obey the following contract: - * - * There is an associated cursor that represents a position on the image. - * The member functions 'left(C&)', 'right(C&)', 'up(C&)', and 'down(C&)' - * move it. - * The state of a cursor can be deferred to temporary storage (typically a - * stack or a queue) using the 'defer(C const&)' member function. - * Calling 'deferred(C&)' restores a cursor's state from temporary storage - * and removes it there. - * The 'select(C const&)' and 'process(C const&)' functions control the - * algorithm. The former is called to determine where to go. It may be - * called multiple times but does not have to (and should not) return - * 'true' more than once for a pixel to be selected (will cause memory - * overuse, otherwise). The latter will never be called for a given pixel - * unless previously selected. It may be called multiple times, in which - * case it should return 'true' upon successful processing and 'false' - * when an already processed pixel has been visited. - * - * Note: The terms "image" and "pixel" are used for illustratory purposes - * and mean "undirected graph with 4-connected 2D grid topology" and "node", - * respectively. - * - */ +// +// Line scanning, iterative flood fill algorithm. +// +// The strategy must obey the following contract: +// +// There is an associated cursor that represents a position on the image. +// The member functions 'left(C&)', 'right(C&)', 'up(C&)', and 'down(C&)' +// move it. +// The state of a cursor can be deferred to temporary storage (typically a +// stack or a queue) using the 'defer(C const&)' member function. +// Calling 'deferred(C&)' restores a cursor's state from temporary storage +// and removes it there. +// The 'select(C const&)' and 'process(C const&)' functions control the +// algorithm. The former is called to determine where to go. It may be +// called multiple times but does not have to (and should not) return +// 'true' more than once for a pixel to be selected (will cause memory +// overuse, otherwise). The latter will never be called for a given pixel +// unless previously selected. It may be called multiple times, in which +// case it should return 'true' upon successful processing and 'false' +// when an already processed pixel has been visited. +// +// Note: The terms "image" and "pixel" are used for illustratory purposes +// and mean "undirected graph with 4-connected 2D grid topology" and "node", +// respectively. +// template< class Strategy, typename Cursor > void floodFill(Cursor const& position, Strategy const& strategy = Strategy()); @@ -63,57 +62,39 @@ struct floodFill_impl : Strategy { } Cursor higher, lower, h,l, i; - bool higherFound, lowerFound, hf, lf; do { if (! process(position)) { continue; } - higher = position; higherFound = false; - up(higher); yTest(higher, higherFound); - lower = position; lowerFound = false; - down(lower); yTest(lower, lowerFound); + higher = position; + up(higher); + if (select(higher)) { defer(higher); } + + lower = position; + down(lower); + if (select(lower)) { defer(lower); } i = position, h = higher, l = lower; - hf = higherFound, lf = lowerFound; do { - right(i), right(h), right(l); yTest(h,hf); yTest(l,lf); - } while (selectAndProcess(i)); + right(i), right(h), right(l); + if (select(h)) { defer(h); } + if (select(l)) { defer(l); } + + } while (select(i) && process(i)); i = position, h = higher, l = lower; - hf = higherFound, lf = lowerFound; do { - left(i); left(h); left(l); yTest(h,hf); yTest(l,lf); + left(i); left(h); left(l); + if (select(h)) { defer(h); } + if (select(l)) { defer(l); } - } while (selectAndProcess(i)); + } while (select(i) && process(i)); } while (deferred(position)); } - - bool selectAndProcess(Cursor const& i) { - - if (select(i)) { - - process(i); - return true; - } - return false; - } - - void yTest(Cursor const& i, bool& state) { - - if (! select(i)) { - - state = false; - - } else if (! state) { - - state = true; - defer(i); - } - } }; template< class Strategy, typename Cursor > From beee875e88069d7e29777998999e888f9c588330 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 10:46:05 -0700 Subject: [PATCH 03/52] add a new AudioInjector class that can be leveraged from eve and injector --- libraries/shared/src/AudioInjector.cpp | 83 ++++++++++++++++++++++++++ libraries/shared/src/AudioInjector.h | 35 +++++++++++ 2 files changed, 118 insertions(+) create mode 100644 libraries/shared/src/AudioInjector.cpp create mode 100644 libraries/shared/src/AudioInjector.h diff --git a/libraries/shared/src/AudioInjector.cpp b/libraries/shared/src/AudioInjector.cpp new file mode 100644 index 0000000000..fac26a78cf --- /dev/null +++ b/libraries/shared/src/AudioInjector.cpp @@ -0,0 +1,83 @@ +// +// AudioInjector.cpp +// hifi +// +// Created by Stephen Birarda on 4/23/13. +// +// + +#include +#include + +#include "SharedUtil.h" +#include "PacketHeaders.h" + +#include "AudioInjector.h" + +const int BUFFER_LENGTH_BYTES = 512; +const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t); +const float SAMPLE_RATE = 22050.0; +const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES / SAMPLE_RATE) * 1000000; + +AudioInjector::AudioInjector(const char* filename) : + _bearing(0), + _attenuationModifier(255) +{ + _position[0] = 0.0f; + _position[1] = 0.0f; + _position[2] = 0.0f; + + std::fstream sourceFile; + + sourceFile.open(filename, std::ios::in | std::ios::binary); + sourceFile.seekg(0, std::ios::end); + + _numTotalBytesAudio = sourceFile.tellg(); + sourceFile.seekg(0, std::ios::beg); + long sizeOfShortArray = _numTotalBytesAudio / 2; + _audioSampleArray = new int16_t[sizeOfShortArray]; + + sourceFile.read((char *)_audioSampleArray, _numTotalBytesAudio); +} + +AudioInjector::~AudioInjector() { + delete[] _audioSampleArray; +} + +void AudioInjector::setPosition(float* position) { + _position[0] = position[0]; + _position[1] = position[1]; + _position[2] = position[2]; +} + +void AudioInjector::injectAudio(UDPSocket *injectorSocket, sockaddr *destinationSocket) { + timeval startTime; + + // one byte for header, 3 positional floats, 1 bearing float, 1 attenuation modifier byte + int leadingBytes = 1 + (sizeof(float) * 4) + 1; + unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes]; + + dataPacket[0] = PACKET_HEADER_INJECT_AUDIO; + unsigned char *currentPacketPtr = dataPacket + 1; + + for (int i = 0; i < 3; i++) { + memcpy(currentPacketPtr, &_position[i], sizeof(float)); + currentPacketPtr += sizeof(float); + } + + memcpy(currentPacketPtr, &_bearing, sizeof(float)); + currentPacketPtr += sizeof(float); + + *currentPacketPtr = _attenuationModifier; + currentPacketPtr++; + + for (int i = 0; i < _numTotalBytesAudio; i += BUFFER_LENGTH_SAMPLES) { + gettimeofday(&startTime, NULL); + + memcpy(currentPacketPtr, _audioSampleArray + i, BUFFER_LENGTH_BYTES); + injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket)); + + double usecToSleep = usecTimestamp(&startTime) + BUFFER_SEND_INTERVAL_USECS - usecTimestampNow(); + usleep(usecToSleep); + } +} diff --git a/libraries/shared/src/AudioInjector.h b/libraries/shared/src/AudioInjector.h new file mode 100644 index 0000000000..2456a95c57 --- /dev/null +++ b/libraries/shared/src/AudioInjector.h @@ -0,0 +1,35 @@ +// +// AudioInjector.h +// hifi +// +// Created by Stephen Birarda on 4/23/13. +// +// + +#ifndef __hifi__AudioInjector__ +#define __hifi__AudioInjector__ + +#include +#include + +#include "UDPSocket.h" + +class AudioInjector { +public: + AudioInjector(const char* filename); + ~AudioInjector(); + + void setPosition(float* position); + void setBearing(float bearing) { _bearing = bearing; } + void setAttenuationModifier(unsigned char attenuationModifier) { _attenuationModifier = attenuationModifier; } + + void injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket); +private: + int16_t* _audioSampleArray; + int _numTotalBytesAudio; + float _position[3]; + float _bearing; + unsigned char _attenuationModifier; +}; + +#endif /* defined(__hifi__AudioInjector__) */ From 8df6a7e05666b026efd29a2215e338a39ce42359 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Tue, 23 Apr 2013 11:12:38 -0700 Subject: [PATCH 04/52] added collision code for avatar (not operational yet). and some cleanup. --- interface/src/Head.cpp | 121 ++++++++++++++++------------------------- interface/src/Head.h | 29 ++++++++-- interface/src/main.cpp | 3 + 3 files changed, 73 insertions(+), 80 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index d1bbf5e65b..28cc3f8ddc 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -120,7 +120,13 @@ Head::Head(bool isMine) { _renderPitch = 0.0; _sphere = NULL; - + + _collisionElipsoid.colliding = false; + _collisionElipsoid.position = glm::vec3( 0.0, 0.0, 0.0 ); + _collisionElipsoid.upVector = glm::vec3( 0.0, 0.0, 0.0 ); + _collisionElipsoid.girth = 0.0; + _collisionElipsoid.height = 0.0; + if (iris_texture.size() == 0) { switchToResourcesParentIfRequired(); unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file); @@ -129,16 +135,12 @@ Head::Head(bool isMine) { } } - //-------------------------------------------------- - // test... just slam them into random positions... - //-------------------------------------------------- - _otherAvatarHandPosition[ 0 ] = glm::vec3( 0.0f, 0.3f, 2.0f ); - _otherAvatarHandPosition[ 1 ] = glm::vec3( 4.0f, 0.3f, 2.0f ); - _otherAvatarHandPosition[ 2 ] = glm::vec3( 2.0f, 0.3f, 2.0f ); - _otherAvatarHandPosition[ 3 ] = glm::vec3( 1.0f, 0.3f, -4.0f ); - _otherAvatarHandPosition[ 4 ] = glm::vec3( -2.0f, 0.3f, -2.0f ); + for (int o=0; ogetLinkedData(); avatar->simulate(deltaTime); + + //not ready yet... + //myAvatar.testForCollision( avatar->getBodyPosition(), avatar->getGirth(), avatar->getHeight(), avatar->getBodyUpDirection() ); } } From 88fe04bcd1eaf79287ccb6a98c636eb01ef043d4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 11:48:01 -0700 Subject: [PATCH 05/52] hook up the injector to the new AudioInjector class --- injector/src/injector.cpp | 129 ++++++++----------------- libraries/shared/src/AudioInjector.cpp | 23 +++-- 2 files changed, 57 insertions(+), 95 deletions(-) diff --git a/injector/src/injector.cpp b/injector/src/injector.cpp index 3f6bb7f689..39981d277b 100644 --- a/injector/src/injector.cpp +++ b/injector/src/injector.cpp @@ -1,5 +1,5 @@ // -// injector.cpp +// main.cpp // Audio Injector // // Created by Leonardo Murillo on 3/5/13. @@ -11,39 +11,27 @@ #include #include #include -#include -#include -#include #include #include #include -#include "UDPSocket.h" -#include "UDPSocket.cpp" + + #include #include - +#include +#include char EC2_WEST_AUDIO_SERVER[] = "54.241.92.53"; const int AUDIO_UDP_LISTEN_PORT = 55443; -const int BUFFER_LENGTH_BYTES = 512; -const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t); -const float SAMPLE_RATE = 22050.0; -const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES / SAMPLE_RATE) * 1000000; // Command line parameter defaults bool loopAudio = true; float sleepIntervalMin = 1.00; float sleepIntervalMax = 2.00; -float positionInUniverse[] = {0, 0, 0, 0}; -unsigned char attenuationModifier = 255; -char *sourceAudioFile; +char *sourceAudioFile = NULL; const char *allowedParameters = ":rb::t::c::a::f:"; - -char *charBuffer; -int16_t *buffer; -long length; - -UDPSocket *streamSocket; +float floatArguments[4] = {0.0f, 0.0f, 0.0f, 0.0f}; +unsigned char attenuationModifier = 255; void usage(void) { @@ -62,19 +50,19 @@ bool processParameters(int parameterCount, char* parameterData[]) while ((p = getopt(parameterCount, parameterData, allowedParameters)) != -1) { switch (p) { case 'r': - loopAudio = false; + ::loopAudio = false; std::cout << "[DEBUG] Random sleep mode enabled" << std::endl; break; case 'b': - sleepIntervalMin = atof(optarg); + ::sleepIntervalMin = atof(optarg); std::cout << "[DEBUG] Min delay between plays " << sleepIntervalMin << "sec" << std::endl; break; case 't': - sleepIntervalMax = atof(optarg); + ::sleepIntervalMax = atof(optarg); std::cout << "[DEBUG] Max delay between plays " << sleepIntervalMax << "sec" << std::endl; break; case 'f': - sourceAudioFile = optarg; + ::sourceAudioFile = optarg; std::cout << "[DEBUG] Opening file: " << sourceAudioFile << std::endl; break; case 'c': @@ -84,7 +72,7 @@ bool processParameters(int parameterCount, char* parameterData[]) int i = 0; while (std::getline(ss, token, ',')) { - positionInUniverse[i] = atof(token.c_str()); + ::floatArguments[i] = atof(token.c_str()); ++i; if (i == 4) { break; @@ -94,7 +82,7 @@ bool processParameters(int parameterCount, char* parameterData[]) break; } case 'a': - attenuationModifier = atoi(optarg); + ::attenuationModifier = atoi(optarg); std::cout << "[DEBUG] Attenuation modifier: " << optarg << std::endl; break; default: @@ -105,77 +93,42 @@ bool processParameters(int parameterCount, char* parameterData[]) return true; }; -void loadFile(void) { - std::fstream sourceFile; - sourceFile.open(sourceAudioFile, std::ios::in | std::ios::binary); - sourceFile.seekg(0, std::ios::end); - length = sourceFile.tellg(); - sourceFile.seekg(0, std::ios::beg); - long sizeOfShortArray = length / 2; - buffer = new int16_t[sizeOfShortArray]; - sourceFile.read((char *)buffer, length); -} - -void stream(void) -{ - timeval startTime; - - int leadingBytes = 1 + (sizeof(float) * 4); - unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes]; - - dataPacket[0] = PACKET_HEADER_INJECT_AUDIO; - unsigned char *currentPacketPtr = dataPacket + 1; - - for (int p = 0; p < 4; p++) { - memcpy(currentPacketPtr, &positionInUniverse[p], sizeof(float)); - currentPacketPtr += sizeof(float); - } - - *currentPacketPtr = attenuationModifier; - currentPacketPtr++; - - for (int i = 0; i < length; i += BUFFER_LENGTH_SAMPLES) { - gettimeofday(&startTime, NULL); - memcpy(currentPacketPtr, &buffer[i], BUFFER_LENGTH_BYTES); - streamSocket->send(EC2_WEST_AUDIO_SERVER, AUDIO_UDP_LISTEN_PORT, dataPacket, sizeof(dataPacket)); - double usecToSleep = usecTimestamp(&startTime) + BUFFER_SEND_INTERVAL_USECS - usecTimestampNow(); - usleep(usecToSleep); - } -}; - -int main(int argc, char* argv[]) -{ +int main(int argc, char* argv[]) { srand(time(0)); int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1)); - streamSocket = new UDPSocket(AUDIO_UDP_SEND_PORT); + UDPSocket streamSocket = UDPSocket(AUDIO_UDP_SEND_PORT); - if (processParameters(argc, argv)) { - if (sourceAudioFile) { - loadFile(); - } else { + sockaddr_in mixerSocket; + mixerSocket.sin_family = AF_INET; + mixerSocket.sin_addr.s_addr = inet_addr(EC2_WEST_AUDIO_SERVER); + mixerSocket.sin_port = htons((uint16_t)AUDIO_UDP_LISTEN_PORT); + + if (processParameters(argc, argv)) { + if (::sourceAudioFile == NULL) { std::cout << "[FATAL] Source audio file not specified" << std::endl; exit(-1); - } - - for (int i = 0; i < sizeof(positionInUniverse)/sizeof(positionInUniverse[0]); ++i) { - std::cout << "Position " << positionInUniverse[i] << std::endl; - } - - float delay; - int usecDelay; - while (true) { - stream(); + } else { + AudioInjector injector = AudioInjector(sourceAudioFile); - if (loopAudio) { - delay = 0; - } else { - delay = randFloatInRange(sleepIntervalMin, sleepIntervalMax); + injector.setPosition(::floatArguments); + injector.setBearing(*(::floatArguments + 3)); + injector.setAttenuationModifier(::attenuationModifier); + + float delay = 0; + int usecDelay = 0; + + while (true) { + injector.injectAudio(&streamSocket, (sockaddr*) &mixerSocket); + + if (!::loopAudio) { + delay = randFloatInRange(::sleepIntervalMin, ::sleepIntervalMax); + usecDelay = delay * 1000 * 1000; + usleep(usecDelay); + } } - usecDelay = delay * 1000 * 1000; - usleep(usecDelay); - } + } } return 0; } diff --git a/libraries/shared/src/AudioInjector.cpp b/libraries/shared/src/AudioInjector.cpp index fac26a78cf..5cd7500bdd 100644 --- a/libraries/shared/src/AudioInjector.cpp +++ b/libraries/shared/src/AudioInjector.cpp @@ -65,19 +65,28 @@ void AudioInjector::injectAudio(UDPSocket *injectorSocket, sockaddr *destination currentPacketPtr += sizeof(float); } - memcpy(currentPacketPtr, &_bearing, sizeof(float)); - currentPacketPtr += sizeof(float); - *currentPacketPtr = _attenuationModifier; currentPacketPtr++; - for (int i = 0; i < _numTotalBytesAudio; i += BUFFER_LENGTH_SAMPLES) { + memcpy(currentPacketPtr, &_bearing, sizeof(float)); + currentPacketPtr += sizeof(float); + + for (int i = 0; i < _numTotalBytesAudio; i += BUFFER_LENGTH_BYTES) { gettimeofday(&startTime, NULL); - memcpy(currentPacketPtr, _audioSampleArray + i, BUFFER_LENGTH_BYTES); + int numBytesToCopy = BUFFER_LENGTH_BYTES; + + if (_numTotalBytesAudio - i < BUFFER_LENGTH_BYTES) { + numBytesToCopy = _numTotalBytesAudio - i; + memset(currentPacketPtr + numBytesToCopy, 0, BUFFER_LENGTH_BYTES - numBytesToCopy); + } + + memcpy(currentPacketPtr, _audioSampleArray + (i / 2), numBytesToCopy); injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket)); - double usecToSleep = usecTimestamp(&startTime) + BUFFER_SEND_INTERVAL_USECS - usecTimestampNow(); - usleep(usecToSleep); + double usecToSleep = BUFFER_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&startTime)); + if (usecToSleep > 0) { + usleep(usecToSleep); + } } } From 1688e2f5c32f82df31e860c41acb6cf967ecbaed Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 11:49:37 -0700 Subject: [PATCH 06/52] replace injector with TARGET_NAME in CMakeLists --- injector/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/injector/CMakeLists.txt b/injector/CMakeLists.txt index 6e3e61326c..6bea5b51d3 100644 --- a/injector/CMakeLists.txt +++ b/injector/CMakeLists.txt @@ -14,4 +14,4 @@ link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) # link the threads library find_package(Threads REQUIRED) -target_link_libraries(injector ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT}) \ No newline at end of file From e19d4fd5f9aac9409f9d159ae068ef1bcc109830 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Tue, 23 Apr 2013 12:23:08 -0700 Subject: [PATCH 07/52] changes from Philip's push - I assume --- interface/src/Head.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 257e50b63d..6f293f2fef 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -1126,13 +1126,13 @@ void Head::updateHandMovement() { _bone[ AVATAR_BONE_RIGHT_HAND ].position += transformedHandMovement; - //----------------------------------------------------- - // if holding hands, apply the appropriate forces... - //----------------------------------------------------- + setHandState(_mousePressed); + + //if holding hands, add a pull to the hand... if ( _usingBodySprings ) { if ( _closestOtherAvatar != -1 ) { if ( _mousePressed ) { - + glm::vec3 handToHandVector( _otherAvatarHandPosition[ _closestOtherAvatar ]); handToHandVector -= _bone[ AVATAR_BONE_RIGHT_HAND ].position; From d550b09399228cc4c73f0f1d8991fe51f8facd7d Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 23 Apr 2013 13:31:05 -0700 Subject: [PATCH 08/52] Added 'gyro look' option to have gyro drive your render yaw, added render menu. --- interface/src/main.cpp | 57 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index df77265ea9..247922f7a6 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -160,8 +160,10 @@ bool perfStatsOn = false; // Do we want to display perfStats? int noiseOn = 0; // Whether to add random noise float noise = 1.0; // Overall magnitude scaling for random noise levels +bool gyroLook = false; // Whether to allow the gyro data from head to move your view + int displayLevels = 0; -bool lookingInMirror = 0; // Are we currently rendering one's own head as if in mirror? +bool lookingInMirror = 0; // Are we currently rendering one's own head as if in mirror? int displayField = 0; int displayHeadMouse = 1; // Display sample mouse pointer controlled by head movement @@ -476,31 +478,18 @@ void updateAvatar(float frametime) headMouseY = min(headMouseY, HEIGHT); // Update render direction (pitch/yaw) based on measured gyro rates - const int MIN_YAW_RATE = 100; - const int MIN_PITCH_RATE = 100; - const float YAW_SENSITIVITY = 0.02; - const float PITCH_SENSITIVITY = 0.05; + const float MIN_YAW_RATE = 5; + const float YAW_SENSITIVITY = 1.0; - // Update render pitch and yaw rates based on keyPositions - const float KEY_YAW_SENSITIVITY = 2.0; - if (myAvatar.getDriveKeys(ROT_LEFT)) renderYawRate -= KEY_YAW_SENSITIVITY*frametime; - if (myAvatar.getDriveKeys(ROT_RIGHT)) renderYawRate += KEY_YAW_SENSITIVITY*frametime; - - if (fabs(gyroYawRate) > MIN_YAW_RATE) - { - if (gyroYawRate > 0) - renderYawRate += (gyroYawRate - MIN_YAW_RATE) * YAW_SENSITIVITY * frametime; - else - renderYawRate += (gyroYawRate + MIN_YAW_RATE) * YAW_SENSITIVITY * frametime; - } - if (fabs(gyroPitchRate) > MIN_PITCH_RATE) + // If enabled, Update render pitch and yaw based on gyro data + if (::gyroLook) { - if (gyroPitchRate > 0) - renderPitchRate += (gyroPitchRate - MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime; - else - renderPitchRate += (gyroPitchRate + MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime; + if (fabs(gyroYawRate) > MIN_YAW_RATE) { + //if (fabs(myAvatar.getHeadYaw()) > MIN_YAW_ANGLE) { + myAvatar.addBodyYaw(-gyroYawRate * YAW_SENSITIVITY * frametime); + } } - + float renderPitch = myAvatar.getRenderPitch(); // Decay renderPitch toward zero because we never look constantly up/down renderPitch *= (1.f - 2.0*frametime); @@ -1072,6 +1061,12 @@ int setNoise(int state) { return iRet; } +int setGyroLook(int state) { + int iRet = setValue(state, &::gyroLook); + std::cout << "gyro look" << ::gyroLook << "\n"; + return iRet; +} + int setVoxels(int state) { return setValue(state, &::showingVoxels); } @@ -1190,16 +1185,20 @@ const char* getFrustumRenderModeName(int state) { } void initMenu() { - MenuColumn *menuColumnOptions, *menuColumnTools, *menuColumnDebug, *menuColumnFrustum; + MenuColumn *menuColumnOptions, *menuColumnRender, *menuColumnTools, *menuColumnDebug, *menuColumnFrustum; // Options menuColumnOptions = menu.addColumn("Options"); menuColumnOptions->addRow("Mirror (h)", setHead); - menuColumnOptions->addRow("Field (f)", setField); - menuColumnOptions->addRow("(N)oise", setNoise); - menuColumnOptions->addRow("(V)oxels", setVoxels); - menuColumnOptions->addRow("Stars (*)", setStars); - menuColumnOptions->addRow("(Q)uit", quitApp); + menuColumnOptions->addRow("Noise (n)", setNoise); + menuColumnOptions->addRow("Gyro Look", setGyroLook); + menuColumnOptions->addRow("Quit (q)", quitApp); + // Render + menuColumnRender = menu.addColumn("Render"); + menuColumnRender->addRow("Voxels (V)", setVoxels); + menuColumnRender->addRow("Stars (*)", setStars); + menuColumnRender->addRow("Field (f)", setField); + // Tools menuColumnTools = menu.addColumn("Tools"); menuColumnTools->addRow("Stats (/)", setStats); From 7ae320d7e1f095b6d573575f5647956d70e52da6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 13:37:49 -0700 Subject: [PATCH 09/52] intial version of eve that says WALL-E every so often --- domain-server/src/main.cpp | 2 +- eve/src/main.cpp | 56 ++++++++++++++++- injector/src/{injector.cpp => main.cpp} | 0 interface/src/Head.cpp | 2 - libraries/shared/src/AgentList.cpp | 6 +- libraries/shared/src/AgentList.h | 2 +- libraries/shared/src/AudioInjector.cpp | 83 ++++++++++++++----------- 7 files changed, 105 insertions(+), 46 deletions(-) rename injector/src/{injector.cpp => main.cpp} (100%) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index fceedc6678..52631a3c25 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -133,7 +133,7 @@ int main(int argc, const char * argv[]) if (DEBUG_TO_SELF || !agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) { - if (memchr(SOLO_AGENT_TYPES_STRING, agent->getType(), 1) == NULL) { + if (memchr(SOLO_AGENT_TYPES, agent->getType(), sizeof(SOLO_AGENT_TYPES)) == NULL) { // this is an agent of which there can be multiple, just add them to the packet // don't send avatar agents to other avatars, that will come from avatar mixer if (agentType != AGENT_TYPE_AVATAR || agent->getType() != AGENT_TYPE_AVATAR) { diff --git a/eve/src/main.cpp b/eve/src/main.cpp index 1478f3d1b2..a86a04456f 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -13,14 +13,22 @@ #include #include #include +#include const int EVE_AGENT_LIST_PORT = 55441; const float DATA_SEND_INTERVAL_MSECS = 10; +const float MIN_AUDIO_SEND_INTERVAL_SECS = 10; +const int MIN_ITERATIONS_BETWEEN_AUDIO_SENDS = (MIN_AUDIO_SEND_INTERVAL_SECS * 1000) / DATA_SEND_INTERVAL_MSECS; +const int MAX_AUDIO_SEND_INTERVAL_SECS = 15; +const float MAX_ITERATIONS_BETWEEN_AUDIO_SENDS = (MAX_AUDIO_SEND_INTERVAL_SECS * 1000) / DATA_SEND_INTERVAL_MSECS; bool stopReceiveAgentDataThread; +bool injectAudioThreadRunning = false; -void *receiveAgentData(void *args) -{ +int TEMP_AUDIO_LISTEN_PORT = 55439; +UDPSocket audioSocket = UDPSocket(TEMP_AUDIO_LISTEN_PORT); + +void *receiveAgentData(void *args) { sockaddr senderAddress; ssize_t bytesReceived; unsigned char incomingPacket[MAX_PACKET_SIZE]; @@ -54,7 +62,33 @@ void *receiveAgentData(void *args) return NULL; } +void *injectAudio(void *args) { + ::injectAudioThreadRunning = true; + + AudioInjector *eveAudioInjector = (AudioInjector *)args; + + // look for an audio mixer in our agent list + Agent *audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER); + + if (audioMixer != NULL) { + // until the audio mixer is setup for ping-reply, activate the public socket if it's not active + if (audioMixer->getActiveSocket() == NULL) { + audioMixer->activatePublicSocket(); + } + + // we have an active audio mixer we can send data to + eveAudioInjector->injectAudio(&::audioSocket, audioMixer->getActiveSocket()); + } + + ::injectAudioThreadRunning = false; + pthread_exit(0); + return NULL; +} + int main(int argc, char* argv[]) { + // new seed for random audio sleep times + srand(time(0)); + // create an AgentList instance to handle communication with other agents AgentList *agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LIST_PORT); @@ -84,6 +118,9 @@ int main(int argc, char* argv[]) { 0.25, eve.getBodyPosition()[2] + 0.1)); + // read eve's audio data + AudioInjector eveAudioInjector = AudioInjector("eve.raw"); + unsigned char broadcastPacket[MAX_PACKET_SIZE]; broadcastPacket[0] = PACKET_HEADER_HEAD_DATA; @@ -92,6 +129,9 @@ int main(int argc, char* argv[]) { timeval thisSend; double numMicrosecondsSleep = 0; + int numIterationsLeftBeforeAudioSend = 0; + pthread_t injectAudioThread; + while (true) { // update the thisSend timeval to the current time gettimeofday(&thisSend, NULL); @@ -104,11 +144,21 @@ int main(int argc, char* argv[]) { // use the getBroadcastData method in the AvatarData class to populate the broadcastPacket buffer numBytesToSend = eve.getBroadcastData((broadcastPacket + 1)); - // use the UDPSocket instance attached to our agent list to send avatar data to mixer agentList->getAgentSocket().send(avatarMixer->getActiveSocket(), broadcastPacket, numBytesToSend); } + if (numIterationsLeftBeforeAudioSend == 0) { + if (!::injectAudioThreadRunning) { + pthread_create(&injectAudioThread, NULL, injectAudio, (void*) &eveAudioInjector); + + numIterationsLeftBeforeAudioSend = randIntInRange(MIN_ITERATIONS_BETWEEN_AUDIO_SENDS, + MAX_ITERATIONS_BETWEEN_AUDIO_SENDS); + } + } else { + numIterationsLeftBeforeAudioSend--; + } + // sleep for the correct amount of time to have data send be consistently timed if ((numMicrosecondsSleep = (DATA_SEND_INTERVAL_MSECS * 1000) - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) { usleep(numMicrosecondsSleep); diff --git a/injector/src/injector.cpp b/injector/src/main.cpp similarity index 100% rename from injector/src/injector.cpp rename to injector/src/main.cpp diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index d1bbf5e65b..89690fc491 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -35,8 +35,6 @@ float browThickness = 0.16; bool usingBigSphereCollisionTest = true; - - char iris_texture_file[] = "resources/images/green_eye.png"; vector iris_texture; diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index 5744c0780a..923052beb3 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -24,7 +24,7 @@ using shared_lib::printLog; -const char SOLO_AGENT_TYPES_STRING[] = { +const char SOLO_AGENT_TYPES[3] = { AGENT_TYPE_AVATAR_MIXER, AGENT_TYPE_AUDIO_MIXER, AGENT_TYPE_VOXEL @@ -305,8 +305,8 @@ void AgentList::handlePingReply(sockaddr *agentAddress) { } } -Agent* AgentList::soloAgentOfType(char agentType) { - if (memchr(SOLO_AGENT_TYPES_STRING, agentType, 1)) { +Agent* AgentList::soloAgentOfType(char agentType) { + if (memchr(SOLO_AGENT_TYPES, agentType, sizeof(SOLO_AGENT_TYPES)) != NULL) { for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { if (agent->getType() == agentType) { return &*agent; diff --git a/libraries/shared/src/AgentList.h b/libraries/shared/src/AgentList.h index f62d527116..d7459aafd3 100644 --- a/libraries/shared/src/AgentList.h +++ b/libraries/shared/src/AgentList.h @@ -22,7 +22,7 @@ const int MAX_PACKET_SIZE = 1500; const unsigned int AGENT_SOCKET_LISTEN_PORT = 40103; const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000; -extern const char SOLO_AGENT_TYPES_STRING[]; +extern const char SOLO_AGENT_TYPES[]; extern char DOMAIN_HOSTNAME[]; extern char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup diff --git a/libraries/shared/src/AudioInjector.cpp b/libraries/shared/src/AudioInjector.cpp index 5cd7500bdd..e96d7288fc 100644 --- a/libraries/shared/src/AudioInjector.cpp +++ b/libraries/shared/src/AudioInjector.cpp @@ -16,10 +16,11 @@ const int BUFFER_LENGTH_BYTES = 512; const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t); -const float SAMPLE_RATE = 22050.0; +const float SAMPLE_RATE = 22050.0f; const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES / SAMPLE_RATE) * 1000000; AudioInjector::AudioInjector(const char* filename) : + _numTotalBytesAudio(0), _bearing(0), _attenuationModifier(255) { @@ -33,11 +34,18 @@ AudioInjector::AudioInjector(const char* filename) : sourceFile.seekg(0, std::ios::end); _numTotalBytesAudio = sourceFile.tellg(); - sourceFile.seekg(0, std::ios::beg); - long sizeOfShortArray = _numTotalBytesAudio / 2; - _audioSampleArray = new int16_t[sizeOfShortArray]; + if (_numTotalBytesAudio == -1) { + printf("Error reading audio data from file %s\n", filename); + _audioSampleArray = NULL; + } else { + printf("Read %d bytes from audio file\n", _numTotalBytesAudio); + sourceFile.seekg(0, std::ios::beg); + long sizeOfShortArray = _numTotalBytesAudio / 2; + _audioSampleArray = new int16_t[sizeOfShortArray]; + + sourceFile.read((char *)_audioSampleArray, _numTotalBytesAudio); + } - sourceFile.read((char *)_audioSampleArray, _numTotalBytesAudio); } AudioInjector::~AudioInjector() { @@ -51,42 +59,45 @@ void AudioInjector::setPosition(float* position) { } void AudioInjector::injectAudio(UDPSocket *injectorSocket, sockaddr *destinationSocket) { - timeval startTime; - - // one byte for header, 3 positional floats, 1 bearing float, 1 attenuation modifier byte - int leadingBytes = 1 + (sizeof(float) * 4) + 1; - unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes]; - - dataPacket[0] = PACKET_HEADER_INJECT_AUDIO; - unsigned char *currentPacketPtr = dataPacket + 1; - - for (int i = 0; i < 3; i++) { - memcpy(currentPacketPtr, &_position[i], sizeof(float)); - currentPacketPtr += sizeof(float); - } - - *currentPacketPtr = _attenuationModifier; - currentPacketPtr++; - - memcpy(currentPacketPtr, &_bearing, sizeof(float)); - currentPacketPtr += sizeof(float); - - for (int i = 0; i < _numTotalBytesAudio; i += BUFFER_LENGTH_BYTES) { - gettimeofday(&startTime, NULL); + if (_audioSampleArray != NULL) { + timeval startTime; - int numBytesToCopy = BUFFER_LENGTH_BYTES; + // one byte for header, 3 positional floats, 1 bearing float, 1 attenuation modifier byte + int leadingBytes = 1 + (sizeof(float) * 4) + 1; + unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes]; - if (_numTotalBytesAudio - i < BUFFER_LENGTH_BYTES) { - numBytesToCopy = _numTotalBytesAudio - i; - memset(currentPacketPtr + numBytesToCopy, 0, BUFFER_LENGTH_BYTES - numBytesToCopy); + dataPacket[0] = PACKET_HEADER_INJECT_AUDIO; + unsigned char *currentPacketPtr = dataPacket + 1; + + for (int i = 0; i < 3; i++) { + memcpy(currentPacketPtr, &_position[i], sizeof(float)); + currentPacketPtr += sizeof(float); } - memcpy(currentPacketPtr, _audioSampleArray + (i / 2), numBytesToCopy); - injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket)); + *currentPacketPtr = _attenuationModifier; + currentPacketPtr++; - double usecToSleep = BUFFER_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&startTime)); - if (usecToSleep > 0) { - usleep(usecToSleep); + memcpy(currentPacketPtr, &_bearing, sizeof(float)); + currentPacketPtr += sizeof(float); + + for (int i = 0; i < _numTotalBytesAudio; i += BUFFER_LENGTH_BYTES) { + gettimeofday(&startTime, NULL); + + int numBytesToCopy = BUFFER_LENGTH_BYTES; + + if (_numTotalBytesAudio - i < BUFFER_LENGTH_BYTES) { + numBytesToCopy = _numTotalBytesAudio - i; + memset(currentPacketPtr + numBytesToCopy, 0, BUFFER_LENGTH_BYTES - numBytesToCopy); + } + + memcpy(currentPacketPtr, _audioSampleArray + (i / 2), numBytesToCopy); + + injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket)); + + double usecToSleep = BUFFER_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&startTime)); + if (usecToSleep > 0) { + usleep(usecToSleep); + } } } } From a73ea8c255e474d3c68038fede1cf95f4cd7ba3d Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Tue, 23 Apr 2013 13:48:34 -0700 Subject: [PATCH 10/52] some preparation for adding hand state to avatar interactions --- interface/src/Head.cpp | 74 ++++++++++++++++++++---------- interface/src/Head.h | 7 ++- interface/src/main.cpp | 6 +-- libraries/avatars/src/AvatarData.h | 2 +- 4 files changed, 57 insertions(+), 32 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 6f293f2fef..25d26d0502 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -136,6 +136,7 @@ Head::Head(bool isMine) { for (int o=0; ogetLinkedData() != NULL && ( agent->getType() == AGENT_TYPE_AVATAR ) )) { Head *otherAvatar = (Head *)agent->getLinkedData(); - if ( _numOtherAvatarsInView < MAX_OTHER_AVATARS ) { + if ( _numOtherAvatarsInView < MAX_OTHER_AVATARS ) { + + //------------------------------------------------------ + // check for collisions with other avatars and respond + //------------------------------------------------------ + updateAvatarCollisionDetectionAndResponse + ( + otherAvatar->getBodyPosition(), + otherAvatar->getGirth(), + otherAvatar->getHeight(), + otherAvatar->getBodyUpDirection(), + deltaTime + ); //----------------------------------------------------------- - // test other avatar hand position for proximity... + // test other avatar hand position for proximity and state //----------------------------------------------------------- _otherAvatarHandPosition[ _numOtherAvatarsInView ] = otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); + _otherAvatarHandState [ _numOtherAvatarsInView ] = (int)otherAvatar->getHandState(); + glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); v -= _otherAvatarHandPosition[ _numOtherAvatarsInView ]; + //if ( otherAvatar->getHandState() == 1 ) + { + printf( "otherAvatar->getHandState() is %d\n", (int)otherAvatar->getHandState() ); + } + float distance = glm::length( v ); if ( distance < _maxArmLength ) { if ( distance < closestDistance ) { @@ -347,7 +367,14 @@ void Head::simulate(float deltaTime) { //-------------------------------------------------------------- // test for avatar collision response (using a big sphere :) //-------------------------------------------------------------- - updateAvatarCollisionDetectionAndResponse(_TEST_bigSpherePosition, _TEST_bigSphereRadius, deltaTime); + updateAvatarCollisionDetectionAndResponse + ( + _TEST_bigSpherePosition, + _TEST_bigSphereRadius, + _TEST_bigSphereRadius, + glm::vec3( 0.0, 1.0, 0.0 ), + deltaTime + ); } if ( AVATAR_GRAVITY ) { @@ -565,37 +592,25 @@ float Head::getHeight() { glm::vec3 Head::getBodyUpDirection() { return _orientation.getUp(); } - - -bool Head::testForCollision( glm::vec3 collisionPosition, float collisionGirth, float collisionHeight, glm::vec3 collisionUpVector ) { - _collisionElipsoid.colliding = false; - _collisionElipsoid.position = glm::vec3( 0.0, 0.0, 0.0 ); - _collisionElipsoid.upVector = glm::vec3( 0.0, 0.0, 0.0 ); - _collisionElipsoid.girth = 0.0; - _collisionElipsoid.height = 0.0; - - return false; -} - - //-------------------------------------------------------------------------------- // This is a workspace for testing avatar body collision detection and response //-------------------------------------------------------------------------------- -void Head::updateAvatarCollisionDetectionAndResponse( glm::vec3 collisionPosition, float collisionRadius, float deltaTime ) { +void Head::updateAvatarCollisionDetectionAndResponse +( glm::vec3 collisionPosition, float collisionGirth, float collisionHeight, glm::vec3 collisionUpVector, float deltaTime ) { float myBodyApproximateBoundingRadius = 1.0f; glm::vec3 vectorFromMyBodyToBigSphere(_bodyPosition - collisionPosition); bool jointCollision = false; float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere); - if ( distanceToBigSphere < myBodyApproximateBoundingRadius + collisionRadius ) + if ( distanceToBigSphere < myBodyApproximateBoundingRadius + collisionGirth ) { for (int b=0; b::iterator agent = agentList->getAgents().begin(); agent != agentList->getAgents().end(); agent++) { @@ -1502,9 +1502,6 @@ void idle(void) { { Head *avatar = (Head *)agent->getLinkedData(); avatar->simulate(deltaTime); - - //not ready yet... - //myAvatar.testForCollision( avatar->getBodyPosition(), avatar->getGirth(), avatar->getHeight(), avatar->getBodyUpDirection() ); } } @@ -1515,7 +1512,6 @@ void idle(void) { glutPostRedisplay(); lastTimeIdle = check; - } // Read serial data diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 4655873dcd..e133d965c5 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -48,7 +48,7 @@ public: // Hand State void setHandState(char s) { _handState = s; }; - const float getHandState() const {return _handState; }; + const float getHandState() const {return _handState; }; //@Philip - shouldn't this be an int or a char? // Instantaneous audio loudness to drive mouth/facial animation void setLoudness(float l) { _audioLoudness = l; }; From ddc74984b5007c4b98b6611a0a15bce86fefde3c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 13:52:25 -0700 Subject: [PATCH 11/52] fix pointer var declarations, AudioInjector constructor in eve main --- eve/src/main.cpp | 14 +++++++------- libraries/shared/src/AudioInjector.cpp | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index a86a04456f..087b28e635 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -33,8 +33,8 @@ void *receiveAgentData(void *args) { ssize_t bytesReceived; unsigned char incomingPacket[MAX_PACKET_SIZE]; - AgentList *agentList = AgentList::getInstance(); - Agent *avatarMixer = NULL; + AgentList* agentList = AgentList::getInstance(); + Agent* avatarMixer = NULL; while (!::stopReceiveAgentDataThread) { if (agentList->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) { @@ -65,10 +65,10 @@ void *receiveAgentData(void *args) { void *injectAudio(void *args) { ::injectAudioThreadRunning = true; - AudioInjector *eveAudioInjector = (AudioInjector *)args; + AudioInjector* eveAudioInjector = (AudioInjector *)args; // look for an audio mixer in our agent list - Agent *audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER); + Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER); if (audioMixer != NULL) { // until the audio mixer is setup for ping-reply, activate the public socket if it's not active @@ -85,12 +85,12 @@ void *injectAudio(void *args) { return NULL; } -int main(int argc, char* argv[]) { +int main(int argc, const char* argv[]) { // new seed for random audio sleep times srand(time(0)); // create an AgentList instance to handle communication with other agents - AgentList *agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LIST_PORT); + AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LIST_PORT); // start telling the domain server that we are alive agentList->startDomainServerCheckInThread(); @@ -119,7 +119,7 @@ int main(int argc, char* argv[]) { eve.getBodyPosition()[2] + 0.1)); // read eve's audio data - AudioInjector eveAudioInjector = AudioInjector("eve.raw"); + AudioInjector eveAudioInjector("eve.raw"); unsigned char broadcastPacket[MAX_PACKET_SIZE]; broadcastPacket[0] = PACKET_HEADER_HEAD_DATA; diff --git a/libraries/shared/src/AudioInjector.cpp b/libraries/shared/src/AudioInjector.cpp index e96d7288fc..046127c50a 100644 --- a/libraries/shared/src/AudioInjector.cpp +++ b/libraries/shared/src/AudioInjector.cpp @@ -45,7 +45,6 @@ AudioInjector::AudioInjector(const char* filename) : sourceFile.read((char *)_audioSampleArray, _numTotalBytesAudio); } - } AudioInjector::~AudioInjector() { From 9d7e29e06f82a38f85d5758dcfbb3daa23376018 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 13:53:24 -0700 Subject: [PATCH 12/52] fix constructors in eve main and injector main --- eve/src/main.cpp | 2 +- injector/src/main.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index 087b28e635..5a16556e06 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -26,7 +26,7 @@ bool stopReceiveAgentDataThread; bool injectAudioThreadRunning = false; int TEMP_AUDIO_LISTEN_PORT = 55439; -UDPSocket audioSocket = UDPSocket(TEMP_AUDIO_LISTEN_PORT); +UDPSocket audioSocket(TEMP_AUDIO_LISTEN_PORT); void *receiveAgentData(void *args) { sockaddr senderAddress; diff --git a/injector/src/main.cpp b/injector/src/main.cpp index 39981d277b..2822f608f9 100644 --- a/injector/src/main.cpp +++ b/injector/src/main.cpp @@ -98,7 +98,7 @@ int main(int argc, char* argv[]) { srand(time(0)); int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1)); - UDPSocket streamSocket = UDPSocket(AUDIO_UDP_SEND_PORT); + UDPSocket streamSocket(AUDIO_UDP_SEND_PORT); sockaddr_in mixerSocket; mixerSocket.sin_family = AF_INET; @@ -110,7 +110,7 @@ int main(int argc, char* argv[]) { std::cout << "[FATAL] Source audio file not specified" << std::endl; exit(-1); } else { - AudioInjector injector = AudioInjector(sourceAudioFile); + AudioInjector injector(sourceAudioFile); injector.setPosition(::floatArguments); injector.setBearing(*(::floatArguments + 3)); From fd6fb60d2498b0c6aed99a424bd6acdcb9150cf7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 13:55:42 -0700 Subject: [PATCH 13/52] fix pointer var declarations in AudioInjector class --- libraries/shared/src/AudioInjector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/AudioInjector.cpp b/libraries/shared/src/AudioInjector.cpp index 046127c50a..25ea16e18a 100644 --- a/libraries/shared/src/AudioInjector.cpp +++ b/libraries/shared/src/AudioInjector.cpp @@ -57,7 +57,7 @@ void AudioInjector::setPosition(float* position) { _position[2] = position[2]; } -void AudioInjector::injectAudio(UDPSocket *injectorSocket, sockaddr *destinationSocket) { +void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) { if (_audioSampleArray != NULL) { timeval startTime; From ed5afb353795156623c600c504b6a4caaa0c69d1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 13:57:41 -0700 Subject: [PATCH 14/52] add const to injectAudio method --- libraries/shared/src/AudioInjector.cpp | 2 +- libraries/shared/src/AudioInjector.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/AudioInjector.cpp b/libraries/shared/src/AudioInjector.cpp index 25ea16e18a..15151f2cef 100644 --- a/libraries/shared/src/AudioInjector.cpp +++ b/libraries/shared/src/AudioInjector.cpp @@ -57,7 +57,7 @@ void AudioInjector::setPosition(float* position) { _position[2] = position[2]; } -void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) { +const void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) { if (_audioSampleArray != NULL) { timeval startTime; diff --git a/libraries/shared/src/AudioInjector.h b/libraries/shared/src/AudioInjector.h index 2456a95c57..220b00bb55 100644 --- a/libraries/shared/src/AudioInjector.h +++ b/libraries/shared/src/AudioInjector.h @@ -23,7 +23,7 @@ public: void setBearing(float bearing) { _bearing = bearing; } void setAttenuationModifier(unsigned char attenuationModifier) { _attenuationModifier = attenuationModifier; } - void injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket); + const void injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket); private: int16_t* _audioSampleArray; int _numTotalBytesAudio; From 49f9dfe03c93f7fd95b6d26d6636fb4e313a6af7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 13:59:59 -0700 Subject: [PATCH 15/52] make argv a const so Brad quiets down --- eve/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index 5a16556e06..a228454f22 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -85,7 +85,7 @@ void *injectAudio(void *args) { return NULL; } -int main(int argc, const char* argv[]) { +int main(const int argc, const char* argv[]) { // new seed for random audio sleep times srand(time(0)); From 620615599f8f5168688a2dbd5317facfe0396e12 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 14:01:19 -0700 Subject: [PATCH 16/52] fix the const for injectAudio --- libraries/shared/src/AudioInjector.cpp | 2 +- libraries/shared/src/AudioInjector.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/AudioInjector.cpp b/libraries/shared/src/AudioInjector.cpp index 15151f2cef..6b0ba7203e 100644 --- a/libraries/shared/src/AudioInjector.cpp +++ b/libraries/shared/src/AudioInjector.cpp @@ -57,7 +57,7 @@ void AudioInjector::setPosition(float* position) { _position[2] = position[2]; } -const void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) { +void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) const { if (_audioSampleArray != NULL) { timeval startTime; diff --git a/libraries/shared/src/AudioInjector.h b/libraries/shared/src/AudioInjector.h index 220b00bb55..2515dcfcdc 100644 --- a/libraries/shared/src/AudioInjector.h +++ b/libraries/shared/src/AudioInjector.h @@ -23,7 +23,7 @@ public: void setBearing(float bearing) { _bearing = bearing; } void setAttenuationModifier(unsigned char attenuationModifier) { _attenuationModifier = attenuationModifier; } - const void injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket); + void injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) const; private: int16_t* _audioSampleArray; int _numTotalBytesAudio; From 32b1e88a0a4c24c7abc9fe857cca70fe74f7fe74 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 14:03:20 -0700 Subject: [PATCH 17/52] add ALL THE CONSTS --- injector/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/injector/src/main.cpp b/injector/src/main.cpp index 2822f608f9..7de6b030be 100644 --- a/injector/src/main.cpp +++ b/injector/src/main.cpp @@ -93,7 +93,7 @@ bool processParameters(int parameterCount, char* parameterData[]) return true; }; -int main(int argc, char* argv[]) { +int main(const int argc, const char* argv[]) { srand(time(0)); int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1)); From eb631e2ef69142b30e4581cf435419fb7d9feffa Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Tue, 23 Apr 2013 14:05:23 -0700 Subject: [PATCH 18/52] renamed "bodyPosition" to "position". (This corresponds to the position of the avatar on the ground, where y=0). I will next add a new "getBodyPosition" which returns the avatar's center of gravity - is useful for certain purposes, such as setting collision volumes, etc. --- interface/src/Audio.cpp | 2 +- interface/src/Head.cpp | 18 +++++++++--------- interface/src/VoxelSystem.cpp | 2 +- interface/src/main.cpp | 14 +++++++------- libraries/avatars/src/AvatarData.cpp | 16 ++++++++-------- libraries/avatars/src/AvatarData.h | 6 +++--- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 0d585ff5bf..9dbfdbf07f 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -157,7 +157,7 @@ int audioCallback (const void *inputBuffer, // memcpy the three float positions for (int p = 0; p < 3; p++) { - memcpy(currentPacketPtr, &data->linkedHead->getBodyPosition()[p], sizeof(float)); + memcpy(currentPacketPtr, &data->linkedHead->getPosition()[p], sizeof(float)); currentPacketPtr += sizeof(float); } diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 25d26d0502..f4269a47bd 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -328,7 +328,7 @@ void Head::simulate(float deltaTime) { //------------------------------------------------------ updateAvatarCollisionDetectionAndResponse ( - otherAvatar->getBodyPosition(), + otherAvatar->getPosition(), otherAvatar->getGirth(), otherAvatar->getHeight(), otherAvatar->getBodyUpDirection(), @@ -378,12 +378,12 @@ void Head::simulate(float deltaTime) { } if ( AVATAR_GRAVITY ) { - if ( _bodyPosition.y > _bone[ AVATAR_BONE_RIGHT_FOOT ].radius * 2.0 ) { + if ( _position.y > _bone[ AVATAR_BONE_RIGHT_FOOT ].radius * 2.0 ) { _velocity += glm::dvec3( 0.0, -1.0, 0.0 ) * ( 6.0 * deltaTime ); } else { - if ( _bodyPosition.y < _bone[ AVATAR_BONE_RIGHT_FOOT ].radius ) { - _bodyPosition.y = _bone[ AVATAR_BONE_RIGHT_FOOT ].radius; + if ( _position.y < _bone[ AVATAR_BONE_RIGHT_FOOT ].radius ) { + _position.y = _bone[ AVATAR_BONE_RIGHT_FOOT ].radius; _velocity.y = 0.0; } } @@ -474,7 +474,7 @@ void Head::simulate(float deltaTime) { //---------------------------------------------------------- // update position by velocity //---------------------------------------------------------- - _bodyPosition += (glm::vec3)_velocity * deltaTime; + _position += (glm::vec3)_velocity * deltaTime; //---------------------------------------------------------- // decay velocity @@ -600,7 +600,7 @@ void Head::updateAvatarCollisionDetectionAndResponse ( glm::vec3 collisionPosition, float collisionGirth, float collisionHeight, glm::vec3 collisionUpVector, float deltaTime ) { float myBodyApproximateBoundingRadius = 1.0f; - glm::vec3 vectorFromMyBodyToBigSphere(_bodyPosition - collisionPosition); + glm::vec3 vectorFromMyBodyToBigSphere(_position - collisionPosition); bool jointCollision = false; float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere); @@ -647,7 +647,7 @@ void Head::render(bool lookingInMirror) { //--------------------------------------------------- glColor4f( 0.5f, 0.5f, 0.5f, 0.6 ); glPushMatrix(); - glTranslatef(_bodyPosition.x, _bodyPosition.y, _bodyPosition.z); + glTranslatef(_position.x, _position.y, _position.z); glScalef( 0.03, 0.03, 0.03 ); glutSolidSphere( 1, 10, 10 ); glPopMatrix(); @@ -1017,7 +1017,7 @@ void Head::updateSkeleton() { for (int b=0; boctalCode) * (0.5 * TREE_SCALE); - glm::vec3 viewerPosition = viewerHead->getBodyPosition(); + glm::vec3 viewerPosition = viewerHead->getPosition(); // debug LOD code glm::vec3 debugNodePosition; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 6483056ac1..d890a380a7 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -304,7 +304,7 @@ void displayStats(void) char legend2[] = "* - toggle stars, & - toggle paint mode, '-' - send erase all, '%' - send add scene"; drawtext(10, statsVerticalOffset + 32, 0.10f, 0, 1.0, 0, legend2); - glm::vec3 avatarPos = myAvatar.getBodyPosition(); + glm::vec3 avatarPos = myAvatar.getPosition(); char stats[200]; sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d Head(x,y,z)= %4.2f, %4.2f, %4.2f ", @@ -396,8 +396,8 @@ void init(void) if (noiseOn) { myAvatar.setNoise(noise); } - myAvatar.setBodyPosition(start_location); - myCamera.setPosition( start_location ); + myAvatar.setPosition(start_location); + myCamera.setPosition(start_location); #ifdef MARKER_CAPTURE @@ -438,7 +438,7 @@ void reset_sensors() renderYawRate = 0; renderPitchRate = 0; - myAvatar.setBodyPosition(start_location); + myAvatar.setPosition(start_location); headMouseX = WIDTH/2; headMouseY = HEIGHT/2; @@ -551,7 +551,7 @@ void updateAvatar(float frametime) // If I'm in paint mode, send a voxel out to VOXEL server agents. if (::paintOn) { - glm::vec3 avatarPos = myAvatar.getBodyPosition(); + glm::vec3 avatarPos = myAvatar.getPosition(); // For some reason, we don't want to flip X and Z here. ::paintingVoxel.x = avatarPos.x/10.0; @@ -833,7 +833,7 @@ void display(void) //---------------------------------------------------- // set the camera to third-person view behind my av //---------------------------------------------------- - myCamera.setTargetPosition ( myAvatar.getBodyPosition() ); + myCamera.setTargetPosition ( myAvatar.getPosition() ); myCamera.setYaw ( 180.0 - myAvatar.getBodyYaw() ); myCamera.setPitch ( 0.0 ); // temporarily, this must be 0.0 or else bad juju myCamera.setRoll ( 0.0 ); @@ -1265,7 +1265,7 @@ void shiftPaintingColor() } void setupPaintingVoxel() { - glm::vec3 avatarPos = myAvatar.getBodyPosition(); + glm::vec3 avatarPos = myAvatar.getPosition(); ::paintingVoxel.x = avatarPos.z/-10.0; // voxel space x is negative z head space ::paintingVoxel.y = avatarPos.y/-10.0; // voxel space y is negative y head space diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 295348a098..fd20e099c0 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -69,7 +69,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { // and return the number of bytes to push the pointer // Body world position - memcpy(destinationBuffer, &_bodyPosition, sizeof(float) * 3); + memcpy(destinationBuffer, &_position, sizeof(float) * 3); destinationBuffer += sizeof(float) * 3; // Body rotation (NOTE: This needs to become a quaternion to save two bytes) @@ -125,7 +125,7 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { unsigned char* startPosition = sourceBuffer; // Body world position - memcpy(&_bodyPosition, sourceBuffer, sizeof(float) * 3); + memcpy(&_position, sourceBuffer, sizeof(float) * 3); sourceBuffer += sizeof(float) * 3; // Body rotation (NOTE: This needs to become a quaternion to save two bytes) @@ -171,14 +171,14 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { return sourceBuffer - startPosition; } -glm::vec3 AvatarData::getBodyPosition() { - return glm::vec3(_bodyPosition.x, - _bodyPosition.y, - _bodyPosition.z); +glm::vec3 AvatarData::getPosition() { + return glm::vec3(_position.x, + _position.y, + _position.z); } -void AvatarData::setBodyPosition(glm::vec3 bodyPosition) { - _bodyPosition = bodyPosition; +void AvatarData::setPosition(glm::vec3 position) { + _position = position; } void AvatarData::setHandPosition(glm::vec3 handPosition) { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index e133d965c5..c403a1683a 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -20,8 +20,8 @@ public: AvatarData* clone() const; - glm::vec3 getBodyPosition(); - void setBodyPosition(glm::vec3 bodyPosition); + glm::vec3 getPosition(); + void setPosition(glm::vec3 position); void setHandPosition(glm::vec3 handPosition); int getBroadcastData(unsigned char* destinationBuffer); @@ -75,7 +75,7 @@ public: void setCameraFarClip(float farClip) { _cameraFarClip = farClip; } protected: - glm::vec3 _bodyPosition; + glm::vec3 _position; glm::vec3 _handPosition; // Body rotation From 8a222da42fbf5467d26dadbc843eaa2686185b82 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 14:05:24 -0700 Subject: [PATCH 19/52] const int is unnecessary --- eve/src/main.cpp | 2 +- injector/src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index a228454f22..5a16556e06 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -85,7 +85,7 @@ void *injectAudio(void *args) { return NULL; } -int main(const int argc, const char* argv[]) { +int main(int argc, const char* argv[]) { // new seed for random audio sleep times srand(time(0)); diff --git a/injector/src/main.cpp b/injector/src/main.cpp index 7de6b030be..b110f7553c 100644 --- a/injector/src/main.cpp +++ b/injector/src/main.cpp @@ -93,7 +93,7 @@ bool processParameters(int parameterCount, char* parameterData[]) return true; }; -int main(const int argc, const char* argv[]) { +int main(int argc, const char* argv[]) { srand(time(0)); int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1)); From ceefda8ce12c4f8440fd479cb6037dd68d9df7d2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 14:09:09 -0700 Subject: [PATCH 20/52] add cstring for memset and memcpy --- libraries/shared/src/AudioInjector.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/shared/src/AudioInjector.cpp b/libraries/shared/src/AudioInjector.cpp index 6b0ba7203e..6e65c168d0 100644 --- a/libraries/shared/src/AudioInjector.cpp +++ b/libraries/shared/src/AudioInjector.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "SharedUtil.h" #include "PacketHeaders.h" From 3344016212a0f87f36820bad53e71f5daf6754d5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 14:12:21 -0700 Subject: [PATCH 21/52] SOLO_AGENT_TYPES needs a defined size --- libraries/shared/src/AgentList.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/AgentList.h b/libraries/shared/src/AgentList.h index d7459aafd3..76d6917168 100644 --- a/libraries/shared/src/AgentList.h +++ b/libraries/shared/src/AgentList.h @@ -22,7 +22,7 @@ const int MAX_PACKET_SIZE = 1500; const unsigned int AGENT_SOCKET_LISTEN_PORT = 40103; const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000; -extern const char SOLO_AGENT_TYPES[]; +extern const char SOLO_AGENT_TYPES[3]; extern char DOMAIN_HOSTNAME[]; extern char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup From 2b7095925d5932efb8edfd7fe7da96ee84cb4d18 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 15:45:29 -0700 Subject: [PATCH 22/52] add randomization of eve's position, face eve down z-axis --- eve/src/main.cpp | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index 5a16556e06..ed4ec36e98 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -15,8 +15,9 @@ #include #include -const int EVE_AGENT_LIST_PORT = 55441; -const float DATA_SEND_INTERVAL_MSECS = 10; +const float RANDOM_POSITION_MAX_DIMENSION = 5.0f; + +const float DATA_SEND_INTERVAL_MSECS = 15; const float MIN_AUDIO_SEND_INTERVAL_SECS = 10; const int MIN_ITERATIONS_BETWEEN_AUDIO_SENDS = (MIN_AUDIO_SEND_INTERVAL_SECS * 1000) / DATA_SEND_INTERVAL_MSECS; const int MAX_AUDIO_SEND_INTERVAL_SECS = 15; @@ -26,7 +27,7 @@ bool stopReceiveAgentDataThread; bool injectAudioThreadRunning = false; int TEMP_AUDIO_LISTEN_PORT = 55439; -UDPSocket audioSocket(TEMP_AUDIO_LISTEN_PORT); +// UDPSocket audioSocket(TEMP_AUDIO_LISTEN_PORT); void *receiveAgentData(void *args) { sockaddr senderAddress; @@ -77,7 +78,7 @@ void *injectAudio(void *args) { } // we have an active audio mixer we can send data to - eveAudioInjector->injectAudio(&::audioSocket, audioMixer->getActiveSocket()); +// eveAudioInjector->injectAudio(&::audioSocket, audioMixer->getActiveSocket()); } ::injectAudioThreadRunning = false; @@ -90,7 +91,7 @@ int main(int argc, const char* argv[]) { srand(time(0)); // create an AgentList instance to handle communication with other agents - AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LIST_PORT); + AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, 55441); // start telling the domain server that we are alive agentList->startDomainServerCheckInThread(); @@ -108,10 +109,14 @@ int main(int argc, const char* argv[]) { AvatarData eve = AvatarData(); // move eve away from the origin - eve.setBodyPosition(glm::vec3(3, 0, -3)); + // pick a random point inside a 10x10 grid - // turn her back towards the origin - eve.setBodyYaw(-45); + eve.setBodyPosition(glm::vec3(randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION), + 0, + randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION))); + + // face any instance of eve down the z-axis + eve.setBodyYaw(0); // put her hand out so somebody can shake it eve.setHandPosition(glm::vec3(eve.getBodyPosition()[0] - 0.2, @@ -129,8 +134,8 @@ int main(int argc, const char* argv[]) { timeval thisSend; double numMicrosecondsSleep = 0; - int numIterationsLeftBeforeAudioSend = 0; - pthread_t injectAudioThread; +// int numIterationsLeftBeforeAudioSend = 0; +// pthread_t injectAudioThread; while (true) { // update the thisSend timeval to the current time @@ -147,17 +152,18 @@ int main(int argc, const char* argv[]) { // use the UDPSocket instance attached to our agent list to send avatar data to mixer agentList->getAgentSocket().send(avatarMixer->getActiveSocket(), broadcastPacket, numBytesToSend); } - - if (numIterationsLeftBeforeAudioSend == 0) { - if (!::injectAudioThreadRunning) { - pthread_create(&injectAudioThread, NULL, injectAudio, (void*) &eveAudioInjector); - - numIterationsLeftBeforeAudioSend = randIntInRange(MIN_ITERATIONS_BETWEEN_AUDIO_SENDS, - MAX_ITERATIONS_BETWEEN_AUDIO_SENDS); - } - } else { - numIterationsLeftBeforeAudioSend--; - } + + // temporarily disable Eve's audio sending until the file is actually available on EC2 box +// if (numIterationsLeftBeforeAudioSend == 0) { +// if (!::injectAudioThreadRunning) { +// pthread_create(&injectAudioThread, NULL, injectAudio, (void*) &eveAudioInjector); +// +// numIterationsLeftBeforeAudioSend = randIntInRange(MIN_ITERATIONS_BETWEEN_AUDIO_SENDS, +// MAX_ITERATIONS_BETWEEN_AUDIO_SENDS); +// } +// } else { +// numIterationsLeftBeforeAudioSend--; +// } // sleep for the correct amount of time to have data send be consistently timed if ((numMicrosecondsSleep = (DATA_SEND_INTERVAL_MSECS * 1000) - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) { From a4244da27efded4db93731827214555afc88cb28 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 15:46:57 -0700 Subject: [PATCH 23/52] add randomization of eve's listening port on launch --- eve/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index ed4ec36e98..d1a82b860d 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -91,7 +91,7 @@ int main(int argc, const char* argv[]) { srand(time(0)); // create an AgentList instance to handle communication with other agents - AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, 55441); + AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, randIntInRange(1500, 65000)); // start telling the domain server that we are alive agentList->startDomainServerCheckInThread(); From 11986ca00f6d87727ef15af89f395f4db08547ed Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 15:58:06 -0700 Subject: [PATCH 24/52] add IP address to DS information output --- libraries/shared/src/AgentList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index 923052beb3..15c4abdd85 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -428,7 +428,7 @@ void *checkInWithDomainServer(void *args) { sockaddr_in tempAddress; memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length); strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr)); - printLog("Domain server: %s \n", DOMAIN_HOSTNAME); + printLog("Domain server: %s - %s\n", DOMAIN_HOSTNAME, DOMAIN_IP); } else { printLog("Failed lookup domainserver\n"); From 0014b045affddff54bce901f84edb0617284fe06 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Apr 2013 17:35:00 -0700 Subject: [PATCH 25/52] hard code eve's listen port again so she shows up on EC2 --- eve/src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index d1a82b860d..6dfe9ea606 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -15,6 +15,8 @@ #include #include +const int EVE_AGENT_LISTEN_PORT = 55441; + const float RANDOM_POSITION_MAX_DIMENSION = 5.0f; const float DATA_SEND_INTERVAL_MSECS = 15; @@ -91,7 +93,7 @@ int main(int argc, const char* argv[]) { srand(time(0)); // create an AgentList instance to handle communication with other agents - AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, randIntInRange(1500, 65000)); + AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LISTEN_PORT); // start telling the domain server that we are alive agentList->startDomainServerCheckInThread(); From 61d7a82fc6020b79f5916823788a4467e38632fc Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Tue, 23 Apr 2013 20:44:12 -0700 Subject: [PATCH 26/52] made lots of changes in the logic of how my avatar encounters other avatars and detects hand state --- interface/src/Head.cpp | 107 +++++++++++++++++++---------------------- interface/src/Head.h | 97 ++++++++++++++++++++----------------- 2 files changed, 102 insertions(+), 102 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index f4269a47bd..f93389511c 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -50,7 +50,7 @@ Head::Head(bool isMine) { _velocity = glm::vec3( 0.0, 0.0, 0.0 ); _thrust = glm::vec3( 0.0, 0.0, 0.0 ); _rotation = glm::quat( 0.0f, 0.0f, 0.0f, 0.0f ); - _closestOtherAvatar = 0; + _nearOtherAvatar = false; _bodyYaw = -90.0; _bodyPitch = 0.0; _bodyRoll = 0.0; @@ -62,7 +62,7 @@ Head::Head(bool isMine) { //_transmitterTimer = 0; _transmitterHz = 0.0; _transmitterPackets = 0; - _numOtherAvatarsInView = 0; + //_numOtherAvatars = 0; initializeSkeleton(); @@ -119,13 +119,11 @@ Head::Head(bool isMine) { _renderPitch = 0.0; _sphere = NULL; - - _collisionElipsoid.colliding = false; - _collisionElipsoid.position = glm::vec3( 0.0, 0.0, 0.0 ); - _collisionElipsoid.upVector = glm::vec3( 0.0, 0.0, 0.0 ); - _collisionElipsoid.girth = 0.0; - _collisionElipsoid.height = 0.0; - + + _handHolding.position = glm::vec3( 0.0, 0.0, 0.0 ); + _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); + _handHolding.force = 10.0f; + if (iris_texture.size() == 0) { switchToResourcesParentIfRequired(); unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file); @@ -133,20 +131,19 @@ Head::Head(bool isMine) { printLog("error %u: %s\n", error, lodepng_error_text(error)); } } - - for (int o=0; o::iterator agent = agentList->getAgents().begin(); agent != agentList->getAgents().end(); @@ -321,7 +318,8 @@ void Head::simulate(float deltaTime) { if (( agent->getLinkedData() != NULL && ( agent->getType() == AGENT_TYPE_AVATAR ) )) { Head *otherAvatar = (Head *)agent->getLinkedData(); - if ( _numOtherAvatarsInView < MAX_OTHER_AVATARS ) { + // if ( _numOtherAvatars < MAX_OTHER_AVATARS ) + { //------------------------------------------------------ // check for collisions with other avatars and respond @@ -334,27 +332,20 @@ void Head::simulate(float deltaTime) { otherAvatar->getBodyUpDirection(), deltaTime ); - - //----------------------------------------------------------- - // test other avatar hand position for proximity and state - //----------------------------------------------------------- - _otherAvatarHandPosition[ _numOtherAvatarsInView ] = otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); - _otherAvatarHandState [ _numOtherAvatarsInView ] = (int)otherAvatar->getHandState(); - - glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); - v -= _otherAvatarHandPosition[ _numOtherAvatarsInView ]; - //if ( otherAvatar->getHandState() == 1 ) - { - printf( "otherAvatar->getHandState() is %d\n", (int)otherAvatar->getHandState() ); - } + //------------------------------------------------- + // test other avatar hand position for proximity + //------------------------------------------------ + glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); + v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); float distance = glm::length( v ); if ( distance < _maxArmLength ) { if ( distance < closestDistance ) { closestDistance = distance; - _closestOtherAvatar = _numOtherAvatarsInView; - _numOtherAvatarsInView++; + _nearOtherAvatar = true; + _otherAvatar.handPosition = otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); + _otherAvatar.handState = (int)otherAvatar->getHandState(); } } } @@ -398,7 +389,7 @@ void Head::simulate(float deltaTime) { // reset hand and arm positions according to hand movement //------------------------------------------------------------ if (_usingBodySprings) { - updateHandMovement(); + updateHandMovement( deltaTime ); updateBodySprings( deltaTime ); } @@ -652,7 +643,6 @@ void Head::render(bool lookingInMirror) { glutSolidSphere( 1, 10, 10 ); glPopMatrix(); - if ( usingBigSphereCollisionTest ) { //--------------------------------------------------- // show TEST big sphere @@ -681,10 +671,10 @@ void Head::render(bool lookingInMirror) { if ( _isMine ) { if (_usingBodySprings) { - if ( _closestOtherAvatar != -1 ) { + if ( _nearOtherAvatar ) { glm::vec3 v1( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); - glm::vec3 v2( _otherAvatarHandPosition[ _closestOtherAvatar ] ); + glm::vec3 v2( _otherAvatar.handPosition ); glLineWidth( 8.0 ); glColor4f( 0.7f, 0.4f, 0.1f, 0.6 ); @@ -987,12 +977,6 @@ void Head::initializeSkeleton() { updateSkeleton(); } -/* -int Head::getHandState() { - return _handState; -} -*/ - void Head::calculateBoneLengths() { for (int b=0; b Date: Tue, 23 Apr 2013 21:07:40 -0700 Subject: [PATCH 27/52] fixed bug - didn't change bodyPosition in eve or voxel --- eve/src/main.cpp | 6 ++--- interface/src/Head.cpp | 35 ++++++++++++++++------------- voxel-server/src/VoxelAgentData.cpp | 2 +- voxel-server/src/main.cpp | 2 +- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index 6dfe9ea606..3e075f7ba0 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -113,7 +113,7 @@ int main(int argc, const char* argv[]) { // move eve away from the origin // pick a random point inside a 10x10 grid - eve.setBodyPosition(glm::vec3(randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION), + eve.setPosition(glm::vec3(randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION), 0, randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION))); @@ -121,9 +121,9 @@ int main(int argc, const char* argv[]) { eve.setBodyYaw(0); // put her hand out so somebody can shake it - eve.setHandPosition(glm::vec3(eve.getBodyPosition()[0] - 0.2, + eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2, 0.25, - eve.getBodyPosition()[2] + 0.1)); + eve.getPosition()[2] + 0.1)); // read eve's audio data AudioInjector eveAudioInjector("eve.raw"); diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index f0c071b9ee..e2b8003a53 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -1128,24 +1128,29 @@ void Head::updateHandMovement( float deltaTime ) { setHandState(_mousePressed); + bool atLeastOneAvatarIsGrasping = false; + + if ( getHandState() == 1 ) { atLeastOneAvatarIsGrasping = true; } + if ( _isMine ) { + if ( _otherAvatar.handState == 1 ) { + atLeastOneAvatarIsGrasping = true; + } + } + //--------------------------------------------------------------------- // if holding hands with another avatar, add a force to the hand... //--------------------------------------------------------------------- - if (( getHandState() == 1 ) - || ( _otherAvatar.handState == 1 )) { - //if ( _usingBodySprings ) - { - if ( _nearOtherAvatar ) { - - glm::vec3 vectorToOtherHand = _otherAvatar.handPosition - _handHolding.position; - glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; - - _handHolding.velocity *= 0.7; - _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; - _handHolding.position += _handHolding.velocity; - - _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; - } + if ( atLeastOneAvatarIsGrasping ) { + if ( _nearOtherAvatar ) { + + glm::vec3 vectorToOtherHand = _otherAvatar.handPosition - _handHolding.position; + glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; + + _handHolding.velocity *= 0.7; + _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; + _handHolding.position += _handHolding.velocity; + + _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; } } else { diff --git a/voxel-server/src/VoxelAgentData.cpp b/voxel-server/src/VoxelAgentData.cpp index 4476cff056..805b6363d7 100644 --- a/voxel-server/src/VoxelAgentData.cpp +++ b/voxel-server/src/VoxelAgentData.cpp @@ -19,7 +19,7 @@ VoxelAgentData::~VoxelAgentData() { } VoxelAgentData::VoxelAgentData(const VoxelAgentData &otherAgentData) { - memcpy(&_bodyPosition, &otherAgentData._bodyPosition, sizeof(_bodyPosition)); + memcpy(&_Position, &otherAgentData._Position, sizeof(_Position)); rootMarkerNode = new MarkerNode(); } diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 91fa2fd596..1d2b961d93 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -199,7 +199,7 @@ void *distributeVoxelsToListeners(void *args) { stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd, randomTree.rootNode, agentData->rootMarkerNode, - agentData->getBodyPosition(), + agentData->getPosition(), treeRoot, viewFrustum, ::viewFrustumCulling, From 61a17060c3f4c3796c21a4960a65409422bfba7d Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Tue, 23 Apr 2013 21:17:39 -0700 Subject: [PATCH 28/52] one more glitch... --- injector/src/main.cpp | 2 +- interface/src/Head.cpp | 24 ++++++++++++------------ voxel-server/src/VoxelAgentData.cpp | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/injector/src/main.cpp b/injector/src/main.cpp index b110f7553c..61327ec41b 100644 --- a/injector/src/main.cpp +++ b/injector/src/main.cpp @@ -91,7 +91,7 @@ bool processParameters(int parameterCount, char* parameterData[]) } } return true; -}; +};_Position int main(int argc, const char* argv[]) { diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index e2b8003a53..306252bc7e 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -1133,7 +1133,9 @@ void Head::updateHandMovement( float deltaTime ) { if ( getHandState() == 1 ) { atLeastOneAvatarIsGrasping = true; } if ( _isMine ) { if ( _otherAvatar.handState == 1 ) { - atLeastOneAvatarIsGrasping = true; + if ( _nearOtherAvatar ) { + atLeastOneAvatarIsGrasping = true; + } } } @@ -1141,17 +1143,15 @@ void Head::updateHandMovement( float deltaTime ) { // if holding hands with another avatar, add a force to the hand... //--------------------------------------------------------------------- if ( atLeastOneAvatarIsGrasping ) { - if ( _nearOtherAvatar ) { - - glm::vec3 vectorToOtherHand = _otherAvatar.handPosition - _handHolding.position; - glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; - - _handHolding.velocity *= 0.7; - _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; - _handHolding.position += _handHolding.velocity; - - _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; - } + + glm::vec3 vectorToOtherHand = _otherAvatar.handPosition - _handHolding.position; + glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; + + _handHolding.velocity *= 0.7; + _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; + _handHolding.position += _handHolding.velocity; + + _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; } else { _handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position; diff --git a/voxel-server/src/VoxelAgentData.cpp b/voxel-server/src/VoxelAgentData.cpp index 805b6363d7..e01ae90a69 100644 --- a/voxel-server/src/VoxelAgentData.cpp +++ b/voxel-server/src/VoxelAgentData.cpp @@ -19,7 +19,7 @@ VoxelAgentData::~VoxelAgentData() { } VoxelAgentData::VoxelAgentData(const VoxelAgentData &otherAgentData) { - memcpy(&_Position, &otherAgentData._Position, sizeof(_Position)); + memcpy(&_position, &otherAgentData._position, sizeof(_position)); rootMarkerNode = new MarkerNode(); } From 54aac82e9c3d715a8ee9784d0e8ca2f8cd47d2b0 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Tue, 23 Apr 2013 21:30:53 -0700 Subject: [PATCH 29/52] cleanup --- interface/src/Head.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 306252bc7e..28a7c53230 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -1131,6 +1131,7 @@ void Head::updateHandMovement( float deltaTime ) { bool atLeastOneAvatarIsGrasping = false; if ( getHandState() == 1 ) { atLeastOneAvatarIsGrasping = true; } + if ( _isMine ) { if ( _otherAvatar.handState == 1 ) { if ( _nearOtherAvatar ) { @@ -1138,7 +1139,7 @@ void Head::updateHandMovement( float deltaTime ) { } } } - + //--------------------------------------------------------------------- // if holding hands with another avatar, add a force to the hand... //--------------------------------------------------------------------- From 8135a45ccfe7b44217ece025d59501da74fbe275 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Tue, 23 Apr 2013 22:05:02 -0700 Subject: [PATCH 30/52] removed pinky orientation lines in avatar bones --- interface/src/Head.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 28a7c53230..de6ce91bbd 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -1132,13 +1132,13 @@ void Head::updateHandMovement( float deltaTime ) { if ( getHandState() == 1 ) { atLeastOneAvatarIsGrasping = true; } - if ( _isMine ) { - if ( _otherAvatar.handState == 1 ) { + //if ( _isMine ) { + //if ( _otherAvatar.handState == 1 ) { if ( _nearOtherAvatar ) { atLeastOneAvatarIsGrasping = true; } - } - } + //} + //} //--------------------------------------------------------------------- // if holding hands with another avatar, add a force to the hand... @@ -1146,7 +1146,7 @@ void Head::updateHandMovement( float deltaTime ) { if ( atLeastOneAvatarIsGrasping ) { glm::vec3 vectorToOtherHand = _otherAvatar.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 += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; @@ -1219,7 +1219,7 @@ void Head::renderBody() { //renderBoneAsBlock( (AvatarBoneID)b); //render bone orientation - renderOrientationDirections( _bone[b].springyPosition, _bone[b].orientation, _bone[b].radius * 2.0 ); + //renderOrientationDirections( _bone[b].springyPosition, _bone[b].orientation, _bone[b].radius * 2.0 ); if ( _usingBodySprings ) { glColor3fv( skinColor ); From 0332b455cbe986e5fced4c847e50bca0c82cfada Mon Sep 17 00:00:00 2001 From: tosh Date: Wed, 24 Apr 2013 13:33:53 +0200 Subject: [PATCH 31/52] removes leftover something and misplaced const-qualification that keeps it from compiling --- injector/src/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/injector/src/main.cpp b/injector/src/main.cpp index 61327ec41b..028de6cb04 100644 --- a/injector/src/main.cpp +++ b/injector/src/main.cpp @@ -42,7 +42,7 @@ void usage(void) std::cout << " -c FLOAT,FLOAT,FLOAT,FLOAT X,Y,Z,YAW position in universe where audio will be originating from and direction. Defaults to 0,0,0,0" << std::endl; std::cout << " -a 0-255 Attenuation curve modifier, defaults to 255" << std::endl; std::cout << " -f FILENAME Name of audio source file. Required - RAW format, 22050hz 16bit signed mono" << std::endl; -}; +} bool processParameters(int parameterCount, char* parameterData[]) { @@ -91,9 +91,9 @@ bool processParameters(int parameterCount, char* parameterData[]) } } return true; -};_Position +}; -int main(int argc, const char* argv[]) { +int main(int argc, char* argv[]) { srand(time(0)); int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1)); From ee9ae3f2208136e7dc499d92faa8b3b9ee54c73b Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 24 Apr 2013 08:13:15 -0700 Subject: [PATCH 32/52] improved avatar hand-holding logic --- interface/src/Head.cpp | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index de6ce91bbd..9770bcbce1 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -1006,11 +1006,14 @@ void Head::updateSkeleton() { _bone[b].position = _bone[ _bone[b].parent ].position; } - ///TEST! - get this working and then add a comment; JJV + //------------------------------------------------------------------------------------- + // if this is not my avatar, then hand position comes from transmitted data + //------------------------------------------------------------------------------------- if ( ! _isMine ) { _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handPosition; } + // the following will be replaced by a proper rotation... float xx = glm::dot( _bone[b].defaultPosePosition, _bone[b].orientation.getRight() ); float yy = glm::dot( _bone[b].defaultPosePosition, _bone[b].orientation.getUp () ); float zz = glm::dot( _bone[b].defaultPosePosition, _bone[b].orientation.getFront() ); @@ -1024,7 +1027,6 @@ void Head::updateSkeleton() { } } - void Head::initializeBodySprings() { for (int b=0; b Date: Wed, 24 Apr 2013 11:02:23 -0700 Subject: [PATCH 33/52] added behavior in Eve for alternating between grasping and ungrasping hand (tho unable to test transmission). Also, improved readability of hand grasping logic in Head.cpp --- eve/src/main.cpp | 15 ++++++++++++++- injector/src/main.cpp | 2 +- interface/src/Head.cpp | 32 ++++++++++++++++++++++++-------- interface/src/Head.h | 4 +--- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index 3e075f7ba0..0166f8e615 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -27,6 +27,7 @@ const float MAX_ITERATIONS_BETWEEN_AUDIO_SENDS = (MAX_AUDIO_SEND_INTERVAL_SECS * bool stopReceiveAgentDataThread; bool injectAudioThreadRunning = false; +int handStateTimer = 0; int TEMP_AUDIO_LISTEN_PORT = 55439; // UDPSocket audioSocket(TEMP_AUDIO_LISTEN_PORT); @@ -124,7 +125,19 @@ int main(int argc, const char* argv[]) { eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2, 0.25, eve.getPosition()[2] + 0.1)); - + + // simulate the effect of pressing and un-pressing the mouse button/pad + handStateTimer ++; + if ( handStateTimer == 100 ) { + eve.setHandState(1); + } + if ( handStateTimer == 150 ) { + eve.setHandState(0); + } + if ( handStateTimer >= 200 ) { + handStateTimer = 0; + } + // read eve's audio data AudioInjector eveAudioInjector("eve.raw"); diff --git a/injector/src/main.cpp b/injector/src/main.cpp index 61327ec41b..b110f7553c 100644 --- a/injector/src/main.cpp +++ b/injector/src/main.cpp @@ -91,7 +91,7 @@ bool processParameters(int parameterCount, char* parameterData[]) } } return true; -};_Position +}; int main(int argc, const char* argv[]) { diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 9770bcbce1..a34d061ab5 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -48,7 +48,6 @@ Head::Head(bool isMine) { _velocity = glm::vec3( 0.0, 0.0, 0.0 ); _thrust = glm::vec3( 0.0, 0.0, 0.0 ); _rotation = glm::quat( 0.0f, 0.0f, 0.0f, 0.0f ); - _nearOtherAvatar = false; _bodyYaw = -90.0; _bodyPitch = 0.0; _bodyRoll = 0.0; @@ -130,6 +129,7 @@ Head::Head(bool isMine) { } } + _otherAvatar.nearby = false; _otherAvatar.handPosition = glm::vec3( 0.0f, 0.0f, 0.0f ); _otherAvatar.handState = 0; } @@ -141,7 +141,7 @@ Head::Head(const Head &otherAvatar) { _velocity = otherAvatar._velocity; _thrust = otherAvatar._thrust; _rotation = otherAvatar._rotation; - _nearOtherAvatar = otherAvatar._nearOtherAvatar; + _otherAvatar.nearby = otherAvatar._otherAvatar.nearby; _bodyYaw = otherAvatar._bodyYaw; _bodyPitch = otherAvatar._bodyPitch; _bodyRoll = otherAvatar._bodyRoll; @@ -303,7 +303,7 @@ void Head::simulate(float deltaTime) { //------------------------------------------------------------- if ( _isMine ) { - _nearOtherAvatar = false; + _otherAvatar.nearby = false; float closestDistance = 10000.0f; AgentList * agentList = AgentList::getInstance(); @@ -341,7 +341,7 @@ void Head::simulate(float deltaTime) { if ( distance < _maxArmLength ) { if ( distance < closestDistance ) { closestDistance = distance; - _nearOtherAvatar = true; + _otherAvatar.nearby = true; _otherAvatar.handPosition = otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); _otherAvatar.handState = (int)otherAvatar->getHandState(); } @@ -669,7 +669,7 @@ void Head::render(bool lookingInMirror) { if ( _isMine ) { if (_usingBodySprings) { - if ( _nearOtherAvatar ) { + if ( _otherAvatar.nearby ) { glm::vec3 v1( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); glm::vec3 v2( _otherAvatar.handPosition ); @@ -1130,12 +1130,28 @@ void Head::updateHandMovement( float deltaTime ) { setHandState(_mousePressed); + if ( _otherAvatar.nearby ) { + if ( _otherAvatar.handState == 1 ) { + printf( "(1)" ); + } + //else { + // printf( "(0)" ); + //} + + if ( _handState == 1 ) { + printf( "1" ); + } + else { + printf( "0" ); + } + } + //--------------------------------------------------------------------- // if holding hands with another avatar, add a force to the hand... //--------------------------------------------------------------------- - if (( getHandState() == 1 ) + if (( _handState == 1 ) || ( _otherAvatar.handState == 1 )) { - if ( _nearOtherAvatar ) { + if ( _otherAvatar.nearby ) { glm::vec3 vectorToOtherHand = _otherAvatar.handPosition - _handHolding.position; glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; @@ -1151,7 +1167,7 @@ void Head::updateHandMovement( float deltaTime ) { _handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position; _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); } - + //------------------------------------------------------------------------------- // determine the arm vector //------------------------------------------------------------------------------- diff --git a/interface/src/Head.h b/interface/src/Head.h index 428ba2228a..1e0a346a35 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -102,11 +102,11 @@ struct AvatarHandHolding struct OtherAvatar { + bool nearby; glm::vec3 handPosition; int handState; }; - struct AvatarBone { AvatarBoneID parent; // which bone is this bone connected to? @@ -191,7 +191,6 @@ class Head : public AvatarData { glm::vec3 getHeadPosition(); glm::vec3 getBonePosition( AvatarBoneID b ); glm::vec3 getBodyUpDirection(); - //int getHandState(); float getGirth(); float getHeight(); @@ -233,7 +232,6 @@ class Head : public AvatarData { OtherAvatar _otherAvatar; bool _mousePressed; float _bodyYawDelta; - bool _nearOtherAvatar; bool _usingBodySprings; glm::vec3 _movedHandOffset; float _springVelocityDecay; From a5ea1dca7e3384123cc42a1efb96cb0035af8257 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 Apr 2013 11:16:13 -0700 Subject: [PATCH 34/52] fix incorrect debugging of agent local and public addresses --- libraries/shared/src/Agent.cpp | 25 +++++++------------------ libraries/shared/src/UDPSocket.cpp | 12 ++++++++++++ libraries/shared/src/UDPSocket.h | 1 + 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/libraries/shared/src/Agent.cpp b/libraries/shared/src/Agent.cpp index bb49783210..3a92e6c05e 100644 --- a/libraries/shared/src/Agent.cpp +++ b/libraries/shared/src/Agent.cpp @@ -261,30 +261,19 @@ float Agent::getAverageKilobitsPerSecond() { } void Agent::printLog(Agent const& agent) { - - sockaddr_in *agentPublicSocket = (sockaddr_in *) agent.publicSocket; - sockaddr_in *agentLocalSocket = (sockaddr_in *) agent.localSocket; - const char* publicAddressString = (agentPublicSocket == NULL) - ? "Unknown" - : inet_ntoa(agentPublicSocket->sin_addr); - unsigned short publicAddressPort = (agentPublicSocket == NULL) - ? 0 - : ntohs(agentPublicSocket->sin_port); + char publicAddressBuffer[16] = {'\0'}; + unsigned short publicAddressPort = loadBufferWithSocketInfo(publicAddressBuffer, agent.publicSocket); + + char localAddressBuffer[16] = {'\0'}; + unsigned short localAddressPort = loadBufferWithSocketInfo(localAddressBuffer, agent.localSocket); - const char* localAddressString = (agentLocalSocket == NULL) - ? "Unknown" - : inet_ntoa(agentLocalSocket->sin_addr); - unsigned short localAddressPort = (agentLocalSocket == NULL) - ? 0 - : ntohs(agentPublicSocket->sin_port); - ::printLog("ID: %d T: %s (%c) PA: %s:%d LA: %s:%d\n", agent.agentId, agent.getTypeName(), agent.type, - publicAddressString, + publicAddressBuffer, publicAddressPort, - localAddressString, + localAddressBuffer, localAddressPort); } \ No newline at end of file diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index 000f0e3d7d..0fa5ce08a4 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -107,6 +107,18 @@ int getLocalAddress() { return localAddress; } +unsigned short loadBufferWithSocketInfo(char *addressBuffer, sockaddr *socket) { + if (socket != NULL) { + char *copyBuffer = inet_ntoa(((sockaddr_in*) socket)->sin_addr); + memcpy(addressBuffer, copyBuffer, strlen(copyBuffer)); + return htons(((sockaddr_in*) socket)->sin_port); + } else { + const char* unknownAddress = "Unknown"; + memcpy(addressBuffer, unknownAddress, strlen(unknownAddress)); + return 0; + } +} + UDPSocket::UDPSocket(int listeningPort) { init(); // create the socket diff --git a/libraries/shared/src/UDPSocket.h b/libraries/shared/src/UDPSocket.h index f20585bbd4..2bc5638b5e 100644 --- a/libraries/shared/src/UDPSocket.h +++ b/libraries/shared/src/UDPSocket.h @@ -36,5 +36,6 @@ int packSocket(unsigned char *packStore, in_addr_t inAddress, in_port_t networkO int packSocket(unsigned char *packStore, sockaddr *socketToPack); int unpackSocket(unsigned char *packedData, sockaddr *unpackDestSocket); int getLocalAddress(); +unsigned short loadBufferWithSocketInfo(char *addressBuffer, sockaddr *socket); #endif /* defined(__interface__UDPSocket__) */ From 78aa4fdf80f207b2f41200a4c9f182c07285ea6b Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 24 Apr 2013 11:26:59 -0700 Subject: [PATCH 35/52] Simplified average loudness calculation, mouths and eyebrows of other people now move again! --- interface/src/Audio.cpp | 7 +++---- interface/src/Audio.h | 2 +- interface/src/AudioData.h | 1 - interface/src/Head.cpp | 18 ++++++++++++++++-- interface/src/main.cpp | 6 +----- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 9dbfdbf07f..17bb5c310b 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -130,7 +130,7 @@ int audioCallback (const void *inputBuffer, loudness /= BUFFER_LENGTH_SAMPLES; data->lastInputLoudness = loudness; - data->averagedInputLoudness = 0.66*data->averagedInputLoudness + 0.33*loudness; + // // If scope is turned on, copy input buffer to scope // @@ -510,9 +510,8 @@ error: } -void Audio::getInputLoudness(float * lastLoudness, float * averageLoudness) { - *lastLoudness = audioData->lastInputLoudness; - *averageLoudness = audioData->averagedInputLoudness; +const float Audio::getInputLoudness() { + return audioData->lastInputLoudness; } void Audio::render(int screenWidth, int screenHeight) diff --git a/interface/src/Audio.h b/interface/src/Audio.h index f983a315e0..3e74596402 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -25,7 +25,7 @@ public: bool getMixerLoopbackFlag(); void setMixerLoopbackFlag(bool newMixerLoopbackFlag); - void getInputLoudness(float * lastLoudness, float * averageLoudness); + const float getInputLoudness(); void updateMixerParams(in_addr_t mixerAddress, in_port_t mixerPort); void setWalkingState(bool newWalkState); diff --git a/interface/src/AudioData.h b/interface/src/AudioData.h index ca7d5ec8b5..fdc15998f0 100644 --- a/interface/src/AudioData.h +++ b/interface/src/AudioData.h @@ -36,7 +36,6 @@ class AudioData { int wasStarved; float lastInputLoudness; - float averagedInputLoudness; bool mixerLoopbackFlag; bool playWalkSound; diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 9770bcbce1..896562b21e 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -566,6 +566,14 @@ void Head::simulate(float deltaTime) { _head.eyebrowRoll [1] *=-1; } } + + // + // Update audio trailing average for rendering facial animations + // + + const float AUDIO_AVERAGING_SECS = 0.05; + _head.averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS)*_head.averageLoudness + + (deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness; } @@ -740,16 +748,22 @@ void Head::renderHead(bool lookingInMirror) { } glPopMatrix(); - // _eyebrows + // + // Update audio attack data for facial animation (eyebrows and mouth) + // + _head.audioAttack = 0.9 * _head.audioAttack + 0.1 * fabs(_audioLoudness - _head.lastLoudness); _head.lastLoudness = _audioLoudness; - + + const float BROW_LIFT_THRESHOLD = 100; if (_head.audioAttack > BROW_LIFT_THRESHOLD) _head.browAudioLift += sqrt(_head.audioAttack) / 1000.0; _head.browAudioLift *= .90; + + // Render Eyebrows glPushMatrix(); glTranslatef(-_head.interBrowDistance / 2.0,0.4,0.45); for(side = 0; side < 2; side++) { diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 119473ef9e..a20ad0e3a2 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -503,11 +503,8 @@ void updateAvatar(float frametime) myAvatar.setRenderPitch(renderPitch + renderPitchRate); // Get audio loudness data from audio input device - float loudness, averageLoudness; #ifndef _WIN32 - audio.getInputLoudness(&loudness, &averageLoudness); - myAvatar.setLoudness(loudness); - myAvatar.setAverageLoudness(averageLoudness); + myAvatar.setLoudness(audio.getInputLoudness()); #endif // Update Avatar with latest camera and view frustum data... @@ -1063,7 +1060,6 @@ int setNoise(int state) { int setGyroLook(int state) { int iRet = setValue(state, &::gyroLook); - std::cout << "gyro look" << ::gyroLook << "\n"; return iRet; } From 4e7f1ee4227f3fd573e4bf7eaa152c9cd8d4c28b Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 24 Apr 2013 11:39:43 -0700 Subject: [PATCH 36/52] more cleanup of hand holding code --- eve/src/main.cpp | 2 +- interface/src/Head.cpp | 102 ++++++++++++++++++++--------------------- 2 files changed, 51 insertions(+), 53 deletions(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index 0166f8e615..903a2e6c96 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -137,7 +137,7 @@ int main(int argc, const char* argv[]) { if ( handStateTimer >= 200 ) { handStateTimer = 0; } - + // read eve's audio data AudioInjector eveAudioInjector("eve.raw"); diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index a34d061ab5..cf78625d4f 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -59,7 +59,6 @@ Head::Head(bool isMine) { //_transmitterTimer = 0; _transmitterHz = 0.0; _transmitterPackets = 0; - //_numOtherAvatars = 0; initializeSkeleton(); @@ -307,8 +306,6 @@ void Head::simulate(float deltaTime) { float closestDistance = 10000.0f; AgentList * agentList = AgentList::getInstance(); - - //_numOtherAvatars = 0; for(std::vector::iterator agent = agentList->getAgents().begin(); agent != agentList->getAgents().end(); @@ -316,35 +313,31 @@ void Head::simulate(float deltaTime) { if (( agent->getLinkedData() != NULL && ( agent->getType() == AGENT_TYPE_AVATAR ) )) { Head *otherAvatar = (Head *)agent->getLinkedData(); - // if ( _numOtherAvatars < MAX_OTHER_AVATARS ) - { - - //------------------------------------------------------ - // check for collisions with other avatars and respond - //------------------------------------------------------ - updateAvatarCollisionDetectionAndResponse - ( - otherAvatar->getPosition(), - otherAvatar->getGirth(), - otherAvatar->getHeight(), - otherAvatar->getBodyUpDirection(), - deltaTime - ); - - //------------------------------------------------- - // test other avatar hand position for proximity - //------------------------------------------------ - glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); - v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); - - float distance = glm::length( v ); - if ( distance < _maxArmLength ) { - if ( distance < closestDistance ) { - closestDistance = distance; - _otherAvatar.nearby = true; - _otherAvatar.handPosition = otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); - _otherAvatar.handState = (int)otherAvatar->getHandState(); - } + //------------------------------------------------------ + // check for collisions with other avatars and respond + //------------------------------------------------------ + updateAvatarCollisionDetectionAndResponse + ( + otherAvatar->getPosition(), + otherAvatar->getGirth(), + otherAvatar->getHeight(), + otherAvatar->getBodyUpDirection(), + deltaTime + ); + + //------------------------------------------------- + // test other avatar hand position for proximity + //------------------------------------------------ + glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); + v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); + + float distance = glm::length( v ); + if ( distance < _maxArmLength ) { + if ( distance < closestDistance ) { + closestDistance = distance; + _otherAvatar.nearby = true; + _otherAvatar.handPosition = otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); + _otherAvatar.handState = (int)otherAvatar->getHandState(); } } } @@ -1130,13 +1123,14 @@ void Head::updateHandMovement( float deltaTime ) { setHandState(_mousePressed); + /* if ( _otherAvatar.nearby ) { if ( _otherAvatar.handState == 1 ) { printf( "(1)" ); } - //else { - // printf( "(0)" ); - //} + else { + printf( "(0)" ); + } if ( _handState == 1 ) { printf( "1" ); @@ -1145,27 +1139,31 @@ void Head::updateHandMovement( float deltaTime ) { printf( "0" ); } } + */ //--------------------------------------------------------------------- - // if holding hands with another avatar, add a force to the hand... + // if I am holding hands with another avatar, a force is added + // to my hand, causing it to move closer to the other avatar's hand... //--------------------------------------------------------------------- - if (( _handState == 1 ) - || ( _otherAvatar.handState == 1 )) { + if ( _isMine ) + { if ( _otherAvatar.nearby ) { - - glm::vec3 vectorToOtherHand = _otherAvatar.handPosition - _handHolding.position; - glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; - - _handHolding.velocity *= 0.7; - _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; - _handHolding.position += _handHolding.velocity; - - _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; - } - } - else { - _handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position; - _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); + if (( getHandState() == 1 ) + || ( _otherAvatar.handState == 1 )) { + glm::vec3 vectorToOtherHand = _otherAvatar.handPosition - _handHolding.position; + glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; + + _handHolding.velocity *= 0.7; + _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; + _handHolding.position += _handHolding.velocity; + + _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; + } + } + else { + _handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position; + _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); + } } //------------------------------------------------------------------------------- From 63a581dae4630e89e67c56c298c9256585d9290d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 24 Apr 2013 11:47:44 -0700 Subject: [PATCH 37/52] Added normals to voxel geometry, enabling lighting. --- interface/src/VoxelSystem.cpp | 151 ++++++++++++++++++++-------------- interface/src/VoxelSystem.h | 5 +- 2 files changed, 91 insertions(+), 65 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 9e50ae80f2..8bf6222aec 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -23,25 +23,27 @@ const int MAX_VOXELS_PER_SYSTEM = 250000; -const int VERTICES_PER_VOXEL = 8; +const int VERTICES_PER_VOXEL = 24; const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int INDICES_PER_VOXEL = 3 * 12; -float identityVertices[] = { 0, 0, 0, - 1, 0, 0, - 1, 1, 0, - 0, 1, 0, - 0, 0, 1, - 1, 0, 1, - 1, 1, 1, - 0, 1, 1 }; +float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, + 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, + 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 }; -GLubyte identityIndices[] = { 0,1,2, 0,2,3, - 0,1,5, 0,4,5, - 0,3,7, 0,4,7, - 1,2,6, 1,5,6, - 2,3,7, 2,6,7, - 4,5,6, 4,6,7 }; +GLfloat identityNormals[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1, + 0,0,+1, 0,0,+1, 0,0,+1, 0,0,+1, + 0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0, + 0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0, + -1,0,0, +1,0,0, +1,0,0, -1,0,0, + -1,0,0, +1,0,0, +1,0,0, -1,0,0 }; + +GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- . + 8,9,13, 8,13,12, // Y- + 16,23,19, 16,20,23, // X- + 17,18,22, 17,22,21, // X+ + 10,11,15, 10,15,14, // Y+ + 4,5,6, 4,6,7 }; // Z+ . VoxelSystem::VoxelSystem() { voxelsRendered = 0; @@ -49,7 +51,7 @@ VoxelSystem::VoxelSystem() { pthread_mutex_init(&bufferWriteLock, NULL); } -VoxelSystem::~VoxelSystem() { +VoxelSystem::~VoxelSystem() { delete[] readVerticesArray; delete[] writeVerticesArray; delete[] readColorsArray; @@ -70,9 +72,9 @@ void VoxelSystem::setViewerHead(Head *newViewerHead) { // Complaints: Brad :) // To Do: Need to add color data to the file. void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { - + tree->loadVoxelsFile(fileName,wantColorRandomizer); - + copyWrittenDataToReadArrays(); } @@ -118,7 +120,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { unsigned char command = *sourceBuffer; unsigned char *voxelData = sourceBuffer + 1; - + switch(command) { case PACKET_HEADER_VOXEL_DATA: // ask the VoxelTree to read the bitstream into the tree @@ -131,7 +133,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { case PACKET_HEADER_Z_COMMAND: // the Z command is a special command that allows the sender to send high level semantic - // requests, like erase all, or add sphere scene, different receivers may handle these + // requests, like erase all, or add sphere scene, different receivers may handle these // messages differently char* packetData = (char *)sourceBuffer; char* command = &packetData[1]; // start of the command @@ -152,7 +154,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { } break; } - + setupNewVoxelsForDrawing(); return numBytes; } @@ -212,11 +214,11 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosi for (int i = 0; i < 8; i++) { // check if there is a child here if (currentNode->children[i] != NULL) { - + glm::vec3 childNodePosition; copyFirstVertexForCode(currentNode->children[i]->octalCode,(float*)&childNodePosition); childNodePosition *= (float)TREE_SCALE; // scale it up - + /**** disabled ************************************************************************************************ // Note: Stephen, I intentionally left this in so you would talk to me about it. Here's the deal, this code // doesn't seem to work correctly. It returns X and Z flipped and the values are negative. Since we use the @@ -226,7 +228,7 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosi // calculate the child's position based on the parent position for (int j = 0; j < 3; j++) { childNodePosition[j] = nodePosition[j]; - + if (oneAtBit(branchIndexWithDescendant(currentNode->octalCode,currentNode->children[i]->octalCode),(7 - j))) { childNodePosition[j] -= (powf(0.5, *currentNode->children[i]->octalCode) * TREE_SCALE); } @@ -243,13 +245,13 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosi float startVertex[3]; copyFirstVertexForCode(currentNode->octalCode,(float*)&startVertex); float voxelScale = 1 / powf(2, *currentNode->octalCode); - + // populate the array with points for the 8 vertices // and RGB color for each added vertex for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { *writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); *(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->getColor()[j % 3]; - + writeVerticesEndPointer++; } voxelsAdded++; @@ -271,7 +273,7 @@ void VoxelSystem::init() { readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; - + // populate the indicesArray // this will not change given new voxels, so we can set it all up now for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { @@ -279,84 +281,107 @@ void VoxelSystem::init() { int voxelIndexOffset = n * INDICES_PER_VOXEL; GLuint *currentIndicesPos = indicesArray + voxelIndexOffset; int startIndex = (n * VERTICES_PER_VOXEL); - + for (int i = 0; i < INDICES_PER_VOXEL; i++) { // add indices for this side of the cube currentIndicesPos[i] = startIndex + identityIndices[i]; } } - + + GLfloat *normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + GLfloat *normalsArrayEndPointer = normalsArray; + + // populate the normalsArray + for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { + for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) { + *(normalsArrayEndPointer++) = identityNormals[i]; + } + } + // VBO for the verticesArray glGenBuffers(1, &vboVerticesID); glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); - + + // VBO for the normalsArray + glGenBuffers(1, &vboNormalsID); + glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); + glBufferData(GL_ARRAY_BUFFER, + VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, + normalsArray, GL_STATIC_DRAW); + // VBO for colorsArray glGenBuffers(1, &vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); - + // VBO for the indicesArray glGenBuffers(1, &vboIndicesID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, indicesArray, GL_STATIC_DRAW); - - // delete the indices array that is no longer needed + + // delete the indices and normals arrays that are no longer needed delete[] indicesArray; + delete[] normalsArray; } void VoxelSystem::render() { glPushMatrix(); - + if (readVerticesEndPointer != readVerticesArray) { // try to lock on the buffer write // just avoid pulling new data if it is currently being written if (pthread_mutex_trylock(&bufferWriteLock) == 0) { - + glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLfloat), readVerticesArray); - + glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLubyte), readColorsArray); - + readVerticesEndPointer = readVerticesArray; - + pthread_mutex_unlock(&bufferWriteLock); } } // tell OpenGL where to find vertex and color information glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); - + glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); glVertexPointer(3, GL_FLOAT, 0, 0); - + + glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); + glNormalPointer(GL_FLOAT, 0, 0); + glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); - + // draw the number of voxels we have glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); glScalef(10, 10, 10); glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0); - + // deactivate vertex and color arrays after drawing glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); - + // bind with 0 to switch back to normal operation glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - + // scale back down to 1 so heads aren't massive glPopMatrix(); } void VoxelSystem::simulate(float deltaTime) { - + } int VoxelSystem::_nodeCount = 0; @@ -367,7 +392,7 @@ bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraDa if (down) { return true; } - + _nodeCount++; if (node->isColored()) { nodeColor newColor = { 0,0,0,1 }; @@ -398,9 +423,9 @@ bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* if (down) { return true; } - + _nodeCount++; - + // always false colorize unsigned char newR = randomColorValue(150); unsigned char newG = randomColorValue(150); @@ -427,7 +452,7 @@ bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraD if (down) { return true; } - + _nodeCount++; node->setFalseColored(false); //printf("setting true color for node %d\n",_nodeCount); @@ -448,23 +473,23 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* if (down) { return true; } - + ViewFrustum* viewFrustum = (ViewFrustum*) extraData; - + _nodeCount++; - + // only do this for truely colored voxels... if (node->isColored()) { // first calculate the AAbox for the voxel AABox voxelBox; node->getAABox(voxelBox); - + voxelBox.scale(TREE_SCALE); - + printf("voxelBox corner=(%f,%f,%f) x=%f\n", voxelBox.getCorner().x, voxelBox.getCorner().y, voxelBox.getCorner().z, voxelBox.getSize().x); - + // If the voxel is outside of the view frustum, then false color it red if (ViewFrustum::OUTSIDE == viewFrustum->boxInFrustum(voxelBox)) { // Out of view voxels are colored RED @@ -481,7 +506,7 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* } else { printf("voxel not colored, don't consider it\n"); } - + return true; // keep going! } @@ -503,7 +528,7 @@ bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool d } ViewFrustum* viewFrustum = (ViewFrustum*) extraData; - + // only do this for truly colored voxels... if (node->isColored()) { @@ -517,10 +542,10 @@ bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool d // scale up the node position nodePosition = nodePosition*(float)TREE_SCALE; - + float halfUnitForVoxel = powf(0.5, *node->octalCode) * (0.5 * TREE_SCALE); glm::vec3 viewerPosition = viewFrustum->getPosition(); - + //printf("halfUnitForVoxel=%f\n",halfUnitForVoxel); //printf("viewer.x=%f y=%f z=%f \n", viewerPosition.x, viewerPosition.y, viewerPosition.z); //printf("node.x=%f y=%f z=%f \n", nodePosition.x, nodePosition.y, nodePosition.z); @@ -533,7 +558,7 @@ bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool d _nodeCount++; float distanceRatio = (_minDistance==_maxDistance) ? 1 : (distance - _minDistance)/(_maxDistance - _minDistance); - + // We want to colorize this in 16 bug chunks of color const unsigned char maxColor = 255; const unsigned char colorBands = 16; @@ -542,7 +567,7 @@ bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool d unsigned char newR = (colorBand*(gradientOver/colorBands))+(maxColor-gradientOver); unsigned char newG = 0; unsigned char newB = 0; - //printf("Setting color down=%s distance=%f min=%f max=%f distanceRatio=%f color=%d \n", + //printf("Setting color down=%s distance=%f min=%f max=%f distanceRatio=%f color=%d \n", // (down ? "TRUE" : "FALSE"), distance, _minDistance, _maxDistance, distanceRatio, (int)newR); node->setFalseColor(newR,newG,newB); @@ -568,7 +593,7 @@ bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, //printf("getDistanceFromViewRangeOperation() down=%s\n",(down ? "TRUE" : "FALSE")); ViewFrustum* viewFrustum = (ViewFrustum*) extraData; - + // only do this for truly colored voxels... if (node->isColored()) { @@ -614,7 +639,7 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { printf("determining distance range for %d nodes\n",_nodeCount); _nodeCount = 0; - + tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); printf("setting in distance false color for %d nodes\n",_nodeCount); setupNewVoxelsForDrawing(); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 4c309a92ea..9d831ee5f2 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -25,10 +25,10 @@ class VoxelSystem : public AgentData { public: VoxelSystem(); ~VoxelSystem(); - + int parseData(unsigned char* sourceBuffer, int numBytes); VoxelSystem* clone() const; - + void init(); void simulate(float deltaTime); void render(); @@ -76,6 +76,7 @@ private: GLubyte *writeColorsArray; GLfloat *writeVerticesEndPointer; GLuint vboVerticesID; + GLuint vboNormalsID; GLuint vboColorsID; GLuint vboIndicesID; pthread_mutex_t bufferWriteLock; From cfbe8a719c3b38873b7a4e3bce33dc547a032b49 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 Apr 2013 12:39:25 -0700 Subject: [PATCH 38/52] fix getter for hand state in AvatarData --- interface/src/Head.cpp | 2 +- libraries/avatars/src/AvatarData.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 9770bcbce1..ac6e412b1e 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -1263,7 +1263,7 @@ void Head::renderBody() { //--------------------------------------------------------- // if the hand is grasping, show it... //--------------------------------------------------------- - if (( _usingBodySprings ) && ( getHandState() == 1 )) { + if (( _usingBodySprings ) && ( _handState == 1 )) { glPushMatrix(); glTranslatef ( diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index c403a1683a..e404efaf84 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -48,7 +48,7 @@ public: // Hand State void setHandState(char s) { _handState = s; }; - const float getHandState() const {return _handState; }; //@Philip - shouldn't this be an int or a char? + const char getHandState() const {return _handState; }; // Instantaneous audio loudness to drive mouth/facial animation void setLoudness(float l) { _audioLoudness = l; }; From 33f95c696bafbcab9242ae06c9420702b73b8cc4 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 24 Apr 2013 13:12:08 -0700 Subject: [PATCH 39/52] Fixes per code review --- interface/src/Audio.cpp | 2 +- interface/src/Audio.h | 2 +- interface/src/Head.cpp | 11 +++-------- interface/src/main.cpp | 4 +--- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 17bb5c310b..287325c090 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -510,7 +510,7 @@ error: } -const float Audio::getInputLoudness() { +float Audio::getInputLoudness() const { return audioData->lastInputLoudness; } diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 3e74596402..f4bf594b0c 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -25,7 +25,7 @@ public: bool getMixerLoopbackFlag(); void setMixerLoopbackFlag(bool newMixerLoopbackFlag); - const float getInputLoudness(); + float getInputLoudness() const; void updateMixerParams(in_addr_t mixerAddress, in_port_t mixerPort); void setWalkingState(bool newWalkState); diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 896562b21e..0a632b4a6b 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -567,12 +567,9 @@ void Head::simulate(float deltaTime) { } } - // // Update audio trailing average for rendering facial animations - // - const float AUDIO_AVERAGING_SECS = 0.05; - _head.averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS)*_head.averageLoudness + + _head.averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _head.averageLoudness + (deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness; } @@ -748,11 +745,9 @@ void Head::renderHead(bool lookingInMirror) { } glPopMatrix(); - // + // Update audio attack data for facial animation (eyebrows and mouth) - // - - _head.audioAttack = 0.9 * _head.audioAttack + 0.1 * fabs(_audioLoudness - _head.lastLoudness); + _head.audioAttack = 0.9 * _head.audioAttack + 0.1 * fabs(_audioLoudness - _head.lastLoudness); _head.lastLoudness = _audioLoudness; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index a20ad0e3a2..41ffdc1e92 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -482,10 +482,8 @@ void updateAvatar(float frametime) const float YAW_SENSITIVITY = 1.0; // If enabled, Update render pitch and yaw based on gyro data - if (::gyroLook) - { + if (::gyroLook) { if (fabs(gyroYawRate) > MIN_YAW_RATE) { - //if (fabs(myAvatar.getHeadYaw()) > MIN_YAW_ANGLE) { myAvatar.addBodyYaw(-gyroYawRate * YAW_SENSITIVITY * frametime); } } From 142a8a6f087849485af4806c2396b6101e1d0f6a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 Apr 2013 13:45:17 -0700 Subject: [PATCH 40/52] remove double const in AvatarData.h --- libraries/avatars/src/AvatarData.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index e404efaf84..06d6f43287 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -48,11 +48,11 @@ public: // Hand State void setHandState(char s) { _handState = s; }; - const char getHandState() const {return _handState; }; + char getHandState() const {return _handState; }; // Instantaneous audio loudness to drive mouth/facial animation void setLoudness(float l) { _audioLoudness = l; }; - const float getLoudness() const {return _audioLoudness; }; + float getLoudness() const {return _audioLoudness; }; // getters for camera details const glm::vec3& getCameraPosition() const { return _cameraPosition; }; From a423d3c38fdffd7a986e02e787b8d9bc7f725526 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 Apr 2013 13:49:24 -0700 Subject: [PATCH 41/52] more const repairs in AvatarData --- libraries/avatars/src/AvatarData.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 06d6f43287..4f08d12d41 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -39,9 +39,9 @@ public: void setHeadPitch(float p) {_headPitch = p; } void setHeadYaw(float y) {_headYaw = y; } void setHeadRoll(float r) {_headRoll = r; }; - const float getHeadPitch() const { return _headPitch; }; - const float getHeadYaw() const { return _headYaw; }; - const float getHeadRoll() const { return _headRoll; }; + float getHeadPitch() const { return _headPitch; }; + float getHeadYaw() const { return _headYaw; }; + float getHeadRoll() const { return _headRoll; }; void addHeadPitch(float p) {_headPitch -= p; } void addHeadYaw(float y){_headYaw -= y; } void addHeadRoll(float r){_headRoll += r; } @@ -55,14 +55,14 @@ public: float getLoudness() const {return _audioLoudness; }; // getters for camera details - const glm::vec3& getCameraPosition() const { return _cameraPosition; }; - const glm::vec3& getCameraDirection() const { return _cameraDirection; } - const glm::vec3& getCameraUp() const { return _cameraUp; } - const glm::vec3& getCameraRight() const { return _cameraRight; } - float getCameraFov() const { return _cameraFov; } - float getCameraAspectRatio() const { return _cameraAspectRatio; } - float getCameraNearClip() const { return _cameraNearClip; } - float getCameraFarClip() const { return _cameraFarClip; } + glm::vec3 getCameraPosition() const { return _cameraPosition; }; + glm::vec3 getCameraDirection() const { return _cameraDirection; } + glm::vec3 getCameraUp() const { return _cameraUp; } + glm::vec3 getCameraRight() const { return _cameraRight; } + float getCameraFov() const { return _cameraFov; } + float getCameraAspectRatio() const { return _cameraAspectRatio; } + float getCameraNearClip() const { return _cameraNearClip; } + float getCameraFarClip() const { return _cameraFarClip; } // setters for camera details void setCameraPosition(const glm::vec3& position) { _cameraPosition = position; }; From 461ca6ecb42c91e6756007a10e5362521ac07261 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 Apr 2013 13:51:27 -0700 Subject: [PATCH 42/52] revert some of the const changes that make sense --- libraries/avatars/src/AvatarData.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 4f08d12d41..05f40b825a 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -55,10 +55,10 @@ public: float getLoudness() const {return _audioLoudness; }; // getters for camera details - glm::vec3 getCameraPosition() const { return _cameraPosition; }; - glm::vec3 getCameraDirection() const { return _cameraDirection; } - glm::vec3 getCameraUp() const { return _cameraUp; } - glm::vec3 getCameraRight() const { return _cameraRight; } + const glm::vec3& getCameraPosition() const { return _cameraPosition; }; + const glm::vec3& getCameraDirection() const { return _cameraDirection; } + const glm::vec3& getCameraUp() const { return _cameraUp; } + const glm::vec3& getCameraRight() const { return _cameraRight; } float getCameraFov() const { return _cameraFov; } float getCameraAspectRatio() const { return _cameraAspectRatio; } float getCameraNearClip() const { return _cameraNearClip; } From 87386cb05a55217931cefb37ca9937bd6490a0d0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 Apr 2013 13:54:35 -0700 Subject: [PATCH 43/52] line the consts back up in AvatarData --- libraries/avatars/src/AvatarData.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 05f40b825a..cb2171cbe5 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -59,10 +59,10 @@ public: const glm::vec3& getCameraDirection() const { return _cameraDirection; } const glm::vec3& getCameraUp() const { return _cameraUp; } const glm::vec3& getCameraRight() const { return _cameraRight; } - float getCameraFov() const { return _cameraFov; } - float getCameraAspectRatio() const { return _cameraAspectRatio; } - float getCameraNearClip() const { return _cameraNearClip; } - float getCameraFarClip() const { return _cameraFarClip; } + float getCameraFov() const { return _cameraFov; } + float getCameraAspectRatio() const { return _cameraAspectRatio; } + float getCameraNearClip() const { return _cameraNearClip; } + float getCameraFarClip() const { return _cameraFarClip; } // setters for camera details void setCameraPosition(const glm::vec3& position) { _cameraPosition = position; }; From 9c3ebf9f64671ca3760f4e7cf8ea05fd9076208b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 Apr 2013 14:11:07 -0700 Subject: [PATCH 44/52] only set hand state for mouse press for me --- interface/src/Head.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 91b9e1b516..f6683b6a9a 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -1137,7 +1137,9 @@ void Head::updateHandMovement( float deltaTime ) { _bone[ AVATAR_BONE_RIGHT_HAND ].position += transformedHandMovement; - setHandState(_mousePressed); + if (_isMine) { + _handState = _mousePressed; + } //--------------------------------------------------------------------- // if holding hands with another avatar, add a force to the hand... From 86086ef20c2d43617434eea8fcb16ef67d262edc Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 24 Apr 2013 14:52:04 -0700 Subject: [PATCH 45/52] just did a fairly major re-ordering of avatar interaction logic in Head.cpp --- interface/src/Head.cpp | 315 +++++++++++++++++++---------------------- interface/src/Head.h | 10 +- 2 files changed, 153 insertions(+), 172 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index cf78625d4f..f736850d4b 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -67,54 +67,51 @@ Head::Head(bool isMine) { for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false; - _head.pupilSize = 0.10; - _head.interPupilDistance = 0.6; - _head.interBrowDistance = 0.75; - _head.nominalPupilSize = 0.10; - //_head.yaw = 0.0; - //_head.pitch = 0.0; - //_head.roll = 0.0; - _head.pitchRate = 0.0; - _head.yawRate = 0.0; - _head.rollRate = 0.0; - _head.eyebrowPitch[0] = -30; - _head.eyebrowPitch[1] = -30; - _head.eyebrowRoll [0] = 20; - _head.eyebrowRoll [1] = -20; - _head.mouthPitch = 0; - _head.mouthYaw = 0; - _head.mouthWidth = 1.0; - _head.mouthHeight = 0.2; - _head.eyeballPitch[0] = 0; - _head.eyeballPitch[1] = 0; - _head.eyeballScaleX = 1.2; - _head.eyeballScaleY = 1.5; - _head.eyeballScaleZ = 1.0; - _head.eyeballYaw[0] = 0; - _head.eyeballYaw[1] = 0; - _head.pitchTarget = 0; - _head.yawTarget = 0; - _head.noiseEnvelope = 1.0; - _head.pupilConverge = 10.0; - _head.leanForward = 0.0; - _head.leanSideways = 0.0; - _head.eyeContact = 1; - _head.eyeContactTarget = LEFT_EYE; - _head.scale = 1.0; - _head.audioAttack = 0.0; - _head.averageLoudness = 0.0; - _head.lastLoudness = 0.0; - _head.browAudioLift = 0.0; - _head.noise = 0; - - _movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 ); - _usingBodySprings = true; - _springForce = 6.0f; - _springVelocityDecay = 16.0f; - _renderYaw = 0.0; - _renderPitch = 0.0; - - _sphere = NULL; + _head.pupilSize = 0.10; + _head.interPupilDistance = 0.6; + _head.interBrowDistance = 0.75; + _head.nominalPupilSize = 0.10; + _head.pitchRate = 0.0; + _head.yawRate = 0.0; + _head.rollRate = 0.0; + _head.eyebrowPitch[0] = -30; + _head.eyebrowPitch[1] = -30; + _head.eyebrowRoll [0] = 20; + _head.eyebrowRoll [1] = -20; + _head.mouthPitch = 0; + _head.mouthYaw = 0; + _head.mouthWidth = 1.0; + _head.mouthHeight = 0.2; + _head.eyeballPitch[0] = 0; + _head.eyeballPitch[1] = 0; + _head.eyeballScaleX = 1.2; + _head.eyeballScaleY = 1.5; + _head.eyeballScaleZ = 1.0; + _head.eyeballYaw[0] = 0; + _head.eyeballYaw[1] = 0; + _head.pitchTarget = 0; + _head.yawTarget = 0; + _head.noiseEnvelope = 1.0; + _head.pupilConverge = 10.0; + _head.leanForward = 0.0; + _head.leanSideways = 0.0; + _head.eyeContact = 1; + _head.eyeContactTarget = LEFT_EYE; + _head.scale = 1.0; + _head.audioAttack = 0.0; + _head.averageLoudness = 0.0; + _head.lastLoudness = 0.0; + _head.browAudioLift = 0.0; + _head.noise = 0; + _movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 ); + _usingBodySprings = true; + _springForce = 6.0f; + _springVelocityDecay = 16.0f; + _renderYaw = 0.0; + _renderPitch = 0.0; + _sphere = NULL; + _interactingOther = NULL; + _interactingOtherIsNearby = false; _handHolding.position = glm::vec3( 0.0, 0.0, 0.0 ); _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); @@ -127,39 +124,35 @@ Head::Head(bool isMine) { printLog("error %u: %s\n", error, lodepng_error_text(error)); } } - - _otherAvatar.nearby = false; - _otherAvatar.handPosition = glm::vec3( 0.0f, 0.0f, 0.0f ); - _otherAvatar.handState = 0; } Head::Head(const Head &otherAvatar) { - _velocity = otherAvatar._velocity; - _thrust = otherAvatar._thrust; - _rotation = otherAvatar._rotation; - _otherAvatar.nearby = otherAvatar._otherAvatar.nearby; - _bodyYaw = otherAvatar._bodyYaw; - _bodyPitch = otherAvatar._bodyPitch; - _bodyRoll = otherAvatar._bodyRoll; - _bodyYawDelta = otherAvatar._bodyYawDelta; - _mousePressed = otherAvatar._mousePressed; - _mode = otherAvatar._mode; - _isMine = otherAvatar._isMine; - _renderYaw = otherAvatar._renderYaw; - _renderPitch = otherAvatar._renderPitch; - _maxArmLength = otherAvatar._maxArmLength; - _transmitterTimer = otherAvatar._transmitterTimer; - _transmitterHz = otherAvatar._transmitterHz; - _transmitterPackets = otherAvatar._transmitterPackets; - _TEST_bigSphereRadius = otherAvatar._TEST_bigSphereRadius; - _TEST_bigSpherePosition = otherAvatar._TEST_bigSpherePosition; - _movedHandOffset = otherAvatar._movedHandOffset; - _usingBodySprings = otherAvatar._usingBodySprings; - _springForce = otherAvatar._springForce; - _springVelocityDecay = otherAvatar._springVelocityDecay; + _velocity = otherAvatar._velocity; + _thrust = otherAvatar._thrust; + _rotation = otherAvatar._rotation; + _interactingOtherIsNearby = otherAvatar._interactingOtherIsNearby; + _bodyYaw = otherAvatar._bodyYaw; + _bodyPitch = otherAvatar._bodyPitch; + _bodyRoll = otherAvatar._bodyRoll; + _bodyYawDelta = otherAvatar._bodyYawDelta; + _mousePressed = otherAvatar._mousePressed; + _mode = otherAvatar._mode; + _isMine = otherAvatar._isMine; + _renderYaw = otherAvatar._renderYaw; + _renderPitch = otherAvatar._renderPitch; + _maxArmLength = otherAvatar._maxArmLength; + _transmitterTimer = otherAvatar._transmitterTimer; + _transmitterHz = otherAvatar._transmitterHz; + _transmitterPackets = otherAvatar._transmitterPackets; + _TEST_bigSphereRadius = otherAvatar._TEST_bigSphereRadius; + _TEST_bigSpherePosition = otherAvatar._TEST_bigSpherePosition; + _movedHandOffset = otherAvatar._movedHandOffset; + _usingBodySprings = otherAvatar._usingBodySprings; + _springForce = otherAvatar._springForce; + _springVelocityDecay = otherAvatar._springVelocityDecay; _orientation.set( otherAvatar._orientation ); _sphere = NULL; @@ -172,9 +165,6 @@ Head::Head(const Head &otherAvatar) { _head.interPupilDistance = otherAvatar._head.interPupilDistance; _head.interBrowDistance = otherAvatar._head.interBrowDistance; _head.nominalPupilSize = otherAvatar._head.nominalPupilSize; - //_head.yaw = otherAvatar._head.yaw; - //_head.pitch = otherAvatar._head.pitch; - //_head.roll = otherAvatar._head.roll; _head.yawRate = otherAvatar._head.yawRate; _head.pitchRate = otherAvatar._head.pitchRate; _head.rollRate = otherAvatar._head.rollRate; @@ -208,7 +198,6 @@ Head::Head(const Head &otherAvatar) { _head.browAudioLift = otherAvatar._head.browAudioLift; _head.noise = otherAvatar._head.noise; - if (iris_texture.size() == 0) { switchToResourcesParentIfRequired(); unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file); @@ -295,16 +284,33 @@ void Head::setMousePressed( bool d ) { } void Head::simulate(float deltaTime) { + + //------------------------ + // update avatar skeleton + //------------------------ + updateSkeleton(); + + //------------------------------------------------------------ + // reset hand and arm positions according to hand movement + //------------------------------------------------------------ + updateHandMovement( deltaTime ); + + if ( !_interactingOtherIsNearby ) { + //initialize _handHolding + _handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position; + _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); + } + + _interactingOtherIsNearby = false; //------------------------------------------------------------- // if the avatar being simulated is mine, then loop through - // all the other avatars to get information about them... + // all the other avatars for potential interactions... //------------------------------------------------------------- if ( _isMine ) { - _otherAvatar.nearby = false; float closestDistance = 10000.0f; - + AgentList * agentList = AgentList::getInstance(); for(std::vector::iterator agent = agentList->getAgents().begin(); @@ -333,18 +339,44 @@ void Head::simulate(float deltaTime) { float distance = glm::length( v ); if ( distance < _maxArmLength ) { - if ( distance < closestDistance ) { + + //if ( distance < closestDistance ) { // perhaps I don't need this if we want to allow multi-avatar interactions + { closestDistance = distance; - _otherAvatar.nearby = true; - _otherAvatar.handPosition = otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); - _otherAvatar.handState = (int)otherAvatar->getHandState(); + _interactingOther = otherAvatar; + _interactingOtherIsNearby = true; + + //--------------------------------------------------------------------- + // if I am holding hands with another avatar, a force is applied + //--------------------------------------------------------------------- + if (( getHandState() == 1 ) + || ( _interactingOther->_handState == 1 )) { + glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHolding.position; + glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; + + _handHolding.velocity *= 0.7; + _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; + _handHolding.position += _handHolding.velocity; + + _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; + } } } } } - }//if ( _isMine ) + // Set the vector we send for hand position to other people to be our right hand + setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position); + }//if ( _isMine ) + + + updateArmIKAndConstraints( deltaTime ); + + if ( ! _interactingOtherIsNearby ) { + _interactingOther = NULL; + } + if ( usingBigSphereCollisionTest ) { //-------------------------------------------------------------- // test for avatar collision response (using a big sphere :) @@ -371,19 +403,10 @@ void Head::simulate(float deltaTime) { } } - //------------------------ - // update avatar skeleton - //------------------------ - updateSkeleton(); - - //------------------------------------------------------------ - // reset hand and arm positions according to hand movement - //------------------------------------------------------------ - if (_usingBodySprings) { - updateHandMovement( deltaTime ); - updateBodySprings( deltaTime ); - } - + // update body springs + updateBodySprings( deltaTime ); + + if ( _isMine ) { // driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely) //------------------------------------------------- // this handles the avatar being driven around... @@ -442,7 +465,6 @@ void Head::simulate(float deltaTime) { _bodyYaw += _bodyYawDelta * deltaTime; } - //---------------------------------------------------------- // decay body yaw delta //---------------------------------------------------------- @@ -620,8 +642,6 @@ void Head::updateAvatarCollisionDetectionAndResponse } - - void Head::render(bool lookingInMirror) { //--------------------------------------------------- @@ -646,9 +666,9 @@ void Head::render(bool lookingInMirror) { glPopMatrix(); } - //--------------------------------------------------- + //--------------- // render body - //--------------------------------------------------- + //--------------- renderBody(); //--------------------------------------------------- @@ -657,28 +677,25 @@ void Head::render(bool lookingInMirror) { renderHead(lookingInMirror); //--------------------------------------------------------------------------- - // if this is my avatar, then render my interactions with the other avatars + // if this is my avatar, then render my interactions with the other avatar //--------------------------------------------------------------------------- if ( _isMine ) { - if (_usingBodySprings) { - if ( _otherAvatar.nearby ) { + if ( _interactingOtherIsNearby ) { - glm::vec3 v1( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); - glm::vec3 v2( _otherAvatar.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(); - } + 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(); } } } - void Head::renderHead(bool lookingInMirror) { int side = 0; @@ -962,9 +979,9 @@ void Head::initializeSkeleton() { //---------------------------------------------------------------------------- calculateBoneLengths(); - //---------------------------------------------------------------------------- + //--------------------------- // generate world positions - //---------------------------------------------------------------------------- + //--------------------------- updateSkeleton(); } @@ -1121,51 +1138,14 @@ void Head::updateHandMovement( float deltaTime ) { _bone[ AVATAR_BONE_RIGHT_HAND ].position += transformedHandMovement; - setHandState(_mousePressed); - - /* - if ( _otherAvatar.nearby ) { - if ( _otherAvatar.handState == 1 ) { - printf( "(1)" ); - } - else { - printf( "(0)" ); - } + if (_isMine) { + setHandState(_mousePressed); + } +} + + +void Head::updateArmIKAndConstraints( float deltaTime ) { - if ( _handState == 1 ) { - printf( "1" ); - } - else { - printf( "0" ); - } - } - */ - - //--------------------------------------------------------------------- - // if I am holding hands with another avatar, a force is added - // to my hand, causing it to move closer to the other avatar's hand... - //--------------------------------------------------------------------- - if ( _isMine ) - { - if ( _otherAvatar.nearby ) { - if (( getHandState() == 1 ) - || ( _otherAvatar.handState == 1 )) { - glm::vec3 vectorToOtherHand = _otherAvatar.handPosition - _handHolding.position; - glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; - - _handHolding.velocity *= 0.7; - _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; - _handHolding.position += _handHolding.velocity; - - _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; - } - } - else { - _handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position; - _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); - } - } - //------------------------------------------------------------------------------- // determine the arm vector //------------------------------------------------------------------------------- @@ -1210,14 +1190,11 @@ void Head::updateHandMovement( float deltaTime ) { glm::vec3 newWristPosition = _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position; newWristPosition += vv * 0.7f; _bone[ AVATAR_BONE_RIGHT_FOREARM ].position = newWristPosition; - - // Set the vector we send for hand position to other people to be our right hand - setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position); - } + void Head::renderBody() { //----------------------------------------- // Render bone positions as spheres diff --git a/interface/src/Head.h b/interface/src/Head.h index 1e0a346a35..377228986d 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -100,12 +100,14 @@ struct AvatarHandHolding float force; }; +/* struct OtherAvatar { bool nearby; - glm::vec3 handPosition; - int handState; + //glm::vec3 handPosition; + //int handState; }; +*/ struct AvatarBone { @@ -205,6 +207,7 @@ class Head : public AvatarData { void stopHandMovement(); void setHandMovementValues( glm::vec3 movement ); void updateHandMovement( float deltaTime ); + void updateArmIKAndConstraints( float deltaTime ); float getAverageLoudness() {return _head.averageLoudness;}; void setAverageLoudness(float al) {_head.averageLoudness = al;}; @@ -229,7 +232,6 @@ class Head : public AvatarData { bool _isMine; glm::vec3 _TEST_bigSpherePosition; float _TEST_bigSphereRadius; - OtherAvatar _otherAvatar; bool _mousePressed; float _bodyYawDelta; bool _usingBodySprings; @@ -251,6 +253,8 @@ class Head : public AvatarData { timeval _transmitterTimer; float _transmitterHz; int _transmitterPackets; + Head* _interactingOther; + bool _interactingOtherIsNearby; //----------------------------- // private methods... From e93430d553e5193319d49dd168def882e40baba5 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 24 Apr 2013 14:56:29 -0700 Subject: [PATCH 46/52] fix --- interface/src/Head.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index f9a4a51dab..94e36c5673 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -1148,7 +1148,8 @@ void Head::updateHandMovement( float deltaTime ) { _bone[ AVATAR_BONE_RIGHT_HAND ].position += transformedHandMovement; if (_isMine) { - setHandState(_mousePressed); + //setHandState(_mousePressed); + _handState = _mousePressed; } } From e02aaa39f703f0db1711781d10156ebc58c1a2ca Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 24 Apr 2013 14:59:11 -0700 Subject: [PATCH 47/52] To fix font rendering on Linux (which uses points), we need to restore the default point size attenuation settings. --- interface/src/Cloud.cpp | 5 +++++ interface/src/Util.cpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/interface/src/Cloud.cpp b/interface/src/Cloud.cpp index ea27b40d49..1931f53d12 100644 --- a/interface/src/Cloud.cpp +++ b/interface/src/Cloud.cpp @@ -46,6 +46,7 @@ Cloud::Cloud(int num, void Cloud::render() { float particleAttenuationQuadratic[] = { 0.0f, 0.0f, 2.0f }; + float particleAttenuationConstant[] = { 1.0f, 0.0f, 0.0f }; glEnable( GL_TEXTURE_2D ); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); @@ -73,6 +74,10 @@ void Cloud::render() { glEnd(); glDisable( GL_POINT_SPRITE_ARB ); glDisable( GL_TEXTURE_2D ); + + glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, particleAttenuationConstant ); + glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, 1.0f ); + glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 0.0f ); } void Cloud::simulate (float deltaTime) { diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 4be30cb8cf..17f11cd64c 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -90,6 +90,7 @@ void render_vector(glm::vec3 * vec) // Draw marker dots for magnitude glEnd(); float particleAttenuationQuadratic[] = { 0.0f, 0.0f, 2.0f }; // larger Z = smaller particles + float particleAttenuationConstant[] = { 1.0f, 0.0f, 0.0f }; glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, particleAttenuationQuadratic ); @@ -104,6 +105,7 @@ void render_vector(glm::vec3 * vec) glVertex3f(0,0,vec->z); glEnd(); + glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, particleAttenuationConstant ); } void render_world_box() From a9ff483d3d03f6db08827dbe73a502602aa3309b Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 24 Apr 2013 15:35:11 -0700 Subject: [PATCH 48/52] fix --- interface/src/Head.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 94e36c5673..1e6e78fef2 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -349,7 +349,7 @@ void Head::simulate(float deltaTime) { //--------------------------------------------------------------------- // if I am holding hands with another avatar, a force is applied //--------------------------------------------------------------------- - if (( getHandState() == 1 ) + if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) { glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHolding.position; glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; @@ -1148,7 +1148,6 @@ void Head::updateHandMovement( float deltaTime ) { _bone[ AVATAR_BONE_RIGHT_HAND ].position += transformedHandMovement; if (_isMine) { - //setHandState(_mousePressed); _handState = _mousePressed; } } From e54fd0dd7d84d798efcddb04d0668948d50cf047 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 24 Apr 2013 16:54:07 -0700 Subject: [PATCH 49/52] renamed "Head" to "Avatar" and did a bunch a cleanups, including removing the three-lined comments --- eve/src/main.cpp | 32 +- interface/src/Audio.cpp | 10 +- interface/src/Audio.h | 4 +- interface/src/AudioData.h | 4 +- interface/src/Head.cpp | 1348 --------------------------------- interface/src/Head.h | 279 ------- interface/src/VoxelSystem.cpp | 6 +- interface/src/VoxelSystem.h | 6 +- interface/src/main.cpp | 12 +- 9 files changed, 37 insertions(+), 1664 deletions(-) delete mode 100644 interface/src/Head.cpp delete mode 100644 interface/src/Head.h diff --git a/eve/src/main.cpp b/eve/src/main.cpp index 903a2e6c96..2da001b368 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -27,7 +27,6 @@ const float MAX_ITERATIONS_BETWEEN_AUDIO_SENDS = (MAX_AUDIO_SEND_INTERVAL_SECS * bool stopReceiveAgentDataThread; bool injectAudioThreadRunning = false; -int handStateTimer = 0; int TEMP_AUDIO_LISTEN_PORT = 55439; // UDPSocket audioSocket(TEMP_AUDIO_LISTEN_PORT); @@ -124,20 +123,7 @@ int main(int argc, const char* argv[]) { // put her hand out so somebody can shake it eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2, 0.25, - eve.getPosition()[2] + 0.1)); - - // simulate the effect of pressing and un-pressing the mouse button/pad - handStateTimer ++; - if ( handStateTimer == 100 ) { - eve.setHandState(1); - } - if ( handStateTimer == 150 ) { - eve.setHandState(0); - } - if ( handStateTimer >= 200 ) { - handStateTimer = 0; - } - + eve.getPosition()[2] + 0.1)); // read eve's audio data AudioInjector eveAudioInjector("eve.raw"); @@ -152,6 +138,8 @@ int main(int argc, const char* argv[]) { // int numIterationsLeftBeforeAudioSend = 0; // pthread_t injectAudioThread; + int handStateTimer = 0; + while (true) { // update the thisSend timeval to the current time gettimeofday(&thisSend, NULL); @@ -183,7 +171,19 @@ int main(int argc, const char* argv[]) { // sleep for the correct amount of time to have data send be consistently timed if ((numMicrosecondsSleep = (DATA_SEND_INTERVAL_MSECS * 1000) - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) { usleep(numMicrosecondsSleep); - } + } + + // simulate the effect of pressing and un-pressing the mouse button/pad + handStateTimer++; + if ( handStateTimer == 100 ) { + eve.setHandState(1); + } + if ( handStateTimer == 150 ) { + eve.setHandState(0); + } + if ( handStateTimer >= 200 ) { + handStateTimer = 0; + } } // stop the receive agent data thread diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 287325c090..4b522d5823 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -157,7 +157,7 @@ int audioCallback (const void *inputBuffer, // memcpy the three float positions for (int p = 0; p < 3; p++) { - memcpy(currentPacketPtr, &data->linkedHead->getPosition()[p], sizeof(float)); + memcpy(currentPacketPtr, &data->linkedAvatar->getPosition()[p], sizeof(float)); currentPacketPtr += sizeof(float); } @@ -165,7 +165,7 @@ int audioCallback (const void *inputBuffer, *(currentPacketPtr++) = 255; // memcpy the corrected render yaw - float correctedYaw = fmodf(data->linkedHead->getRenderYaw(), 360); + float correctedYaw = fmodf(data->linkedAvatar->getRenderYaw(), 360); if (correctedYaw > 180) { correctedYaw -= 360; @@ -259,7 +259,7 @@ int audioCallback (const void *inputBuffer, // rotation of the head relative to body, this may effect flange effect! // // - int lastYawMeasured = fabsf(data->linkedHead->getLastMeasuredHeadYaw()); + int lastYawMeasured = fabsf(data->linkedAvatar->getLastMeasuredHeadYaw()); if (!samplesLeftForFlange && lastYawMeasured > MIN_FLANGE_EFFECT_THRESHOLD) { // we should flange for one second @@ -448,7 +448,7 @@ void Audio::setWalkingState(bool newWalkState) { * @return Returns true if successful or false if an error occurred. Use Audio::getError() to retrieve the error code. */ -Audio::Audio(Oscilloscope *s, Head *linkedHead) +Audio::Audio(Oscilloscope *s, Avatar *linkedAvatar) { // read the walking sound from the raw file and store it // in the in memory array @@ -472,7 +472,7 @@ Audio::Audio(Oscilloscope *s, Head *linkedHead) audioData = new AudioData(); - audioData->linkedHead = linkedHead; + audioData->linkedAvatar = linkedAvatar; // setup a UDPSocket audioData->audioSocket = new UDPSocket(AUDIO_UDP_LISTEN_PORT); diff --git a/interface/src/Audio.h b/interface/src/Audio.h index f4bf594b0c..73ff7f32d1 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -12,12 +12,12 @@ #include #include "AudioData.h" #include "Oscilloscope.h" -#include "Head.h" +#include "Avatar.h" class Audio { public: // initializes audio I/O - Audio(Oscilloscope *s, Head *linkedHead); + Audio(Oscilloscope *s, Avatar *linkedAvatar); void render(); void render(int screenWidth, int screenHeight); diff --git a/interface/src/AudioData.h b/interface/src/AudioData.h index fdc15998f0..520291e3e6 100644 --- a/interface/src/AudioData.h +++ b/interface/src/AudioData.h @@ -13,7 +13,7 @@ #include #include "AudioRingBuffer.h" #include "UDPSocket.h" -#include "Head.h" +#include "Avatar.h" class AudioData { public: @@ -23,7 +23,7 @@ class AudioData { UDPSocket *audioSocket; - Head *linkedHead; + Avatar *linkedAvatar; // store current mixer address and port in_addr_t mixerAddress; diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp deleted file mode 100644 index 1e6e78fef2..0000000000 --- a/interface/src/Head.cpp +++ /dev/null @@ -1,1348 +0,0 @@ -// -// Head.cpp -// interface -// -// Created by Philip Rosedale on 9/11/12. -// adapted by Jeffrey Ventrella -// Copyright (c) 2012 Physical, Inc.. All rights reserved. -// - -#include -#include -#include -#include -#include "Head.h" -#include "Log.h" -#include -#include -#include - -using namespace std; - -float skinColor[] = {1.0, 0.84, 0.66}; -float lightBlue[] = { 0.7, 0.8, 1.0 }; -float browColor[] = {210.0/255.0, 105.0/255.0, 30.0/255.0}; -float mouthColor[] = {1, 0, 0}; - -float BrowRollAngle[5] = {0, 15, 30, -30, -15}; -float BrowPitchAngle[3] = {-70, -60, -50}; -float eyeColor[3] = {1,1,1}; - -float MouthWidthChoices[3] = {0.5, 0.77, 0.3}; - -float browWidth = 0.8; -float browThickness = 0.16; - -bool usingBigSphereCollisionTest = true; - -char iris_texture_file[] = "resources/images/green_eye.png"; - -vector iris_texture; -unsigned int iris_texture_width = 512; -unsigned int iris_texture_height = 256; - -Head::Head(bool isMine) { - - _orientation.setToIdentity(); - - _velocity = glm::vec3( 0.0, 0.0, 0.0 ); - _thrust = glm::vec3( 0.0, 0.0, 0.0 ); - _rotation = glm::quat( 0.0f, 0.0f, 0.0f, 0.0f ); - _bodyYaw = -90.0; - _bodyPitch = 0.0; - _bodyRoll = 0.0; - _bodyYawDelta = 0.0; - _mousePressed = false; - _mode = AVATAR_MODE_STANDING; - _isMine = isMine; - _maxArmLength = 0.0; - //_transmitterTimer = 0; - _transmitterHz = 0.0; - _transmitterPackets = 0; - - initializeSkeleton(); - - _TEST_bigSphereRadius = 0.3f; - _TEST_bigSpherePosition = glm::vec3( 0.0f, _TEST_bigSphereRadius, 2.0f ); - - for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false; - - _head.pupilSize = 0.10; - _head.interPupilDistance = 0.6; - _head.interBrowDistance = 0.75; - _head.nominalPupilSize = 0.10; - _head.pitchRate = 0.0; - _head.yawRate = 0.0; - _head.rollRate = 0.0; - _head.eyebrowPitch[0] = -30; - _head.eyebrowPitch[1] = -30; - _head.eyebrowRoll [0] = 20; - _head.eyebrowRoll [1] = -20; - _head.mouthPitch = 0; - _head.mouthYaw = 0; - _head.mouthWidth = 1.0; - _head.mouthHeight = 0.2; - _head.eyeballPitch[0] = 0; - _head.eyeballPitch[1] = 0; - _head.eyeballScaleX = 1.2; - _head.eyeballScaleY = 1.5; - _head.eyeballScaleZ = 1.0; - _head.eyeballYaw[0] = 0; - _head.eyeballYaw[1] = 0; - _head.pitchTarget = 0; - _head.yawTarget = 0; - _head.noiseEnvelope = 1.0; - _head.pupilConverge = 10.0; - _head.leanForward = 0.0; - _head.leanSideways = 0.0; - _head.eyeContact = 1; - _head.eyeContactTarget = LEFT_EYE; - _head.scale = 1.0; - _head.audioAttack = 0.0; - _head.averageLoudness = 0.0; - _head.lastLoudness = 0.0; - _head.browAudioLift = 0.0; - _head.noise = 0; - _movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 ); - _usingBodySprings = true; - _springForce = 6.0f; - _springVelocityDecay = 16.0f; - _renderYaw = 0.0; - _renderPitch = 0.0; - _sphere = NULL; - _interactingOther = NULL; - _interactingOtherIsNearby = false; - - _handHolding.position = glm::vec3( 0.0, 0.0, 0.0 ); - _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); - _handHolding.force = 10.0f; - - if (iris_texture.size() == 0) { - switchToResourcesParentIfRequired(); - unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file); - if (error != 0) { - printLog("error %u: %s\n", error, lodepng_error_text(error)); - } - } -} - - - -Head::Head(const Head &otherAvatar) { - - _velocity = otherAvatar._velocity; - _thrust = otherAvatar._thrust; - _rotation = otherAvatar._rotation; - _interactingOtherIsNearby = otherAvatar._interactingOtherIsNearby; - _bodyYaw = otherAvatar._bodyYaw; - _bodyPitch = otherAvatar._bodyPitch; - _bodyRoll = otherAvatar._bodyRoll; - _bodyYawDelta = otherAvatar._bodyYawDelta; - _mousePressed = otherAvatar._mousePressed; - _mode = otherAvatar._mode; - _isMine = otherAvatar._isMine; - _renderYaw = otherAvatar._renderYaw; - _renderPitch = otherAvatar._renderPitch; - _maxArmLength = otherAvatar._maxArmLength; - _transmitterTimer = otherAvatar._transmitterTimer; - _transmitterHz = otherAvatar._transmitterHz; - _transmitterPackets = otherAvatar._transmitterPackets; - _TEST_bigSphereRadius = otherAvatar._TEST_bigSphereRadius; - _TEST_bigSpherePosition = otherAvatar._TEST_bigSpherePosition; - _movedHandOffset = otherAvatar._movedHandOffset; - _usingBodySprings = otherAvatar._usingBodySprings; - _springForce = otherAvatar._springForce; - _springVelocityDecay = otherAvatar._springVelocityDecay; - _orientation.set( otherAvatar._orientation ); - - _sphere = NULL; - - initializeSkeleton(); - - for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = otherAvatar._driveKeys[i]; - - _head.pupilSize = otherAvatar._head.pupilSize; - _head.interPupilDistance = otherAvatar._head.interPupilDistance; - _head.interBrowDistance = otherAvatar._head.interBrowDistance; - _head.nominalPupilSize = otherAvatar._head.nominalPupilSize; - _head.yawRate = otherAvatar._head.yawRate; - _head.pitchRate = otherAvatar._head.pitchRate; - _head.rollRate = otherAvatar._head.rollRate; - _head.eyebrowPitch[0] = otherAvatar._head.eyebrowPitch[0]; - _head.eyebrowPitch[1] = otherAvatar._head.eyebrowPitch[1]; - _head.eyebrowRoll [0] = otherAvatar._head.eyebrowRoll [0]; - _head.eyebrowRoll [1] = otherAvatar._head.eyebrowRoll [1]; - _head.mouthPitch = otherAvatar._head.mouthPitch; - _head.mouthYaw = otherAvatar._head.mouthYaw; - _head.mouthWidth = otherAvatar._head.mouthWidth; - _head.mouthHeight = otherAvatar._head.mouthHeight; - _head.eyeballPitch[0] = otherAvatar._head.eyeballPitch[0]; - _head.eyeballPitch[1] = otherAvatar._head.eyeballPitch[1]; - _head.eyeballScaleX = otherAvatar._head.eyeballScaleX; - _head.eyeballScaleY = otherAvatar._head.eyeballScaleY; - _head.eyeballScaleZ = otherAvatar._head.eyeballScaleZ; - _head.eyeballYaw[0] = otherAvatar._head.eyeballYaw[0]; - _head.eyeballYaw[1] = otherAvatar._head.eyeballYaw[1]; - _head.pitchTarget = otherAvatar._head.pitchTarget; - _head.yawTarget = otherAvatar._head.yawTarget; - _head.noiseEnvelope = otherAvatar._head.noiseEnvelope; - _head.pupilConverge = otherAvatar._head.pupilConverge; - _head.leanForward = otherAvatar._head.leanForward; - _head.leanSideways = otherAvatar._head.leanSideways; - _head.eyeContact = otherAvatar._head.eyeContact; - _head.eyeContactTarget = otherAvatar._head.eyeContactTarget; - _head.scale = otherAvatar._head.scale; - _head.audioAttack = otherAvatar._head.audioAttack; - _head.averageLoudness = otherAvatar._head.averageLoudness; - _head.lastLoudness = otherAvatar._head.lastLoudness; - _head.browAudioLift = otherAvatar._head.browAudioLift; - _head.noise = otherAvatar._head.noise; - - if (iris_texture.size() == 0) { - switchToResourcesParentIfRequired(); - unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file); - if (error != 0) { - printLog("error %u: %s\n", error, lodepng_error_text(error)); - } - } -} - -Head::~Head() { - if (_sphere != NULL) { - gluDeleteQuadric(_sphere); - } -} - -Head* Head::clone() const { - return new Head(*this); -} - -void Head::reset() { - _headPitch = _headYaw = _headRoll = 0; - _head.leanForward = _head.leanSideways = 0; -} - - -//this pertains to moving the head with the glasses -//--------------------------------------------------- -void Head::UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity) -// Using serial data, update avatar/render position and angles -{ - const float PITCH_ACCEL_COUPLING = 0.5; - const float ROLL_ACCEL_COUPLING = -1.0; - float measured_pitch_rate = serialInterface->getRelativeValue(HEAD_PITCH_RATE); - _head.yawRate = serialInterface->getRelativeValue(HEAD_YAW_RATE); - float measured_lateral_accel = serialInterface->getRelativeValue(ACCEL_X) - - ROLL_ACCEL_COUPLING*serialInterface->getRelativeValue(HEAD_ROLL_RATE); - float measured_fwd_accel = serialInterface->getRelativeValue(ACCEL_Z) - - PITCH_ACCEL_COUPLING*serialInterface->getRelativeValue(HEAD_PITCH_RATE); - float measured_roll_rate = serialInterface->getRelativeValue(HEAD_ROLL_RATE); - - //printLog("Pitch Rate: %d ACCEL_Z: %d\n", serialInterface->getRelativeValue(PITCH_RATE), - // serialInterface->getRelativeValue(ACCEL_Z)); - //printLog("Pitch Rate: %d ACCEL_X: %d\n", serialInterface->getRelativeValue(PITCH_RATE), - // serialInterface->getRelativeValue(ACCEL_Z)); - //printLog("Pitch: %f\n", Pitch); - - // Update avatar head position based on measured gyro rates - const float HEAD_ROTATION_SCALE = 0.70; - const float HEAD_ROLL_SCALE = 0.40; - const float HEAD_LEAN_SCALE = 0.01; - const float MAX_PITCH = 45; - const float MIN_PITCH = -45; - const float MAX_YAW = 85; - const float MIN_YAW = -85; - - if ((_headPitch < MAX_PITCH) && (_headPitch > MIN_PITCH)) - addHeadPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); - - addHeadRoll(measured_roll_rate * HEAD_ROLL_SCALE * frametime); - - if ((_headYaw < MAX_YAW) && (_headYaw > MIN_YAW)) - addHeadYaw(_head.yawRate * HEAD_ROTATION_SCALE * frametime); - - addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE); -} - -void Head::addLean(float x, float z) { - // Add Body lean as impulse - _head.leanSideways += x; - _head.leanForward += z; -} - - -void Head::setLeanForward(float dist){ - _head.leanForward = dist; -} - -void Head::setLeanSideways(float dist){ - _head.leanSideways = dist; -} - -void Head::setMousePressed( bool d ) { - _mousePressed = d; -} - -void Head::simulate(float deltaTime) { - - //------------------------ - // update avatar skeleton - //------------------------ - updateSkeleton(); - - //------------------------------------------------------------ - // reset hand and arm positions according to hand movement - //------------------------------------------------------------ - updateHandMovement( deltaTime ); - - if ( !_interactingOtherIsNearby ) { - //initialize _handHolding - _handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position; - _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); - } - - _interactingOtherIsNearby = false; - - //------------------------------------------------------------- - // if the avatar being simulated is mine, then loop through - // all the other avatars for potential interactions... - //------------------------------------------------------------- - if ( _isMine ) - { - float closestDistance = 10000.0f; - - AgentList * agentList = AgentList::getInstance(); - - for(std::vector::iterator agent = agentList->getAgents().begin(); - agent != agentList->getAgents().end(); - agent++) { - if (( agent->getLinkedData() != NULL && ( agent->getType() == AGENT_TYPE_AVATAR ) )) { - Head *otherAvatar = (Head *)agent->getLinkedData(); - - //------------------------------------------------------ - // check for collisions with other avatars and respond - //------------------------------------------------------ - updateAvatarCollisionDetectionAndResponse - ( - otherAvatar->getPosition(), - otherAvatar->getGirth(), - otherAvatar->getHeight(), - otherAvatar->getBodyUpDirection(), - deltaTime - ); - - //------------------------------------------------- - // test other avatar hand position for proximity - //------------------------------------------------ - glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); - v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); - - float distance = glm::length( v ); - if ( distance < _maxArmLength ) { - - //if ( distance < closestDistance ) { // perhaps I don't need this if we want to allow multi-avatar interactions - { - closestDistance = distance; - _interactingOther = otherAvatar; - _interactingOtherIsNearby = true; - - //--------------------------------------------------------------------- - // if I am holding hands with another avatar, a force is applied - //--------------------------------------------------------------------- - if (( _handState == 1 ) - || ( _interactingOther->_handState == 1 )) { - glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHolding.position; - glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; - - _handHolding.velocity *= 0.7; - _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; - _handHolding.position += _handHolding.velocity; - - _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; - } - } - } - } - } - - // Set the vector we send for hand position to other people to be our right hand - setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position); - - }//if ( _isMine ) - - - updateArmIKAndConstraints( deltaTime ); - - if ( ! _interactingOtherIsNearby ) { - _interactingOther = NULL; - } - - if ( usingBigSphereCollisionTest ) { - //-------------------------------------------------------------- - // test for avatar collision response (using a big sphere :) - //-------------------------------------------------------------- - updateAvatarCollisionDetectionAndResponse - ( - _TEST_bigSpherePosition, - _TEST_bigSphereRadius, - _TEST_bigSphereRadius, - glm::vec3( 0.0, 1.0, 0.0 ), - deltaTime - ); - } - - if ( AVATAR_GRAVITY ) { - if ( _position.y > _bone[ AVATAR_BONE_RIGHT_FOOT ].radius * 2.0 ) { - _velocity += glm::dvec3( 0.0, -1.0, 0.0 ) * ( 6.0 * deltaTime ); - } - else { - if ( _position.y < _bone[ AVATAR_BONE_RIGHT_FOOT ].radius ) { - _position.y = _bone[ AVATAR_BONE_RIGHT_FOOT ].radius; - _velocity.y = 0.0; - } - } - } - - // update body springs - updateBodySprings( deltaTime ); - - - if ( _isMine ) { // driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely) - //------------------------------------------------- - // this handles the avatar being driven around... - //------------------------------------------------- - _thrust = glm::vec3( 0.0, 0.0, 0.0 ); - - if (_driveKeys[FWD]) { - glm::vec3 front( _orientation.getFront().x, _orientation.getFront().y, _orientation.getFront().z ); - _thrust += front * THRUST_MAG; - } - if (_driveKeys[BACK]) { - glm::vec3 front( _orientation.getFront().x, _orientation.getFront().y, _orientation.getFront().z ); - _thrust -= front * THRUST_MAG; - } - if (_driveKeys[RIGHT]) { - glm::vec3 right( _orientation.getRight().x, _orientation.getRight().y, _orientation.getRight().z ); - _thrust += right * THRUST_MAG; - } - if (_driveKeys[LEFT]) { - glm::vec3 right( _orientation.getRight().x, _orientation.getRight().y, _orientation.getRight().z ); - _thrust -= right * THRUST_MAG; - } - if (_driveKeys[UP]) { - glm::vec3 up( _orientation.getUp().x, _orientation.getUp().y, _orientation.getUp().z ); - _thrust += up * THRUST_MAG; - } - if (_driveKeys[DOWN]) { - glm::vec3 up( _orientation.getUp().x, _orientation.getUp().y, _orientation.getUp().z ); - _thrust -= up * THRUST_MAG; - } - if (_driveKeys[ROT_RIGHT]) { - _bodyYawDelta -= YAW_MAG * deltaTime; - } - if (_driveKeys[ROT_LEFT]) { - _bodyYawDelta += YAW_MAG * deltaTime; - } - } - - - //---------------------------------------------------------- - float translationalSpeed = glm::length( _velocity ); - float rotationalSpeed = fabs( _bodyYawDelta ); - if ( translationalSpeed + rotationalSpeed > 0.2 ) - { - _mode = AVATAR_MODE_WALKING; - } - else - { - _mode = AVATAR_MODE_INTERACTING; - } - - //---------------------------------------------------------- - // update body yaw by body yaw delta - //---------------------------------------------------------- - if (_isMine) { - _bodyYaw += _bodyYawDelta * deltaTime; - } - - //---------------------------------------------------------- - // decay body yaw delta - //---------------------------------------------------------- - _bodyYawDelta *= (1.0 - TEST_YAW_DECAY * deltaTime); - - //---------------------------------------------------------- - // add thrust to velocity - //---------------------------------------------------------- - _velocity += glm::dvec3(_thrust * deltaTime); - - //---------------------------------------------------------- - // update position by velocity - //---------------------------------------------------------- - _position += (glm::vec3)_velocity * deltaTime; - - //---------------------------------------------------------- - // decay velocity - //---------------------------------------------------------- - _velocity *= ( 1.0 - LIN_VEL_DECAY * deltaTime ); - - // - // Update Head information - // - - // we will be eventually getting head rotation from elsewhere. For now, just setting it to body rotation - //_head.yaw = _bodyYaw; - //_head.pitch = _bodyPitch; - //_head.roll = _bodyRoll; - - if (!_head.noise) { - // Decay back toward center - _headPitch *= (1.0f - DECAY * 2 * deltaTime); - _headYaw *= (1.0f - DECAY * 2 * deltaTime); - _headRoll *= (1.0f - DECAY * 2 * deltaTime); - } - else { - // Move toward new target - _headPitch += (_head.pitchTarget - _headPitch) * 10 * deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ; - _headYaw += (_head.yawTarget - _headYaw ) * 10 * deltaTime; // (1.f - DECAY*deltaTime); - _headRoll *= 1.f - (DECAY * deltaTime); - } - - _head.leanForward *= (1.f - DECAY * 30 * deltaTime); - _head.leanSideways *= (1.f - DECAY * 30 * deltaTime); - - // Update where the avatar's eyes are - // - // First, decide if we are making eye contact or not - if (randFloat() < 0.005) { - _head.eyeContact = !_head.eyeContact; - _head.eyeContact = 1; - if (!_head.eyeContact) { - // If we just stopped making eye contact,move the eyes markedly away - _head.eyeballPitch[0] = _head.eyeballPitch[1] = _head.eyeballPitch[0] + 5.0 + (randFloat() - 0.5) * 10; - _head.eyeballYaw [0] = _head.eyeballYaw [1] = _head.eyeballYaw [0] + 5.0 + (randFloat() - 0.5) * 5; - } else { - // If now making eye contact, turn head to look right at viewer - SetNewHeadTarget(0,0); - } - } - - const float DEGREES_BETWEEN_VIEWER_EYES = 3; - const float DEGREES_TO_VIEWER_MOUTH = 7; - - if (_head.eyeContact) { - // Should we pick a new eye contact target? - if (randFloat() < 0.01) { - // Choose where to look next - if (randFloat() < 0.1) { - _head.eyeContactTarget = MOUTH; - } else { - if (randFloat() < 0.5) _head.eyeContactTarget = LEFT_EYE; else _head.eyeContactTarget = RIGHT_EYE; - } - } - // Set eyeball pitch and yaw to make contact - float eye_target_yaw_adjust = 0; - float eye_target_pitch_adjust = 0; - if (_head.eyeContactTarget == LEFT_EYE) eye_target_yaw_adjust = DEGREES_BETWEEN_VIEWER_EYES; - if (_head.eyeContactTarget == RIGHT_EYE) eye_target_yaw_adjust = -DEGREES_BETWEEN_VIEWER_EYES; - if (_head.eyeContactTarget == MOUTH) eye_target_pitch_adjust = DEGREES_TO_VIEWER_MOUTH; - - _head.eyeballPitch[0] = _head.eyeballPitch[1] = -_headPitch + eye_target_pitch_adjust; - _head.eyeballYaw[0] = _head.eyeballYaw[1] = -_headYaw + eye_target_yaw_adjust; - } - - - if (_head.noise) - { - _headPitch += (randFloat() - 0.5) * 0.2 * _head.noiseEnvelope; - _headYaw += (randFloat() - 0.5) * 0.3 *_head.noiseEnvelope; - //PupilSize += (randFloat() - 0.5) * 0.001*NoiseEnvelope; - - if (randFloat() < 0.005) _head.mouthWidth = MouthWidthChoices[rand()%3]; - - if (!_head.eyeContact) { - if (randFloat() < 0.01) _head.eyeballPitch[0] = _head.eyeballPitch[1] = (randFloat() - 0.5) * 20; - if (randFloat() < 0.01) _head.eyeballYaw[0] = _head.eyeballYaw[1] = (randFloat()- 0.5) * 10; - } - - if ((randFloat() < 0.005) && (fabs(_head.pitchTarget - _headPitch) < 1.0) && (fabs(_head.yawTarget - _headYaw) < 1.0)) { - SetNewHeadTarget((randFloat()-0.5) * 20.0, (randFloat()-0.5) * 45.0); - } - - if (0) { - - // Pick new target - _head.pitchTarget = (randFloat() - 0.5) * 45; - _head.yawTarget = (randFloat() - 0.5) * 22; - } - if (randFloat() < 0.01) - { - _head.eyebrowPitch[0] = _head.eyebrowPitch[1] = BrowPitchAngle[rand()%3]; - _head.eyebrowRoll [0] = _head.eyebrowRoll[1] = BrowRollAngle[rand()%5]; - _head.eyebrowRoll [1] *=-1; - } - } - - // Update audio trailing average for rendering facial animations - const float AUDIO_AVERAGING_SECS = 0.05; - _head.averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _head.averageLoudness + - (deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness; -} - - -float Head::getGirth() { - return COLLISION_BODY_RADIUS; -} - -float Head::getHeight() { - return COLLISION_HEIGHT; -} - - -glm::vec3 Head::getBodyUpDirection() { - return _orientation.getUp(); -} - -//-------------------------------------------------------------------------------- -// This is a workspace for testing avatar body collision detection and response -//-------------------------------------------------------------------------------- -void Head::updateAvatarCollisionDetectionAndResponse -( glm::vec3 collisionPosition, float collisionGirth, float collisionHeight, glm::vec3 collisionUpVector, float deltaTime ) { - - float myBodyApproximateBoundingRadius = 1.0f; - glm::vec3 vectorFromMyBodyToBigSphere(_position - collisionPosition); - bool jointCollision = false; - - float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere); - if ( distanceToBigSphere < myBodyApproximateBoundingRadius + collisionGirth ) - { - for (int b=0; b 0.0) - { - glm::vec3 directionVector = vectorFromJointToBigSphereCenter / distanceToBigSphereCenter; - - float penetration = 1.0 - (distanceToBigSphereCenter / combinedRadius); - glm::vec3 collisionForce = vectorFromJointToBigSphereCenter * penetration; - - _bone[b].springyVelocity += collisionForce * 30.0f * deltaTime; - _velocity += collisionForce * 100.0f * deltaTime; - _bone[b].springyPosition = collisionPosition + directionVector * combinedRadius; - } - } - } - - if ( jointCollision ) { - if (!_usingBodySprings) { - _usingBodySprings = true; - initializeBodySprings(); - } - } - } -} - - -void Head::render(bool lookingInMirror) { - - //--------------------------------------------------- - // show avatar position - //--------------------------------------------------- - glColor4f( 0.5f, 0.5f, 0.5f, 0.6 ); - glPushMatrix(); - glTranslatef(_position.x, _position.y, _position.z); - glScalef( 0.03, 0.03, 0.03 ); - glutSolidSphere( 1, 10, 10 ); - glPopMatrix(); - - if ( usingBigSphereCollisionTest ) { - //--------------------------------------------------- - // show TEST big sphere - //--------------------------------------------------- - glColor4f( 0.5f, 0.6f, 0.8f, 0.7 ); - glPushMatrix(); - glTranslatef(_TEST_bigSpherePosition.x, _TEST_bigSpherePosition.y, _TEST_bigSpherePosition.z); - glScalef( _TEST_bigSphereRadius, _TEST_bigSphereRadius, _TEST_bigSphereRadius ); - glutSolidSphere( 1, 20, 20 ); - glPopMatrix(); - } - - //--------------- - // render body - //--------------- - renderBody(); - - //--------------------------------------------------- - // render head - //--------------------------------------------------- - renderHead(lookingInMirror); - - //--------------------------------------------------------------------------- - // if this is my avatar, then render my interactions with the other avatar - //--------------------------------------------------------------------------- - if ( _isMine ) - { - if ( _interactingOtherIsNearby ) { - - 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(); - } - } -} - - -void Head::renderHead(bool lookingInMirror) { - int side = 0; - - glEnable(GL_DEPTH_TEST); - glEnable(GL_RESCALE_NORMAL); - - //--------------------------------------------------- - // show head orientation - //--------------------------------------------------- - //renderOrientationDirections( _bone[ AVATAR_BONE_HEAD ].position, _bone[ AVATAR_BONE_HEAD ].orientation, 0.2f ); - - glPushMatrix(); - - if (_usingBodySprings) { - glTranslatef(_bone[ AVATAR_BONE_HEAD ].springyPosition.x, - _bone[ AVATAR_BONE_HEAD ].springyPosition.y, - _bone[ AVATAR_BONE_HEAD ].springyPosition.z); - } - else { - glTranslatef(_bone[ AVATAR_BONE_HEAD ].position.x, - _bone[ AVATAR_BONE_HEAD ].position.y, - _bone[ AVATAR_BONE_HEAD ].position.z); - } - - glScalef( 0.03, 0.03, 0.03 ); - - if (lookingInMirror) { - glRotatef(_bodyYaw - _headYaw, 0, 1, 0); - glRotatef(_bodyPitch + _headPitch, 1, 0, 0); - glRotatef(_bodyRoll - _headRoll, 0, 0, 1); - } else { - glRotatef(_bodyYaw + _headYaw, 0, 1, 0); - glRotatef(_bodyPitch + _headPitch, 1, 0, 0); - glRotatef(_bodyRoll + _headRoll, 0, 0, 1); - } - - glScalef(2.0, 2.0, 2.0); - glColor3fv(skinColor); - - glutSolidSphere(1, 30, 30); - - // Ears - glPushMatrix(); - glTranslatef(1.0, 0, 0); - for(side = 0; side < 2; side++) { - glPushMatrix(); - glScalef(0.3, 0.65, .65); - glutSolidSphere(0.5, 30, 30); - glPopMatrix(); - glTranslatef(-2.0, 0, 0); - } - glPopMatrix(); - - - // Update audio attack data for facial animation (eyebrows and mouth) - _head.audioAttack = 0.9 * _head.audioAttack + 0.1 * fabs(_audioLoudness - _head.lastLoudness); - _head.lastLoudness = _audioLoudness; - - - const float BROW_LIFT_THRESHOLD = 100; - if (_head.audioAttack > BROW_LIFT_THRESHOLD) - _head.browAudioLift += sqrt(_head.audioAttack) / 1000.0; - - _head.browAudioLift *= .90; - - - // Render Eyebrows - glPushMatrix(); - glTranslatef(-_head.interBrowDistance / 2.0,0.4,0.45); - for(side = 0; side < 2; side++) { - glColor3fv(browColor); - glPushMatrix(); - glTranslatef(0, 0.35 + _head.browAudioLift, 0); - glRotatef(_head.eyebrowPitch[side]/2.0, 1, 0, 0); - glRotatef(_head.eyebrowRoll[side]/2.0, 0, 0, 1); - glScalef(browWidth, browThickness, 1); - glutSolidCube(0.5); - glPopMatrix(); - glTranslatef(_head.interBrowDistance, 0, 0); - } - glPopMatrix(); - - - // Mouth - - glPushMatrix(); - glTranslatef(0,-0.35,0.75); - glColor3f(0,0,0); - glRotatef(_head.mouthPitch, 1, 0, 0); - glRotatef(_head.mouthYaw, 0, 0, 1); - glScalef(_head.mouthWidth*(.7 + sqrt(_head.averageLoudness)/60.0), _head.mouthHeight*(1.0 + sqrt(_head.averageLoudness)/30.0), 1); - glutSolidCube(0.5); - glPopMatrix(); - - glTranslatef(0, 1.0, 0); - - glTranslatef(-_head.interPupilDistance/2.0,-0.68,0.7); - // Right Eye - glRotatef(-10, 1, 0, 0); - glColor3fv(eyeColor); - glPushMatrix(); - { - glTranslatef(_head.interPupilDistance/10.0, 0, 0.05); - glRotatef(20, 0, 0, 1); - glScalef(_head.eyeballScaleX, _head.eyeballScaleY, _head.eyeballScaleZ); - glutSolidSphere(0.25, 30, 30); - } - glPopMatrix(); - - // Right Pupil - if (_sphere == NULL) { - _sphere = gluNewQuadric(); - gluQuadricTexture(_sphere, GL_TRUE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluQuadricOrientation(_sphere, GLU_OUTSIDE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]); - } - - glPushMatrix(); - { - glRotatef(_head.eyeballPitch[1], 1, 0, 0); - glRotatef(_head.eyeballYaw[1] + _headYaw + _head.pupilConverge, 0, 1, 0); - glTranslatef(0,0,.35); - glRotatef(-75,1,0,0); - glScalef(1.0, 0.4, 1.0); - - glEnable(GL_TEXTURE_2D); - gluSphere(_sphere, _head.pupilSize, 15, 15); - glDisable(GL_TEXTURE_2D); - } - - glPopMatrix(); - // Left Eye - glColor3fv(eyeColor); - glTranslatef(_head.interPupilDistance, 0, 0); - glPushMatrix(); - { - glTranslatef(-_head.interPupilDistance/10.0, 0, .05); - glRotatef(-20, 0, 0, 1); - glScalef(_head.eyeballScaleX, _head.eyeballScaleY, _head.eyeballScaleZ); - glutSolidSphere(0.25, 30, 30); - } - glPopMatrix(); - // Left Pupil - glPushMatrix(); - { - glRotatef(_head.eyeballPitch[0], 1, 0, 0); - glRotatef(_head.eyeballYaw[0] + _headYaw - _head.pupilConverge, 0, 1, 0); - glTranslatef(0, 0, .35); - glRotatef(-75, 1, 0, 0); - glScalef(1.0, 0.4, 1.0); - - glEnable(GL_TEXTURE_2D); - gluSphere(_sphere, _head.pupilSize, 15, 15); - glDisable(GL_TEXTURE_2D); - } - - glPopMatrix(); - - - glPopMatrix(); - } - -void Head::startHandMovement() { - - if (!_usingBodySprings) { - initializeBodySprings(); - _usingBodySprings = true; - } -} - -void Head::stopHandMovement() { -//_usingBodySprings = false; -} - -void Head::setHandMovementValues( glm::vec3 handOffset ) { - _movedHandOffset = handOffset; -} - -AvatarMode Head::getMode() { - return _mode; -} - -void Head::initializeSkeleton() { - - for (int b=0; b 0.0f ) { - glm::vec3 springDirection = springVector / length; - - float force = ( length - _bone[b].length ) * _springForce * deltaTime; - - _bone[b].springyVelocity -= springDirection * force; - - if ( _bone[b].parent != AVATAR_BONE_NULL ) { - _bone[ _bone[b].parent ].springyVelocity += springDirection * force; - } - } - - _bone[b].springyVelocity += ( _bone[b].position - _bone[b].springyPosition ) * _bone[b].springBodyTightness * deltaTime; - - float decay = 1.0 - _springVelocityDecay * deltaTime; - - if ( decay > 0.0 ) { - _bone[b].springyVelocity *= decay; - } - else { - _bone[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f ); - } - - _bone[b].springyPosition += _bone[b].springyVelocity; - } -} - -glm::vec3 Head::getHeadLookatDirection() { - return glm::vec3 - ( - _orientation.getFront().x, - _orientation.getFront().y, - _orientation.getFront().z - ); -} - -glm::vec3 Head::getHeadLookatDirectionUp() { - return glm::vec3 - ( - _orientation.getUp().x, - _orientation.getUp().y, - _orientation.getUp().z - ); -} - -glm::vec3 Head::getHeadLookatDirectionRight() { - return glm::vec3 - ( - _orientation.getRight().x, - _orientation.getRight().y, - _orientation.getRight().z - ); -} - -glm::vec3 Head::getHeadPosition() { - - if ( _usingBodySprings ) { - return _bone[ AVATAR_BONE_HEAD ].springyPosition; - } - - return _bone[ AVATAR_BONE_HEAD ].position; -} - - -glm::vec3 Head::getBonePosition( AvatarBoneID b ) { - return _bone[b].position; -} - - - -void Head::updateHandMovement( float deltaTime ) { - glm::vec3 transformedHandMovement; - - transformedHandMovement - = _orientation.getRight() * _movedHandOffset.x - + _orientation.getUp() * -_movedHandOffset.y * 0.5f - + _orientation.getFront() * -_movedHandOffset.y; - - _bone[ AVATAR_BONE_RIGHT_HAND ].position += transformedHandMovement; - - if (_isMine) { - _handState = _mousePressed; - } -} - - -void Head::updateArmIKAndConstraints( float deltaTime ) { - - //------------------------------------------------------------------------------- - // determine the arm vector - //------------------------------------------------------------------------------- - glm::vec3 armVector = _bone[ AVATAR_BONE_RIGHT_HAND ].position; - armVector -= _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; - - //------------------------------------------------------------------------------- - // test to see if right hand is being dragged beyond maximum arm length - //------------------------------------------------------------------------------- - float distance = glm::length( armVector ); - - //------------------------------------------------------------------------------- - // if right hand is being dragged beyond maximum arm length... - //------------------------------------------------------------------------------- - if ( distance > _maxArmLength ) { - //------------------------------------------------------------------------------- - // reset right hand to be constrained to maximum arm length - //------------------------------------------------------------------------------- - _bone[ AVATAR_BONE_RIGHT_HAND ].position = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; - glm::vec3 armNormal = armVector / distance; - armVector = armNormal * _maxArmLength; - distance = _maxArmLength; - glm::vec3 constrainedPosition = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; - constrainedPosition += armVector; - _bone[ AVATAR_BONE_RIGHT_HAND ].position = constrainedPosition; - } - - //----------------------------------------------------------------------------- - // set elbow position - //----------------------------------------------------------------------------- - glm::vec3 newElbowPosition = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; - newElbowPosition += armVector * ONE_HALF; - glm::vec3 perpendicular = glm::cross( _orientation.getFront(), armVector ); - newElbowPosition += perpendicular * ( 1.0f - ( _maxArmLength / distance ) ) * ONE_HALF; - _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position = newElbowPosition; - - //----------------------------------------------------------------------------- - // set wrist position - //----------------------------------------------------------------------------- - glm::vec3 vv( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); - vv -= _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position; - glm::vec3 newWristPosition = _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position; - newWristPosition += vv * 0.7f; - _bone[ AVATAR_BONE_RIGHT_FOREARM ].position = newWristPosition; -} - - - - -void Head::renderBody() { - //----------------------------------------- - // Render bone positions as spheres - //----------------------------------------- - for (int b=0; b( (double)TRANSMITTER_COUNT/(msecsElapsed/1000.0) ); - _transmitterTimer = now; - } - /* NOTE: PR: Will add back in when ready to animate avatar hand - - // Add rotational forces to the hand - const float ANG_VEL_SENSITIVITY = 4.0; - const float ANG_VEL_THRESHOLD = 0.0; - float angVelScale = ANG_VEL_SENSITIVITY*(1.0f/getTransmitterHz()); - - addAngularVelocity(fabs(gyrX*angVelScale)>ANG_VEL_THRESHOLD?gyrX*angVelScale:0, - fabs(gyrZ*angVelScale)>ANG_VEL_THRESHOLD?gyrZ*angVelScale:0, - fabs(-gyrY*angVelScale)>ANG_VEL_THRESHOLD?-gyrY*angVelScale:0); - - // Add linear forces to the hand - //const float LINEAR_VEL_SENSITIVITY = 50.0; - const float LINEAR_VEL_SENSITIVITY = 5.0; - float linVelScale = LINEAR_VEL_SENSITIVITY*(1.0f/getTransmitterHz()); - glm::vec3 linVel(linX*linVelScale, linZ*linVelScale, -linY*linVelScale); - addVelocity(linVel); - */ - -} - diff --git a/interface/src/Head.h b/interface/src/Head.h deleted file mode 100644 index 377228986d..0000000000 --- a/interface/src/Head.h +++ /dev/null @@ -1,279 +0,0 @@ -// -// Head.h -// interface -// -// Created by Philip Rosedale on 9/11/12. -// Copyright (c) 2012 High Fidelity, Inc. All rights reserved. -// - -#ifndef __interface__head__ -#define __interface__head__ - -#include -#include - -#include "Field.h" -#include "world.h" - -#include "InterfaceConfig.h" -#include "SerialInterface.h" - -#include -#include -#include //looks like we might not need this - -const bool AVATAR_GRAVITY = true; -const float DECAY = 0.1; -const float THRUST_MAG = 10.0; -const float YAW_MAG = 300.0; -const float TEST_YAW_DECAY = 5.0; -const float LIN_VEL_DECAY = 5.0; - -const float COLLISION_BODY_RADIUS = 0.1; -const float COLLISION_HEIGHT = 1.5; - -enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH}; - -#define FWD 0 -#define BACK 1 -#define LEFT 2 -#define RIGHT 3 -#define UP 4 -#define DOWN 5 -#define ROT_LEFT 6 -#define ROT_RIGHT 7 -#define MAX_DRIVE_KEYS 8 - -#define MAX_OTHER_AVATARS 10 // temporary - for testing purposes! - -enum AvatarMode -{ - AVATAR_MODE_STANDING = 0, - AVATAR_MODE_WALKING, - AVATAR_MODE_INTERACTING, - NUM_AVATAR_MODES -}; - -enum AvatarBoneID -{ - AVATAR_BONE_NULL = -1, - AVATAR_BONE_PELVIS_SPINE, // connects pelvis joint with torso joint (not supposed to be rotated) - AVATAR_BONE_MID_SPINE, // connects torso joint with chest joint - AVATAR_BONE_CHEST_SPINE, // connects chest joint with neckBase joint (not supposed to be rotated) - AVATAR_BONE_NECK, // connects neckBase joint with headBase joint - AVATAR_BONE_HEAD, // connects headBase joint with headTop joint - AVATAR_BONE_LEFT_CHEST, // connects chest joint with left clavicle joint (not supposed to be rotated) - AVATAR_BONE_LEFT_SHOULDER, // connects left clavicle joint with left shoulder joint - AVATAR_BONE_LEFT_UPPER_ARM, // connects left shoulder joint with left elbow joint - AVATAR_BONE_LEFT_FOREARM, // connects left elbow joint with left wrist joint - AVATAR_BONE_LEFT_HAND, // connects left wrist joint with left fingertips joint - AVATAR_BONE_RIGHT_CHEST, // connects chest joint with right clavicle joint (not supposed to be rotated) - AVATAR_BONE_RIGHT_SHOULDER, // connects right clavicle joint with right shoulder joint - AVATAR_BONE_RIGHT_UPPER_ARM, // connects right shoulder joint with right elbow joint - AVATAR_BONE_RIGHT_FOREARM, // connects right elbow joint with right wrist joint - AVATAR_BONE_RIGHT_HAND, // connects right wrist joint with right fingertips joint - AVATAR_BONE_LEFT_PELVIS, // connects pelvis joint with left hip joint (not supposed to be rotated) - AVATAR_BONE_LEFT_THIGH, // connects left hip joint with left knee joint - AVATAR_BONE_LEFT_SHIN, // connects left knee joint with left heel joint - AVATAR_BONE_LEFT_FOOT, // connects left heel joint with left toes joint - AVATAR_BONE_RIGHT_PELVIS, // connects pelvis joint with right hip joint (not supposed to be rotated) - AVATAR_BONE_RIGHT_THIGH, // connects right hip joint with right knee joint - AVATAR_BONE_RIGHT_SHIN, // connects right knee joint with right heel joint - AVATAR_BONE_RIGHT_FOOT, // connects right heel joint with right toes joint - - NUM_AVATAR_BONES -}; - -struct AvatarCollisionElipsoid -{ - bool colliding; - glm::vec3 position; - float girth; - float height; - glm::vec3 upVector; -}; - -struct AvatarHandHolding -{ - glm::vec3 position; - glm::vec3 velocity; - float force; -}; - -/* -struct OtherAvatar -{ - bool nearby; - //glm::vec3 handPosition; - //int handState; -}; -*/ - -struct AvatarBone -{ - AvatarBoneID parent; // which bone is this bone connected to? - glm::vec3 position; // the position at the "end" of the bone - glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose" - glm::vec3 springyPosition; // used for special effects (a 'flexible' variant of position) - glm::dvec3 springyVelocity; // used for special effects ( the velocity of the springy position) - float springBodyTightness; // how tightly the springy position tries to stay on the position - glm::quat rotation; // this will eventually replace yaw, pitch and roll (and maybe orientation) - float yaw; // the yaw Euler angle of the bone rotation off the parent - float pitch; // the pitch Euler angle of the bone rotation off the parent - float roll; // the roll Euler angle of the bone rotation off the parent - Orientation orientation; // three orthogonal normals determined by yaw, pitch, roll - float length; // the length of the bone - float radius; // used for detecting collisions for certain physical effects -}; - -struct AvatarHead -{ - float pitchRate; - float yawRate; - float rollRate; - float noise; - float eyeballPitch[2]; - float eyeballYaw [2]; - float eyebrowPitch[2]; - float eyebrowRoll [2]; - float eyeballScaleX; - float eyeballScaleY; - float eyeballScaleZ; - float interPupilDistance; - float interBrowDistance; - float nominalPupilSize; - float pupilSize; - float mouthPitch; - float mouthYaw; - float mouthWidth; - float mouthHeight; - float leanForward; - float leanSideways; - float pitchTarget; - float yawTarget; - float noiseEnvelope; - float pupilConverge; - float scale; - int eyeContact; - float browAudioLift; - eyeContactTargets eyeContactTarget; - - // Sound loudness information - float lastLoudness; - float averageLoudness; - float audioAttack; -}; - - -class Head : public AvatarData { - public: - Head(bool isMine); - ~Head(); - Head(const Head &otherHead); - Head* clone() const; - - void reset(); - void UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity); - void setNoise (float mag) { _head.noise = mag; } - void setScale(float s) {_head.scale = s; }; - void setRenderYaw(float y) {_renderYaw = y;} - void setRenderPitch(float p) {_renderPitch = p;} - float getRenderYaw() {return _renderYaw;} - float getRenderPitch() {return _renderPitch;} - void setLeanForward(float dist); - void setLeanSideways(float dist); - void addLean(float x, float z); - float getLastMeasuredHeadYaw() const {return _head.yawRate;} - float getBodyYaw() {return _bodyYaw;}; - void addBodyYaw(float y) {_bodyYaw += y;}; - - glm::vec3 getHeadLookatDirection(); - glm::vec3 getHeadLookatDirectionUp(); - glm::vec3 getHeadLookatDirectionRight(); - glm::vec3 getHeadPosition(); - glm::vec3 getBonePosition( AvatarBoneID b ); - glm::vec3 getBodyUpDirection(); - float getGirth(); - float getHeight(); - - AvatarMode getMode(); - - void setMousePressed( bool pressed ); - void render(bool lookingInMirror); - void renderBody(); - void renderHead(bool lookingInMirror); - void simulate(float); - void startHandMovement(); - void stopHandMovement(); - void setHandMovementValues( glm::vec3 movement ); - void updateHandMovement( float deltaTime ); - void updateArmIKAndConstraints( float deltaTime ); - - float getAverageLoudness() {return _head.averageLoudness;}; - void setAverageLoudness(float al) {_head.averageLoudness = al;}; - - void SetNewHeadTarget(float, float); - - // 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]; }; - - // Set/Get update the thrust that will move the avatar around - void setThrust(glm::vec3 newThrust) { _thrust = newThrust; }; - void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; - glm::vec3 getThrust() { return _thrust; }; - - // Related to getting transmitter UDP data used to animate the avatar hand - void processTransmitterData(unsigned char * packetData, int numBytes); - float getTransmitterHz() { return _transmitterHz; }; - - private: - AvatarHead _head; - bool _isMine; - glm::vec3 _TEST_bigSpherePosition; - float _TEST_bigSphereRadius; - bool _mousePressed; - float _bodyYawDelta; - bool _usingBodySprings; - glm::vec3 _movedHandOffset; - float _springVelocityDecay; - float _springForce; - glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion - AvatarBone _bone[ NUM_AVATAR_BONES ]; - AvatarMode _mode; - AvatarHandHolding _handHolding; - glm::dvec3 _velocity; - glm::vec3 _thrust; - float _maxArmLength; - Orientation _orientation; - int _driveKeys[MAX_DRIVE_KEYS]; - GLUquadric* _sphere; - float _renderYaw; - float _renderPitch; // Pitch from view frustum when this is own head - timeval _transmitterTimer; - float _transmitterHz; - int _transmitterPackets; - Head* _interactingOther; - bool _interactingOtherIsNearby; - - //----------------------------- - // private methods... - //----------------------------- - void initializeSkeleton(); - void updateSkeleton(); - void initializeBodySprings(); - void updateBodySprings( float deltaTime ); - void calculateBoneLengths(); - void readSensors(); - void renderBoneAsBlock( AvatarBoneID b ); - void updateAvatarCollisionDetectionAndResponse - ( - glm::vec3 collisionPosition, - float collisionGirth, - float collisionHeight, - glm::vec3 collisionUpVector, - float deltaTime - ); -}; - -#endif diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 8bf6222aec..e96dc5ef8b 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -60,8 +60,8 @@ VoxelSystem::~VoxelSystem() { pthread_mutex_destroy(&bufferWriteLock); } -void VoxelSystem::setViewerHead(Head *newViewerHead) { - viewerHead = newViewerHead; +void VoxelSystem::setViewerAvatar(Avatar *newViewerAvatar) { + viewerAvatar = newViewerAvatar; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -187,7 +187,7 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosi int voxelsAdded = 0; float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE); - glm::vec3 viewerPosition = viewerHead->getPosition(); + glm::vec3 viewerPosition = viewerAvatar->getPosition(); // debug LOD code glm::vec3 debugNodePosition; diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 9d831ee5f2..ca4825121b 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -15,7 +15,7 @@ #include #include #include -#include "Head.h" +#include "Avatar.h" #include "Util.h" #include "world.h" @@ -34,7 +34,7 @@ public: void render(); void setVoxelsRendered(int v) {voxelsRendered = v;}; int getVoxelsRendered() {return voxelsRendered;}; - void setViewerHead(Head *newViewerHead); + void setViewerAvatar(Avatar *newViewerAvatar); void loadVoxelsFile(const char* fileName,bool wantColorRandomizer); void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer); @@ -67,7 +67,7 @@ private: static float _minDistance; int voxelsRendered; - Head *viewerHead; + Avatar *viewerAvatar; VoxelTree *tree; GLfloat *readVerticesArray; GLubyte *readColorsArray; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 41ffdc1e92..b4e6545271 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -64,7 +64,7 @@ #include "MenuColumn.h" #include "Menu.h" #include "Camera.h" -#include "Head.h" +#include "Avatar.h" #include "Particle.h" #include "Texture.h" #include "Cloud.h" @@ -107,7 +107,7 @@ Oscilloscope audioScope(256,200,true); ViewFrustum viewFrustum; // current state of view frustum, perspective, orientation, etc. -Head myAvatar(true); // The rendered avatar of oneself +Avatar myAvatar(true); // The rendered avatar of oneself Camera myCamera; // My view onto the world (sometimes on myself :) Camera viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode @@ -382,7 +382,7 @@ void initDisplay(void) void init(void) { voxels.init(); - voxels.setViewerHead(&myAvatar); + voxels.setViewerAvatar(&myAvatar); myAvatar.setRenderYaw(startYaw); initializeHandController(); @@ -911,7 +911,7 @@ void display(void) agent != agentList->getAgents().end(); agent++) { if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { - Head *avatar = (Head *)agent->getLinkedData(); + Avatar *avatar = (Avatar *)agent->getLinkedData(); avatar->render(0); } } @@ -1493,7 +1493,7 @@ void idle(void) { { if (agent->getLinkedData() != NULL) { - Head *avatar = (Head *)agent->getLinkedData(); + Avatar *avatar = (Avatar *)agent->getLinkedData(); avatar->simulate(deltaTime); } } @@ -1604,7 +1604,7 @@ void mouseoverFunc( int x, int y) void attachNewHeadToAgent(Agent *newAgent) { if (newAgent->getLinkedData() == NULL) { - newAgent->setLinkedData(new Head(false)); + newAgent->setLinkedData(new Avatar(false)); } } From bc6512600479c346f3417757d816cdce6793e6b7 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 24 Apr 2013 16:58:52 -0700 Subject: [PATCH 50/52] Wider log window, log panel on by default, menu->tools->log to control. --- interface/src/Log.h | 2 +- interface/src/main.cpp | 29 ++++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/interface/src/Log.h b/interface/src/Log.h index 7def966c32..30f9098bc9 100644 --- a/interface/src/Log.h +++ b/interface/src/Log.h @@ -55,7 +55,7 @@ class Log { public: explicit Log(FILE* tPipeTo = stdout, unsigned bufferedLines = 1024, - unsigned defaultLogWidth = 240, unsigned defaultCharWidth = 6, unsigned defaultCharHeight = 20); + unsigned defaultLogWidth = 400, unsigned defaultCharWidth = 6, unsigned defaultCharHeight = 20); ~Log(); void setLogWidth(unsigned pixels); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 41ffdc1e92..0305df5e6a 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -157,6 +157,8 @@ VoxelDetail paintingVoxel; // The voxel we're painting if we're paintin unsigned char dominantColor = 0; // The dominant color of the voxel we're painting bool perfStatsOn = false; // Do we want to display perfStats? +bool logOn = true; // Whether to show on-screen log + int noiseOn = 0; // Whether to add random noise float noise = 1.0; // Overall magnitude scaling for random noise levels @@ -919,7 +921,7 @@ void display(void) if ( !::lookingInMirror ) balls.render(); // Render the world box - if (!::lookingInMirror && statsOn) render_world_box(); + if (!::lookingInMirror && ::statsOn) { render_world_box(); } // brad's frustum for debugging if (::frustumOn) renderViewFrustum(::viewFrustum); @@ -961,13 +963,12 @@ void display(void) // Show detected levels from the serial I/O ADC channel sensors if (displayLevels) serialPort.renderLevels(WIDTH,HEIGHT); - // Display miscellaneous text stats onscreen - if (statsOn) { - glLineWidth(1.0f); - glPointSize(1.0f); - displayStats(); - logger.render(WIDTH, HEIGHT); - } + // Display stats and log text onscreen + glLineWidth(1.0f); + glPointSize(1.0f); + + if (::statsOn) { displayStats(); } + if (::logOn) { logger.render(WIDTH, HEIGHT); } // Show menu if (::menuOn) { @@ -1056,6 +1057,11 @@ int setNoise(int state) { return iRet; } +int setLog(int state) { + int iRet = setValue(state, &::logOn); + return iRet; +} + int setGyroLook(int state) { int iRet = setValue(state, &::gyroLook); return iRet; @@ -1070,7 +1076,7 @@ int setStars(int state) { } int setStats(int state) { - return setValue(state, &statsOn); + return setValue(state, &::statsOn); } int setMenu(int state) { @@ -1195,7 +1201,8 @@ void initMenu() { // Tools menuColumnTools = menu.addColumn("Tools"); - menuColumnTools->addRow("Stats (/)", setStats); + menuColumnTools->addRow("Stats (/)", setStats); + menuColumnTools->addRow("Log ", setLog); menuColumnTools->addRow("(M)enu", setMenu); // Frustum Options @@ -1353,7 +1360,7 @@ void key(unsigned char k, int x, int y) // Process keypresses if (k == 'q' || k == 'Q') ::terminate(); - if (k == '/') statsOn = !statsOn; // toggle stats + if (k == '/') ::statsOn = !::statsOn; // toggle stats if (k == '*') ::starsOn = !::starsOn; // toggle stars if (k == 'V' || k == 'v') ::showingVoxels = !::showingVoxels; // toggle voxels if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging From 2163976f067c26fb677884ccf59dfb30ace4795c Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 24 Apr 2013 17:01:59 -0700 Subject: [PATCH 51/52] adding the files --- interface/src/Avatar.cpp | 1270 ++++++++++++++++++++++++++++++++++++++ interface/src/Avatar.h | 268 ++++++++ 2 files changed, 1538 insertions(+) create mode 100644 interface/src/Avatar.cpp create mode 100644 interface/src/Avatar.h diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp new file mode 100644 index 0000000000..ae082fd71c --- /dev/null +++ b/interface/src/Avatar.cpp @@ -0,0 +1,1270 @@ +// +// Avatar.cpp +// interface +// +// Created by Philip Rosedale on 9/11/12. +// adapted by Jeffrey Ventrella +// Copyright (c) 2012 Physical, Inc.. All rights reserved. +// + +#include +#include +#include +#include +#include "Avatar.h" +#include "Log.h" +#include +#include +#include + +using namespace std; + +float skinColor[] = {1.0, 0.84, 0.66}; +float lightBlue[] = { 0.7, 0.8, 1.0 }; +float browColor[] = {210.0/255.0, 105.0/255.0, 30.0/255.0}; +float mouthColor[] = {1, 0, 0}; + +float BrowRollAngle[5] = {0, 15, 30, -30, -15}; +float BrowPitchAngle[3] = {-70, -60, -50}; +float eyeColor[3] = {1,1,1}; + +float MouthWidthChoices[3] = {0.5, 0.77, 0.3}; + +float browWidth = 0.8; +float browThickness = 0.16; + +bool usingBigSphereCollisionTest = true; + +char iris_texture_file[] = "resources/images/green_eye.png"; + +vector iris_texture; +unsigned int iris_texture_width = 512; +unsigned int iris_texture_height = 256; + +Avatar::Avatar(bool isMine) { + + _orientation.setToIdentity(); + + _velocity = glm::vec3( 0.0, 0.0, 0.0 ); + _thrust = glm::vec3( 0.0, 0.0, 0.0 ); + _rotation = glm::quat( 0.0f, 0.0f, 0.0f, 0.0f ); + _bodyYaw = -90.0; + _bodyPitch = 0.0; + _bodyRoll = 0.0; + _bodyYawDelta = 0.0; + _mousePressed = false; + _mode = AVATAR_MODE_STANDING; + _isMine = isMine; + _maxArmLength = 0.0; + //_transmitterTimer = 0; + _transmitterHz = 0.0; + _transmitterPackets = 0; + + initializeSkeleton(); + + _TEST_bigSphereRadius = 0.3f; + _TEST_bigSpherePosition = glm::vec3( 0.0f, _TEST_bigSphereRadius, 2.0f ); + + for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false; + + _head.pupilSize = 0.10; + _head.interPupilDistance = 0.6; + _head.interBrowDistance = 0.75; + _head.nominalPupilSize = 0.10; + _head.pitchRate = 0.0; + _head.yawRate = 0.0; + _head.rollRate = 0.0; + _head.eyebrowPitch[0] = -30; + _head.eyebrowPitch[1] = -30; + _head.eyebrowRoll [0] = 20; + _head.eyebrowRoll [1] = -20; + _head.mouthPitch = 0; + _head.mouthYaw = 0; + _head.mouthWidth = 1.0; + _head.mouthHeight = 0.2; + _head.eyeballPitch[0] = 0; + _head.eyeballPitch[1] = 0; + _head.eyeballScaleX = 1.2; + _head.eyeballScaleY = 1.5; + _head.eyeballScaleZ = 1.0; + _head.eyeballYaw[0] = 0; + _head.eyeballYaw[1] = 0; + _head.pitchTarget = 0; + _head.yawTarget = 0; + _head.noiseEnvelope = 1.0; + _head.pupilConverge = 10.0; + _head.leanForward = 0.0; + _head.leanSideways = 0.0; + _head.eyeContact = 1; + _head.eyeContactTarget = LEFT_EYE; + _head.scale = 1.0; + _head.audioAttack = 0.0; + _head.averageLoudness = 0.0; + _head.lastLoudness = 0.0; + _head.browAudioLift = 0.0; + _head.noise = 0; + _movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 ); + _usingBodySprings = true; + _springForce = 6.0f; + _springVelocityDecay = 16.0f; + _renderYaw = 0.0; + _renderPitch = 0.0; + _sphere = NULL; + _interactingOther = NULL; + _interactingOtherIsNearby = false; + + _handHolding.position = glm::vec3( 0.0, 0.0, 0.0 ); + _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); + _handHolding.force = 10.0f; + + if (iris_texture.size() == 0) { + switchToResourcesParentIfRequired(); + unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file); + if (error != 0) { + printLog("error %u: %s\n", error, lodepng_error_text(error)); + } + } +} + + + +Avatar::Avatar(const Avatar &otherAvatar) { + + _velocity = otherAvatar._velocity; + _thrust = otherAvatar._thrust; + _rotation = otherAvatar._rotation; + _interactingOtherIsNearby = otherAvatar._interactingOtherIsNearby; + _bodyYaw = otherAvatar._bodyYaw; + _bodyPitch = otherAvatar._bodyPitch; + _bodyRoll = otherAvatar._bodyRoll; + _bodyYawDelta = otherAvatar._bodyYawDelta; + _mousePressed = otherAvatar._mousePressed; + _mode = otherAvatar._mode; + _isMine = otherAvatar._isMine; + _renderYaw = otherAvatar._renderYaw; + _renderPitch = otherAvatar._renderPitch; + _maxArmLength = otherAvatar._maxArmLength; + _transmitterTimer = otherAvatar._transmitterTimer; + _transmitterHz = otherAvatar._transmitterHz; + _transmitterPackets = otherAvatar._transmitterPackets; + _TEST_bigSphereRadius = otherAvatar._TEST_bigSphereRadius; + _TEST_bigSpherePosition = otherAvatar._TEST_bigSpherePosition; + _movedHandOffset = otherAvatar._movedHandOffset; + _usingBodySprings = otherAvatar._usingBodySprings; + _springForce = otherAvatar._springForce; + _springVelocityDecay = otherAvatar._springVelocityDecay; + _orientation.set( otherAvatar._orientation ); + + _sphere = NULL; + + initializeSkeleton(); + + for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = otherAvatar._driveKeys[i]; + + _head.pupilSize = otherAvatar._head.pupilSize; + _head.interPupilDistance = otherAvatar._head.interPupilDistance; + _head.interBrowDistance = otherAvatar._head.interBrowDistance; + _head.nominalPupilSize = otherAvatar._head.nominalPupilSize; + _head.yawRate = otherAvatar._head.yawRate; + _head.pitchRate = otherAvatar._head.pitchRate; + _head.rollRate = otherAvatar._head.rollRate; + _head.eyebrowPitch[0] = otherAvatar._head.eyebrowPitch[0]; + _head.eyebrowPitch[1] = otherAvatar._head.eyebrowPitch[1]; + _head.eyebrowRoll [0] = otherAvatar._head.eyebrowRoll [0]; + _head.eyebrowRoll [1] = otherAvatar._head.eyebrowRoll [1]; + _head.mouthPitch = otherAvatar._head.mouthPitch; + _head.mouthYaw = otherAvatar._head.mouthYaw; + _head.mouthWidth = otherAvatar._head.mouthWidth; + _head.mouthHeight = otherAvatar._head.mouthHeight; + _head.eyeballPitch[0] = otherAvatar._head.eyeballPitch[0]; + _head.eyeballPitch[1] = otherAvatar._head.eyeballPitch[1]; + _head.eyeballScaleX = otherAvatar._head.eyeballScaleX; + _head.eyeballScaleY = otherAvatar._head.eyeballScaleY; + _head.eyeballScaleZ = otherAvatar._head.eyeballScaleZ; + _head.eyeballYaw[0] = otherAvatar._head.eyeballYaw[0]; + _head.eyeballYaw[1] = otherAvatar._head.eyeballYaw[1]; + _head.pitchTarget = otherAvatar._head.pitchTarget; + _head.yawTarget = otherAvatar._head.yawTarget; + _head.noiseEnvelope = otherAvatar._head.noiseEnvelope; + _head.pupilConverge = otherAvatar._head.pupilConverge; + _head.leanForward = otherAvatar._head.leanForward; + _head.leanSideways = otherAvatar._head.leanSideways; + _head.eyeContact = otherAvatar._head.eyeContact; + _head.eyeContactTarget = otherAvatar._head.eyeContactTarget; + _head.scale = otherAvatar._head.scale; + _head.audioAttack = otherAvatar._head.audioAttack; + _head.averageLoudness = otherAvatar._head.averageLoudness; + _head.lastLoudness = otherAvatar._head.lastLoudness; + _head.browAudioLift = otherAvatar._head.browAudioLift; + _head.noise = otherAvatar._head.noise; + + if (iris_texture.size() == 0) { + switchToResourcesParentIfRequired(); + unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file); + if (error != 0) { + printLog("error %u: %s\n", error, lodepng_error_text(error)); + } + } +} + +Avatar::~Avatar() { + if (_sphere != NULL) { + gluDeleteQuadric(_sphere); + } +} + +Avatar* Avatar::clone() const { + return new Avatar(*this); +} + +void Avatar::reset() { + _headPitch = _headYaw = _headRoll = 0; + _head.leanForward = _head.leanSideways = 0; +} + + +//this pertains to moving the head with the glasses +void Avatar::UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity) +// Using serial data, update avatar/render position and angles +{ + const float PITCH_ACCEL_COUPLING = 0.5; + const float ROLL_ACCEL_COUPLING = -1.0; + float measured_pitch_rate = serialInterface->getRelativeValue(HEAD_PITCH_RATE); + _head.yawRate = serialInterface->getRelativeValue(HEAD_YAW_RATE); + float measured_lateral_accel = serialInterface->getRelativeValue(ACCEL_X) - + ROLL_ACCEL_COUPLING*serialInterface->getRelativeValue(HEAD_ROLL_RATE); + float measured_fwd_accel = serialInterface->getRelativeValue(ACCEL_Z) - + PITCH_ACCEL_COUPLING*serialInterface->getRelativeValue(HEAD_PITCH_RATE); + float measured_roll_rate = serialInterface->getRelativeValue(HEAD_ROLL_RATE); + + //printLog("Pitch Rate: %d ACCEL_Z: %d\n", serialInterface->getRelativeValue(PITCH_RATE), + // serialInterface->getRelativeValue(ACCEL_Z)); + //printLog("Pitch Rate: %d ACCEL_X: %d\n", serialInterface->getRelativeValue(PITCH_RATE), + // serialInterface->getRelativeValue(ACCEL_Z)); + //printLog("Pitch: %f\n", Pitch); + + // Update avatar head position based on measured gyro rates + const float HEAD_ROTATION_SCALE = 0.70; + const float HEAD_ROLL_SCALE = 0.40; + const float HEAD_LEAN_SCALE = 0.01; + const float MAX_PITCH = 45; + const float MIN_PITCH = -45; + const float MAX_YAW = 85; + const float MIN_YAW = -85; + + if ((_headPitch < MAX_PITCH) && (_headPitch > MIN_PITCH)) + addHeadPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); + + addHeadRoll(measured_roll_rate * HEAD_ROLL_SCALE * frametime); + + if ((_headYaw < MAX_YAW) && (_headYaw > MIN_YAW)) + addHeadYaw(_head.yawRate * HEAD_ROTATION_SCALE * frametime); + + addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE); +} + +void Avatar::addLean(float x, float z) { + // Add Body lean as impulse + _head.leanSideways += x; + _head.leanForward += z; +} + + +void Avatar::setLeanForward(float dist){ + _head.leanForward = dist; +} + +void Avatar::setLeanSideways(float dist){ + _head.leanSideways = dist; +} + +void Avatar::setMousePressed( bool d ) { + _mousePressed = d; +} + +void Avatar::simulate(float deltaTime) { + + // update avatar skeleton + updateSkeleton(); + + // reset hand and arm positions according to hand movement + updateHandMovement( deltaTime ); + + if ( !_interactingOtherIsNearby ) { + //initialize _handHolding + _handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position; + _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); + } + + _interactingOtherIsNearby = false; + + // if the avatar being simulated is mine, then loop through + // all the other avatars for potential interactions... + if ( _isMine ) + { + float closestDistance = 10000.0f; + + AgentList * agentList = AgentList::getInstance(); + + for(std::vector::iterator agent = agentList->getAgents().begin(); + agent != agentList->getAgents().end(); + agent++) { + if (( agent->getLinkedData() != NULL && ( agent->getType() == AGENT_TYPE_AVATAR ) )) { + Avatar *otherAvatar = (Avatar *)agent->getLinkedData(); + + // check for collisions with other avatars and respond + updateAvatarCollisionDetectionAndResponse + ( + otherAvatar->getPosition(), + otherAvatar->getGirth(), + otherAvatar->getHeight(), + otherAvatar->getBodyUpDirection(), + deltaTime + ); + + // test other avatar hand position for proximity + glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); + v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); + + float distance = glm::length( v ); + if ( distance < _maxArmLength ) { + + //if ( distance < closestDistance ) { // perhaps I don't need this if we want to allow multi-avatar interactions + { + closestDistance = distance; + _interactingOther = otherAvatar; + _interactingOtherIsNearby = true; + + // if I am holding hands with another avatar, a force is applied + if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) { + glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHolding.position; + glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; + + _handHolding.velocity *= 0.7; + _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; + _handHolding.position += _handHolding.velocity; + + _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; + } + } + } + } + } + + // Set the vector we send for hand position to other people to be our right hand + setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position); + + }//if ( _isMine ) + + + updateArmIKAndConstraints( deltaTime ); + + if (!_interactingOtherIsNearby) { + _interactingOther = NULL; + } + + if ( usingBigSphereCollisionTest ) { + + // test for avatar collision response (using a big sphere :) + updateAvatarCollisionDetectionAndResponse + ( + _TEST_bigSpherePosition, + _TEST_bigSphereRadius, + _TEST_bigSphereRadius, + glm::vec3( 0.0, 1.0, 0.0 ), + deltaTime + ); + } + + if ( AVATAR_GRAVITY ) { + if ( _position.y > _bone[ AVATAR_BONE_RIGHT_FOOT ].radius * 2.0 ) { + _velocity += glm::dvec3( 0.0, -1.0, 0.0 ) * ( 6.0 * deltaTime ); + } + else { + if ( _position.y < _bone[ AVATAR_BONE_RIGHT_FOOT ].radius ) { + _position.y = _bone[ AVATAR_BONE_RIGHT_FOOT ].radius; + _velocity.y = 0.0; + } + } + } + + // update body springs + updateBodySprings( deltaTime ); + + // driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely) + if ( _isMine ) { + + _thrust = glm::vec3( 0.0, 0.0, 0.0 ); + + if (_driveKeys[FWD]) { + glm::vec3 front( _orientation.getFront().x, _orientation.getFront().y, _orientation.getFront().z ); + _thrust += front * THRUST_MAG; + } + if (_driveKeys[BACK]) { + glm::vec3 front( _orientation.getFront().x, _orientation.getFront().y, _orientation.getFront().z ); + _thrust -= front * THRUST_MAG; + } + if (_driveKeys[RIGHT]) { + glm::vec3 right( _orientation.getRight().x, _orientation.getRight().y, _orientation.getRight().z ); + _thrust += right * THRUST_MAG; + } + if (_driveKeys[LEFT]) { + glm::vec3 right( _orientation.getRight().x, _orientation.getRight().y, _orientation.getRight().z ); + _thrust -= right * THRUST_MAG; + } + if (_driveKeys[UP]) { + glm::vec3 up( _orientation.getUp().x, _orientation.getUp().y, _orientation.getUp().z ); + _thrust += up * THRUST_MAG; + } + if (_driveKeys[DOWN]) { + glm::vec3 up( _orientation.getUp().x, _orientation.getUp().y, _orientation.getUp().z ); + _thrust -= up * THRUST_MAG; + } + if (_driveKeys[ROT_RIGHT]) { + _bodyYawDelta -= YAW_MAG * deltaTime; + } + if (_driveKeys[ROT_LEFT]) { + _bodyYawDelta += YAW_MAG * deltaTime; + } + } + + float translationalSpeed = glm::length( _velocity ); + float rotationalSpeed = fabs( _bodyYawDelta ); + if ( translationalSpeed + rotationalSpeed > 0.2 ) + { + _mode = AVATAR_MODE_WALKING; + } + else + { + _mode = AVATAR_MODE_INTERACTING; + } + + // update body yaw by body yaw delta + if (_isMine) { + _bodyYaw += _bodyYawDelta * deltaTime; + } + + // decay body yaw delta + _bodyYawDelta *= (1.0 - TEST_YAW_DECAY * deltaTime); + + // add thrust to velocity + _velocity += glm::dvec3(_thrust * deltaTime); + + // update position by velocity + _position += (glm::vec3)_velocity * deltaTime; + + // decay velocity + _velocity *= ( 1.0 - LIN_VEL_DECAY * deltaTime ); + + // + // Update Head information + // + + if (!_head.noise) { + // Decay back toward center + _headPitch *= (1.0f - DECAY * 2 * deltaTime); + _headYaw *= (1.0f - DECAY * 2 * deltaTime); + _headRoll *= (1.0f - DECAY * 2 * deltaTime); + } + else { + // Move toward new target + _headPitch += (_head.pitchTarget - _headPitch) * 10 * deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ; + _headYaw += (_head.yawTarget - _headYaw ) * 10 * deltaTime; // (1.f - DECAY*deltaTime); + _headRoll *= 1.f - (DECAY * deltaTime); + } + + _head.leanForward *= (1.f - DECAY * 30 * deltaTime); + _head.leanSideways *= (1.f - DECAY * 30 * deltaTime); + + // Update where the avatar's eyes are + // + // First, decide if we are making eye contact or not + if (randFloat() < 0.005) { + _head.eyeContact = !_head.eyeContact; + _head.eyeContact = 1; + if (!_head.eyeContact) { + // If we just stopped making eye contact,move the eyes markedly away + _head.eyeballPitch[0] = _head.eyeballPitch[1] = _head.eyeballPitch[0] + 5.0 + (randFloat() - 0.5) * 10; + _head.eyeballYaw [0] = _head.eyeballYaw [1] = _head.eyeballYaw [0] + 5.0 + (randFloat() - 0.5) * 5; + } else { + // If now making eye contact, turn head to look right at viewer + SetNewHeadTarget(0,0); + } + } + + const float DEGREES_BETWEEN_VIEWER_EYES = 3; + const float DEGREES_TO_VIEWER_MOUTH = 7; + + if (_head.eyeContact) { + // Should we pick a new eye contact target? + if (randFloat() < 0.01) { + // Choose where to look next + if (randFloat() < 0.1) { + _head.eyeContactTarget = MOUTH; + } else { + if (randFloat() < 0.5) _head.eyeContactTarget = LEFT_EYE; else _head.eyeContactTarget = RIGHT_EYE; + } + } + // Set eyeball pitch and yaw to make contact + float eye_target_yaw_adjust = 0; + float eye_target_pitch_adjust = 0; + if (_head.eyeContactTarget == LEFT_EYE) eye_target_yaw_adjust = DEGREES_BETWEEN_VIEWER_EYES; + if (_head.eyeContactTarget == RIGHT_EYE) eye_target_yaw_adjust = -DEGREES_BETWEEN_VIEWER_EYES; + if (_head.eyeContactTarget == MOUTH) eye_target_pitch_adjust = DEGREES_TO_VIEWER_MOUTH; + + _head.eyeballPitch[0] = _head.eyeballPitch[1] = -_headPitch + eye_target_pitch_adjust; + _head.eyeballYaw[0] = _head.eyeballYaw[1] = -_headYaw + eye_target_yaw_adjust; + } + + + if (_head.noise) + { + _headPitch += (randFloat() - 0.5) * 0.2 * _head.noiseEnvelope; + _headYaw += (randFloat() - 0.5) * 0.3 *_head.noiseEnvelope; + //PupilSize += (randFloat() - 0.5) * 0.001*NoiseEnvelope; + + if (randFloat() < 0.005) _head.mouthWidth = MouthWidthChoices[rand()%3]; + + if (!_head.eyeContact) { + if (randFloat() < 0.01) _head.eyeballPitch[0] = _head.eyeballPitch[1] = (randFloat() - 0.5) * 20; + if (randFloat() < 0.01) _head.eyeballYaw[0] = _head.eyeballYaw[1] = (randFloat()- 0.5) * 10; + } + + if ((randFloat() < 0.005) && (fabs(_head.pitchTarget - _headPitch) < 1.0) && (fabs(_head.yawTarget - _headYaw) < 1.0)) { + SetNewHeadTarget((randFloat()-0.5) * 20.0, (randFloat()-0.5) * 45.0); + } + + if (0) { + + // Pick new target + _head.pitchTarget = (randFloat() - 0.5) * 45; + _head.yawTarget = (randFloat() - 0.5) * 22; + } + if (randFloat() < 0.01) + { + _head.eyebrowPitch[0] = _head.eyebrowPitch[1] = BrowPitchAngle[rand()%3]; + _head.eyebrowRoll [0] = _head.eyebrowRoll[1] = BrowRollAngle[rand()%5]; + _head.eyebrowRoll [1] *=-1; + } + } + + // Update audio trailing average for rendering facial animations + const float AUDIO_AVERAGING_SECS = 0.05; + _head.averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _head.averageLoudness + + (deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness; +} + + +float Avatar::getGirth() { + return COLLISION_BODY_RADIUS; +} + +float Avatar::getHeight() { + return COLLISION_HEIGHT; +} + + +glm::vec3 Avatar::getBodyUpDirection() { + return _orientation.getUp(); +} + +// This is a workspace for testing avatar body collision detection and response +void Avatar::updateAvatarCollisionDetectionAndResponse +( glm::vec3 collisionPosition, float collisionGirth, float collisionHeight, glm::vec3 collisionUpVector, float deltaTime ) { + + float myBodyApproximateBoundingRadius = 1.0f; + glm::vec3 vectorFromMyBodyToBigSphere(_position - collisionPosition); + bool jointCollision = false; + + float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere); + if ( distanceToBigSphere < myBodyApproximateBoundingRadius + collisionGirth ) + { + for (int b=0; b 0.0) + { + glm::vec3 directionVector = vectorFromJointToBigSphereCenter / distanceToBigSphereCenter; + + float penetration = 1.0 - (distanceToBigSphereCenter / combinedRadius); + glm::vec3 collisionForce = vectorFromJointToBigSphereCenter * penetration; + + _bone[b].springyVelocity += collisionForce * 30.0f * deltaTime; + _velocity += collisionForce * 100.0f * deltaTime; + _bone[b].springyPosition = collisionPosition + directionVector * combinedRadius; + } + } + } + + if ( jointCollision ) { + if (!_usingBodySprings) { + _usingBodySprings = true; + initializeBodySprings(); + } + } + } +} + + +void Avatar::render(bool lookingInMirror) { + + // show avatar position + glColor4f( 0.5f, 0.5f, 0.5f, 0.6 ); + glPushMatrix(); + glTranslatef(_position.x, _position.y, _position.z); + glScalef( 0.03, 0.03, 0.03 ); + glutSolidSphere( 1, 10, 10 ); + glPopMatrix(); + + if ( usingBigSphereCollisionTest ) { + + // show TEST big sphere + glColor4f( 0.5f, 0.6f, 0.8f, 0.7 ); + glPushMatrix(); + glTranslatef(_TEST_bigSpherePosition.x, _TEST_bigSpherePosition.y, _TEST_bigSpherePosition.z); + glScalef( _TEST_bigSphereRadius, _TEST_bigSphereRadius, _TEST_bigSphereRadius ); + glutSolidSphere( 1, 20, 20 ); + glPopMatrix(); + } + + // render body + renderBody(); + + // render head + renderHead(lookingInMirror); + + // if this is my avatar, then render my interactions with the other avatar + if ( _isMine ) + { + if ( _interactingOtherIsNearby ) { + + 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(); + } + } +} + + +void Avatar::renderHead(bool lookingInMirror) { + int side = 0; + + glEnable(GL_DEPTH_TEST); + glEnable(GL_RESCALE_NORMAL); + + // show head orientation + //renderOrientationDirections( _bone[ AVATAR_BONE_HEAD ].position, _bone[ AVATAR_BONE_HEAD ].orientation, 0.2f ); + + glPushMatrix(); + + if (_usingBodySprings) { + glTranslatef(_bone[ AVATAR_BONE_HEAD ].springyPosition.x, + _bone[ AVATAR_BONE_HEAD ].springyPosition.y, + _bone[ AVATAR_BONE_HEAD ].springyPosition.z); + } + else { + glTranslatef(_bone[ AVATAR_BONE_HEAD ].position.x, + _bone[ AVATAR_BONE_HEAD ].position.y, + _bone[ AVATAR_BONE_HEAD ].position.z); + } + + glScalef( 0.03, 0.03, 0.03 ); + + if (lookingInMirror) { + glRotatef(_bodyYaw - _headYaw, 0, 1, 0); + glRotatef(_bodyPitch + _headPitch, 1, 0, 0); + glRotatef(_bodyRoll - _headRoll, 0, 0, 1); + } else { + glRotatef(_bodyYaw + _headYaw, 0, 1, 0); + glRotatef(_bodyPitch + _headPitch, 1, 0, 0); + glRotatef(_bodyRoll + _headRoll, 0, 0, 1); + } + + glScalef(2.0, 2.0, 2.0); + glColor3fv(skinColor); + + glutSolidSphere(1, 30, 30); + + // Ears + glPushMatrix(); + glTranslatef(1.0, 0, 0); + for(side = 0; side < 2; side++) { + glPushMatrix(); + glScalef(0.3, 0.65, .65); + glutSolidSphere(0.5, 30, 30); + glPopMatrix(); + glTranslatef(-2.0, 0, 0); + } + glPopMatrix(); + + + // Update audio attack data for facial animation (eyebrows and mouth) + _head.audioAttack = 0.9 * _head.audioAttack + 0.1 * fabs(_audioLoudness - _head.lastLoudness); + _head.lastLoudness = _audioLoudness; + + + const float BROW_LIFT_THRESHOLD = 100; + if (_head.audioAttack > BROW_LIFT_THRESHOLD) + _head.browAudioLift += sqrt(_head.audioAttack) / 1000.0; + + _head.browAudioLift *= .90; + + + // Render Eyebrows + glPushMatrix(); + glTranslatef(-_head.interBrowDistance / 2.0,0.4,0.45); + for(side = 0; side < 2; side++) { + glColor3fv(browColor); + glPushMatrix(); + glTranslatef(0, 0.35 + _head.browAudioLift, 0); + glRotatef(_head.eyebrowPitch[side]/2.0, 1, 0, 0); + glRotatef(_head.eyebrowRoll[side]/2.0, 0, 0, 1); + glScalef(browWidth, browThickness, 1); + glutSolidCube(0.5); + glPopMatrix(); + glTranslatef(_head.interBrowDistance, 0, 0); + } + glPopMatrix(); + + + // Mouth + + glPushMatrix(); + glTranslatef(0,-0.35,0.75); + glColor3f(0,0,0); + glRotatef(_head.mouthPitch, 1, 0, 0); + glRotatef(_head.mouthYaw, 0, 0, 1); + glScalef(_head.mouthWidth*(.7 + sqrt(_head.averageLoudness)/60.0), _head.mouthHeight*(1.0 + sqrt(_head.averageLoudness)/30.0), 1); + glutSolidCube(0.5); + glPopMatrix(); + + glTranslatef(0, 1.0, 0); + + glTranslatef(-_head.interPupilDistance/2.0,-0.68,0.7); + // Right Eye + glRotatef(-10, 1, 0, 0); + glColor3fv(eyeColor); + glPushMatrix(); + { + glTranslatef(_head.interPupilDistance/10.0, 0, 0.05); + glRotatef(20, 0, 0, 1); + glScalef(_head.eyeballScaleX, _head.eyeballScaleY, _head.eyeballScaleZ); + glutSolidSphere(0.25, 30, 30); + } + glPopMatrix(); + + // Right Pupil + if (_sphere == NULL) { + _sphere = gluNewQuadric(); + gluQuadricTexture(_sphere, GL_TRUE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gluQuadricOrientation(_sphere, GLU_OUTSIDE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]); + } + + glPushMatrix(); + { + glRotatef(_head.eyeballPitch[1], 1, 0, 0); + glRotatef(_head.eyeballYaw[1] + _headYaw + _head.pupilConverge, 0, 1, 0); + glTranslatef(0,0,.35); + glRotatef(-75,1,0,0); + glScalef(1.0, 0.4, 1.0); + + glEnable(GL_TEXTURE_2D); + gluSphere(_sphere, _head.pupilSize, 15, 15); + glDisable(GL_TEXTURE_2D); + } + + glPopMatrix(); + // Left Eye + glColor3fv(eyeColor); + glTranslatef(_head.interPupilDistance, 0, 0); + glPushMatrix(); + { + glTranslatef(-_head.interPupilDistance/10.0, 0, .05); + glRotatef(-20, 0, 0, 1); + glScalef(_head.eyeballScaleX, _head.eyeballScaleY, _head.eyeballScaleZ); + glutSolidSphere(0.25, 30, 30); + } + glPopMatrix(); + // Left Pupil + glPushMatrix(); + { + glRotatef(_head.eyeballPitch[0], 1, 0, 0); + glRotatef(_head.eyeballYaw[0] + _headYaw - _head.pupilConverge, 0, 1, 0); + glTranslatef(0, 0, .35); + glRotatef(-75, 1, 0, 0); + glScalef(1.0, 0.4, 1.0); + + glEnable(GL_TEXTURE_2D); + gluSphere(_sphere, _head.pupilSize, 15, 15); + glDisable(GL_TEXTURE_2D); + } + + glPopMatrix(); + + + glPopMatrix(); + } + +void Avatar::startHandMovement() { + + if (!_usingBodySprings) { + initializeBodySprings(); + _usingBodySprings = true; + } +} + +void Avatar::stopHandMovement() { +//_usingBodySprings = false; +} + +void Avatar::setHandMovementValues( glm::vec3 handOffset ) { + _movedHandOffset = handOffset; +} + +AvatarMode Avatar::getMode() { + return _mode; +} + +void Avatar::initializeSkeleton() { + + for (int b=0; b 0.0f ) { + glm::vec3 springDirection = springVector / length; + + float force = ( length - _bone[b].length ) * _springForce * deltaTime; + + _bone[b].springyVelocity -= springDirection * force; + + if ( _bone[b].parent != AVATAR_BONE_NULL ) { + _bone[ _bone[b].parent ].springyVelocity += springDirection * force; + } + } + + _bone[b].springyVelocity += ( _bone[b].position - _bone[b].springyPosition ) * _bone[b].springBodyTightness * deltaTime; + + float decay = 1.0 - _springVelocityDecay * deltaTime; + + if ( decay > 0.0 ) { + _bone[b].springyVelocity *= decay; + } + else { + _bone[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f ); + } + + _bone[b].springyPosition += _bone[b].springyVelocity; + } +} + +glm::vec3 Avatar::getHeadLookatDirection() { + return glm::vec3 + ( + _orientation.getFront().x, + _orientation.getFront().y, + _orientation.getFront().z + ); +} + +glm::vec3 Avatar::getHeadLookatDirectionUp() { + return glm::vec3 + ( + _orientation.getUp().x, + _orientation.getUp().y, + _orientation.getUp().z + ); +} + +glm::vec3 Avatar::getHeadLookatDirectionRight() { + return glm::vec3 + ( + _orientation.getRight().x, + _orientation.getRight().y, + _orientation.getRight().z + ); +} + +glm::vec3 Avatar::getHeadPosition() { + + if ( _usingBodySprings ) { + return _bone[ AVATAR_BONE_HEAD ].springyPosition; + } + + return _bone[ AVATAR_BONE_HEAD ].position; +} + + +glm::vec3 Avatar::getBonePosition( AvatarBoneID b ) { + return _bone[b].position; +} + + + +void Avatar::updateHandMovement( float deltaTime ) { + glm::vec3 transformedHandMovement; + + transformedHandMovement + = _orientation.getRight() * _movedHandOffset.x + + _orientation.getUp() * -_movedHandOffset.y * 0.5f + + _orientation.getFront() * -_movedHandOffset.y; + + _bone[ AVATAR_BONE_RIGHT_HAND ].position += transformedHandMovement; + + if (_isMine) { + _handState = _mousePressed; + } +} + + +void Avatar::updateArmIKAndConstraints( float deltaTime ) { + + // determine the arm vector + glm::vec3 armVector = _bone[ AVATAR_BONE_RIGHT_HAND ].position; + armVector -= _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; + + // test to see if right hand is being dragged beyond maximum arm length + float distance = glm::length( armVector ); + + // if right hand is being dragged beyond maximum arm length... + if ( distance > _maxArmLength ) { + // reset right hand to be constrained to maximum arm length + _bone[ AVATAR_BONE_RIGHT_HAND ].position = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; + glm::vec3 armNormal = armVector / distance; + armVector = armNormal * _maxArmLength; + distance = _maxArmLength; + glm::vec3 constrainedPosition = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; + constrainedPosition += armVector; + _bone[ AVATAR_BONE_RIGHT_HAND ].position = constrainedPosition; + } + + // set elbow position + glm::vec3 newElbowPosition = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; + newElbowPosition += armVector * ONE_HALF; + glm::vec3 perpendicular = glm::cross( _orientation.getFront(), armVector ); + newElbowPosition += perpendicular * ( 1.0f - ( _maxArmLength / distance ) ) * ONE_HALF; + _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position = newElbowPosition; + + // set wrist position + glm::vec3 vv( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); + vv -= _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position; + glm::vec3 newWristPosition = _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position; + newWristPosition += vv * 0.7f; + _bone[ AVATAR_BONE_RIGHT_FOREARM ].position = newWristPosition; +} + + + + +void Avatar::renderBody() { + + // Render bone positions as spheres + for (int b=0; b( (double)TRANSMITTER_COUNT/(msecsElapsed/1000.0) ); + _transmitterTimer = now; + } + /* NOTE: PR: Will add back in when ready to animate avatar hand + + // Add rotational forces to the hand + const float ANG_VEL_SENSITIVITY = 4.0; + const float ANG_VEL_THRESHOLD = 0.0; + float angVelScale = ANG_VEL_SENSITIVITY*(1.0f/getTransmitterHz()); + + addAngularVelocity(fabs(gyrX*angVelScale)>ANG_VEL_THRESHOLD?gyrX*angVelScale:0, + fabs(gyrZ*angVelScale)>ANG_VEL_THRESHOLD?gyrZ*angVelScale:0, + fabs(-gyrY*angVelScale)>ANG_VEL_THRESHOLD?-gyrY*angVelScale:0); + + // Add linear forces to the hand + //const float LINEAR_VEL_SENSITIVITY = 50.0; + const float LINEAR_VEL_SENSITIVITY = 5.0; + float linVelScale = LINEAR_VEL_SENSITIVITY*(1.0f/getTransmitterHz()); + glm::vec3 linVel(linX*linVelScale, linZ*linVelScale, -linY*linVelScale); + addVelocity(linVel); + */ + +} + diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h new file mode 100644 index 0000000000..32d31184a8 --- /dev/null +++ b/interface/src/Avatar.h @@ -0,0 +1,268 @@ +// +// Avatar.h +// interface +// +// Created by Philip Rosedale on 9/11/12. +// Copyright (c) 2012 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__avatar__ +#define __interface__avatar__ + +#include +#include + +#include "Field.h" +#include "world.h" + +#include "InterfaceConfig.h" +#include "SerialInterface.h" + +#include +#include +#include //looks like we might not need this + +const bool AVATAR_GRAVITY = true; +const float DECAY = 0.1; +const float THRUST_MAG = 10.0; +const float YAW_MAG = 300.0; +const float TEST_YAW_DECAY = 5.0; +const float LIN_VEL_DECAY = 5.0; + +const float COLLISION_BODY_RADIUS = 0.1; +const float COLLISION_HEIGHT = 1.5; + +enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH}; + +#define FWD 0 +#define BACK 1 +#define LEFT 2 +#define RIGHT 3 +#define UP 4 +#define DOWN 5 +#define ROT_LEFT 6 +#define ROT_RIGHT 7 +#define MAX_DRIVE_KEYS 8 + +#define MAX_OTHER_AVATARS 10 // temporary - for testing purposes! + +enum AvatarMode +{ + AVATAR_MODE_STANDING = 0, + AVATAR_MODE_WALKING, + AVATAR_MODE_INTERACTING, + NUM_AVATAR_MODES +}; + +enum AvatarBoneID +{ + AVATAR_BONE_NULL = -1, + AVATAR_BONE_PELVIS_SPINE, // connects pelvis joint with torso joint (not supposed to be rotated) + AVATAR_BONE_MID_SPINE, // connects torso joint with chest joint + AVATAR_BONE_CHEST_SPINE, // connects chest joint with neckBase joint (not supposed to be rotated) + AVATAR_BONE_NECK, // connects neckBase joint with headBase joint + AVATAR_BONE_HEAD, // connects headBase joint with headTop joint + AVATAR_BONE_LEFT_CHEST, // connects chest joint with left clavicle joint (not supposed to be rotated) + AVATAR_BONE_LEFT_SHOULDER, // connects left clavicle joint with left shoulder joint + AVATAR_BONE_LEFT_UPPER_ARM, // connects left shoulder joint with left elbow joint + AVATAR_BONE_LEFT_FOREARM, // connects left elbow joint with left wrist joint + AVATAR_BONE_LEFT_HAND, // connects left wrist joint with left fingertips joint + AVATAR_BONE_RIGHT_CHEST, // connects chest joint with right clavicle joint (not supposed to be rotated) + AVATAR_BONE_RIGHT_SHOULDER, // connects right clavicle joint with right shoulder joint + AVATAR_BONE_RIGHT_UPPER_ARM, // connects right shoulder joint with right elbow joint + AVATAR_BONE_RIGHT_FOREARM, // connects right elbow joint with right wrist joint + AVATAR_BONE_RIGHT_HAND, // connects right wrist joint with right fingertips joint + AVATAR_BONE_LEFT_PELVIS, // connects pelvis joint with left hip joint (not supposed to be rotated) + AVATAR_BONE_LEFT_THIGH, // connects left hip joint with left knee joint + AVATAR_BONE_LEFT_SHIN, // connects left knee joint with left heel joint + AVATAR_BONE_LEFT_FOOT, // connects left heel joint with left toes joint + AVATAR_BONE_RIGHT_PELVIS, // connects pelvis joint with right hip joint (not supposed to be rotated) + AVATAR_BONE_RIGHT_THIGH, // connects right hip joint with right knee joint + AVATAR_BONE_RIGHT_SHIN, // connects right knee joint with right heel joint + AVATAR_BONE_RIGHT_FOOT, // connects right heel joint with right toes joint + + NUM_AVATAR_BONES +}; + +struct AvatarCollisionElipsoid +{ + bool colliding; + glm::vec3 position; + float girth; + float height; + glm::vec3 upVector; +}; + +struct AvatarHandHolding +{ + glm::vec3 position; + glm::vec3 velocity; + float force; +}; + +struct AvatarBone +{ + AvatarBoneID parent; // which bone is this bone connected to? + glm::vec3 position; // the position at the "end" of the bone + glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose" + glm::vec3 springyPosition; // used for special effects (a 'flexible' variant of position) + glm::dvec3 springyVelocity; // used for special effects ( the velocity of the springy position) + float springBodyTightness; // how tightly the springy position tries to stay on the position + glm::quat rotation; // this will eventually replace yaw, pitch and roll (and maybe orientation) + float yaw; // the yaw Euler angle of the bone rotation off the parent + float pitch; // the pitch Euler angle of the bone rotation off the parent + float roll; // the roll Euler angle of the bone rotation off the parent + Orientation orientation; // three orthogonal normals determined by yaw, pitch, roll + float length; // the length of the bone + float radius; // used for detecting collisions for certain physical effects +}; + +struct AvatarHead +{ + float pitchRate; + float yawRate; + float rollRate; + float noise; + float eyeballPitch[2]; + float eyeballYaw [2]; + float eyebrowPitch[2]; + float eyebrowRoll [2]; + float eyeballScaleX; + float eyeballScaleY; + float eyeballScaleZ; + float interPupilDistance; + float interBrowDistance; + float nominalPupilSize; + float pupilSize; + float mouthPitch; + float mouthYaw; + float mouthWidth; + float mouthHeight; + float leanForward; + float leanSideways; + float pitchTarget; + float yawTarget; + float noiseEnvelope; + float pupilConverge; + float scale; + int eyeContact; + float browAudioLift; + eyeContactTargets eyeContactTarget; + + // Sound loudness information + float lastLoudness; + float averageLoudness; + float audioAttack; +}; + + +class Avatar : public AvatarData { + public: + Avatar(bool isMine); + ~Avatar(); + Avatar(const Avatar &otherAvatar); + Avatar* clone() const; + + void reset(); + void UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity); + void setNoise (float mag) { _head.noise = mag; } + void setScale(float s) {_head.scale = s; }; + void setRenderYaw(float y) {_renderYaw = y;} + void setRenderPitch(float p) {_renderPitch = p;} + float getRenderYaw() {return _renderYaw;} + float getRenderPitch() {return _renderPitch;} + void setLeanForward(float dist); + void setLeanSideways(float dist); + void addLean(float x, float z); + float getLastMeasuredHeadYaw() const {return _head.yawRate;} + float getBodyYaw() {return _bodyYaw;}; + void addBodyYaw(float y) {_bodyYaw += y;}; + + glm::vec3 getHeadLookatDirection(); + glm::vec3 getHeadLookatDirectionUp(); + glm::vec3 getHeadLookatDirectionRight(); + glm::vec3 getHeadPosition(); + glm::vec3 getBonePosition( AvatarBoneID b ); + glm::vec3 getBodyUpDirection(); + float getGirth(); + float getHeight(); + + AvatarMode getMode(); + + void setMousePressed( bool pressed ); + void render(bool lookingInMirror); + void renderBody(); + void renderHead(bool lookingInMirror); + void simulate(float); + void startHandMovement(); + void stopHandMovement(); + void setHandMovementValues( glm::vec3 movement ); + void updateHandMovement( float deltaTime ); + void updateArmIKAndConstraints( float deltaTime ); + + float getAverageLoudness() {return _head.averageLoudness;}; + void setAverageLoudness(float al) {_head.averageLoudness = al;}; + + void SetNewHeadTarget(float, float); + + // 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]; }; + + // Set/Get update the thrust that will move the avatar around + void setThrust(glm::vec3 newThrust) { _thrust = newThrust; }; + void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; + glm::vec3 getThrust() { return _thrust; }; + + // Related to getting transmitter UDP data used to animate the avatar hand + void processTransmitterData(unsigned char * packetData, int numBytes); + float getTransmitterHz() { return _transmitterHz; }; + + private: + AvatarHead _head; + bool _isMine; + glm::vec3 _TEST_bigSpherePosition; + float _TEST_bigSphereRadius; + bool _mousePressed; + float _bodyYawDelta; + bool _usingBodySprings; + glm::vec3 _movedHandOffset; + float _springVelocityDecay; + float _springForce; + glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion + AvatarBone _bone[ NUM_AVATAR_BONES ]; + AvatarMode _mode; + AvatarHandHolding _handHolding; + glm::dvec3 _velocity; + glm::vec3 _thrust; + float _maxArmLength; + Orientation _orientation; + int _driveKeys[MAX_DRIVE_KEYS]; + GLUquadric* _sphere; + float _renderYaw; + float _renderPitch; // Pitch from view frustum when this is own head + timeval _transmitterTimer; + float _transmitterHz; + int _transmitterPackets; + Avatar* _interactingOther; + bool _interactingOtherIsNearby; + + // private methods... + void initializeSkeleton(); + void updateSkeleton(); + void initializeBodySprings(); + void updateBodySprings( float deltaTime ); + void calculateBoneLengths(); + void readSensors(); + void renderBoneAsBlock( AvatarBoneID b ); + void updateAvatarCollisionDetectionAndResponse + ( + glm::vec3 collisionPosition, + float collisionGirth, + float collisionHeight, + glm::vec3 collisionUpVector, + float deltaTime + ); +}; + +#endif From 72e6e18992076ee833d045fe9e74f400cf864ca7 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 24 Apr 2013 17:54:09 -0700 Subject: [PATCH 52/52] fixed avatar collisions --- interface/src/Avatar.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index ae082fd71c..9f9d1febba 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -315,9 +315,9 @@ void Avatar::simulate(float deltaTime) { // check for collisions with other avatars and respond updateAvatarCollisionDetectionAndResponse ( - otherAvatar->getPosition(), - otherAvatar->getGirth(), - otherAvatar->getHeight(), + otherAvatar->getBonePosition( AVATAR_BONE_PELVIS_SPINE ), + 0.2, + 0.2, otherAvatar->getBodyUpDirection(), deltaTime ); @@ -610,7 +610,6 @@ void Avatar::updateAvatarCollisionDetectionAndResponse } } - void Avatar::render(bool lookingInMirror) { // show avatar position