From f859d8ed9c74d639174d6bfff75b35946fa2f0e3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 3 Apr 2013 22:42:02 -0700 Subject: [PATCH 01/33] Added PaintMode, toggle for stars, etc. --- interface/src/main.cpp | 52 ++++++++++++++++++++++++++----- shared/src/AgentList.cpp | 1 + shared/src/AgentList.h | 1 + shared/src/SharedUtil.cpp | 65 +++++++++++++++++++++++++++++++++++++++ shared/src/SharedUtil.h | 13 ++++++++ 5 files changed, 124 insertions(+), 8 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 08cbf05b8f..2cba377d8f 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -142,6 +142,8 @@ float renderPitchRate = 0.f; glm::vec3 start_location(6.1f, 0, 1.4f); int stats_on = 0; // Whether to show onscreen text overlay with stats +bool starsOn = true; // Whether to display the stars +bool paintOn = false; // Whether to paint voxels as you fly around int noise_on = 0; // Whether to add random noise float noise = 1.0; // Overall magnitude scaling for random noise levels @@ -250,11 +252,14 @@ void display_stats(void) // bitmap chars are about 10 pels high char legend[] = "/ - toggle this display, Q - exit, H - show head, M - show hand, T - test audio"; drawtext(10, 15, 0.10f, 0, 1.0, 0, legend); + + char legend2[] = "* - toggle stars, & - toggle paint mode"; + drawtext(10, 32, 0.10f, 0, 1.0, 0, legend2); char stats[200]; sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d ", FPS, packets_per_second, bytes_per_second); - drawtext(10, 30, 0.10f, 0, 1.0, 0, stats); + drawtext(10, 49, 0.10f, 0, 1.0, 0, stats); if (serialPort.active) { sprintf(stats, "ADC samples = %d, LED = %d", serialPort.getNumSamples(), serialPort.getLED()); @@ -485,6 +490,34 @@ void simulateHead(float frametime) char broadcast_string[MAX_BROADCAST_STRING]; int broadcast_bytes = myHead.getBroadcastData(broadcast_string); agentList.broadcastToAgents(broadcast_string, broadcast_bytes,AgentList::AGENTS_OF_TYPE_VOXEL_AND_INTERFACE); + + // If I'm in paint mode, send a voxel out to VOXEL server agents. + if (::paintOn) { + + glm::vec3 headPos = myHead.getPos(); + + VoxelDetail paintingVoxel; + paintingVoxel.x = headPos.z/10.0; // voxel space x is positive z head space + paintingVoxel.y = headPos.y/-10.0; // voxel space y is negative y head space + paintingVoxel.z = headPos.x/-10.0; // voxel space z is negative x head space + paintingVoxel.s = 1.0/256; + paintingVoxel.red = 0; + paintingVoxel.green = 255; + paintingVoxel.blue = 0; + + unsigned char* bufferOut; + int sizeOut; + + if (paintingVoxel.x >= 0.0 && paintingVoxel.x <= 1.0 && + paintingVoxel.y >= 0.0 && paintingVoxel.y <= 1.0 && + paintingVoxel.z >= 0.0 && paintingVoxel.z <= 1.0) { + + if (createVoxelEditMessage('I',0,1,&paintingVoxel,bufferOut,sizeOut)){ + agentList.broadcastToAgents((char*)bufferOut, sizeOut,AgentList::AGENTS_OF_TYPE_VOXEL); + delete bufferOut; + } + } + } } int render_test_spot = WIDTH/2; @@ -531,7 +564,9 @@ void display(void) glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); - stars.render(fov); + if (::starsOn) { + stars.render(fov); + } glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); @@ -642,6 +677,10 @@ void display(void) sprintf(agents, "Agents nearby: %ld\n", agentList.getAgents().size()); drawtext(WIDTH-200,20, 0.10, 0, 1.0, 0, agents, 1, 1, 0); + if (::paintOn) { + drawtext(WIDTH-200,40, 0.10, 0, 1.0, 0, "Paint ON", 1, 1, 0); + } + glPopMatrix(); @@ -753,8 +792,9 @@ void key(unsigned char k, int x, int y) // Process keypresses if (k == 'q') ::terminate(); - if (k == '/') stats_on = !stats_on; // toggle stats + if (k == '*') ::starsOn = !::starsOn; // toggle stars + if (k == '&') ::paintOn = !::paintOn; // toggle paint if (k == 'n') { noise_on = !noise_on; // Toggle noise @@ -810,11 +850,7 @@ void key(unsigned char k, int x, int y) } // press the . key to get a new random sphere of voxels added - if (k == '.') - { - addRandomSphere(wantColorRandomizer); - //testPointToVoxel(); - } + if (k == '.') addRandomSphere(wantColorRandomizer); } // diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index 5fa28bba9a..9aa6422543 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -212,6 +212,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, const char* AgentList::AGENTS_OF_TYPE_HEAD = "H"; const char* AgentList::AGENTS_OF_TYPE_VOXEL_AND_INTERFACE = "VI"; +const char* AgentList::AGENTS_OF_TYPE_VOXEL = "V"; void AgentList::broadcastToAgents(char *broadcastData, size_t dataBytes,const char* agentTypes) { for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { diff --git a/shared/src/AgentList.h b/shared/src/AgentList.h index 99146c1984..ca6d844b48 100644 --- a/shared/src/AgentList.h +++ b/shared/src/AgentList.h @@ -69,6 +69,7 @@ public: static const char* AGENTS_OF_TYPE_HEAD; static const char* AGENTS_OF_TYPE_VOXEL_AND_INTERFACE; + static const char* AGENTS_OF_TYPE_VOXEL; }; diff --git a/shared/src/SharedUtil.cpp b/shared/src/SharedUtil.cpp index 5d1072ff57..be4d081c5a 100644 --- a/shared/src/SharedUtil.cpp +++ b/shared/src/SharedUtil.cpp @@ -10,6 +10,7 @@ #include #include #include "SharedUtil.h" +#include "OctalCode.h" #ifdef __APPLE__ #include @@ -124,6 +125,70 @@ bool cmdOptionExists(int argc, const char * argv[],const char* option) { return false; } +////////////////////////////////////////////////////////////////////////////////////////// +// Function: createVoxelEditMessage() +// Description: creates an "insert" or "remove" voxel message for a voxel code +// corresponding to the closest voxel which encloses a cube with +// lower corners at x,y,z, having side of length S. +// The input values x,y,z range 0.0 <= v < 1.0 +// message should be either 'I' for insert or 'R' for remove +// +// IMPORTANT: The buffer is returned to you a buffer which you MUST delete when you are +// done with it. +// +// HACK ATTACK: Well, what if this is larger than the MTU? That's the caller's problem, we +// just truncate the message +// Usage: +// unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue); +// tree->readCodeColorBufferToTree(voxelData); +// delete voxelData; +// +// Complaints: Brad :) +#define GUESS_OF_VOXELCODE_SIZE 10 +#define MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE 1500 +#define SIZE_OF_COLOR_DATA 3 +bool createVoxelEditMessage(unsigned char command, short int sequence, + int voxelCount, VoxelDetail* voxelDetails, unsigned char*& bufferOut, int& sizeOut) { + + bool success = true; // assume the best + int messageSize = MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE; // just a guess for now + int actualMessageSize = 3; + unsigned char* messageBuffer = new unsigned char[messageSize]; + unsigned short int* sequenceAt = (unsigned short int*)&messageBuffer[1]; + + messageBuffer[0]=command; + *sequenceAt=sequence; + unsigned char* copyAt = &messageBuffer[3]; + + for (int i=0;i MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) { + success=false; + } else { + // add it to our message + memcpy(copyAt,voxelData,lengthOfVoxelData); + copyAt+=lengthOfVoxelData+SIZE_OF_COLOR_DATA; + actualMessageSize+=lengthOfVoxelData+SIZE_OF_COLOR_DATA; + } + // cleanup + delete voxelData; + } + + if (success) { + // finally, copy the result to the output + bufferOut = new unsigned char[actualMessageSize]; + sizeOut=actualMessageSize; + memcpy(bufferOut,messageBuffer,actualMessageSize); + } + return success; +} + ////////////////////////////////////////////////////////////////////////////////////////// // Function: pointToVoxel() // Description: Given a universal point with location x,y,z this will return the voxel diff --git a/shared/src/SharedUtil.h b/shared/src/SharedUtil.h index e81592d5fd..8468a5601a 100644 --- a/shared/src/SharedUtil.h +++ b/shared/src/SharedUtil.h @@ -35,6 +35,19 @@ void switchToResourcesIfRequired(); const char* getCmdOption(int argc, const char * argv[],const char* option); bool cmdOptionExists(int argc, const char * argv[],const char* option); + +struct VoxelDetail { + float x; + float y; + float z; + float s; + unsigned char red; + unsigned char green; + unsigned char blue; +}; + unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r, unsigned char g, unsigned char b ); +bool createVoxelEditMessage(unsigned char command, short int sequence, + int voxelCount, VoxelDetail* voxelDetails, unsigned char*& bufferOut, int& sizeOut); #endif /* defined(__hifi__SharedUtil__) */ From 7d479af9c77d60a534cbe23e07bb0e2e7ddf1023 Mon Sep 17 00:00:00 2001 From: tosh Date: Thu, 4 Apr 2013 10:52:42 +0200 Subject: [PATCH 02/33] adjusts braces to agreed conventions --- shared/src/AngleUtils.h | 38 ++++++++++----------- shared/src/FloodFill.h | 55 +++++++++++++++++-------------- shared/src/Radix2InplaceSort.h | 34 +++++++++---------- shared/src/Radix2IntegerScanner.h | 21 ++++++------ shared/src/UrlReader.cpp | 16 ++++----- shared/src/UrlReader.h | 55 +++++++++++++++---------------- 6 files changed, 111 insertions(+), 108 deletions(-) diff --git a/shared/src/AngleUtils.h b/shared/src/AngleUtils.h index 533df57da9..dfe4f09124 100644 --- a/shared/src/AngleUtils.h +++ b/shared/src/AngleUtils.h @@ -11,22 +11,22 @@ #include -struct Degrees -{ +struct Degrees { + static float pi() { return 180.0f; } static float twicePi() { return 360.0f; } static float halfPi() { return 90.0f; } }; -struct Radians -{ +struct Radians { + static float pi() { return 3.141592653589793f; } static float twicePi() { return 6.283185307179586f; } static float halfPi() { return 1.5707963267948966; } }; -struct Rotations -{ +struct Rotations { + static float pi() { return 0.5f; } static float twicePi() { return 1.0f; } static float halfPi() { return 0.25f; } @@ -36,8 +36,8 @@ struct Rotations * Converts an angle from one unit to another. */ template< class UnitFrom, class UnitTo > -float angleConvert(float a) -{ +float angleConvert(float a) { + return a * (UnitTo::halfPi() / UnitFrom::halfPi()); } @@ -46,8 +46,8 @@ float angleConvert(float a) * Clamps an angle to the range of [-180; 180) degrees. */ template< class Unit > -float angleSignedNormal(float a) -{ +float angleSignedNormal(float a) { + float result = remainder(a, Unit::twicePi()); if (result == Unit::pi()) result = -Unit::pi(); @@ -58,8 +58,8 @@ float angleSignedNormal(float a) * Clamps an angle to the range of [0; 360) degrees. */ template< class Unit > -float angleUnsignedNormal(float a) -{ +float angleUnsignedNormal(float a) { + return angleSignedNormal(a - Unit::pi()) + Unit::pi(); } @@ -72,16 +72,16 @@ float angleUnsignedNormal(float a) * Both poles can be reached from any azimuthal direction. */ template< class Unit > -void angleHorizontalPolar(float& azimuth, float& altitude) -{ +void angleHorizontalPolar(float& azimuth, float& altitude) { + altitude = angleSignedNormal(altitude); - if (altitude > Unit::halfPi()) - { + if (altitude > Unit::halfPi()) { + altitude = Unit::pi() - altitude; azimuth += Unit::pi(); - } - else if (altitude < -Unit::halfPi()) - { + + } else if (altitude < -Unit::halfPi()) { + altitude = -Unit::pi() - altitude; azimuth += Unit::pi(); } diff --git a/shared/src/FloodFill.h b/shared/src/FloodFill.h index ff278b185b..b52720a7b1 100644 --- a/shared/src/FloodFill.h +++ b/shared/src/FloodFill.h @@ -18,8 +18,8 @@ void floodFill(Cursor const& position, template< class Strategy, typename Cursor > -struct floodFill_impl : Strategy -{ +struct floodFill_impl : Strategy { + floodFill_impl(Strategy const& s) : Strategy(s) { } using Strategy::select; @@ -33,14 +33,15 @@ struct floodFill_impl : Strategy using Strategy::defer; using Strategy::deferred; - void go(Cursor position) - { + void go(Cursor position) { + Cursor higher, lower, h,l, i; bool higherFound, lowerFound, hf, lf; - do - { - if (! select(position)) + do { + + if (! select(position)) { continue; + } process(position); @@ -51,33 +52,39 @@ struct floodFill_impl : Strategy 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)); + do { + right(i), right(h), right(l); yTest(h,hf); yTest(l,lf); + + } while (selectAndProcess(i)); i = position, h = higher, l = lower; hf = higherFound, lf = lowerFound; - do { left(i); left(h); left(l); yTest(h,hf); yTest(l,lf); } - while (selectAndProcess(i)); - } - while (deferred(position)); + do { + left(i); left(h); left(l); yTest(h,hf); yTest(l,lf); + + } while (selectAndProcess(i)); + + } while (deferred(position)); } - bool selectAndProcess(Cursor const& i) - { - if (select(i)) - { + bool selectAndProcess(Cursor const& i) { + + if (select(i)) { + process(i); return true; } return false; } - void yTest(Cursor const& i, bool& state) - { - if (! select(i)) + void yTest(Cursor const& i, bool& state) { + + if (! select(i)) { + state = false; - else if (! state) - { + + } else if (! state) { + state = true; defer(i); } @@ -85,8 +92,8 @@ struct floodFill_impl : Strategy }; template< class Strategy, typename Cursor > -void floodFill(Cursor const& p, Strategy const& s) -{ +void floodFill(Cursor const& p, Strategy const& s) { + floodFill_impl(s).go(p); } diff --git a/shared/src/Radix2InplaceSort.h b/shared/src/Radix2InplaceSort.h index cf89f13583..abd650b2a6 100644 --- a/shared/src/Radix2InplaceSort.h +++ b/shared/src/Radix2InplaceSort.h @@ -25,30 +25,27 @@ void radix2InplaceSort( BidiIterator from, BidiIterator to, template< class Scanner, typename Iterator > -struct radix2InplaceSort_impl : Scanner -{ +struct radix2InplaceSort_impl : Scanner { + radix2InplaceSort_impl(Scanner const& s) : Scanner(s) { } using Scanner::advance; using Scanner::bit; - void go(Iterator& from, Iterator& to, typename Scanner::state_type s) - { + void go(Iterator& from, Iterator& to, typename Scanner::state_type s) { + Iterator l(from), r(to); unsigned cl, cr; using std::swap; - for (;;) - { + while (true) { // scan from left for set bit for (cl = cr = 0u; l != r ; ++l, ++cl) - if (bit(*l, s)) - { + if (bit(*l, s)) { // scan from the right for unset bit for (++cr; --r != l ;++cr) - if (! bit(*r, s)) - { + if (! bit(*r, s)) { // swap, continue scanning from left swap(*l, *r); break; @@ -58,22 +55,23 @@ struct radix2InplaceSort_impl : Scanner } // on to the next digit, if any - if (! advance(s)) + if (! advance(s)) { return; + } // recurse into smaller branch and prepare iterative // processing of the other - if (cl < cr) - { + if (cl < cr) { + if (cl > 1u) go(from, l, s); else if (cr <= 1u) return; l = from = r; r = to; - } - else - { + + } else { + if (cr > 1u) go(r, to, s); else if (cl <= 1u) return; @@ -87,8 +85,8 @@ struct radix2InplaceSort_impl : Scanner template< class Radix2Scanner, typename BidiIterator > void radix2InplaceSort( BidiIterator from, BidiIterator to, - Radix2Scanner const& scanner) -{ + Radix2Scanner const& scanner) { + radix2InplaceSort_impl(scanner) .go(from, to, scanner.initial_state()); } diff --git a/shared/src/Radix2IntegerScanner.h b/shared/src/Radix2IntegerScanner.h index c617a1080d..355ecfef46 100644 --- a/shared/src/Radix2IntegerScanner.h +++ b/shared/src/Radix2IntegerScanner.h @@ -12,8 +12,8 @@ #include #include -namespace type_traits // those are needed for the declaration, see below -{ +namespace type_traits { // those are needed for the declaration, see below + // Note: There are better / more generally appicable implementations // in C++11, make_signed is missing in TR1 too - so I just use C++98 // hacks that get the job done... @@ -39,8 +39,8 @@ class Radix2IntegerScanner; template< typename UInt > -class Radix2IntegerScanner< UInt, false > -{ +class Radix2IntegerScanner< UInt, false > { + UInt valMsb; public: @@ -48,9 +48,8 @@ class Radix2IntegerScanner< UInt, false > : valMsb(~UInt(0) &~ (~UInt(0) >> 1)) { } explicit Radix2IntegerScanner(int bits) - : valMsb(UInt(1u) << (bits - 1)) - { } - + : valMsb(UInt(1u) << (bits - 1)) { + } typedef UInt state_type; @@ -67,12 +66,12 @@ class Radix2IntegerScanner< Int, true > public: Radix2IntegerScanner() - : valMsb(~state_type(0u) &~ (~state_type(0u) >> 1)) - { } + : valMsb(~state_type(0u) &~ (~state_type(0u) >> 1)) { + } explicit Radix2IntegerScanner(int bits) - : valMsb(state_type(1u) << (bits - 1)) - { } + : valMsb(state_type(1u) << (bits - 1)) { + } typedef typename type_traits::make_unsigned::type state_type; diff --git a/shared/src/UrlReader.cpp b/shared/src/UrlReader.cpp index ee1f6efc3f..571456f2be 100644 --- a/shared/src/UrlReader.cpp +++ b/shared/src/UrlReader.cpp @@ -23,8 +23,8 @@ char const* const UrlReader::error_leftover_input = "UrlReader: Incomplete pro #define hnd_curl static_cast(_ptrImpl) UrlReader::UrlReader() - : _ptrImpl(0l), _arrXtra(0l), _strError(0l) -{ + : _ptrImpl(0l), _arrXtra(0l), _strError(0l) { + _arrXtra = new(std::nothrow) char[max_read_ahead]; if (! _arrXtra) { _strError = error_init_failed; return; } _ptrImpl = curl_easy_init(); @@ -34,15 +34,15 @@ UrlReader::UrlReader() curl_easy_setopt(hnd_curl, CURLOPT_FILETIME, 1l); } -UrlReader::~UrlReader() -{ +UrlReader::~UrlReader() { + delete _arrXtra; if (! hnd_curl) return; curl_easy_cleanup(hnd_curl); } -bool UrlReader::perform(char const* url, transfer_callback* cb) -{ +bool UrlReader::perform(char const* url, transfer_callback* cb) { + curl_easy_setopt(hnd_curl, CURLOPT_URL, url); curl_easy_setopt(hnd_curl, CURLOPT_WRITEFUNCTION, cb); curl_easy_setopt(hnd_curl, CURLOPT_WRITEDATA, this); @@ -61,8 +61,8 @@ bool UrlReader::perform(char const* url, transfer_callback* cb) } void UrlReader::getinfo(char const*& url, - char const*& type, int64_t& length, int64_t& stardate) -{ + char const*& type, int64_t& length, int64_t& stardate) { + curl_easy_getinfo(hnd_curl, CURLINFO_EFFECTIVE_URL, & url); curl_easy_getinfo(hnd_curl, CURLINFO_CONTENT_TYPE, & type); diff --git a/shared/src/UrlReader.h b/shared/src/UrlReader.h index 3ee4f04241..c50fe88d5b 100644 --- a/shared/src/UrlReader.h +++ b/shared/src/UrlReader.h @@ -17,8 +17,8 @@ * UrlReader class that encapsulates a context for sequential data retrieval * via URLs. Use one per thread. */ -class UrlReader -{ +class UrlReader { + void* _ptrImpl; char* _arrXtra; char const* _strError; @@ -149,8 +149,7 @@ class UrlReader }; template< class ContentStream > -bool UrlReader::readUrl(char const* url, ContentStream& s) -{ +bool UrlReader::readUrl(char const* url, ContentStream& s) { if (! _ptrImpl) return false; _strError = success; _ptrStream = & s; @@ -162,24 +161,24 @@ bool UrlReader::readUrl(char const* url, ContentStream& s) inline char const* UrlReader::getError() const { return this->_strError; } -inline void UrlReader::setError(char const* static_c_string) -{ +inline void UrlReader::setError(char const* static_c_string) { + if (this->_strError == success) this->_strError = static_c_string; } template< class Stream > size_t UrlReader::callback_template( - char *input, size_t size, size_t nmemb, void* thiz) -{ + char *input, size_t size, size_t nmemb, void* thiz) { + size *= nmemb; UrlReader* me = static_cast(thiz); Stream* stream = static_cast(me->_ptrStream); // first call? - if (me->_valXtraSize == ~size_t(0)) - { + if (me->_valXtraSize == ~size_t(0)) { + me->_valXtraSize = 0u; // extract meta information and call 'begin' char const* url, * type; @@ -190,14 +189,14 @@ size_t UrlReader::callback_template( size_t input_offset = 0u; - for (;;) - { + while (true) { + char* buffer = input + input_offset; size_t bytes = size - input_offset; // data in extra buffer? - if (me->_valXtraSize > 0) - { + if (me->_valXtraSize > 0) { + // fill extra buffer with beginning of input size_t fill = max_read_ahead - me->_valXtraSize; if (bytes < fill) fill = bytes; @@ -210,36 +209,36 @@ size_t UrlReader::callback_template( // call 'transfer' size_t processed = stream->transfer(buffer, bytes); - if (processed == abort) - { + if (processed == abort) { + me->setError(error_aborted); return 0u; - } - else if (! processed && ! input) - { + + } else if (! processed && ! input) { + me->setError(error_leftover_input); return 0u; } size_t unprocessed = bytes - processed; // can switch to input buffer, now? - if (buffer == me->_arrXtra && unprocessed <= input_offset) - { + if (buffer == me->_arrXtra && unprocessed <= input_offset) { + me->_valXtraSize = 0u; input_offset -= unprocessed; - } - else // no? unprocessed data -> extra buffer - { - if (unprocessed > max_read_ahead) - { + + } else { // no? unprocessed data -> extra buffer + + if (unprocessed > max_read_ahead) { + me->setError(error_buffer_overflow); return 0; } me->_valXtraSize = unprocessed; memmove(me->_arrXtra, buffer + processed, unprocessed); - if (input_offset == size || buffer != me->_arrXtra) - { + if (input_offset == size || buffer != me->_arrXtra) { + return size; } } From 9046e5e89c1c0cae77b1a47f58f7f058bc7a9989 Mon Sep 17 00:00:00 2001 From: tosh Date: Thu, 4 Apr 2013 10:55:08 +0200 Subject: [PATCH 03/33] silences warning by using pointer to const as string parameter for 'drawtext' (conversion of string literals to char* is deprecated) --- interface/src/Util.cpp | 4 ++-- interface/src/Util.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 99dafa8c23..03a11e3308 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -90,8 +90,8 @@ double diffclock(timeval *clock1,timeval *clock2) return diffms; } -void drawtext(int x, int y, float scale, float rotate, float thick, int mono, char *string, - float r, float g, float b) +void drawtext(int x, int y, float scale, float rotate, float thick, int mono, + char const* string, float r, float g, float b) { // // Draws text on screen as stroked so it can be resized diff --git a/interface/src/Util.h b/interface/src/Util.h index e2cd566b6e..448258932f 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -23,8 +23,8 @@ float angle_to(glm::vec3 head_pos, glm::vec3 source_pos, float render_yaw, float float randFloat(); void render_world_box(); void render_vector(glm::vec3 * vec); -void drawtext(int x, int y, float scale, float rotate, float thick, int mono, char *string, - float r=1.0, float g=1.0, float b=1.0); +void drawtext(int x, int y, float scale, float rotate, float thick, int mono, + char const* string, float r=1.0, float g=1.0, float b=1.0); void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, glm::vec3 vec, float r=1.0, float g=1.0, float b=1.0); double diffclock(timeval *clock1,timeval *clock2); From de4734d6fb435d09dbe8a06e6ff42fc84745c3e9 Mon Sep 17 00:00:00 2001 From: tosh Date: Thu, 4 Apr 2013 10:59:57 +0200 Subject: [PATCH 04/33] tightens ogl state handling (also fixes unreadably thick text for stats display) --- interface/src/main.cpp | 16 ++++++++-------- interface/src/starfield/renderer/Renderer.h | 11 +++++++---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 2cba377d8f..e6f6b6fd52 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -527,8 +527,6 @@ void display(void) { PerfStat("display"); - glEnable (GL_DEPTH_TEST); - glEnable(GL_LIGHTING); glEnable(GL_LINE_SMOOTH); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); @@ -559,14 +557,12 @@ void display(void) -myHead.getRenderPitch(), glm::vec3(1.0f,0.0f,0.0f)) ); glLoadMatrixf( glm::value_ptr(fov.getWorldViewerXform()) ); - glRotatef(myHead.getRenderPitch(), 1, 0, 0); - glRotatef(myHead.getRenderYaw(), 0, 1, 0); - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); if (::starsOn) { + // should be the first rendering pass - w/o depth buffer / lighting stars.render(fov); } + glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); @@ -670,8 +666,12 @@ void display(void) if (display_levels) serialPort.renderLevels(WIDTH,HEIGHT); // Display miscellaneous text stats onscreen - if (stats_on) display_stats(); - + if (stats_on) { + glLineWidth(1.0f); + glPointSize(1.0f); + display_stats(); + } + // Draw number of nearby people always char agents[100]; sprintf(agents, "Agents nearby: %ld\n", agentList.getAgents().size()); diff --git a/interface/src/starfield/renderer/Renderer.h b/interface/src/starfield/renderer/Renderer.h index abb553cd06..0cfb6df0c9 100644 --- a/interface/src/starfield/renderer/Renderer.h +++ b/interface/src/starfield/renderer/Renderer.h @@ -106,8 +106,8 @@ namespace starfield { this->glUpload(n); } - ~Renderer() - { + ~Renderer() { + delete[] _arrData; delete[] _arrTile; delete[] _arrBatchCount; @@ -119,8 +119,7 @@ namespace starfield { void render(float perspective, float aspect, mat4 const& orientation, - BrightnessLevel minBright) - { + BrightnessLevel minBright) { // fprintf(stderr, " // Stars.cpp: rendering at minimal brightness %d\n", minBright); @@ -479,6 +478,9 @@ namespace starfield { // fprintf(stderr, "Stars.cpp: Batch #%d - %d stars @ %d\n", i, // _arrBatchOffs[i], _arrBatchCount[i]); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + // setup modelview matrix (identity) glMatrixMode(GL_MODELVIEW); glPushMatrix(); @@ -507,6 +509,7 @@ namespace starfield { glBindVertexArray(0); glUseProgram(0); glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); + glDisable(GL_POINT_SMOOTH); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); From 284530f7d6940540838215b258e96688dafc04db Mon Sep 17 00:00:00 2001 From: tosh Date: Thu, 4 Apr 2013 11:59:16 +0200 Subject: [PATCH 05/33] tightens memory use --- interface/src/starfield/renderer/Renderer.h | 34 +++++++++++++++------ shared/src/FloodFill.h | 31 +++++++++++++++++-- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/interface/src/starfield/renderer/Renderer.h b/interface/src/starfield/renderer/Renderer.h index 0cfb6df0c9..a45e1f50a5 100644 --- a/interface/src/starfield/renderer/Renderer.h +++ b/interface/src/starfield/renderer/Renderer.h @@ -96,10 +96,14 @@ namespace starfield { Tiling tiling(k); size_t nTiles = tiling.getTileCount(); + // REVISIT: could coalesce allocation for faster rebuild + // REVISIT: batch arrays are probably oversized, but - hey - they + // are not very large (unless for insane tiling) and we're better + // off safe than sorry _arrData = new GpuVertex[n]; _arrTile = new Tile[nTiles + 1]; - _arrBatchOffs = new GLint[nTiles]; - _arrBatchCount = new GLsizei[nTiles]; + _arrBatchOffs = new GLint[nTiles * 2]; + _arrBatchCount = new GLsizei[nTiles * 2]; prepareVertexData(src, n, tiling, b, bMin); @@ -290,21 +294,31 @@ namespace starfield { bool select(Tile* t) { if (t < _arrTile || t >= _itrTilesEnd || - !! (t->flags & Tile::visited)) { + !! (t->flags & Tile::checked)) { - return false; + // out of bounds or been here already + return false; } - if (! (t->flags & Tile::checked)) { - if (_refRenderer.visitTile(t)) - t->flags |= Tile::render; + // will check now and never again + t->flags |= Tile::checked; + if (_refRenderer.visitTile(t)) { + + // good one -> remember (for batching) and propagate + t->flags |= Tile::render; + return true; } - return !! (t->flags & Tile::render); + return false; } - void process(Tile* t) { + bool process(Tile* t) { - t->flags |= Tile::visited; + if (! (t->flags & Tile::visited)) { + + t->flags |= Tile::visited; + return true; + } + return false; } void right(Tile*& cursor) const { cursor += 1; } diff --git a/shared/src/FloodFill.h b/shared/src/FloodFill.h index b52720a7b1..273c1c4f6e 100644 --- a/shared/src/FloodFill.h +++ b/shared/src/FloodFill.h @@ -11,6 +11,29 @@ /** * 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, @@ -35,16 +58,18 @@ struct floodFill_impl : Strategy { void go(Cursor position) { + if (! select(position)) { + return; + } + Cursor higher, lower, h,l, i; bool higherFound, lowerFound, hf, lf; do { - if (! select(position)) { + if (! process(position)) { continue; } - process(position); - higher = position; higherFound = false; up(higher); yTest(higher, higherFound); lower = position; lowerFound = false; From 31262340d4c773301b16dc54d4e5da36591015f6 Mon Sep 17 00:00:00 2001 From: tosh Date: Fri, 5 Apr 2013 01:24:00 +0200 Subject: [PATCH 06/33] adjusts formatting to agreed conventions --- interface/src/FieldOfView.cpp | 98 ++++++++++++------------ interface/src/FieldOfView.h | 137 ++++++++++++++++------------------ 2 files changed, 114 insertions(+), 121 deletions(-) diff --git a/interface/src/FieldOfView.cpp b/interface/src/FieldOfView.cpp index d1f535bb39..c255d7232f 100644 --- a/interface/src/FieldOfView.cpp +++ b/interface/src/FieldOfView.cpp @@ -15,95 +15,93 @@ using namespace glm; -FieldOfView::FieldOfView() - : mat_orientation(mat4(1.0f)), - vec_bounds_low(vec3(-1.0f,-1.0f,-1.0f)), - vec_bounds_high(vec3(1.0f,1.0f,1.0f)), - val_width(256.0f), - val_height(256.0f), - val_angle(0.61), - val_zoom(1.0f), - enm_aspect_balancing(expose_less) -{ +FieldOfView::FieldOfView() : + _matOrientation(mat4(1.0f)), + _vecBoundsLow(vec3(-1.0f,-1.0f,-1.0f)), + _vecBoundsHigh(vec3(1.0f,1.0f,1.0f)), + _valWidth(256.0f), + _valHeight(256.0f), + _valAngle(0.61), + _valZoom(1.0f), + _enmAspectBalancing(expose_less) { } -mat4 FieldOfView::getViewerScreenXform() const -{ +mat4 FieldOfView::getViewerScreenXform() const { + mat4 projection; vec3 low, high; getFrustum(low, high); // perspective projection? determine correct near distance - if (val_angle != 0.0f) - { + if (_valAngle != 0.0f) { + projection = translate( frustum(low.x, high.x, low.y, high.y, low.z, high.z), vec3(0.f, 0.f, -low.z) ); - } - else - { + } else { + projection = ortho(low.x, high.x, low.y, high.y, low.z, high.z); } return projection; } -mat4 FieldOfView::getWorldViewerXform() const -{ - return translate(affineInverse(mat_orientation), - vec3(0.0f, 0.0f, -vec_bounds_high.z) ); +mat4 FieldOfView::getWorldViewerXform() const { + + return translate(affineInverse(_matOrientation), + vec3(0.0f, 0.0f, -_vecBoundsHigh.z) ); } -mat4 FieldOfView::getWorldScreenXform() const -{ +mat4 FieldOfView::getWorldScreenXform() const { + return translate( - getViewerScreenXform() * affineInverse(mat_orientation), - vec3(0.0f, 0.0f, -vec_bounds_high.z) ); + getViewerScreenXform() * affineInverse(_matOrientation), + vec3(0.0f, 0.0f, -_vecBoundsHigh.z) ); } -mat4 FieldOfView::getViewerWorldXform() const -{ - vec3 n_translate = vec3(0.0f, 0.0f, vec_bounds_high.z); +mat4 FieldOfView::getViewerWorldXform() const { + + vec3 n_translate = vec3(0.0f, 0.0f, _vecBoundsHigh.z); return translate( translate(mat4(1.0f), n_translate) - * mat_orientation, -n_translate ); + * _matOrientation, -n_translate ); } -float FieldOfView::getPixelSize() const -{ +float FieldOfView::getPixelSize() const { + vec3 low, high; getFrustum(low, high); return std::min( - abs(high.x - low.x) / val_width, - abs(high.y - low.y) / val_height); + abs(high.x - low.x) / _valWidth, + abs(high.y - low.y) / _valHeight); } -void FieldOfView::getFrustum(vec3& low, vec3& high) const -{ - low = vec_bounds_low; - high = vec_bounds_high; +void FieldOfView::getFrustum(vec3& low, vec3& high) const { + + low = _vecBoundsLow; + high = _vecBoundsHigh; // start with uniform zoom - float inv_zoom = 1.0f / val_zoom; + float inv_zoom = 1.0f / _valZoom; float adj_x = inv_zoom, adj_y = inv_zoom; // balance aspect - if (enm_aspect_balancing != stretch) - { - float f_aspect = (high.x - low.x) / (high.y - low.y); - float vp_aspect = val_width / val_height; + if (_enmAspectBalancing != stretch) { + + float f_aspect = (high.x - low.x) / (high.y - low.y); + float vp_aspect = _valWidth / _valHeight; + + if ((_enmAspectBalancing == expose_more) + != (f_aspect > vp_aspect)) { - if ((enm_aspect_balancing == expose_more) - != (f_aspect > vp_aspect)) - { // expose_more -> f_aspect <= vp_aspect <=> adj >= 1 // expose_less -> f_aspect > vp_aspect <=> adj < 1 adj_x = vp_aspect / f_aspect; - } - else - { + + } else { + // expose_more -> f_aspect > vp_aspect <=> adj > 1 // expose_less -> f_aspect <= vp_aspect <=> adj <= 1 adj_y = f_aspect / vp_aspect; @@ -121,8 +119,8 @@ void FieldOfView::getFrustum(vec3& low, vec3& high) const // calc and apply near distance based on near diagonal and perspective float w = high.x - low.x, h = high.y - low.y; high.z -= low.z; - low.z = val_angle == 0.0f ? 0.0f : - sqrt(w*w+h*h) * 0.5f / tan(val_angle * 0.5f); + low.z = _valAngle == 0.0f ? 0.0f : + sqrt(w*w+h*h) * 0.5f / tan(_valAngle * 0.5f); high.z += low.z; } diff --git a/interface/src/FieldOfView.h b/interface/src/FieldOfView.h index 1bfa7c7f33..f4caf582c2 100644 --- a/interface/src/FieldOfView.h +++ b/interface/src/FieldOfView.h @@ -11,39 +11,35 @@ #include -/** - * Viewing parameter encapsulation. - */ -class FieldOfView -{ - glm::mat4 mat_orientation; - glm::vec3 vec_bounds_low; - glm::vec3 vec_bounds_high; - float val_width; - float val_height; - float val_angle; - float val_zoom; - int enm_aspect_balancing; +// +// Viewing parameter encapsulation. +// +class FieldOfView { + + glm::mat4 _matOrientation; + glm::vec3 _vecBoundsLow; + glm::vec3 _vecBoundsHigh; + float _valWidth; + float _valHeight; + float _valAngle; + float _valZoom; + int _enmAspectBalancing; public: FieldOfView(); // mutators - FieldOfView& setBounds(glm::vec3 const& low, glm::vec3 const& high) - { vec_bounds_low = low; vec_bounds_high = high; return *this; } + FieldOfView& setBounds(glm::vec3 const& low, glm::vec3 const& high) { + _vecBoundsLow = low; _vecBoundsHigh = high; return *this; } - FieldOfView& setOrientation(glm::mat4 const& matrix) - { mat_orientation = matrix; return *this; } + FieldOfView& setOrientation(glm::mat4 const& matrix) { _matOrientation = matrix; return *this; } - FieldOfView& setPerspective(float angle) - { val_angle = angle; return *this; } + FieldOfView& setPerspective(float angle) { _valAngle = angle; return *this; } - FieldOfView& setResolution(unsigned width, unsigned height) - { val_width = width; val_height = height; return *this; } + FieldOfView& setResolution(unsigned width, unsigned height) { _valWidth = width; _valHeight = height; return *this; } - FieldOfView& setZoom(float factor) - { val_zoom = factor; return *this; } + FieldOfView& setZoom(float factor) { _valZoom = factor; return *this; } enum aspect_balancing { @@ -52,76 +48,75 @@ class FieldOfView stretch }; - FieldOfView& setAspectBalancing(aspect_balancing v) - { enm_aspect_balancing = v; return *this; } + FieldOfView& setAspectBalancing(aspect_balancing v) { _enmAspectBalancing = v; return *this; } // dumb accessors - glm::mat4 const& getOrientation() const { return mat_orientation; } - float getWidthInPixels() const { return val_width; } - float getHeightInPixels() const { return val_height; } - float getPerspective() const { return val_angle; } + glm::mat4 const& getOrientation() const { return _matOrientation; } + float getWidthInPixels() const { return _valWidth; } + float getHeightInPixels() const { return _valHeight; } + float getPerspective() const { return _valAngle; } // matrices - /** - * Returns a full transformation matrix to project world coordinates - * onto the screen. - */ + // + // Returns a full transformation matrix to project world coordinates + // onto the screen. + // glm::mat4 getWorldScreenXform() const; - /** - * Transforms world coordinates to viewer-relative coordinates. - * - * This matrix can be used as the modelview matrix in legacy GL code - * where the projection matrix is kept separately. - */ + // + // Transforms world coordinates to viewer-relative coordinates. + // + // This matrix can be used as the modelview matrix in legacy GL code + // where the projection matrix is kept separately. + // glm::mat4 getWorldViewerXform() const; - /** - * Returns the transformation to of viewer-relative coordinates back - * to world space. - * - * This matrix can be used to set up a coordinate system for avatar - * rendering. - */ + // + // Returns the transformation to of viewer-relative coordinates back + // to world space. + // + // This matrix can be used to set up a coordinate system for avatar + // rendering. + // glm::mat4 getViewerWorldXform() const; - /** - * Returns the transformation of viewer-relative coordinates to the - * screen. - * - * This matrix can be used as the projection matrix in legacy GL code. - */ + // + // Returns the transformation of viewer-relative coordinates to the + // screen. + // + // This matrix can be used as the projection matrix in legacy GL code. + // glm::mat4 getViewerScreenXform() const; // other useful information - /** - * Returns the size of a pixel in world space, that is the minimum - * in respect to x/y screen directions. - */ + // + // Returns the size of a pixel in world space, that is the minimum + // in respect to x/y screen directions. + // float getPixelSize() const; - /** - * Returns the frustum as used for the projection matrices. - * The result depdends on the bounds, eventually aspect correction - * for the current resolution, the perspective angle (specified in - * respect to diagonal) and zoom. - */ + // + // Returns the frustum as used for the projection matrices. + // The result depdends on the bounds, eventually aspect correction + // for the current resolution, the perspective angle (specified in + // respect to diagonal) and zoom. + // void getFrustum(glm::vec3& low, glm::vec3& high) const; - /** - * Returns the z-offset from the origin to where orientation ia - * applied. - */ - float getTransformOffset() const { return vec_bounds_high.z; } + // + // Returns the z-offset from the origin to where orientation ia + // applied. + // + float getTransformOffset() const { return _vecBoundsHigh.z; } - /** - * Returns the aspect ratio. - */ - float getAspectRatio() const { return val_height / val_width; } + // + // Returns the aspect ratio. + // + float getAspectRatio() const { return _valHeight / _valWidth; } }; #endif From d3f6c19e83c8b9e84030aa65768e2ea911a4ae52 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Thu, 4 Apr 2013 18:04:32 -0700 Subject: [PATCH 07/33] adding Camera and some utility classes and start of prototype avatar --- interface/src/Camera.cpp | 19 +++ interface/src/Camera.h | 41 +++++ interface/src/Hand.h | 1 + interface/src/Head.cpp | 302 ++++++++++++++++++++++++++++++++-- interface/src/Head.h | 113 ++++++++++++- interface/src/Orientation.cpp | 232 ++++++++++++++++++++++++++ interface/src/Orientation.h | 52 ++++++ interface/src/Util.h | 14 ++ interface/src/Vector3D.cpp | 267 ++++++++++++++++++++++++++++++ interface/src/Vector3D.h | 66 ++++++++ interface/src/main.cpp | 63 +++++-- 11 files changed, 1141 insertions(+), 29 deletions(-) create mode 100755 interface/src/Camera.cpp create mode 100755 interface/src/Camera.h mode change 100644 => 100755 interface/src/Head.cpp create mode 100755 interface/src/Orientation.cpp create mode 100755 interface/src/Orientation.h create mode 100755 interface/src/Vector3D.cpp create mode 100755 interface/src/Vector3D.h diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp new file mode 100755 index 0000000000..b0c5a2c0dd --- /dev/null +++ b/interface/src/Camera.cpp @@ -0,0 +1,19 @@ +//----------------------------------------------------------- +// +// Created by Jeffrey Ventrella and added as a utility +// class for High Fidelity Code base, April 2013 +// +//----------------------------------------------------------- + +#include "Camera.h" + +//------------------------ +Camera::Camera() +{ + yaw = 0.0; + pitch = 0.0; + roll = 0.0; + position = glm::dvec3( 0.0, 0.0, 0.0 ); + orientation.setToIdentity(); +} + diff --git a/interface/src/Camera.h b/interface/src/Camera.h new file mode 100755 index 0000000000..b0bf9373cd --- /dev/null +++ b/interface/src/Camera.h @@ -0,0 +1,41 @@ +//----------------------------------------------------------- +// +// Created by Jeffrey Ventrella and added as a utility +// class for High Fidelity Code base, April 2013 +// +//----------------------------------------------------------- + +#ifndef __interface__camera__ +#define __interface__camera__ + +#include "Vector3D.h" +#include "Orientation.h" +#include + +class Camera +{ +public: + Camera(); + + void setYaw ( double y ) { yaw = y; } + void setPitch ( double p ) { pitch = p; } + void setRoll ( double r ) { roll = r; } + void setPosition ( glm::dvec3 p ) { position = p; }; + void setOrientation ( Orientation o ) { orientation.set(o); } + + double getYaw () { return yaw; } + double getPitch () { return pitch; } + double getRoll () { return roll; } + glm::dvec3 getPosition () { return position; } + Orientation getOrientation () { return orientation; } + +private: + + glm::dvec3 position; + double yaw; + double pitch; + double roll; + Orientation orientation; +}; + +#endif diff --git a/interface/src/Hand.h b/interface/src/Hand.h index bda0fb2145..cf887a897f 100644 --- a/interface/src/Hand.h +++ b/interface/src/Hand.h @@ -40,6 +40,7 @@ private: float transmitterHz; int transmitterPackets; bool renderPointer; + }; diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp old mode 100644 new mode 100755 index 8cf831d426..18b5d60690 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -38,8 +38,13 @@ vector iris_texture; unsigned int iris_texture_width = 512; unsigned int iris_texture_height = 256; + + +//--------------------------------------------------- Head::Head() { + initializeAvatar(); + position = glm::vec3(0,0,0); velocity = glm::vec3(0,0,0); thrust = glm::vec3(0,0,0); @@ -77,6 +82,8 @@ Head::Head() lastLoudness = 0.0; browAudioLift = 0.0; noise = 0; + + handOffset.clear(); sphere = NULL; @@ -91,7 +98,14 @@ Head::Head() } } -Head::Head(const Head &otherHead) { + + + +//--------------------------------------------------- +Head::Head(const Head &otherHead) +{ + initializeAvatar(); + position = otherHead.position; velocity = otherHead.velocity; thrust = otherHead.thrust; @@ -141,22 +155,42 @@ Head::Head(const Head &otherHead) { hand = &newHand; } -Head::~Head() { - if (sphere != NULL) { + + + +//--------------------------------------------------- +Head::~Head() +{ + if (sphere != NULL) + { gluDeleteQuadric(sphere); } } -Head* Head::clone() const { + + +//--------------------------------------------------- +Head* Head::clone() const +{ return new Head(*this); } + + + + +//--------------------------------------------------- void Head::reset() { Pitch = Yaw = Roll = 0; leanForward = leanSideways = 0; } + + + + +//--------------------------------------------------- void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int head_mirror, glm::vec3 * gravity) // Using serial data, update avatar/render position and angles { @@ -201,24 +235,49 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea } } + + + +//--------------------------------------------------- +void Head::setAvatarPosition( double x, double y, double z ) +{ + avatar.position.setXYZ( x, y, z ); +} + + +//--------------------------------------------------- void Head::addLean(float x, float z) { // Add Body lean as impulse leanSideways += x; leanForward += z; } + + +//--------------------------------------------------- void Head::setLeanForward(float dist){ leanForward = dist; } + + + +//--------------------------------------------------- void Head::setLeanSideways(float dist){ leanSideways = dist; } + + + + + // Simulate the head over time +//--------------------------------------------------- void Head::simulate(float deltaTime) { - + simulateAvatar( deltaTime ); + glm::vec3 forward(-sinf(getRenderYaw()*PI/180), sinf(getRenderPitch()*PI/180), cosf(getRenderYaw()*PI/180)); @@ -350,28 +409,48 @@ void Head::simulate(float deltaTime) } } - hand->simulate(deltaTime); - - +//hand->simulate(deltaTime); } + + + + +//--------------------------------------------------- void Head::render(int faceToFace, int isMine) { + // render avatar + renderAvatar(); + int side = 0; // Always render own hand, but don't render head unless showing face2face glEnable(GL_DEPTH_TEST); glPushMatrix(); - glScalef(scale, scale, scale); - glTranslatef(leanSideways, 0.f, leanForward); +//glScalef(scale, scale, scale); + + +glTranslatef +( + avatar.bone[ AVATAR_BONE_HEAD ].position.x, + avatar.bone[ AVATAR_BONE_HEAD ].position.y, + avatar.bone[ AVATAR_BONE_HEAD ].position.z +); + + +glScalef( 0.03, 0.03, 0.03 ); + + + glTranslatef(leanSideways, 0.f, leanForward); glRotatef(Yaw, 0, 1, 0); - hand->render(1); +//hand->render(1); // Don't render a head if it is really close to your location, because that is your own head! - if (!isMine || faceToFace) { +//if (!isMine || faceToFace) + { glRotatef(Pitch, 1, 0, 0); glRotatef(Roll, 0, 0, 1); @@ -380,6 +459,7 @@ void Head::render(int faceToFace, int isMine) // Overall scale of head if (faceToFace) glScalef(1.5, 2.0, 2.0); else glScalef(0.75, 1.0, 1.0); + glColor3fv(skinColor); @@ -400,7 +480,6 @@ void Head::render(int faceToFace, int isMine) glTranslatef(-2.0, 0, 0); } glPopMatrix(); - // Eyebrows audioAttack = 0.9*audioAttack + 0.1*fabs(loudness - lastLoudness); @@ -509,9 +588,201 @@ void Head::render(int faceToFace, int isMine) } glPopMatrix(); } + + + + +//--------------------------------------------------------- +void Head::setHandMovement( glm::dvec3 movement ) +{ + handOffset.setXYZ( movement.x, movement.y, movement.z ); +} + + + +//----------------------------------------- +void Head::initializeAvatar() +{ + //printf( "initializeAvatar\n" ); + + avatar.position.clear(); + //avatar.position.setXYZ( -3.0, 0.0, 0.0 ); + + avatar.velocity.clear(); + avatar.orientation.setToIdentity(); + + for (int b=0; b 0.0) hand->setPos(handPos); } +//--------------------------------------------------- void Head::SetNewHeadTarget(float pitch, float yaw) { PitchTarget = pitch; diff --git a/interface/src/Head.h b/interface/src/Head.h index abde89deea..618bdcc16b 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -13,8 +13,9 @@ #include "AgentData.h" #include "Field.h" #include "world.h" -#include "Head.h" #include "Hand.h" +#include "Vector3D.h" // added by Ventrella as a utility +#include "Orientation.h" // added by Ventrella as a utility #include "InterfaceConfig.h" #include "SerialInterface.h" @@ -30,6 +31,101 @@ enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH}; #define ROT_RIGHT 7 #define MAX_DRIVE_KEYS 8 +/* +enum AvatarJoints +{ + AVATAR_JOINT_NULL = -1, + AVATAR_JOINT_PELVIS, + AVATAR_JOINT_TORSO, + AVATAR_JOINT_CHEST, + AVATAR_JOINT_NECK_BASE, + AVATAR_JOINT_HEAD_BASE, + AVATAR_JOINT_HEAD_TOP, + + AVATAR_JOINT_LEFT_CLAVICLE, + AVATAR_JOINT_LEFT_SHOULDER, + AVATAR_JOINT_LEFT_ELBOW, + AVATAR_JOINT_LEFT_WRIST, + AVATAR_JOINT_LEFT_FINGERTIPS, + + AVATAR_JOINT_RIGHT_CLAVICLE, + AVATAR_JOINT_RIGHT_SHOULDER, + AVATAR_JOINT_RIGHT_ELBOW, + AVATAR_JOINT_RIGHT_WRIST, + AVATAR_JOINT_RIGHT_FINGERTIPS, + + AVATAR_JOINT_LEFT_HIP, + AVATAR_JOINT_LEFT_KNEE, + AVATAR_JOINT_LEFT_HEEL, + AVATAR_JOINT_LEFT_TOES, + + AVATAR_JOINT_RIGHT_HIP, + AVATAR_JOINT_RIGHT_KNEE, + AVATAR_JOINT_RIGHT_HEEL, + AVATAR_JOINT_RIGHT_TOES, + + NUM_AVATAR_JOINTS +}; +*/ + + + + +enum AvatarBones +{ + AVATAR_BONE_NULL = -1, + AVATAR_BONE_PELVIS_SPINE, // connects pelvis joint with torso joint (cannot be rotated) + AVATAR_BONE_MID_SPINE, // connects torso joint with chest joint + AVATAR_BONE_CHEST_SPINE, // connects chest joint with neckBase joint (cannot 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 (cannot 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 (cannot 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 (cannot 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 (cannot 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 AvatarBone +{ + AvatarBones parent; + Vector3D position; + Vector3D defaultPosePosition; + Vector3D velocity; + double yaw; + double pitch; + double roll; + Orientation orientation; + double length; +}; + +struct Avatar +{ + Vector3D position; + Vector3D velocity; + Orientation orientation; + AvatarBone bone[ NUM_AVATAR_BONES ]; +}; + class Head : public AgentData { public: Head(); @@ -60,7 +156,12 @@ class Head : public AgentData { float getLastMeasuredYaw() {return YawRate;} void render(int faceToFace, int isMine); + + void setAvatarPosition( double, double, double ); + void simulate(float); + + void setHandMovement( glm::dvec3 movement ); // Send and receive network data int getBroadcastData(char * data); @@ -124,6 +225,8 @@ class Head : public AgentData { glm::vec3 position; glm::vec3 velocity; glm::vec3 thrust; + + Vector3D handOffset; int driveKeys[MAX_DRIVE_KEYS]; @@ -131,10 +234,16 @@ class Head : public AgentData { eyeContactTargets eyeContactTarget; GLUquadric *sphere; + Avatar avatar; + + void initializeAvatar(); + void simulateAvatar( float deltaTime ); + void updateAvatarSkeleton(); + void renderAvatar(); void readSensors(); float renderYaw, renderPitch; // Pitch from view frustum when this is own head. }; -#endif \ No newline at end of file +#endif diff --git a/interface/src/Orientation.cpp b/interface/src/Orientation.cpp new file mode 100755 index 0000000000..16176e736d --- /dev/null +++ b/interface/src/Orientation.cpp @@ -0,0 +1,232 @@ +//----------------------------------------------------------- +// +// Created by Jeffrey Ventrella and added as a utility +// class for High Fidelity Code base, April 2013 +// +//----------------------------------------------------------- + +#include "Orientation.h" +#include "Vector3D.h" +#include "Util.h" + +//------------------------ +Orientation::Orientation() +{ + right.setXYZ ( 1.0, 0.0, 0.0 ); + up.setXYZ ( 0.0, 1.0, 0.0 ); + front.setXYZ ( 0.0, 0.0, 1.0 ); +} + + +//-------------------------------- +void Orientation::setToIdentity() +{ + right.setXYZ ( 1.0, 0.0, 0.0 ); + up.setXYZ ( 0.0, 1.0, 0.0 ); + front.setXYZ ( 0.0, 0.0, 1.0 ); +} + + +//------------------------------------ +void Orientation::set( Orientation o ) +{ + right.set ( o.getRight() ); + up.set ( o.getUp () ); + front.set ( o.getFront() ); +} + + +//----------------------------------------------------------------------------------------- +void Orientation::forceAxisInDirection( int whichAxis, const Vector3D &direction, double forceAmount ) +{ + Vector3D diff; + + if ( whichAxis == ORIENTATION_RIGHT_AXIS ) + { + diff.setToDifference( direction, right ); + right.addScaled( diff, forceAmount ); + right.normalize(); + up.setToCross( front, right ); + up.normalize(); + front.setToCross( right, up ); + } + else if ( whichAxis == ORIENTATION_UP_AXIS ) + { + diff.setToDifference( direction, up ); + up.addScaled( diff, forceAmount ); + up.normalize(); + front.setToCross( right, up ); + front.normalize(); + right.setToCross( up, front ); + } + else if ( whichAxis == ORIENTATION_FRONT_AXIS ) + { + diff.setToDifference( direction, front ); + front.addScaled( diff, forceAmount ); + front.normalize(); + right.setToCross( up, front ); + right.normalize(); + up.setToCross( front, right ); + } +} + + +//------------------------------------------------------------------------------------------------------ +void Orientation::forceFrontInDirection( const Vector3D &direction, const Vector3D &upDirection, double forceAmount ) +{ + Vector3D diff; + diff.setToDifference( direction, front ); + front.addScaled( diff, forceAmount ); + front.normalize(); + right.setToCross( upDirection, front ); + right.normalize(); + up.setToCross( front, right ); +} + + + + +//--------------------------------------- +void Orientation::yaw( double angle ) +{ + double r = angle * PI_OVER_180; + double s = sin( r ); + double c = cos( r ); + + Vector3D cosineFront; + Vector3D cosineRight; + Vector3D sineFront; + Vector3D sineRight; + + cosineFront.setToScaled ( front, c ); + cosineRight.setToScaled ( right, c ); + sineFront.setToScaled ( front, s ); + sineRight.setToScaled ( right, s ); + + front.set( cosineFront ); + front.add( sineRight ); + + right.set( cosineRight ); + right.subtract( sineFront ); +} + + +//--------------------------------------- +void Orientation::pitch( double angle ) +{ + double r = angle * PI_OVER_180; + double s = sin( r ); + double c = cos( r ); + + Vector3D cosineUp; + Vector3D cosineFront; + Vector3D sineUp; + Vector3D sineFront; + + cosineUp.setToScaled ( up, c ); + cosineFront.setToScaled ( front, c ); + sineUp.setToScaled ( up, s ); + sineFront.setToScaled ( front, s ); + + up.set( cosineUp ); + up.add( sineFront ); + + front.set( cosineFront ); + front.subtract( sineUp ); +} + + +//--------------------------------------- +void Orientation::roll( double angle ) +{ + double r = angle * PI_OVER_180; + double s = sin( r ); + double c = cos( r ); + + Vector3D cosineUp; + Vector3D cosineRight; + Vector3D sineUp; + Vector3D sineRight; + + cosineUp.setToScaled ( up, c ); + cosineRight.setToScaled ( right, c ); + sineUp.setToScaled ( up, s ); + sineRight.setToScaled ( right, s ); + + up.set( cosineUp ); + up.add( sineRight ); + + right.set( cosineRight ); + right.subtract( sineUp ); +} + + +Vector3D Orientation::getRight () { return right; } +Vector3D Orientation::getUp () { return up; } +Vector3D Orientation::getFront () { return front; } + + +//----------------------------------------------------------------------------- +void Orientation::setRightUpFront( const Vector3D &r, const Vector3D &u, const Vector3D &f ) +{ + //verifyValidOrientation(); + + right.set (r); + up.set (u); + front.set (f); +} + + +//----------------------------------------------------------------------------- +void Orientation::verifyValidOrientation() +{ + assert( right.getMagnitude () < 1.0 + BIG_EPSILON ); + assert( right.getMagnitude () > 1.0 - BIG_EPSILON ); + assert( up.getMagnitude () < 1.0 + BIG_EPSILON ); + assert( up.getMagnitude () > 1.0 - BIG_EPSILON ); + assert( front.getMagnitude () < 1.0 + BIG_EPSILON ); + assert( front.getMagnitude () > 1.0 - BIG_EPSILON ); + + if ( right.getMagnitude() > 1.0 + BIG_EPSILON ) + { + printf( "oops: the magnitude of the 'right' part of the orientation is %f!\n", right.getMagnitude() ); + } + else if ( right.getMagnitude() < 1.0 - BIG_EPSILON ) + { + printf( "oops: the magnitude of the 'right' part of the orientation is %f!\n", right.getMagnitude() ); + } + + + if ( up.getMagnitude() > 1.0 + BIG_EPSILON ) + { + printf( "oops: the magnitude of the 'up' part of the orientation is %f!\n", up.getMagnitude() ); + } + else if ( up.getMagnitude() < 1.0 - BIG_EPSILON ) + { + printf( "oops: the magnitude of the 'up' part of the orientation is %f!\n", up.getMagnitude() ); + } + + + if ( front.getMagnitude() > 1.0 + BIG_EPSILON ) + { + printf( "oops: the magnitude of the 'front' part of the orientation is %f!\n", front.getMagnitude() ); + } + else if ( front.getMagnitude() < 1.0 - BIG_EPSILON ) + { + printf( "oops: the magnitude of the 'front' part of the orientation is %f!\n", front.getMagnitude() ); + } + + if (( right.dotWith ( up ) > BIG_EPSILON ) + || ( right.dotWith ( up ) < -BIG_EPSILON )) { printf( "oops: the 'right' and 'up' parts of the orientation are not perpendicular! The dot is: %f\n", right.dotWith ( up ) ); } + + if (( right.dotWith ( front ) > BIG_EPSILON ) + || ( right.dotWith ( front ) < -BIG_EPSILON )) { printf( "oops: the 'right' and 'front' parts of the orientation are not perpendicular! The dot is: %f\n", right.dotWith ( front ) ); } + + if (( up.dotWith ( front ) > BIG_EPSILON ) + || ( up.dotWith ( front ) < -BIG_EPSILON )) { printf( "oops: the 'up' and 'front' parts of the orientation are not perpendicular! The dot is: %f\n", up.dotWith ( front ) ); } + +} + + + + diff --git a/interface/src/Orientation.h b/interface/src/Orientation.h new file mode 100755 index 0000000000..217366f8ef --- /dev/null +++ b/interface/src/Orientation.h @@ -0,0 +1,52 @@ +//----------------------------------------------------------- +// +// Created by Jeffrey Ventrella and added as a utility +// class for High Fidelity Code base, April 2013 +// +//----------------------------------------------------------- + +#ifndef __interface__orientation__ +#define __interface__orientation__ + +#include "Math.h" +#include "Vector3D.h" + +enum Axis +{ + ORIENTATION_RIGHT_AXIS, + ORIENTATION_UP_AXIS, + ORIENTATION_FRONT_AXIS +}; + +class Orientation +{ +private: + + Vector3D right; + Vector3D up; + Vector3D front; + + void verifyValidOrientation(); + +public: + Orientation(); + + void yaw ( double ); + void pitch ( double ); + void roll ( double ); + + void set( Orientation ); + void setToIdentity(); + + void forceFrontInDirection( const Vector3D &, const Vector3D &, double ); + void forceAxisInDirection( int, const Vector3D &, double ); + + Vector3D getRight(); + Vector3D getUp(); + Vector3D getFront(); + + void setRightUpFront( const Vector3D &, const Vector3D &, const Vector3D & ); +}; + + +#endif diff --git a/interface/src/Util.h b/interface/src/Util.h index e2cd566b6e..ea74aafde1 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -17,6 +17,20 @@ #include + +// added by Ventrella for utility purposes +static const double ZERO = 0.0; +static const double ONE = 1.0; +static const double ONE_HALF = 0.5; +static const double ONE_THIRD = 0.3333333; +//static const double PI = 3.14159265359; +static const double PI_TIMES_TWO = 3.14159265359 * 2.0; +static const double PI_OVER_180 = 3.14159265359 / 180.0; +static const double EPSILON = 0.00001; // a smallish number meant to be used as a margin of error for some normalized values +static const double BIG_EPSILON = 0.01; // not as smallish as EPSILON +static const double SQUARE_ROOT_OF_3 = sqrt(3); + + float azimuth_to(glm::vec3 head_pos, glm::vec3 source_pos); float angle_to(glm::vec3 head_pos, glm::vec3 source_pos, float render_yaw, float head_yaw); diff --git a/interface/src/Vector3D.cpp b/interface/src/Vector3D.cpp new file mode 100755 index 0000000000..792d55c16a --- /dev/null +++ b/interface/src/Vector3D.cpp @@ -0,0 +1,267 @@ +//----------------------------------------------------------- +// +// Created by Jeffrey Ventrella and added as a utility +// class for High Fidelity Code base, April 2013 +// +//----------------------------------------------------------- + +#include "Vector3D.h" +#include "Math.h" + +//--------------------------------------- +Vector3D::Vector3D() +{ + x = 0.0; + y = 0.0; + z = 0.0; +} + +//--------------------------------------- +Vector3D::Vector3D( double x_, double y_, double z_ ) +{ + x = x_; + y = y_; + z = z_; +} + +//--------------------------------------- +Vector3D::Vector3D( const Vector3D & v ) +{ + x = v.x; + y = v.y; + z = v.z; +} + +//----------------------------------------------------- +void Vector3D::setXYZ( double x_, double y_, double z_ ) +{ + x = x_; + y = y_; + z = z_; +} + + +//--------------------- +void Vector3D::clear() +{ + x = 0.0; + y = 0.0; + z = 0.0; +} + + +//----------------------------------------------------- +void Vector3D::addXYZ( double x_, double y_, double z_ ) +{ + x += x_; + y += y_; + z += z_; +} + +//--------------------------------------- +void Vector3D::set( const Vector3D &v ) +{ + x = v.x; + y = v.y; + z = v.z; +} + +//------------------------------------- +void Vector3D::add( const Vector3D &v ) +{ + x += v.x; + y += v.y; + z += v.z; +} + + +//-------------------------------------------- +void Vector3D::subtract ( const Vector3D &v ) +{ + x -= v.x; + y -= v.y; + z -= v.z; +} + +//----------------------------------------------------- +void Vector3D::addScaled( const Vector3D &v, double s ) +{ + x += v.x * s; + y += v.y * s; + z += v.z * s; +} + +//----------------------------------------------------- +void Vector3D::subtractScaled( const Vector3D &v, double s ) +{ + x -= v.x * s; + y -= v.y * s; + z -= v.z * s; +} + + +//------------------------- +void Vector3D::normalize() +{ + double d = sqrt( x * x + y * y + z * z ); + + if ( d > 0.0 ) + { + x /= d; + y /= d; + z /= d; + } +} + + +//-------------------------------------------- +void Vector3D::setX ( double x_ ) { x = x_; } +void Vector3D::setY ( double y_ ) { y = y_; } +void Vector3D::setZ ( double z_ ) { z = z_; } + +void Vector3D::addX ( double x_ ) { x += x_; } +void Vector3D::addY ( double y_ ) { y += y_; } +void Vector3D::addZ ( double z_ ) { z += z_; } + +double Vector3D::getX () { return x; } +double Vector3D::getY () { return y; } +double Vector3D::getZ () { return z; } + +void Vector3D::scaleX ( double s ) { x *= s; } +void Vector3D::scaleY ( double s ) { y *= s; } +void Vector3D::scaleZ ( double s ) { z *= s; } + + +//----------------------------------------------------- +void Vector3D::setToScaled( const Vector3D &v, double s ) +{ + Vector3D c; + + x = v.x * s; + y = v.y * s; + z = v.z * s; +} + +//-------------------------------------------------------------------- +void Vector3D::setToAverage( const Vector3D &v1, const Vector3D &v2 ) +{ + x = v1.x + ( v2.x - v1.x ) * 0.5; + y = v1.y + ( v2.y - v1.y ) * 0.5; + z = v1.z + ( v2.z - v1.z ) * 0.5; +} + + +//----------------------------------------------------- +void Vector3D::setToDifference( const Vector3D &v1, const Vector3D &v2 ) +{ + x = v1.x - v2.x; + y = v1.y - v2.y; + z = v1.z - v2.z; +} + +//----------------------------------------------------- +void Vector3D::scale( double s ) +{ + x *= s; + y *= s; + z *= s; +} + +//----------------------------------------------------- +double Vector3D::getMagnitude() +{ + return sqrt( x * x + y * y + z * z ); +} + + +//----------------------------------------------------- +double Vector3D::getMagnitudeSquared() +{ + return x * x + y * y + z * z ; +} + +//----------------------------------------------------- +double Vector3D::getDistanceTo( const Vector3D &v ) +{ + double xx = v.x - x; + double yy = v.y - y; + double zz = v.z - z; + + return sqrt( xx * xx + yy * yy + zz * zz ); +} + + +//----------------------------------------------------- +double Vector3D::getDistanceSquaredTo( const Vector3D &v ) +{ + double xx = v.x - x; + double yy = v.y - y; + double zz = v.z - z; + + return xx * xx + yy * yy + zz * zz; +} + + +//------------------------------------------------------------------- +double Vector3D::getDistance( const Vector3D &v1, const Vector3D &v2 ) +{ + double xx = v2.x - v1.x; + double yy = v2.y - v1.y; + double zz = v2.z - v1.z; + + return sqrt( xx * xx + yy * yy + zz * zz ); +} + + +//--------------------------------------------------------------------------- +double Vector3D::getDistanceSquared( const Vector3D &v1, const Vector3D &v2 ) +{ + double xx = v2.x - v1.x; + double yy = v2.y - v1.y; + double zz = v2.z - v1.z; + + return xx * xx + yy * yy + zz * zz; +} + + +//----------------------------------------------------- +double Vector3D::dotWith( const Vector3D &v ) +{ + return + x * v.x + + y * v.y + + z * v.z; +} + + + +//----------------------------------------------------------------- +void Vector3D::setToCross( const Vector3D &v1, const Vector3D &v2 ) +{ + x = v1.z * v2.y - v1.y * v2.z; + y = v1.x * v2.z - v1.z * v2.x; + z = v1.y * v2.x - v1.x * v2.y; +} + + +//--------------------------------------------------------------- +void Vector3D::setToSum( const Vector3D &v1, const Vector3D &v2 ) +{ + x = v1.x + v2.x; + y = v1.y + v2.y; + z = v1.z + v2.z; +} + + +//----------------------------------------------------- +void Vector3D::halve() +{ + x *= 0.5; + y *= 0.5; + z *= 0.5; +} + + + + + diff --git a/interface/src/Vector3D.h b/interface/src/Vector3D.h new file mode 100755 index 0000000000..9b2bc9744c --- /dev/null +++ b/interface/src/Vector3D.h @@ -0,0 +1,66 @@ +//----------------------------------------------------------- +// +// Created by Jeffrey Ventrella and added as a utility +// class for High Fidelity Code base, April 2013 +// +//----------------------------------------------------------- + +#ifndef __interface__vector3D__ +#define __interface__vector3D__ + +class Vector3D +{ +public: + + //------------------ + // members + //------------------ + double x; + double y; + double z; + + //------------------ + // methods + //------------------ + Vector3D(); + Vector3D( double, double, double ); + Vector3D( const Vector3D & ); + + void clear(); + void set ( const Vector3D & ); + void setToScaled ( const Vector3D &, double ); + void add ( const Vector3D & ); + void subtract ( const Vector3D & ); + void addScaled ( const Vector3D &, double ); + void subtractScaled ( const Vector3D &, double ); + void normalize (); + void setToCross ( const Vector3D &, const Vector3D & ); + void setToAverage ( const Vector3D &, const Vector3D & ); + void setToSum ( const Vector3D &, const Vector3D & ); + void setXYZ ( double, double, double ); + void addXYZ ( double, double, double ); + void setX ( double ); + void setY ( double ); + void setZ ( double ); + void addX ( double ); + void addY ( double ); + void addZ ( double ); + void scaleX ( double ); + void scaleY ( double ); + void scaleZ ( double ); + void halve (); + double getX (); + double getY (); + double getZ (); + double getMagnitude (); + double getMagnitudeSquared (); + double getDistance ( const Vector3D &, const Vector3D & ); + double getDistanceSquared ( const Vector3D &, const Vector3D & ); + double getDistanceTo ( const Vector3D & ); + double getDistanceSquaredTo( const Vector3D & ); + double dotWith ( const Vector3D & ); + void scale ( double ); + void setToDifference ( const Vector3D &, const Vector3D & ); +}; + +#endif diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 2cba377d8f..91cae9f4c9 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -50,6 +50,7 @@ #include "Head.h" #include "Hand.h" +#include "Camera.h" #include "Particle.h" #include "Texture.h" #include "Cloud.h" @@ -65,7 +66,10 @@ using namespace std; -int audio_on = 0; // Whether to turn on the audio support + +double testThingy = 0.0; + +int audio_on = 1; // Whether to turn on the audio support int simulate_on = 1; AgentList agentList('I'); @@ -95,6 +99,7 @@ Oscilloscope audioScope(256,200,true); #define HAND_RADIUS 0.25 // Radius of in-world 'hand' of you Head myHead; // The rendered head of oneself +Camera myCamera; // My view onto the world (sometimes on myself :) char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt"; FieldOfView fov; @@ -342,8 +347,10 @@ void init(void) if (noise_on) { myHead.setNoise(noise); } - myHead.setPos(start_location); - + myHead.setPos(start_location ); + + myCamera.setPosition( glm::dvec3( start_location ) ); + #ifdef MARKER_CAPTURE if(marker_capture_enabled){ marker_capturer.position_updated(&position_updated); @@ -406,6 +413,12 @@ void simulateHand(float deltaTime) { float dy = mouse_y - mouse_start_y; glm::vec3 vel(dx*MOUSE_HAND_FORCE, -dy*MOUSE_HAND_FORCE*(WIDTH/HEIGHT), 0); myHead.hand->addVelocity(vel*deltaTime); + + double leftRight = dx * 0.001; + double downUp = dy * 0.001; + double backFront = 0.0; + glm::dvec3 handMovement( leftRight, downUp, backFront ); + myHead.setHandMovement( handMovement ); } } @@ -422,7 +435,12 @@ void simulateHead(float frametime) //float measured_fwd_accel = serialPort.getRelativeValue(ACCEL_Z); myHead.UpdatePos(frametime, &serialPort, head_mirror, &gravity); - + + //------------------------------------------------------------------------------------- + // set the position of the avatar + //------------------------------------------------------------------------------------- + myHead.setAvatarPosition( -myHead.getPos().x, -myHead.getPos().y, -myHead.getPos().z ); + // Update head_mouse model const float MIN_MOUSE_RATE = 30.0; const float MOUSE_SENSITIVITY = 0.1f; @@ -551,16 +569,29 @@ void display(void) glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color); glMateriali(GL_FRONT, GL_SHININESS, 96); - - // Rotate, translate to camera location - fov.setOrientation( - glm::rotate(glm::rotate(glm::translate(glm::mat4(1.0f), -myHead.getPos()), - -myHead.getRenderYaw(), glm::vec3(0.0f,1.0f,0.0f)), - -myHead.getRenderPitch(), glm::vec3(1.0f,0.0f,0.0f)) ); + + //------------------------------------------------------------------------------------- + // set the caemra to third-person view + //------------------------------------------------------------------------------------- + myCamera.setYaw ( myHead.getRenderYaw() ); + myCamera.setPitch ( 0.0 ); + myCamera.setRoll ( 0.0 ); + + glm::dvec3 offset( 0.7, -0.2, 0.7 ); - glLoadMatrixf( glm::value_ptr(fov.getWorldViewerXform()) ); - glRotatef(myHead.getRenderPitch(), 1, 0, 0); - glRotatef(myHead.getRenderYaw(), 0, 1, 0); + glm::dvec3 positionWithOffset( myHead.getPos() ); + + positionWithOffset += offset; + + myCamera.setPosition( positionWithOffset ); + + //------------------------------------------------------------------------------------- + // transform to camera view + //------------------------------------------------------------------------------------- + glRotatef ( myCamera.getPitch(), 1, 0, 0 ); + glRotatef ( myCamera.getYaw(), 0, 1, 0 ); + glRotatef ( myCamera.getRoll(), 0, 0, 1 ); + glTranslatef( myCamera.getPosition().x, myCamera.getPosition().y, myCamera.getPosition().z ); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); @@ -601,12 +632,18 @@ void display(void) // Render the world box if (!display_head && stats_on) render_world_box(); + +myHead.render( true, 1 ); + + /* // Render my own head glPushMatrix(); glLoadIdentity(); glTranslatef(0.f, 0.f, -7.f); myHead.render(display_head, 1); glPopMatrix(); + */ + } glPopMatrix(); From 57829785eb3b53bbccdd0e464a80cd7bf167a7bf Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Apr 2013 20:50:51 -0700 Subject: [PATCH 08/33] fix to LOD bug caused by flip-flopped X and Z, add color randomization to inserted voxels on server, added head position display to display_stats() --- interface/src/VoxelSystem.cpp | 33 +++++++++++++++++++++++++++------ interface/src/main.cpp | 9 ++++++--- shared/src/VoxelTree.cpp | 11 +++++++++-- voxel/src/main.cpp | 27 ++++++++++++++++++++++++--- 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 03a83d086e..68914e2d6b 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -133,12 +133,35 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, float nodePosition[3]) { float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE); glm::vec3 viewerPosition = viewerHead->getPos(); + + // XXXBHG - Note: It appears as if the X and Z coordinates of Head or Agent are flip-flopped relative to the + // coords of the voxel space. This flip flop causes LOD behavior to be extremely odd. This is my temporary hack + // to fix this behavior. To disable this swap, set swapXandZ to false. + bool swapXandZ=true; + float viewerX = swapXandZ ? viewerPosition[2] : viewerPosition[0]; + float viewerZ = swapXandZ ? viewerPosition[0] : viewerPosition[2]; + + // debugging code. + //printf("treeToArrays() halfUnitForVoxel=%f\n",halfUnitForVoxel); + //printf("treeToArrays() viewerPosition {x,y,z or [0],[1],[2]} ={%f,%f,%f}\n", + // viewerPosition[0],viewerPosition[1],viewerPosition[2]); + //printf("treeToArrays() nodePosition {x,y,z or [0],[1],[2]} = {%f,%f,%f}\n", + // nodePosition[0],nodePosition[1],nodePosition[2]); + //float* vertices = firstVertexForCode(currentNode->octalCode); + //printf("treeToArrays() firstVerticesForCode(currentNode->octalCode)={x,y,z or [0],[1],[2]} = {%f,%f,%f}\n", + // vertices[0],vertices[1],vertices[2]); + //delete []vertices; - float distanceToVoxelCenter = sqrtf(powf(viewerPosition[0] - nodePosition[0] - halfUnitForVoxel, 2) + + float distanceToVoxelCenter = sqrtf(powf(viewerX - nodePosition[0] - halfUnitForVoxel, 2) + powf(viewerPosition[1] - nodePosition[1] - halfUnitForVoxel, 2) + - powf(viewerPosition[2] - nodePosition[2] - halfUnitForVoxel, 2)); - - if (distanceToVoxelCenter < boundaryDistanceForRenderLevel(*currentNode->octalCode + 1)) { + powf(viewerZ - nodePosition[2] - halfUnitForVoxel, 2)); + + int boundaryPosition = boundaryDistanceForRenderLevel(*currentNode->octalCode + 1); + //printf("treeToArrays() distanceToVoxelCenter=%f boundaryPosition=%d\n",distanceToVoxelCenter,boundaryPosition); + + bool alwaysDraw = false; // XXXBHG - temporary debug code. Flip this to true to disable LOD blurring + + if (alwaysDraw || distanceToVoxelCenter < boundaryPosition) { for (int i = 0; i < 8; i++) { // check if there is a child here if (currentNode->children[i] != NULL) { @@ -155,8 +178,6 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, float nodePosition[3]) { childNodePosition[j] -= (powf(0.5, *currentNode->children[i]->octalCode) * TREE_SCALE); } } - - voxelsAdded += treeToArrays(currentNode->children[i], childNodePosition); } } diff --git a/interface/src/main.cpp b/interface/src/main.cpp index e6f6b6fd52..fd29241e51 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -98,6 +98,7 @@ Head myHead; // The rendered head of oneself char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt"; FieldOfView fov; + Stars stars; #ifdef STARFIELD_KEYS int starsTiles = 20; @@ -255,10 +256,12 @@ void display_stats(void) char legend2[] = "* - toggle stars, & - toggle paint mode"; drawtext(10, 32, 0.10f, 0, 1.0, 0, legend2); + + glm::vec3 headPos = myHead.getPos(); char stats[200]; - sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d ", - FPS, packets_per_second, bytes_per_second); + sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d Head(x,y,z)=( %f , %f , %f )", + FPS, packets_per_second, bytes_per_second, headPos.x,headPos.y,headPos.z); drawtext(10, 49, 0.10f, 0, 1.0, 0, stats); if (serialPort.active) { sprintf(stats, "ADC samples = %d, LED = %d", @@ -490,7 +493,7 @@ void simulateHead(float frametime) char broadcast_string[MAX_BROADCAST_STRING]; int broadcast_bytes = myHead.getBroadcastData(broadcast_string); agentList.broadcastToAgents(broadcast_string, broadcast_bytes,AgentList::AGENTS_OF_TYPE_VOXEL_AND_INTERFACE); - + // If I'm in paint mode, send a voxel out to VOXEL server agents. if (::paintOn) { diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index e9c8c67c0b..a00fb48cf5 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -255,10 +255,17 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer, unsigned char * childMaskPointer = NULL; float halfUnitForVoxel = powf(0.5, *currentVoxelNode->octalCode) * (0.5 * TREE_SCALE); + + // XXXBHG - Note: It appears as if the X and Z coordinates of Head or Agent are flip-flopped relative to the + // coords of the voxel space. This flip flop causes LOD behavior to be extremely odd. This is my temporary hack + // to fix this behavior. To disable this swap, set swapXandZ to false. + bool swapXandZ=true; + float agentX = swapXandZ ? agentPosition[2] : agentPosition[0]; + float agentZ = swapXandZ ? agentPosition[0] : agentPosition[2]; - float distanceToVoxelCenter = sqrtf(powf(agentPosition[0] - thisNodePosition[0] - halfUnitForVoxel, 2) + + float distanceToVoxelCenter = sqrtf(powf(agentX - thisNodePosition[0] - halfUnitForVoxel, 2) + powf(agentPosition[1] - thisNodePosition[1] - halfUnitForVoxel, 2) + - powf(agentPosition[2] - thisNodePosition[2] - halfUnitForVoxel, 2)); + powf(agentZ - thisNodePosition[2] - halfUnitForVoxel, 2)); // if the distance to this voxel's center is less than the threshold // distance for its children, we should send the children diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 8e1bb52535..914411db64 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -47,6 +47,8 @@ const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; AgentList agentList('V', VOXEL_LISTEN_PORT); VoxelTree randomTree; +bool wantColorRandomizer = false; + void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) { float r = random ? randFloatInRange(0.05,0.1) : 0.25; float xc = random ? randFloatInRange(r,(1-r)) : 0.5; @@ -229,7 +231,7 @@ int main(int argc, const char * argv[]) // Voxel File. If so, load it now. const char* WANT_COLOR_RANDOMIZER="--WantColorRandomizer"; const char* INPUT_FILE="-i"; - bool wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER); + ::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER); printf("wantColorRandomizer=%s\n",(wantColorRandomizer?"yes":"no")); const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE); @@ -273,19 +275,38 @@ int main(int argc, const char * argv[]) // XXXBHG: Hacked in support for 'I' insert command if (packetData[0] == 'I') { unsigned short int itemNumber = (*((unsigned short int*)&packetData[1])); - printf("got I - insert voxels - command from client receivedBytes=%ld itemNumber=%d\n",receivedBytes,itemNumber); + printf("got I - insert voxels - command from client receivedBytes=%ld itemNumber=%d\n", + receivedBytes,itemNumber); int atByte = 3; unsigned char* pVoxelData = (unsigned char*)&packetData[3]; while (atByte < receivedBytes) { unsigned char octets = (unsigned char)*pVoxelData; int voxelDataSize = bytesRequiredForCodeLength(octets)+3; // 3 for color! + int voxelCodeSize = bytesRequiredForCodeLength(octets); + + // color randomization on insert + int colorRandomizer = ::wantColorRandomizer ? randIntInRange (-50, 50) : 0; + int red = pVoxelData[voxelCodeSize+0]; + int green = pVoxelData[voxelCodeSize+1]; + int blue = pVoxelData[voxelCodeSize+2]; + printf("insert voxels - wantColorRandomizer=%s old r=%d,g=%d,b=%d \n", + (::wantColorRandomizer?"yes":"no"),red,green,blue); + red = std::max(0,std::min(255,red + colorRandomizer)); + green = std::max(0,std::min(255,green + colorRandomizer)); + blue = std::max(0,std::min(255,blue + colorRandomizer)); + printf("insert voxels - wantColorRandomizer=%s NEW r=%d,g=%d,b=%d \n", + (::wantColorRandomizer?"yes":"no"),red,green,blue); + pVoxelData[voxelCodeSize+0]=red; + pVoxelData[voxelCodeSize+1]=green; + pVoxelData[voxelCodeSize+2]=blue; float* vertices = firstVertexForCode(pVoxelData); printf("inserting voxel at: %f,%f,%f\n",vertices[0],vertices[1],vertices[2]); delete []vertices; randomTree.readCodeColorBufferToTree(pVoxelData); - //printf("readCodeColorBufferToTree() of size=%d atByte=%d receivedBytes=%ld\n",voxelDataSize,atByte,receivedBytes); + //printf("readCodeColorBufferToTree() of size=%d atByte=%d receivedBytes=%ld\n", + // voxelDataSize,atByte,receivedBytes); // skip to next pVoxelData+=voxelDataSize; atByte+=voxelDataSize; From e57e2bdf38ebf9aafefa9a3e0b3a73f32d7f4499 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 5 Apr 2013 10:48:08 -0700 Subject: [PATCH 09/33] thingy2 --- interface/src/main.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 91cae9f4c9..acfb7c8424 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -67,7 +67,7 @@ using namespace std; -double testThingy = 0.0; +double testThingy = 90.0; int audio_on = 1; // Whether to turn on the audio support int simulate_on = 1; @@ -573,11 +573,20 @@ void display(void) //------------------------------------------------------------------------------------- // set the caemra to third-person view //------------------------------------------------------------------------------------- - myCamera.setYaw ( myHead.getRenderYaw() ); + + testThingy += 1.0; + + //myCamera.setYaw ( myHead.getRenderYaw() ); + myCamera.setYaw ( testThingy ); myCamera.setPitch ( 0.0 ); myCamera.setRoll ( 0.0 ); - glm::dvec3 offset( 0.7, -0.2, 0.7 ); + double radian = ( testThingy / 180.0 ) * PI; + double x = 0.7 * sin( radian ); + double z = 0.7 * cos( radian ); + double y = -0.2; + + glm::dvec3 offset( x, y, z ); glm::dvec3 positionWithOffset( myHead.getPos() ); From 16ad4fc2200287deeb084060d58ba5b8ee9ee850 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Apr 2013 10:54:39 -0700 Subject: [PATCH 10/33] hack to always send voxels to client (even if already visited), added paint mode features to client --- interface/src/main.cpp | 58 +++++++++++++++++++++++++++++++----------- voxel/src/main.cpp | 7 ++++- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index fd29241e51..9f005255cf 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -145,7 +145,8 @@ glm::vec3 start_location(6.1f, 0, 1.4f); int stats_on = 0; // Whether to show onscreen text overlay with stats bool starsOn = true; // Whether to display the stars bool paintOn = false; // Whether to paint voxels as you fly around - +VoxelDetail paintingVoxel; // The voxel we're painting if we're painting +unsigned char dominantColor = 0; // The dominant color of the voxel we're painting int noise_on = 0; // Whether to add random noise float noise = 1.0; // Overall magnitude scaling for random noise levels @@ -499,23 +500,18 @@ void simulateHead(float frametime) glm::vec3 headPos = myHead.getPos(); - VoxelDetail paintingVoxel; - paintingVoxel.x = headPos.z/10.0; // voxel space x is positive z head space - paintingVoxel.y = headPos.y/-10.0; // voxel space y is negative y head space - paintingVoxel.z = headPos.x/-10.0; // voxel space z is negative x head space - paintingVoxel.s = 1.0/256; - paintingVoxel.red = 0; - paintingVoxel.green = 255; - paintingVoxel.blue = 0; + ::paintingVoxel.x = headPos.z/-10.0; // voxel space x is negative z head space + ::paintingVoxel.y = headPos.y/-10.0; // voxel space y is negative y head space + ::paintingVoxel.z = headPos.x/-10.0; // voxel space z is negative x head space unsigned char* bufferOut; int sizeOut; - if (paintingVoxel.x >= 0.0 && paintingVoxel.x <= 1.0 && - paintingVoxel.y >= 0.0 && paintingVoxel.y <= 1.0 && - paintingVoxel.z >= 0.0 && paintingVoxel.z <= 1.0) { + if (::paintingVoxel.x >= 0.0 && ::paintingVoxel.x <= 1.0 && + ::paintingVoxel.y >= 0.0 && ::paintingVoxel.y <= 1.0 && + ::paintingVoxel.z >= 0.0 && ::paintingVoxel.z <= 1.0) { - if (createVoxelEditMessage('I',0,1,&paintingVoxel,bufferOut,sizeOut)){ + if (createVoxelEditMessage('I',0,1,&::paintingVoxel,bufferOut,sizeOut)){ agentList.broadcastToAgents((char*)bufferOut, sizeOut,AgentList::AGENTS_OF_TYPE_VOXEL); delete bufferOut; } @@ -681,7 +677,12 @@ void display(void) drawtext(WIDTH-200,20, 0.10, 0, 1.0, 0, agents, 1, 1, 0); if (::paintOn) { - drawtext(WIDTH-200,40, 0.10, 0, 1.0, 0, "Paint ON", 1, 1, 0); + + char paintMessage[100]; + sprintf(paintMessage,"Painting (%.3f,%.3f,%.3f/%.3f/%d,%d,%d)", + ::paintingVoxel.x,::paintingVoxel.y,::paintingVoxel.z,::paintingVoxel.s, + (unsigned int)::paintingVoxel.red,(unsigned int)::paintingVoxel.green,(unsigned int)::paintingVoxel.blue); + drawtext(WIDTH-350,40, 0.10, 0, 1.0, 0, paintMessage, 1, 1, 0); } glPopMatrix(); @@ -711,6 +712,27 @@ void testPointToVoxel() } } +void shiftPaintingColor() +{ + // About the color of the paintbrush... first determine the dominant color + ::dominantColor = (::dominantColor+1)%3; // 0=red,1=green,2=blue + ::paintingVoxel.red = (::dominantColor==0)?randIntInRange(200,255):randIntInRange(40,100); + ::paintingVoxel.green = (::dominantColor==1)?randIntInRange(200,255):randIntInRange(40,100); + ::paintingVoxel.blue = (::dominantColor==2)?randIntInRange(200,255):randIntInRange(40,100); +} + +void setupPaintingVoxel() +{ + glm::vec3 headPos = myHead.getPos(); + + ::paintingVoxel.x = headPos.z/-10.0; // voxel space x is negative z head space + ::paintingVoxel.y = headPos.y/-10.0; // voxel space y is negative y head space + ::paintingVoxel.z = headPos.x/-10.0; // voxel space z is negative x head space + ::paintingVoxel.s = 1.0/256; + + shiftPaintingColor(); +} + void addRandomSphere(bool wantColorRandomizer) { float r = randFloatInRange(0.05,0.1); @@ -797,7 +819,13 @@ void key(unsigned char k, int x, int y) if (k == 'q') ::terminate(); if (k == '/') stats_on = !stats_on; // toggle stats if (k == '*') ::starsOn = !::starsOn; // toggle stars - if (k == '&') ::paintOn = !::paintOn; // toggle paint + if (k == '&') { + ::paintOn = !::paintOn; // toggle paint + setupPaintingVoxel(); // also randomizes colors + } + if (k == '^') { + shiftPaintingColor(); // shifts randomize color between R,G,B dominant + } if (k == 'n') { noise_on = !noise_on; // Toggle noise diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 914411db64..5cf4606900 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -171,7 +171,12 @@ void *distributeVoxelsToListeners(void *args) { packetCount++; totalBytesSent += voxelPacketEnd - voxelPacket; - if (agentData->rootMarkerNode->childrenVisitedMask == 255) { + // XXXBHG Hack Attack: This is temporary code to help debug an issue. + // Normally we use this break to prevent resending voxels that an agent has + // already visited. But since we might be modifying the voxel tree we might + // want to always send. This is a hack to test the behavior + bool alwaysSend = true; + if (!alwaysSend && agentData->rootMarkerNode->childrenVisitedMask == 255) { break; } } From 12e06135bbd1cc6d6b8e87562587c4e701a42dc4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Apr 2013 13:18:06 -0700 Subject: [PATCH 11/33] fixed reaverageVoxelColors() behavior. seems to work better now --- shared/src/VoxelNode.cpp | 25 ++++++++++--------------- shared/src/VoxelNode.h | 2 +- shared/src/VoxelTree.cpp | 9 +-------- voxel/src/main.cpp | 17 ++++------------- 4 files changed, 16 insertions(+), 37 deletions(-) diff --git a/shared/src/VoxelNode.cpp b/shared/src/VoxelNode.cpp index 8b71a04893..7300af814a 100644 --- a/shared/src/VoxelNode.cpp +++ b/shared/src/VoxelNode.cpp @@ -37,25 +37,20 @@ void VoxelNode::addChildAtIndex(int childIndex) { } // will average the child colors... -void VoxelNode::setColorFromAverageOfChildren(int * colorArray) { - if (colorArray == NULL) { - colorArray = new int[4]; - memset(colorArray, 0, 4*sizeof(int)); - - for (int i = 0; i < 8; i++) { - if (children[i] != NULL && children[i]->color[3] == 1) { - for (int j = 0; j < 3; j++) { - colorArray[j] += children[i]->color[j]; - } - colorArray[3]++; - } - } - } +void VoxelNode::setColorFromAverageOfChildren() { + int colorArray[4] = {0,0,0,0}; + for (int i = 0; i < 8; i++) { + if (children[i] != NULL && children[i]->color[3] == 1) { + for (int j = 0; j < 3; j++) { + colorArray[j] += children[i]->color[j]; + } + colorArray[3]++; + } + } if (colorArray[3] > 4) { // we need at least 4 colored children to have an average color value // or if we have none we generate random values - for (int c = 0; c < 3; c++) { // set the average color value color[c] = colorArray[c] / colorArray[3]; diff --git a/shared/src/VoxelNode.h b/shared/src/VoxelNode.h index 9be1b64c70..e97689aa9b 100644 --- a/shared/src/VoxelNode.h +++ b/shared/src/VoxelNode.h @@ -17,7 +17,7 @@ public: ~VoxelNode(); void addChildAtIndex(int childIndex); - void setColorFromAverageOfChildren(int * colorArray = NULL); + void setColorFromAverageOfChildren(); void setRandomColor(int minimumBrightness); bool collapseIdenticalLeaves(); diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index a00fb48cf5..a7390dd06f 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -100,8 +100,6 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, // instantiate variable for bytes already read int bytesRead = 1; - int colorArray[4] = {}; - for (int i = 0; i < 8; i++) { // check the colors mask to see if we have a child to color in if (oneAtBit(*nodeData, i)) { @@ -115,17 +113,12 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, memcpy(destinationNode->children[i]->color, nodeData + bytesRead, 3); destinationNode->children[i]->color[3] = 1; - for (int j = 0; j < 3; j++) { - colorArray[j] += destinationNode->children[i]->color[j]; - } - bytesRead += 3; - colorArray[3]++; } } // average node's color based on color of children - destinationNode->setColorFromAverageOfChildren(colorArray); + destinationNode->setColorFromAverageOfChildren(); // give this destination node the child mask from the packet unsigned char childMask = *(nodeData + bytesRead); diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 5cf4606900..0a2ae0c584 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -85,8 +85,6 @@ void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { if (levelsToGo > 0) { bool createdChildren = false; - int colorArray[4] = {}; - createdChildren = false; for (int i = 0; i < 8; i++) { @@ -96,17 +94,8 @@ void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { // give this child it's octal code currentRootNode->children[i]->octalCode = childOctalCode(currentRootNode->octalCode, i); - - randomlyFillVoxelTree(levelsToGo - 1, currentRootNode->children[i]); - if (currentRootNode->children[i]->color[3] == 1) { - for (int c = 0; c < 3; c++) { - colorArray[c] += currentRootNode->children[i]->color[c]; - } - - colorArray[3]++; - } - + randomlyFillVoxelTree(levelsToGo - 1, currentRootNode->children[i]); createdChildren = true; } } @@ -117,7 +106,7 @@ void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { currentRootNode->setRandomColor(MIN_BRIGHTNESS); } else { // set the color value for this node - currentRootNode->setColorFromAverageOfChildren(colorArray); + currentRootNode->setColorFromAverageOfChildren(); } } else { // this is a leaf node, just give it a color @@ -316,6 +305,8 @@ int main(int argc, const char * argv[]) pVoxelData+=voxelDataSize; atByte+=voxelDataSize; } + // after done inserting all these voxels, then reaverage colors + randomTree.reaverageVoxelColors(randomTree.rootNode); } if (packetData[0] == 'R') { From a0f09b597ad832dd6a9ab63bb648a6e8186cedb0 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 5 Apr 2013 16:19:23 -0700 Subject: [PATCH 12/33] got a basic avatar skeleton with a simpler starter user interaction for moving the right hand --- interface/src/Camera.cpp | 26 +++++++++-- interface/src/Camera.h | 18 ++++++-- interface/src/Head.cpp | 59 ++++++++++++++++++++++-- interface/src/Head.h | 2 +- interface/src/Orientation.cpp | 36 +++++++-------- interface/src/Util.h | 10 ++-- interface/src/main.cpp | 86 +++++++++++++++++------------------ 7 files changed, 158 insertions(+), 79 deletions(-) diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index b0c5a2c0dd..e7bf3d751b 100755 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -6,14 +6,32 @@ //----------------------------------------------------------- #include "Camera.h" +#include "Util.h" //------------------------ Camera::Camera() { - yaw = 0.0; - pitch = 0.0; - roll = 0.0; - position = glm::dvec3( 0.0, 0.0, 0.0 ); + yaw = 0.0; + pitch = 0.0; + roll = 0.0; + up = 0.0; + distance = 0.0; + targetPosition = glm::dvec3( 0.0, 0.0, 0.0 ); + position = glm::dvec3( 0.0, 0.0, 0.0 ); orientation.setToIdentity(); } + +//------------------------ +void Camera::update() +{ + double radian = ( yaw / 180.0 ) * PIE; + + double x = distance * sin( radian ); + double z = distance * -cos( radian ); + double y = -up; + + position = glm::dvec3( targetPosition ); + position += glm::dvec3( x, y, z ); +} + diff --git a/interface/src/Camera.h b/interface/src/Camera.h index b0bf9373cd..eed70c1c92 100755 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -17,11 +17,16 @@ class Camera public: Camera(); - void setYaw ( double y ) { yaw = y; } - void setPitch ( double p ) { pitch = p; } - void setRoll ( double r ) { roll = r; } - void setPosition ( glm::dvec3 p ) { position = p; }; - void setOrientation ( Orientation o ) { orientation.set(o); } + void update(); + + void setYaw ( double y ) { yaw = y; } + void setPitch ( double p ) { pitch = p; } + void setRoll ( double r ) { roll = r; } + void setUp ( double u ) { up = u; } + void setDistance ( double d ) { distance = d; } + void setTargetPosition ( glm::dvec3 t ) { targetPosition = t; }; + void setPosition ( glm::dvec3 p ) { position = p; }; + void setOrientation ( Orientation o ) { orientation.set(o); } double getYaw () { return yaw; } double getPitch () { return pitch; } @@ -32,9 +37,12 @@ public: private: glm::dvec3 position; + glm::dvec3 targetPosition; double yaw; double pitch; double roll; + double up; + double distance; Orientation orientation; }; diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 18b5d60690..91cb91bcec 100755 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -595,7 +595,7 @@ glScalef( 0.03, 0.03, 0.03 ); //--------------------------------------------------------- void Head::setHandMovement( glm::dvec3 movement ) { - handOffset.setXYZ( movement.x, movement.y, movement.z ); + handOffset.setXYZ( movement.x, -movement.y, movement.z ); } @@ -744,6 +744,9 @@ void Head::simulateAvatar( float deltaTime ) //----------------------------------------- void Head::updateAvatarSkeleton() { + //------------------------------------------------------------------------ + // calculate positions of all bones by traversing the skeleton tree: + //------------------------------------------------------------------------ for (int b=0; b maxArmLength ) + { + //------------------------------------------------------------------------------- + // reset right hand to be constrained to maximum arm length + //------------------------------------------------------------------------------- + avatar.bone[ AVATAR_BONE_RIGHT_HAND ].position.set( avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); + + glm::dvec3 armNormal = armVector / distance; + armVector = armNormal * maxArmLength; + distance = maxArmLength; + + glm::dvec3 constrainedPosition = glm::dvec3( avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.x, avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.y, avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.z ); + + constrainedPosition += armVector; + + avatar.bone[ AVATAR_BONE_RIGHT_HAND ].position.setXYZ( constrainedPosition.x, constrainedPosition.y, constrainedPosition.z ); + } + + + //----------------------------------------------------------------------------- + // set elbow position + //----------------------------------------------------------------------------- + glm::dvec3 newElbowPosition = glm::dvec3( avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.x, avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.y, avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.z ); + + newElbowPosition += armVector * ONE_HALF; + + glm::dvec3 perpendicular = glm::dvec3( -armVector.y, armVector.x, armVector.z ); + + newElbowPosition += perpendicular * ( 1.0 - ( maxArmLength / distance ) ) * ONE_HALF; + + avatar.bone[ AVATAR_BONE_RIGHT_FOREARM ].position.setXYZ( newElbowPosition.x, newElbowPosition.y, newElbowPosition.z ); } + //----------------------------------------- void Head::renderAvatar() { @@ -772,7 +825,7 @@ void Head::renderAvatar() glPushMatrix(); glTranslatef( avatar.bone[b].position.x, avatar.bone[b].position.y, avatar.bone[b].position.z ); glScalef( 0.02, 0.02, 0.02 ); - glutSolidSphere( 1, 6, 3 ); + glutSolidSphere( 1, 8, 4 ); glPopMatrix(); } } diff --git a/interface/src/Head.h b/interface/src/Head.h index 618bdcc16b..b5ae162c80 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -158,6 +158,7 @@ class Head : public AgentData { void render(int faceToFace, int isMine); void setAvatarPosition( double, double, double ); + void renderAvatar(); void simulate(float); @@ -239,7 +240,6 @@ class Head : public AgentData { void initializeAvatar(); void simulateAvatar( float deltaTime ); void updateAvatarSkeleton(); - void renderAvatar(); void readSensors(); float renderYaw, renderPitch; // Pitch from view frustum when this is own head. diff --git a/interface/src/Orientation.cpp b/interface/src/Orientation.cpp index 16176e736d..63ea77f4dd 100755 --- a/interface/src/Orientation.cpp +++ b/interface/src/Orientation.cpp @@ -180,50 +180,50 @@ void Orientation::setRightUpFront( const Vector3D &r, const Vector3D &u, const V //----------------------------------------------------------------------------- void Orientation::verifyValidOrientation() { - assert( right.getMagnitude () < 1.0 + BIG_EPSILON ); - assert( right.getMagnitude () > 1.0 - BIG_EPSILON ); - assert( up.getMagnitude () < 1.0 + BIG_EPSILON ); - assert( up.getMagnitude () > 1.0 - BIG_EPSILON ); - assert( front.getMagnitude () < 1.0 + BIG_EPSILON ); - assert( front.getMagnitude () > 1.0 - BIG_EPSILON ); + assert( right.getMagnitude () < 1.0 + CENTIMETER ); + assert( right.getMagnitude () > 1.0 - CENTIMETER ); + assert( up.getMagnitude () < 1.0 + CENTIMETER ); + assert( up.getMagnitude () > 1.0 - CENTIMETER ); + assert( front.getMagnitude () < 1.0 + CENTIMETER ); + assert( front.getMagnitude () > 1.0 - CENTIMETER ); - if ( right.getMagnitude() > 1.0 + BIG_EPSILON ) + if ( right.getMagnitude() > 1.0 + CENTIMETER ) { printf( "oops: the magnitude of the 'right' part of the orientation is %f!\n", right.getMagnitude() ); } - else if ( right.getMagnitude() < 1.0 - BIG_EPSILON ) + else if ( right.getMagnitude() < 1.0 - CENTIMETER ) { printf( "oops: the magnitude of the 'right' part of the orientation is %f!\n", right.getMagnitude() ); } - if ( up.getMagnitude() > 1.0 + BIG_EPSILON ) + if ( up.getMagnitude() > 1.0 + CENTIMETER ) { printf( "oops: the magnitude of the 'up' part of the orientation is %f!\n", up.getMagnitude() ); } - else if ( up.getMagnitude() < 1.0 - BIG_EPSILON ) + else if ( up.getMagnitude() < 1.0 - CENTIMETER ) { printf( "oops: the magnitude of the 'up' part of the orientation is %f!\n", up.getMagnitude() ); } - if ( front.getMagnitude() > 1.0 + BIG_EPSILON ) + if ( front.getMagnitude() > 1.0 + CENTIMETER ) { printf( "oops: the magnitude of the 'front' part of the orientation is %f!\n", front.getMagnitude() ); } - else if ( front.getMagnitude() < 1.0 - BIG_EPSILON ) + else if ( front.getMagnitude() < 1.0 - CENTIMETER ) { printf( "oops: the magnitude of the 'front' part of the orientation is %f!\n", front.getMagnitude() ); } - if (( right.dotWith ( up ) > BIG_EPSILON ) - || ( right.dotWith ( up ) < -BIG_EPSILON )) { printf( "oops: the 'right' and 'up' parts of the orientation are not perpendicular! The dot is: %f\n", right.dotWith ( up ) ); } + if (( right.dotWith ( up ) > CENTIMETER ) + || ( right.dotWith ( up ) < -CENTIMETER )) { printf( "oops: the 'right' and 'up' parts of the orientation are not perpendicular! The dot is: %f\n", right.dotWith ( up ) ); } - if (( right.dotWith ( front ) > BIG_EPSILON ) - || ( right.dotWith ( front ) < -BIG_EPSILON )) { printf( "oops: the 'right' and 'front' parts of the orientation are not perpendicular! The dot is: %f\n", right.dotWith ( front ) ); } + if (( right.dotWith ( front ) > CENTIMETER ) + || ( right.dotWith ( front ) < -CENTIMETER )) { printf( "oops: the 'right' and 'front' parts of the orientation are not perpendicular! The dot is: %f\n", right.dotWith ( front ) ); } - if (( up.dotWith ( front ) > BIG_EPSILON ) - || ( up.dotWith ( front ) < -BIG_EPSILON )) { printf( "oops: the 'up' and 'front' parts of the orientation are not perpendicular! The dot is: %f\n", up.dotWith ( front ) ); } + if (( up.dotWith ( front ) > CENTIMETER ) + || ( up.dotWith ( front ) < -CENTIMETER )) { printf( "oops: the 'up' and 'front' parts of the orientation are not perpendicular! The dot is: %f\n", up.dotWith ( front ) ); } } diff --git a/interface/src/Util.h b/interface/src/Util.h index 8537f9c769..c5a02df5aa 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -23,13 +23,17 @@ static const double ZERO = 0.0; static const double ONE = 1.0; static const double ONE_HALF = 0.5; static const double ONE_THIRD = 0.3333333; -//static const double PI = 3.14159265359; +static const double PIE = 3.14159265359; static const double PI_TIMES_TWO = 3.14159265359 * 2.0; static const double PI_OVER_180 = 3.14159265359 / 180.0; -static const double EPSILON = 0.00001; // a smallish number meant to be used as a margin of error for some normalized values -static const double BIG_EPSILON = 0.01; // not as smallish as EPSILON +static const double EPSILON = 0.00001; //smallish number - used as margin of error for some values +static const double SQUARE_ROOT_OF_2 = sqrt(2); static const double SQUARE_ROOT_OF_3 = sqrt(3); +static const double METER = 1.0; +static const double DECIMETER = 0.1; +static const double CENTIMETER = 0.01; +static const double MILLIIMETER = 0.001; float azimuth_to(glm::vec3 head_pos, glm::vec3 source_pos); float angle_to(glm::vec3 head_pos, glm::vec3 source_pos, float render_yaw, float head_yaw); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index bacd25e3d8..4ae10b94d3 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -66,9 +66,6 @@ using namespace std; - -double testThingy = 90.0; - int audio_on = 1; // Whether to turn on the audio support int simulate_on = 1; @@ -196,7 +193,6 @@ char texture_filename[] = "images/int-texture256-v4.png"; unsigned int texture_width = 256; unsigned int texture_height = 256; - float particle_attenuation_quadratic[] = { 0.0f, 0.0f, 2.0f }; // larger Z = smaller particles float pointer_attenuation_quadratic[] = { 1.0f, 0.0f, 0.0f }; // for 2D view @@ -253,6 +249,9 @@ void Timer(int extra) } } + + + void display_stats(void) { // bitmap chars are about 10 pels high @@ -330,6 +329,9 @@ void initDisplay(void) if (fullscreen) glutFullScreen(); } + + + void init(void) { voxels.init(); @@ -366,7 +368,6 @@ void init(void) } #endif - gettimeofday(&timer_start, NULL); gettimeofday(&last_frame, NULL); } @@ -416,12 +417,6 @@ void simulateHand(float deltaTime) { float dy = mouse_y - mouse_start_y; glm::vec3 vel(dx*MOUSE_HAND_FORCE, -dy*MOUSE_HAND_FORCE*(WIDTH/HEIGHT), 0); myHead.hand->addVelocity(vel*deltaTime); - - double leftRight = dx * 0.001; - double downUp = dy * 0.001; - double backFront = 0.0; - glm::dvec3 handMovement( leftRight, downUp, backFront ); - myHead.setHandMovement( handMovement ); } } @@ -544,6 +539,9 @@ void simulateHead(float frametime) int render_test_spot = WIDTH/2; int render_test_direction = 1; + + + void display(void) { PerfStat("display"); @@ -571,30 +569,16 @@ void display(void) glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color); glMateriali(GL_FRONT, GL_SHININESS, 96); - //------------------------------------------------------------------------------------- // set the caemra to third-person view - //------------------------------------------------------------------------------------- - - testThingy += 1.0; - - //myCamera.setYaw ( myHead.getRenderYaw() ); - myCamera.setYaw ( testThingy ); - myCamera.setPitch ( 0.0 ); - myCamera.setRoll ( 0.0 ); - - double radian = ( testThingy / 180.0 ) * PI; - double x = 0.7 * sin( radian ); - double z = 0.7 * cos( radian ); - double y = -0.2; - - glm::dvec3 offset( x, y, z ); - - glm::dvec3 positionWithOffset( myHead.getPos() ); - - positionWithOffset += offset; - - myCamera.setPosition( positionWithOffset ); + //------------------------------------------------------------------------------------- + myCamera.setTargetPosition ( (glm::dvec3)myHead.getPos() ); + myCamera.setYaw ( 0.0 ); + myCamera.setPitch ( 0.0 ); + myCamera.setRoll ( 0.0 ); + myCamera.setUp ( 0.15 ); + myCamera.setDistance ( 0.08 ); + myCamera.update(); //------------------------------------------------------------------------------------- // transform to camera view @@ -604,16 +588,6 @@ void display(void) glRotatef ( myCamera.getRoll(), 0, 0, 1 ); glTranslatef( myCamera.getPosition().x, myCamera.getPosition().y, myCamera.getPosition().z ); - /* - // Rotate, translate to camera location - fov.setOrientation( - glm::rotate(glm::rotate(glm::translate(glm::mat4(1.0f), -myHead.getPos()), - -myHead.getRenderYaw(), glm::vec3(0.0f,1.0f,0.0f)), - -myHead.getRenderPitch(), glm::vec3(1.0f,0.0f,0.0f)) ); - - glLoadMatrixf( glm::value_ptr(fov.getWorldViewerXform()) ); - */ - if (::starsOn) { // should be the first rendering pass - w/o depth buffer / lighting stars.render(fov); @@ -631,7 +605,7 @@ void display(void) // if (!display_head) cloud.render(); // Draw voxels - voxels.render(); +//voxels.render(); // Draw field vectors if (display_field) field.render(); @@ -654,7 +628,8 @@ void display(void) if (!display_head && stats_on) render_world_box(); -myHead.render( true, 1 ); + myHead.render( true, 1 ); + //myHead.renderAvatar(); /* // Render my own head @@ -750,6 +725,10 @@ myHead.render( true, 1 ); framecount++; } + + + + void testPointToVoxel() { float y=0; @@ -953,6 +932,23 @@ void idle(void) if (diffclock(&last_frame, &check) > RENDER_FRAME_MSECS) { steps_per_frame++; + + //---------------------------------------------------------------- + // If mouse is being dragged, update hand movement in the avatar + //---------------------------------------------------------------- + if ( mouse_pressed == 1 ) + { + double xOffset = ( mouse_x - mouse_start_x ) / (double)WIDTH; + double yOffset = ( mouse_y - mouse_start_y ) / (double)WIDTH; + + double leftRight = xOffset; + double downUp = yOffset; + double backFront = 0.0; + + glm::dvec3 handMovement( leftRight, downUp, backFront ); + myHead.setHandMovement( handMovement ); + } + // Simulation simulateHead(1.f/FPS); simulateHand(1.f/FPS); From 87fe21f835a5854c277609a0992e57500b09843f Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 5 Apr 2013 16:21:13 -0700 Subject: [PATCH 13/33] got a basic avatar skeleton with a simpler starter user interaction for moving the right hand --- interface/src/main.cpp | 58 +++++++++++++++++++++++++++++----------- shared/src/VoxelNode.cpp | 25 +++++++---------- shared/src/VoxelNode.h | 2 +- shared/src/VoxelTree.cpp | 9 +------ voxel/src/main.cpp | 24 +++++++---------- 5 files changed, 65 insertions(+), 53 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 4ae10b94d3..0c1fb05ebf 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -147,7 +147,8 @@ glm::vec3 start_location(6.1f, 0, 1.4f); int stats_on = 0; // Whether to show onscreen text overlay with stats bool starsOn = true; // Whether to display the stars bool paintOn = false; // Whether to paint voxels as you fly around - +VoxelDetail paintingVoxel; // The voxel we're painting if we're painting +unsigned char dominantColor = 0; // The dominant color of the voxel we're painting int noise_on = 0; // Whether to add random noise float noise = 1.0; // Overall magnitude scaling for random noise levels @@ -512,23 +513,18 @@ void simulateHead(float frametime) glm::vec3 headPos = myHead.getPos(); - VoxelDetail paintingVoxel; - paintingVoxel.x = headPos.z/10.0; // voxel space x is positive z head space - paintingVoxel.y = headPos.y/-10.0; // voxel space y is negative y head space - paintingVoxel.z = headPos.x/-10.0; // voxel space z is negative x head space - paintingVoxel.s = 1.0/256; - paintingVoxel.red = 0; - paintingVoxel.green = 255; - paintingVoxel.blue = 0; + ::paintingVoxel.x = headPos.z/-10.0; // voxel space x is negative z head space + ::paintingVoxel.y = headPos.y/-10.0; // voxel space y is negative y head space + ::paintingVoxel.z = headPos.x/-10.0; // voxel space z is negative x head space unsigned char* bufferOut; int sizeOut; - if (paintingVoxel.x >= 0.0 && paintingVoxel.x <= 1.0 && - paintingVoxel.y >= 0.0 && paintingVoxel.y <= 1.0 && - paintingVoxel.z >= 0.0 && paintingVoxel.z <= 1.0) { + if (::paintingVoxel.x >= 0.0 && ::paintingVoxel.x <= 1.0 && + ::paintingVoxel.y >= 0.0 && ::paintingVoxel.y <= 1.0 && + ::paintingVoxel.z >= 0.0 && ::paintingVoxel.z <= 1.0) { - if (createVoxelEditMessage('I',0,1,&paintingVoxel,bufferOut,sizeOut)){ + if (createVoxelEditMessage('I',0,1,&::paintingVoxel,bufferOut,sizeOut)){ agentList.broadcastToAgents((char*)bufferOut, sizeOut,AgentList::AGENTS_OF_TYPE_VOXEL); delete bufferOut; } @@ -715,7 +711,12 @@ void display(void) drawtext(WIDTH-200,20, 0.10, 0, 1.0, 0, agents, 1, 1, 0); if (::paintOn) { - drawtext(WIDTH-200,40, 0.10, 0, 1.0, 0, "Paint ON", 1, 1, 0); + + char paintMessage[100]; + sprintf(paintMessage,"Painting (%.3f,%.3f,%.3f/%.3f/%d,%d,%d)", + ::paintingVoxel.x,::paintingVoxel.y,::paintingVoxel.z,::paintingVoxel.s, + (unsigned int)::paintingVoxel.red,(unsigned int)::paintingVoxel.green,(unsigned int)::paintingVoxel.blue); + drawtext(WIDTH-350,40, 0.10, 0, 1.0, 0, paintMessage, 1, 1, 0); } glPopMatrix(); @@ -749,6 +750,27 @@ void testPointToVoxel() } } +void shiftPaintingColor() +{ + // About the color of the paintbrush... first determine the dominant color + ::dominantColor = (::dominantColor+1)%3; // 0=red,1=green,2=blue + ::paintingVoxel.red = (::dominantColor==0)?randIntInRange(200,255):randIntInRange(40,100); + ::paintingVoxel.green = (::dominantColor==1)?randIntInRange(200,255):randIntInRange(40,100); + ::paintingVoxel.blue = (::dominantColor==2)?randIntInRange(200,255):randIntInRange(40,100); +} + +void setupPaintingVoxel() +{ + glm::vec3 headPos = myHead.getPos(); + + ::paintingVoxel.x = headPos.z/-10.0; // voxel space x is negative z head space + ::paintingVoxel.y = headPos.y/-10.0; // voxel space y is negative y head space + ::paintingVoxel.z = headPos.x/-10.0; // voxel space z is negative x head space + ::paintingVoxel.s = 1.0/256; + + shiftPaintingColor(); +} + void addRandomSphere(bool wantColorRandomizer) { float r = randFloatInRange(0.05,0.1); @@ -835,7 +857,13 @@ void key(unsigned char k, int x, int y) if (k == 'q') ::terminate(); if (k == '/') stats_on = !stats_on; // toggle stats if (k == '*') ::starsOn = !::starsOn; // toggle stars - if (k == '&') ::paintOn = !::paintOn; // toggle paint + if (k == '&') { + ::paintOn = !::paintOn; // toggle paint + setupPaintingVoxel(); // also randomizes colors + } + if (k == '^') { + shiftPaintingColor(); // shifts randomize color between R,G,B dominant + } if (k == 'n') { noise_on = !noise_on; // Toggle noise diff --git a/shared/src/VoxelNode.cpp b/shared/src/VoxelNode.cpp index 8b71a04893..7300af814a 100644 --- a/shared/src/VoxelNode.cpp +++ b/shared/src/VoxelNode.cpp @@ -37,25 +37,20 @@ void VoxelNode::addChildAtIndex(int childIndex) { } // will average the child colors... -void VoxelNode::setColorFromAverageOfChildren(int * colorArray) { - if (colorArray == NULL) { - colorArray = new int[4]; - memset(colorArray, 0, 4*sizeof(int)); - - for (int i = 0; i < 8; i++) { - if (children[i] != NULL && children[i]->color[3] == 1) { - for (int j = 0; j < 3; j++) { - colorArray[j] += children[i]->color[j]; - } - colorArray[3]++; - } - } - } +void VoxelNode::setColorFromAverageOfChildren() { + int colorArray[4] = {0,0,0,0}; + for (int i = 0; i < 8; i++) { + if (children[i] != NULL && children[i]->color[3] == 1) { + for (int j = 0; j < 3; j++) { + colorArray[j] += children[i]->color[j]; + } + colorArray[3]++; + } + } if (colorArray[3] > 4) { // we need at least 4 colored children to have an average color value // or if we have none we generate random values - for (int c = 0; c < 3; c++) { // set the average color value color[c] = colorArray[c] / colorArray[3]; diff --git a/shared/src/VoxelNode.h b/shared/src/VoxelNode.h index 9be1b64c70..e97689aa9b 100644 --- a/shared/src/VoxelNode.h +++ b/shared/src/VoxelNode.h @@ -17,7 +17,7 @@ public: ~VoxelNode(); void addChildAtIndex(int childIndex); - void setColorFromAverageOfChildren(int * colorArray = NULL); + void setColorFromAverageOfChildren(); void setRandomColor(int minimumBrightness); bool collapseIdenticalLeaves(); diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index a00fb48cf5..a7390dd06f 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -100,8 +100,6 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, // instantiate variable for bytes already read int bytesRead = 1; - int colorArray[4] = {}; - for (int i = 0; i < 8; i++) { // check the colors mask to see if we have a child to color in if (oneAtBit(*nodeData, i)) { @@ -115,17 +113,12 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, memcpy(destinationNode->children[i]->color, nodeData + bytesRead, 3); destinationNode->children[i]->color[3] = 1; - for (int j = 0; j < 3; j++) { - colorArray[j] += destinationNode->children[i]->color[j]; - } - bytesRead += 3; - colorArray[3]++; } } // average node's color based on color of children - destinationNode->setColorFromAverageOfChildren(colorArray); + destinationNode->setColorFromAverageOfChildren(); // give this destination node the child mask from the packet unsigned char childMask = *(nodeData + bytesRead); diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 914411db64..0a2ae0c584 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -85,8 +85,6 @@ void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { if (levelsToGo > 0) { bool createdChildren = false; - int colorArray[4] = {}; - createdChildren = false; for (int i = 0; i < 8; i++) { @@ -96,17 +94,8 @@ void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { // give this child it's octal code currentRootNode->children[i]->octalCode = childOctalCode(currentRootNode->octalCode, i); - - randomlyFillVoxelTree(levelsToGo - 1, currentRootNode->children[i]); - if (currentRootNode->children[i]->color[3] == 1) { - for (int c = 0; c < 3; c++) { - colorArray[c] += currentRootNode->children[i]->color[c]; - } - - colorArray[3]++; - } - + randomlyFillVoxelTree(levelsToGo - 1, currentRootNode->children[i]); createdChildren = true; } } @@ -117,7 +106,7 @@ void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { currentRootNode->setRandomColor(MIN_BRIGHTNESS); } else { // set the color value for this node - currentRootNode->setColorFromAverageOfChildren(colorArray); + currentRootNode->setColorFromAverageOfChildren(); } } else { // this is a leaf node, just give it a color @@ -171,7 +160,12 @@ void *distributeVoxelsToListeners(void *args) { packetCount++; totalBytesSent += voxelPacketEnd - voxelPacket; - if (agentData->rootMarkerNode->childrenVisitedMask == 255) { + // XXXBHG Hack Attack: This is temporary code to help debug an issue. + // Normally we use this break to prevent resending voxels that an agent has + // already visited. But since we might be modifying the voxel tree we might + // want to always send. This is a hack to test the behavior + bool alwaysSend = true; + if (!alwaysSend && agentData->rootMarkerNode->childrenVisitedMask == 255) { break; } } @@ -311,6 +305,8 @@ int main(int argc, const char * argv[]) pVoxelData+=voxelDataSize; atByte+=voxelDataSize; } + // after done inserting all these voxels, then reaverage colors + randomTree.reaverageVoxelColors(randomTree.rootNode); } if (packetData[0] == 'R') { From 5415543dcd1e6654deb6b9d5c8b82aab6661a16a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Apr 2013 12:03:46 -0700 Subject: [PATCH 14/33] adding Z command to voxel server and interface, Z command allows sending "erase all" and "add scene" commands --- interface/src/VoxelSystem.cpp | 23 ++++++++++++++ interface/src/main.cpp | 2 +- shared/src/VoxelTree.cpp | 10 +++++++ shared/src/VoxelTree.h | 2 ++ tools/sendvoxels.php | 26 ++++++++++++++-- voxel/src/main.cpp | 56 ++++++++++++++++++++++++++++++++++- 6 files changed, 115 insertions(+), 4 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 68914e2d6b..0f4d7bf7ca 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -97,6 +97,29 @@ void VoxelSystem::parseData(void *data, int size) { // ask the tree to read the "remove" bitstream tree->processRemoveVoxelBitstream((unsigned char*)data,size); break; + case 'Z': + + // 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 + // messages differently + char* packetData =(char*)data; + char* command = &packetData[1]; // start of the command + int commandLength = strlen(command); // commands are null terminated strings + int totalLength = 1+commandLength+1; + + printf("got Z message len(%d)= %s\n",size,command); + + while (totalLength <= size) { + if (0==strcmp(command,(char*)"erase all")) { + printf("got Z message == erase all\n"); + tree->eraseAllVoxels(); + } + if (0==strcmp(command,(char*)"add scene")) { + printf("got Z message == add scene - NOT SUPPORTED ON INTERFACE\n"); + } + totalLength += commandLength+1; + } + break; } setupNewVoxelsForDrawing(); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 9f005255cf..bd62bbf35d 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -901,7 +901,7 @@ void *networkReceive(void *args) if (incomingPacket[0] == 't') { // Pass everything but transmitter data to the agent list myHead.hand->processTransmitterData(incomingPacket, bytesReceived); - } else if (incomingPacket[0] == 'V' || incomingPacket[0] == 'R') { + } else if (incomingPacket[0] == 'V' || incomingPacket[0] == 'R' || incomingPacket[0] == 'Z') { voxels.parseData(incomingPacket, bytesReceived); } else { agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived); diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index a7390dd06f..7536bf9042 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -202,6 +202,16 @@ void VoxelTree::deleteVoxelCodeFromTree(unsigned char *codeBuffer) { } } +void VoxelTree::eraseAllVoxels() { + + // XXXBHG Hack attack - is there a better way to erase the voxel tree? + + delete rootNode; // this will recurse and delete all children + rootNode = new VoxelNode(); + rootNode->octalCode = new unsigned char[1]; + *rootNode->octalCode = 0; +} + void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer) { VoxelNode *lastCreatedNode = nodeForOctalCode(rootNode, codeColorBuffer, NULL); diff --git a/shared/src/VoxelTree.h b/shared/src/VoxelTree.h index 8a998a73bf..59f8e47eda 100644 --- a/shared/src/VoxelTree.h +++ b/shared/src/VoxelTree.h @@ -27,6 +27,8 @@ public: VoxelNode *rootNode; int leavesWrittenToBitstream; + void eraseAllVoxels(); + void processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes); void readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes); void readCodeColorBufferToTree(unsigned char *codeColorBuffer); diff --git a/tools/sendvoxels.php b/tools/sendvoxels.php index 69f0f798fc..b71c50c8df 100644 --- a/tools/sendvoxels.php +++ b/tools/sendvoxels.php @@ -38,13 +38,31 @@ function send_voxels($inputFileName,$server,$port,$command) { socket_close($socketHandle); } +function send_zcommand($server,$port,$command) { + $socketHandle = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + $serverIP = $server; + $serverSendPort = $port; + + // [1:'Z'][2:command][0]... + $netData = pack("c",ord('Z')); + $netData .= $command; + $netData .= pack("c",0); + + $packetSize = 2+strlen($command); + echo "sending packet server=$serverIP port=$serverSendPort size=$packetSize \n"; + $result = socket_sendto($socketHandle, $netData, $packetSize, 0, $serverIP, $serverSendPort); + socket_close($socketHandle); +} + function testmode_send_voxels($server,$port) { echo "psych! test mode not implemented!\n"; } -$options = getopt("i:s:p:c:",array('testmode')); +$options = getopt("i:s:p:c:",array('testmode','zcommand:')); +//print_r($options); +//break; -if (empty($options['i']) || empty($options['i'])) { +if (empty($options['i']) && empty($options['zcommand'])) { echo "USAGE: sendvoxels.php -i 'inputFileName' -s [serverip] -p [port] -c [I|R] \n"; } else { $filename = $options['i']; @@ -54,6 +72,7 @@ if (empty($options['i']) || empty($options['i'])) { switch($command) { case 'I': case 'R': + case 'Z': //$command is good break; default: @@ -63,6 +82,9 @@ if (empty($options['i']) || empty($options['i'])) { if ($options['testmode']) { echo "TEST MODE Sending Voxels server:$server port:$port \n"; testmode_send_voxels($server,$port); + } else if ($options['zcommand'] && $command=='Z') { + echo "Sending Z command to server:$server port:$port \n"; + send_zcommand($server,$port,$options['zcommand']); } else { echo "Sending Voxels file:$filename server:$server port:$port command:$command \n"; send_voxels($filename,$server,$port,$command); diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 0a2ae0c584..c3b955b22e 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -114,6 +114,33 @@ void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { } } +void eraseVoxelTreeAndCleanupAgentVisitData() { + + // As our tree to erase all it's voxels + ::randomTree.eraseAllVoxels(); + + // enumerate the agents clean up their marker nodes + for (int i = 0; i < agentList.getAgents().size(); i++) { + + //printf("eraseVoxelTreeAndCleanupAgentVisitData() agent[%d]\n",i); + + Agent *thisAgent = (Agent *)&::agentList.getAgents()[i]; + VoxelAgentData *agentData = (VoxelAgentData *)(thisAgent->getLinkedData()); + + // lock this agent's delete mutex so that the delete thread doesn't + // kill the agent while we are working with it + pthread_mutex_lock(&thisAgent->deleteMutex); + + // clean up the agent visit data + delete agentData->rootMarkerNode; + agentData->rootMarkerNode = new MarkerNode(); + + // unlock the delete mutex so the other thread can + // kill the agent if it has dissapeared + pthread_mutex_unlock(&thisAgent->deleteMutex); + } +} + void *distributeVoxelsToListeners(void *args) { timeval lastSendTime; @@ -133,7 +160,7 @@ void *distributeVoxelsToListeners(void *args) { // enumerate the agents to send 3 packets to each for (int i = 0; i < agentList.getAgents().size(); i++) { - + Agent *thisAgent = (Agent *)&agentList.getAgents()[i]; VoxelAgentData *agentData = (VoxelAgentData *)(thisAgent->getLinkedData()); @@ -319,6 +346,33 @@ int main(int argc, const char * argv[]) agentList.broadcastToAgents(packetData,receivedBytes,AgentList::AGENTS_OF_TYPE_HEAD); } + if (packetData[0] == 'Z') { + + // the Z command is a special command that allows the sender to send the voxel server high level semantic + // requests, like erase all, or add sphere scene + char* command = &packetData[1]; // start of the command + int commandLength = strlen(command); // commands are null terminated strings + int totalLength = 1+commandLength+1; + + printf("got Z message len(%ld)= %s\n",receivedBytes,command); + + while (totalLength <= receivedBytes) { + if (0==strcmp(command,(char*)"erase all")) { + printf("got Z message == erase all\n"); + + eraseVoxelTreeAndCleanupAgentVisitData(); + } + if (0==strcmp(command,(char*)"add scene")) { + printf("got Z message == add scene\n"); + addSphereScene(&randomTree,false); + } + totalLength += commandLength+1; + } + + // Now send this to the connected agents so they can also process these messages + printf("rebroadcasting Z message to connected agents... agentList.broadcastToAgents()\n"); + agentList.broadcastToAgents(packetData,receivedBytes,AgentList::AGENTS_OF_TYPE_HEAD); + } if (packetData[0] == 'H') { if (agentList.addOrUpdateAgent(&agentPublicAddress, &agentPublicAddress, From d3fd5d1a757658835dcb0b0f9732c31e455ba6ac Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 7 Apr 2013 12:45:46 -0700 Subject: [PATCH 15/33] added keyboard commands for erase all and add scene --- interface/src/main.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index bd62bbf35d..6ded0215ab 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -712,6 +712,20 @@ void testPointToVoxel() } } +void sendVoxelServerEraseAll() { + char message[100]; + sprintf(message,"%c%s",'Z',"erase all"); + int messageSize = strlen(message)+1; + ::agentList.broadcastToAgents(message, messageSize,AgentList::AGENTS_OF_TYPE_VOXEL); +} + +void sendVoxelServerAddScene() { + char message[100]; + sprintf(message,"%c%s",'Z',"add scene"); + int messageSize = strlen(message)+1; + ::agentList.broadcastToAgents(message, messageSize,AgentList::AGENTS_OF_TYPE_VOXEL); +} + void shiftPaintingColor() { // About the color of the paintbrush... first determine the dominant color @@ -821,11 +835,11 @@ void key(unsigned char k, int x, int y) if (k == '*') ::starsOn = !::starsOn; // toggle stars if (k == '&') { ::paintOn = !::paintOn; // toggle paint - setupPaintingVoxel(); // also randomizes colors - } - if (k == '^') { - shiftPaintingColor(); // shifts randomize color between R,G,B dominant + ::setupPaintingVoxel(); // also randomizes colors } + if (k == '^') ::shiftPaintingColor(); // shifts randomize color between R,G,B dominant + if (k == '-') ::sendVoxelServerEraseAll(); // sends erase all command to voxel server + if (k == '%') ::sendVoxelServerAddScene(); // sends add scene command to voxel server if (k == 'n') { noise_on = !noise_on; // Toggle noise From aa40fd96d4e417be58393eaef3cdefa1e83867fc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 7 Apr 2013 12:49:15 -0700 Subject: [PATCH 16/33] added -/% to menu text --- interface/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 6ded0215ab..7ae2fc2a10 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -255,7 +255,7 @@ void display_stats(void) char legend[] = "/ - toggle this display, Q - exit, H - show head, M - show hand, T - test audio"; drawtext(10, 15, 0.10f, 0, 1.0, 0, legend); - char legend2[] = "* - toggle stars, & - toggle paint mode"; + char legend2[] = "* - toggle stars, & - toggle paint mode, '-' - send erase all, '%' - send add scene"; drawtext(10, 32, 0.10f, 0, 1.0, 0, legend2); glm::vec3 headPos = myHead.getPos(); From dbd9688f1f78a23d0443ee9fc4ec5a1a9963d69a Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 8 Apr 2013 09:34:19 -0700 Subject: [PATCH 17/33] Turned off default for star field rendering until we find/fix the rendering bug --- interface/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 7ae2fc2a10..4e09fb127c 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -143,7 +143,7 @@ float renderPitchRate = 0.f; glm::vec3 start_location(6.1f, 0, 1.4f); int stats_on = 0; // Whether to show onscreen text overlay with stats -bool starsOn = true; // Whether to display the stars +bool starsOn = false; // Whether to display the stars bool paintOn = false; // Whether to paint voxels as you fly around VoxelDetail paintingVoxel; // The voxel we're painting if we're painting unsigned char dominantColor = 0; // The dominant color of the voxel we're painting From aee27bfc168d7ba2c2e47e6d987c5651de4fd622 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Apr 2013 11:18:07 -0700 Subject: [PATCH 18/33] Hmmm, when painting, X and Z are not flipped? I'm totally confused, but now but LOD and painting seems to work. --- interface/src/main.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 7ae2fc2a10..ecb7d3a152 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -500,9 +500,10 @@ void simulateHead(float frametime) glm::vec3 headPos = myHead.getPos(); - ::paintingVoxel.x = headPos.z/-10.0; // voxel space x is negative z head space - ::paintingVoxel.y = headPos.y/-10.0; // voxel space y is negative y head space - ::paintingVoxel.z = headPos.x/-10.0; // voxel space z is negative x head space + // For some reason, we don't want to flip X and Z here. + ::paintingVoxel.x = headPos.x/-10.0; + ::paintingVoxel.y = headPos.y/-10.0; + ::paintingVoxel.z = headPos.z/-10.0; unsigned char* bufferOut; int sizeOut; From 53cfd0ecdd18e414f9493fb867c6b2177c05a6fc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Apr 2013 17:03:22 -0700 Subject: [PATCH 19/33] adding CounterStats class and support for showing running average stats on voxels recieved, created, and colored in client --- interface/src/VoxelSystem.cpp | 24 ++++++++++ interface/src/VoxelSystem.h | 8 ++++ interface/src/main.cpp | 52 +++++++++++++++----- shared/src/CounterStats.cpp | 90 +++++++++++++++++++++++++++++++++++ shared/src/CounterStats.h | 79 ++++++++++++++++++++++++++++++ shared/src/VoxelTree.cpp | 22 +++++++++ shared/src/VoxelTree.h | 12 +++++ 7 files changed, 275 insertions(+), 12 deletions(-) create mode 100644 shared/src/CounterStats.cpp create mode 100644 shared/src/CounterStats.h diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 0f4d7bf7ca..f3eb8ec957 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -82,6 +82,30 @@ void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bo setupNewVoxelsForDrawing(); } +long int VoxelSystem::getVoxelsCreated() { + return tree->voxelsCreated; +} + +long int VoxelSystem::getVoxelsCreatedRunningAverage() { + return tree->voxelsCreatedStats.getRunningAverage(); +} + +long int VoxelSystem::getVoxelsColored() { + return tree->voxelsColored; +} + +long int VoxelSystem::getVoxelsColoredRunningAverage() { + return tree->voxelsColoredStats.getRunningAverage(); +} + +long int VoxelSystem::getVoxelsBytesRead() { + return tree->voxelsBytesRead; +} + +long int VoxelSystem::getVoxelsBytesReadRunningAverage() { + return tree->voxelsBytesReadStats.getRunningAverage(); +} + void VoxelSystem::parseData(void *data, int size) { diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index c35e2bd5b8..f49b57d612 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -37,6 +37,14 @@ public: void setViewerHead(Head *newViewerHead); void loadVoxelsFile(const char* fileName,bool wantColorRandomizer); void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer); + + long int getVoxelsCreated(); + long int getVoxelsColored(); + long int getVoxelsBytesRead(); + long int getVoxelsCreatedRunningAverage(); + long int getVoxelsColoredRunningAverage(); + long int getVoxelsBytesReadRunningAverage(); + private: int voxelsRendered; Head *viewerHead; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 8c083fe4bc..b290ab5bac 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -147,6 +147,7 @@ bool starsOn = false; // Whether to display the stars bool paintOn = false; // Whether to paint voxels as you fly around VoxelDetail paintingVoxel; // The voxel we're painting if we're painting unsigned char dominantColor = 0; // The dominant color of the voxel we're painting +bool perfStatsOn = false; // Do we want to display perfStats? int noise_on = 0; // Whether to add random noise float noise = 1.0; // Overall magnitude scaling for random noise levels @@ -282,18 +283,45 @@ void display_stats(void) voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered(); drawtext(10,70,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); - // Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups - char** perfStatLinesArray = new char*[PerfStat::getGroupCount()+1]; - int lines = PerfStat::DumpStats(perfStatLinesArray); - int atZ = 150; // arbitrary place on screen that looks good - for (int line=0; line < lines; line++) { - drawtext(10,atZ,0.10f, 0, 1.0, 0, perfStatLinesArray[line]); - delete perfStatLinesArray[line]; // we're responsible for cleanup - perfStatLinesArray[line]=NULL; - atZ+=20; // height of a line - } - delete []perfStatLinesArray; // we're responsible for cleanup - + voxelStats.str(""); + voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() << " (" << voxels.getVoxelsCreatedRunningAverage() + << "/sec in last "<< COUNTETSTATS_TIME_FRAME << " seconds) "; + drawtext(10,250,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + + voxelStats.str(""); + voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() << " (" << voxels.getVoxelsColoredRunningAverage() + << "/sec in last "<< COUNTETSTATS_TIME_FRAME << " seconds) "; + drawtext(10,270,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + + voxelStats.str(""); + voxelStats << "Voxels Bytes Read: " << voxels.getVoxelsBytesRead() + << " (" << voxels.getVoxelsBytesReadRunningAverage() << "/sec in last "<< COUNTETSTATS_TIME_FRAME << " seconds) "; + drawtext(10,290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + + voxelStats.str(""); + long int voxelsBytesPerColored = voxels.getVoxelsColored() ? voxels.getVoxelsBytesRead()/voxels.getVoxelsColored() : 0; + long int voxelsBytesPerColoredAvg = voxels.getVoxelsColoredRunningAverage() ? + voxels.getVoxelsBytesReadRunningAverage()/voxels.getVoxelsColoredRunningAverage() : 0; + + voxelStats << "Voxels Bytes per Colored: " << voxelsBytesPerColored + << " (" << voxelsBytesPerColoredAvg << "/sec in last "<< COUNTETSTATS_TIME_FRAME << " seconds) "; + drawtext(10,310,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + + + if (::perfStatsOn) { + // Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups + char** perfStatLinesArray = new char*[PerfStat::getGroupCount()+1]; + int lines = PerfStat::DumpStats(perfStatLinesArray); + int atZ = 150; // arbitrary place on screen that looks good + for (int line=0; line < lines; line++) { + drawtext(10,atZ,0.10f, 0, 1.0, 0, perfStatLinesArray[line]); + delete perfStatLinesArray[line]; // we're responsible for cleanup + perfStatLinesArray[line]=NULL; + atZ+=20; // height of a line + } + delete []perfStatLinesArray; // we're responsible for cleanup + } + /* std::stringstream angles; angles << "render_yaw: " << myHead.getRenderYaw() << ", Yaw: " << myHead.getYaw(); diff --git a/shared/src/CounterStats.cpp b/shared/src/CounterStats.cpp new file mode 100644 index 0000000000..3b56fada04 --- /dev/null +++ b/shared/src/CounterStats.cpp @@ -0,0 +1,90 @@ +// +// CounterStats.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 2013/04/08. +// +// Poor-man's counter stats collector class. Useful for collecting running averages +// and other stats for countable things. +// +// + +#include "CounterStats.h" +#include +#include +#include +#include + + +//private: +// long int currentCount; +// long int currentDelta; +// double currentTime; +// double totalTime; +// +// long int countSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; +// long int deltaSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; +// double timeSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; +// int sampleAt; + + +void CounterStatHistory::recordSample(long int thisCount) { + timeval now; + gettimeofday(&now,NULL); + double nowSeconds = (now.tv_usec/1000000.0)+(now.tv_sec); + this->recordSample(nowSeconds,thisCount); +} + +void CounterStatHistory::recordSample(double thisTime, long int thisCount) { + + // how much did we change since last sample? + long int thisDelta = thisCount - this->lastCount; + double elapsed = thisTime - this->lastTime; + + // record the latest values + this->currentCount = thisCount; + this->currentTime = thisTime; + this->currentDelta = thisDelta; + + //printf("CounterStatHistory[%s]::recordSample(thisTime %lf, thisCount= %ld)\n",this->name.c_str(),thisTime,thisCount); + + // if more than 1/10th of a second has passed, then record + // things in our rolling history + if (elapsed > 0.1) { + this->lastTime = thisTime; + this->lastCount = thisCount; + + // record it in our history... + this->sampleAt = (this->sampleAt+1)%COUNTETSTATS_SAMPLES_TO_KEEP; + if (this->sampleCountsampleCount++; + } + this->countSamples[this->sampleAt]=thisCount; + this->timeSamples[this->sampleAt]=thisTime; + this->deltaSamples[this->sampleAt]=thisDelta; + + //printf("CounterStatHistory[%s]::recordSample() ACTUALLY RECORDING IT sampleAt=%d thisTime %lf, thisCount= %ld)\n",this->name.c_str(),this->sampleAt,thisTime,thisCount); + + } + +} + +long int CounterStatHistory::getRunningAverage() { + // before we calculate our running average, always "reset" the current count, with the current time + // this will flush out old data, if we haven't been adding any new data. + this->recordSample(this->currentCount); + + long int runningTotal = 0; + double minTime = this->timeSamples[0]; + double maxTime = this->timeSamples[0]; + + for (int i =0; i < this->sampleCount; i++) { + minTime = std::min(minTime,this->timeSamples[i]); + maxTime = std::max(maxTime,this->timeSamples[i]); + runningTotal += this->deltaSamples[i]; + } + + double elapsedTime = maxTime-minTime; + long int runningAverage = runningTotal/elapsedTime; + return runningAverage; +} diff --git a/shared/src/CounterStats.h b/shared/src/CounterStats.h new file mode 100644 index 0000000000..a5a2443388 --- /dev/null +++ b/shared/src/CounterStats.h @@ -0,0 +1,79 @@ +// +// CounterStats.h +// hifi +// +// Created by Brad Hefta-Gaub on 3/29/13. +// +// Poor-man's counter stats collector class. Useful for collecting running averages +// and other stats for countable things. +// +// + +#ifndef __hifi__CounterStats__ +#define __hifi__CounterStats__ + +#include +#include +#include + +// TIME_FRAME should be SAMPLES_TO_KEEP * TIME_BETWEEN_SAMPLES +#define COUNTETSTATS_SAMPLES_TO_KEEP 50 +#define COUNTETSTATS_TIME_BETWEEN_SAMPLES 0.1 +#define COUNTETSTATS_TIME_FRAME (COUNTETSTATS_SAMPLES_TO_KEEP*COUNTETSTATS_TIME_BETWEEN_SAMPLES) + +class CounterStatHistory { + +private: + long int currentCount; + long int currentDelta; + double currentTime; + + long int lastCount; + double lastTime; + + double totalTime; + + long int countSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; + long int deltaSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; + double timeSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; + int sampleAt; + int sampleCount; + +public: + std::string name; + + CounterStatHistory(std::string myName): + currentCount(0), currentDelta(0),currentTime(0.0), + lastCount(0),lastTime(0.0), + totalTime(0.0), + sampleAt(-1),sampleCount(0), name(myName) {}; + + CounterStatHistory(): + currentCount(0), currentDelta(0),currentTime(0.0), + lastCount(0),lastTime(0.0), + totalTime(0.0), + sampleAt(-1),sampleCount(0) {}; + + CounterStatHistory(std::string myName, double initialTime, long int initialCount) : + currentCount(initialCount), currentDelta(0), currentTime(initialTime), + lastCount(initialCount),lastTime(initialTime), + totalTime(initialTime), + sampleAt(-1), sampleCount(0), name(myName) {}; + + void recordSample(long int thisCount); + void recordSample(double thisTime, long int thisCount); + long int getRunningAverage(); + + long int getAverage() { + return currentCount/totalTime; + }; + + double getTotalTime() { + return totalTime; + }; + long int getCount() { + return currentCount; + }; +}; + +#endif /* defined(__hifi__CounterStat__) */ diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index 7536bf9042..dfda1de2b5 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -10,6 +10,7 @@ #include #include #include "SharedUtil.h" +#include "CounterStats.h" #include "OctalCode.h" #include "VoxelTree.h" #include // to load voxels from file @@ -44,6 +45,15 @@ VoxelTree::VoxelTree() { rootNode = new VoxelNode(); rootNode->octalCode = new unsigned char[1]; *rootNode->octalCode = 0; + + // Some stats tracking + this->voxelsCreated = 0; // when a voxel is created in the tree (object new'd) + this->voxelsColored = 0; // when a voxel is colored/set in the tree (object may have already existed) + this->voxelsBytesRead = 0; + voxelsCreatedStats.name = "voxelsCreated"; + voxelsColoredStats.name = "voxelsColored"; + voxelsBytesReadStats.name = "voxelsBytesRead"; + } VoxelTree::~VoxelTree() { @@ -94,6 +104,9 @@ VoxelNode * VoxelTree::createMissingNode(VoxelNode *lastParentNode, unsigned cha } } +// BHG Notes: We appear to call this function for every Voxel Node getting created. +// This is recursive in nature. So, for example, if we are given an octal code for +// a 1/256th size voxel, we appear to call this function 8 times. Maybe?? int VoxelTree::readNodeData(VoxelNode *destinationNode, unsigned char * nodeData, int bytesLeftToRead) { @@ -107,11 +120,15 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, // create the child if it doesn't exist if (destinationNode->children[i] == NULL) { destinationNode->addChildAtIndex(i); + this->voxelsCreated++; + this->voxelsCreatedStats.recordSample(this->voxelsCreated); } // pull the color for this child memcpy(destinationNode->children[i]->color, nodeData + bytesRead, 3); destinationNode->children[i]->color[3] = 1; + this->voxelsColored++; + this->voxelsColoredStats.recordSample(this->voxelsColored); bytesRead += 3; } @@ -133,6 +150,8 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, if (destinationNode->children[childIndex] == NULL) { // add a child at that index, if it doesn't exist destinationNode->addChildAtIndex(childIndex); + this->voxelsCreated++; + this->voxelsCreatedStats.recordSample(this->voxelsCreated); } // tell the child to read the subsequent data @@ -158,6 +177,9 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeByt int octalCodeBytes = bytesRequiredForCodeLength(*bitstream); readNodeData(bitstreamRootNode, bitstream + octalCodeBytes, bufferSizeBytes - octalCodeBytes); + + this->voxelsBytesRead += bufferSizeBytes; + this->voxelsBytesReadStats.recordSample(this->voxelsBytesRead); } // Note: uses the codeColorBuffer format, but the color's are ignored, because diff --git a/shared/src/VoxelTree.h b/shared/src/VoxelTree.h index 59f8e47eda..486d560be8 100644 --- a/shared/src/VoxelTree.h +++ b/shared/src/VoxelTree.h @@ -9,6 +9,8 @@ #ifndef __hifi__VoxelTree__ #define __hifi__VoxelTree__ +#include "CounterStats.h" + #include "VoxelNode.h" #include "MarkerNode.h" @@ -20,7 +22,17 @@ class VoxelTree { VoxelNode * nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode); VoxelNode * createMissingNode(VoxelNode *lastParentNode, unsigned char *deepestCodeToCreate); int readNodeData(VoxelNode *destinationNode, unsigned char * nodeData, int bufferSizeBytes); + + public: + long int voxelsCreated; + long int voxelsColored; + long int voxelsBytesRead; + + CounterStatHistory voxelsCreatedStats; + CounterStatHistory voxelsColoredStats; + CounterStatHistory voxelsBytesReadStats; + VoxelTree(); ~VoxelTree(); From 7f1af81cf902da14881d0c2e2b714aa66bbc10bd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Apr 2013 17:08:14 -0700 Subject: [PATCH 20/33] fixed compiler error for strict compilers --- shared/src/CounterStats.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shared/src/CounterStats.h b/shared/src/CounterStats.h index a5a2443388..29481461b6 100644 --- a/shared/src/CounterStats.h +++ b/shared/src/CounterStats.h @@ -33,9 +33,9 @@ private: double totalTime; - long int countSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; - long int deltaSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; - double timeSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; + long int countSamples[COUNTETSTATS_SAMPLES_TO_KEEP]; + long int deltaSamples[COUNTETSTATS_SAMPLES_TO_KEEP]; + double timeSamples[COUNTETSTATS_SAMPLES_TO_KEEP]; int sampleAt; int sampleCount; From 69fa462151bcbf43b87df7d7523f1ca508aa7c70 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 8 Apr 2013 18:10:20 -0700 Subject: [PATCH 21/33] don't steal ping replies from AgentList --- interface/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index b290ab5bac..4aa93884a1 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -944,7 +944,7 @@ void *networkReceive(void *args) if (incomingPacket[0] == 't') { // Pass everything but transmitter data to the agent list myHead.hand->processTransmitterData(incomingPacket, bytesReceived); - } else if (incomingPacket[0] == 'V' || incomingPacket[0] == 'R' || incomingPacket[0] == 'Z') { + } else if (incomingPacket[0] == 'V' || incomingPacket[0] == 'Z') { voxels.parseData(incomingPacket, bytesReceived); } else { agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived); From d462bff51267fecd7f6109623336113111d799e3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 8 Apr 2013 18:22:21 -0700 Subject: [PATCH 22/33] add a PacketHeaders header file and sub a couple as an example --- shared/src/AgentList.cpp | 6 ++++-- shared/src/PacketHeaders.h | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 shared/src/PacketHeaders.h diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index 9aa6422543..913dced62f 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -11,6 +11,7 @@ #include #include #include "AgentList.h" +#include "PacketHeaders.h" #include "SharedUtil.h" #ifdef _WIN32 @@ -225,10 +226,11 @@ void AgentList::broadcastToAgents(char *broadcastData, size_t dataBytes,const ch } void AgentList::pingAgents() { - char payload[] = "P"; + char payload[1]; + *payload = PACKET_HEADER_PING; for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { - if (agent->getType() == 'I') { + if (agent->getType() == PACKET_HEADER_INTERFACE) { if (agent->getActiveSocket() != NULL) { // we know which socket is good for this agent, send there agentSocket.send(agent->getActiveSocket(), payload, 1); diff --git a/shared/src/PacketHeaders.h b/shared/src/PacketHeaders.h new file mode 100644 index 0000000000..bbb3d29fe4 --- /dev/null +++ b/shared/src/PacketHeaders.h @@ -0,0 +1,15 @@ +// +// PacketHeaders.h +// hifi +// +// Created by Stephen Birarda on 4/8/13. +// +// + +#ifndef hifi_PacketHeaders_h +#define hifi_PacketHeaders_h + +const char PACKET_HEADER_INTERFACE = 'I'; +const char PACKET_HEADER_PING = 'P'; + +#endif From 2031d26ffed9a211647c5fab48da5cc47300449e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 8 Apr 2013 18:23:01 -0700 Subject: [PATCH 23/33] fix incorrect agent type replacement --- shared/src/AgentList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index 913dced62f..83d099ee72 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -230,7 +230,7 @@ void AgentList::pingAgents() { *payload = PACKET_HEADER_PING; for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { - if (agent->getType() == PACKET_HEADER_INTERFACE) { + if (agent->getType() == 'I') { if (agent->getActiveSocket() != NULL) { // we know which socket is good for this agent, send there agentSocket.send(agent->getActiveSocket(), payload, 1); From b636536ab715ce48762c27884c11ff3808956f01 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 8 Apr 2013 18:23:57 -0700 Subject: [PATCH 24/33] remove interface define in PacketHeader.h --- shared/src/PacketHeaders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/src/PacketHeaders.h b/shared/src/PacketHeaders.h index bbb3d29fe4..16e57f60ea 100644 --- a/shared/src/PacketHeaders.h +++ b/shared/src/PacketHeaders.h @@ -9,7 +9,7 @@ #ifndef hifi_PacketHeaders_h #define hifi_PacketHeaders_h -const char PACKET_HEADER_INTERFACE = 'I'; +const char PACKET_HEADER_DOMAIN = 'D'; const char PACKET_HEADER_PING = 'P'; #endif From f018d8e323f0e50295303b3447c54e7482fba77a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 8 Apr 2013 18:24:47 -0700 Subject: [PATCH 25/33] replace ping header char in processAgentData switch case --- shared/src/AgentList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index 83d099ee72..20d230fb67 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -79,7 +79,7 @@ void AgentList::processAgentData(sockaddr *senderAddress, void *packetData, size updateAgentWithData(senderAddress, packetData, dataBytes); break; } - case 'P': { + case PACKET_HEADER_PING: { // ping from another agent //std::cout << "Got ping from " << inet_ntoa(((sockaddr_in *)senderAddress)->sin_addr) << "\n"; char reply[] = "R"; From 6f8808e565d328f644a985ea28e7fa7937041841 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 8 Apr 2013 18:25:21 -0700 Subject: [PATCH 26/33] add the ping reply header --- shared/src/AgentList.cpp | 2 +- shared/src/PacketHeaders.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index 20d230fb67..729a88ca6d 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -86,7 +86,7 @@ void AgentList::processAgentData(sockaddr *senderAddress, void *packetData, size agentSocket.send(senderAddress, reply, 1); break; } - case 'R': { + case PACKET_HEADER_PING_REPLY: { // ping reply from another agent //std::cout << "Got ping reply from " << inet_ntoa(((sockaddr_in *)senderAddress)->sin_addr) << "\n"; handlePingReply(senderAddress); diff --git a/shared/src/PacketHeaders.h b/shared/src/PacketHeaders.h index 16e57f60ea..7c76c5d7f9 100644 --- a/shared/src/PacketHeaders.h +++ b/shared/src/PacketHeaders.h @@ -11,5 +11,6 @@ const char PACKET_HEADER_DOMAIN = 'D'; const char PACKET_HEADER_PING = 'P'; +const char PACKET_HEADER_PING_REPLY = 'R'; #endif From cd1533dc7c02407cf5c335e5daecd8d3c12051d9 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Mon, 8 Apr 2013 18:46:00 -0700 Subject: [PATCH 27/33] Lots of small changes in the head (evolving into "avatar") to include skeleton. Also, added camera behaviors for navigation --- interface/src/Head.cpp | 520 ++++++++++++++++++++++++++++------------- interface/src/Head.h | 44 ++-- interface/src/main.cpp | 52 ++++- 3 files changed, 425 insertions(+), 191 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 91cb91bcec..efd07bf8d6 100755 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -3,6 +3,7 @@ // interface // // Created by Philip Rosedale on 9/11/12. +// adapted by Jeffrey Ventrella, starting on April 2, 2013 // Copyright (c) 2012 Physical, Inc.. All rights reserved. // @@ -45,9 +46,9 @@ Head::Head() { initializeAvatar(); - position = glm::vec3(0,0,0); - velocity = glm::vec3(0,0,0); - thrust = glm::vec3(0,0,0); + position = glm::vec3(0,0,0); + velocity = glm::vec3(0,0,0); + thrust = glm::vec3(0,0,0); for (int i = 0; i < MAX_DRIVE_KEYS; i++) driveKeys[i] = false; @@ -83,7 +84,7 @@ Head::Head() browAudioLift = 0.0; noise = 0; - handOffset.clear(); + handOffset = glm::vec3( 0.0, 0.0, 0.0 ); sphere = NULL; @@ -194,7 +195,6 @@ void Head::reset() void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int head_mirror, 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(PITCH_RATE); @@ -241,7 +241,7 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea //--------------------------------------------------- void Head::setAvatarPosition( double x, double y, double z ) { - avatar.position.setXYZ( x, y, z ); + avatar.position = glm::dvec3( x, y, z ); } @@ -276,48 +276,159 @@ void Head::setLeanSideways(float dist){ //--------------------------------------------------- void Head::simulate(float deltaTime) { - simulateAvatar( deltaTime ); + updateAvatarSkeleton(); + + /* + glm::vec3 forward + ( + -sin( avatar.yaw * PI_OVER_180 ), + sin( avatar.pitch * PI_OVER_180 ), + cos( avatar.roll * PI_OVER_180 ) + ); + */ + + /* glm::vec3 forward(-sinf(getRenderYaw()*PI/180), sinf(getRenderPitch()*PI/180), cosf(getRenderYaw()*PI/180)); thrust = glm::vec3(0); + */ + const float THRUST_MAG = 10.0; - const float THRUST_LATERAL_MAG = 10.0; - const float THRUST_VERTICAL_MAG = 10.0; - if (driveKeys[FWD]) { - thrust += THRUST_MAG*forward; + /* + const float THRUST_LATERAL_MAG = 10.0; + const float THRUST_VERTICAL_MAG = 10.0; + */ + + + avatar.thrust = glm::dvec3( 0.0, 0.0, 0.0 ); + + if (driveKeys[FWD]) + { + //position.x += avatar.orientation.getFront().getX() * 0.01; + //position.y += avatar.orientation.getFront().getY() * 0.01; + //position.z -= avatar.orientation.getFront().getZ() * 0.01; + + avatar.thrust.x += avatar.orientation.getFront().getX() * THRUST_MAG; + avatar.thrust.y += avatar.orientation.getFront().getY() * THRUST_MAG; + avatar.thrust.z -= avatar.orientation.getFront().getZ() * THRUST_MAG; + + //thrust += THRUST_MAG*forward; } - if (driveKeys[BACK]) { - thrust += -THRUST_MAG*forward; - } - if (driveKeys[RIGHT]) { - thrust.x += forward.z*-THRUST_LATERAL_MAG; - thrust.z += forward.x*THRUST_LATERAL_MAG; - } - if (driveKeys[LEFT]) { - thrust.x += forward.z*THRUST_LATERAL_MAG; - thrust.z += forward.x*-THRUST_LATERAL_MAG; - } - if (driveKeys[UP]) { - thrust.y += -THRUST_VERTICAL_MAG; - } - if (driveKeys[DOWN]) { - thrust.y += THRUST_VERTICAL_MAG; + + if (driveKeys[BACK]) + { + //position.x -= avatar.orientation.getFront().getX() * 0.01; + //position.y -= avatar.orientation.getFront().getY() * 0.01; + //position.z += avatar.orientation.getFront().getZ() * 0.01; + + avatar.thrust.x -= avatar.orientation.getFront().getX() * THRUST_MAG; + avatar.thrust.y -= avatar.orientation.getFront().getY() * THRUST_MAG; + avatar.thrust.z += avatar.orientation.getFront().getZ() * THRUST_MAG; + + //thrust += -THRUST_MAG*forward; } + + if (driveKeys[RIGHT]) + { + //position.x += avatar.orientation.getRight().getX() * 0.01; + //position.y += avatar.orientation.getRight().getY() * 0.01; + //position.z -= avatar.orientation.getRight().getZ() * 0.01; + + avatar.thrust.x += avatar.orientation.getRight().getX() * THRUST_MAG; + avatar.thrust.y += avatar.orientation.getRight().getY() * THRUST_MAG; + avatar.thrust.z -= avatar.orientation.getRight().getZ() * THRUST_MAG; + + //thrust.x += forward.z*-THRUST_LATERAL_MAG; + //thrust.z += forward.x*THRUST_LATERAL_MAG; + } + if (driveKeys[LEFT]) + { + //position.x -= avatar.orientation.getRight().getX() * 0.01; + //position.y -= avatar.orientation.getRight().getY() * 0.01; + //position.z += avatar.orientation.getRight().getZ() * 0.01; + + avatar.thrust.x -= avatar.orientation.getRight().getX() * THRUST_MAG; + avatar.thrust.y -= avatar.orientation.getRight().getY() * THRUST_MAG; + avatar.thrust.z += avatar.orientation.getRight().getZ() * THRUST_MAG; + + //thrust.x += forward.z*THRUST_LATERAL_MAG; + //thrust.z += forward.x*-THRUST_LATERAL_MAG; + } + + + if (driveKeys[UP]) + { + //position.x -= avatar.orientation.getUp().getX() * 0.01; + //position.y -= avatar.orientation.getUp().getY() * 0.01; + //position.z += avatar.orientation.getUp().getZ() * 0.01; + + avatar.thrust.x -= avatar.orientation.getUp().getX() * THRUST_MAG; + avatar.thrust.y -= avatar.orientation.getUp().getY() * THRUST_MAG; + avatar.thrust.z += avatar.orientation.getUp().getZ() * THRUST_MAG; + + //thrust.y += -THRUST_VERTICAL_MAG; + } + if (driveKeys[DOWN]) + { + //position.x += avatar.orientation.getUp().getX() * 0.01; + //position.y += avatar.orientation.getUp().getY() * 0.01; + //position.z -= avatar.orientation.getUp().getZ() * 0.01; + + avatar.thrust.x += avatar.orientation.getUp().getX() * THRUST_MAG; + avatar.thrust.y += avatar.orientation.getUp().getY() * THRUST_MAG; + avatar.thrust.z -= avatar.orientation.getUp().getZ() * THRUST_MAG; + + //thrust.y += THRUST_VERTICAL_MAG; + } + + if (driveKeys[ROT_RIGHT]) + { + avatar.yawDelta -= 300.0 * deltaTime; + } + if (driveKeys[ROT_LEFT]) + { + avatar.yawDelta += 300.0 * deltaTime; + } + + avatar.yaw += avatar.yawDelta * deltaTime; + + + const float TEST_YAW_DECAY = 5.0; + avatar.yawDelta *= ( 1.0 - TEST_YAW_DECAY * deltaTime ); + + //avatar.yawDelta *= 0.99; + + avatar.velocity += avatar.thrust * (double)deltaTime; + + position += avatar.velocity * (double)deltaTime; + + //avatar.velocity *= 0.9; + + const float LIN_VEL_DECAY = 5.0; + avatar.velocity *= ( 1.0 - LIN_VEL_DECAY * deltaTime ); + + + /* // Increment velocity as time velocity += thrust * deltaTime; // Increment position as a function of velocity position += velocity * deltaTime; - + */ + + + /* // Decay velocity const float LIN_VEL_DECAY = 5.0; velocity *= (1.0 - LIN_VEL_DECAY*deltaTime); - + */ + + if (!noise) { // Decay back toward center @@ -335,6 +446,8 @@ void Head::simulate(float deltaTime) leanForward *= (1.f - DECAY*30.f*deltaTime); leanSideways *= (1.f - DECAY*30.f*deltaTime); + + // Update where the avatar's eyes are // // First, decide if we are making eye contact or not @@ -351,6 +464,8 @@ void Head::simulate(float deltaTime) } } + + const float DEGREES_BETWEEN_VIEWER_EYES = 3; const float DEGREES_TO_VIEWER_MOUTH = 7; @@ -374,8 +489,8 @@ void Head::simulate(float deltaTime) EyeballPitch[0] = EyeballPitch[1] = -Pitch + eye_target_pitch_adjust; EyeballYaw[0] = EyeballYaw[1] = -Yaw + eye_target_yaw_adjust; } + - if (noise) { Pitch += (randFloat() - 0.5)*0.2*NoiseEnvelope; @@ -409,7 +524,8 @@ void Head::simulate(float deltaTime) } } -//hand->simulate(deltaTime); + + //hand->simulate(deltaTime); } @@ -419,43 +535,49 @@ void Head::simulate(float deltaTime) //--------------------------------------------------- void Head::render(int faceToFace, int isMine) { - // render avatar - renderAvatar(); + renderBody(); + renderHead( faceToFace, isMine ); +} + + + +//--------------------------------------------------- +void Head::renderHead( int faceToFace, int isMine ) +{ int side = 0; // Always render own hand, but don't render head unless showing face2face glEnable(GL_DEPTH_TEST); glPushMatrix(); -//glScalef(scale, scale, scale); + //glScalef(scale, scale, scale); + + glTranslatef + ( + avatar.bone[ AVATAR_BONE_HEAD ].worldPosition.x, + avatar.bone[ AVATAR_BONE_HEAD ].worldPosition.y, + avatar.bone[ AVATAR_BONE_HEAD ].worldPosition.z + ); + + glScalef( 0.03, 0.03, 0.03 ); -glTranslatef -( - avatar.bone[ AVATAR_BONE_HEAD ].position.x, - avatar.bone[ AVATAR_BONE_HEAD ].position.y, - avatar.bone[ AVATAR_BONE_HEAD ].position.z -); - - -glScalef( 0.03, 0.03, 0.03 ); - - - glTranslatef(leanSideways, 0.f, leanForward); + //glTranslatef(leanSideways, 0.f, leanForward); - glRotatef(Yaw, 0, 1, 0); + //glRotatef(Yaw, 0, 1, 0); + + glRotatef( avatar.yaw, 0, 1, 0); -//hand->render(1); + //hand->render(1); // Don't render a head if it is really close to your location, because that is your own head! -//if (!isMine || faceToFace) + //if (!isMine || faceToFace) { glRotatef(Pitch, 1, 0, 0); glRotatef(Roll, 0, 0, 1); - // Overall scale of head if (faceToFace) glScalef(1.5, 2.0, 2.0); else glScalef(0.75, 1.0, 1.0); @@ -595,7 +717,7 @@ glScalef( 0.03, 0.03, 0.03 ); //--------------------------------------------------------- void Head::setHandMovement( glm::dvec3 movement ) { - handOffset.setXYZ( movement.x, -movement.y, movement.z ); + handOffset = glm::dvec3( movement.x, -movement.y, movement.z ); } @@ -603,19 +725,23 @@ void Head::setHandMovement( glm::dvec3 movement ) //----------------------------------------- void Head::initializeAvatar() { - //printf( "initializeAvatar\n" ); - - avatar.position.clear(); - //avatar.position.setXYZ( -3.0, 0.0, 0.0 ); - - avatar.velocity.clear(); + avatar.position = glm::dvec3( 0.0, 0.0, 0.0 ); + avatar.velocity = glm::dvec3( 0.0, 0.0, 0.0 ); + avatar.thrust = glm::dvec3( 0.0, 0.0, 0.0 ); avatar.orientation.setToIdentity(); + avatar.yaw = 0.0; + avatar.pitch = 0.0; + avatar.roll = 0.0; + + avatar.yawDelta = 0.0; + for (int b=0; b avatar.maxArmLength ) + { + avatar.bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].worldPosition += v * 0.2; + } + */ + + + + /* + //------------------------------------------------------------------------ + // update offset position + //------------------------------------------------------------------------ + for (int b=0; b maxArmLength ) + if ( distance > avatar.maxArmLength ) { //------------------------------------------------------------------------------- // reset right hand to be constrained to maximum arm length //------------------------------------------------------------------------------- - avatar.bone[ AVATAR_BONE_RIGHT_HAND ].position.set( avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); - + avatar.bone[ AVATAR_BONE_RIGHT_HAND ].worldPosition = avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].worldPosition; glm::dvec3 armNormal = armVector / distance; - armVector = armNormal * maxArmLength; - distance = maxArmLength; - - glm::dvec3 constrainedPosition = glm::dvec3( avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.x, avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.y, avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.z ); - + armVector = armNormal * avatar.maxArmLength; + distance = avatar.maxArmLength; + glm::dvec3 constrainedPosition = avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].worldPosition; constrainedPosition += armVector; - - avatar.bone[ AVATAR_BONE_RIGHT_HAND ].position.setXYZ( constrainedPosition.x, constrainedPosition.y, constrainedPosition.z ); + avatar.bone[ AVATAR_BONE_RIGHT_HAND ].worldPosition = constrainedPosition; } - //----------------------------------------------------------------------------- - // set elbow position + // set elbow position //----------------------------------------------------------------------------- - glm::dvec3 newElbowPosition = glm::dvec3( avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.x, avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.y, avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].position.z ); - + glm::dvec3 newElbowPosition = avatar.bone[ AVATAR_BONE_RIGHT_SHOULDER ].worldPosition; newElbowPosition += armVector * ONE_HALF; - glm::dvec3 perpendicular = glm::dvec3( -armVector.y, armVector.x, armVector.z ); - - newElbowPosition += perpendicular * ( 1.0 - ( maxArmLength / distance ) ) * ONE_HALF; - - avatar.bone[ AVATAR_BONE_RIGHT_FOREARM ].position.setXYZ( newElbowPosition.x, newElbowPosition.y, newElbowPosition.z ); + newElbowPosition += perpendicular * ( 1.0 - ( avatar.maxArmLength / distance ) ) * ONE_HALF; + avatar.bone[ AVATAR_BONE_RIGHT_FOREARM ].worldPosition = newElbowPosition; } + //----------------------------------------- -void Head::renderAvatar() +void Head::renderBody() { glColor3fv(skinColor); for (int b=0; bgetPos().x, hand->getPos().y, hand->getPos().z); + //hand->getPos().x, hand->getPos().y, hand->getPos().z); //previous to Ventrella change + avatar.bone[ AVATAR_BONE_RIGHT_HAND ].worldPosition.x, + avatar.bone[ AVATAR_BONE_RIGHT_HAND ].worldPosition.y, + avatar.bone[ AVATAR_BONE_RIGHT_HAND ].worldPosition.z ); // Ventrella change return strlen(data); } +//called on the other agents - assigns it to my views of the others + //--------------------------------------------------- -void Head::parseData(void *data, int size) { +void Head::parseData(void *data, int size) +{ + //glm::vec3 pos;//( (glm::vec3)avatar.bone[ AVATAR_BONE_RIGHT_HAND ].worldPosition ); + // parse head data for this agent - glm::vec3 handPos(0,0,0); - sscanf((char *)data, "H%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f", - &Pitch, &Yaw, &Roll, - &position.x, &position.y, &position.z, - &loudness, &averageLoudness, - &handPos.x, &handPos.y, &handPos.z); + glm::vec3 handPos( 0,0,0 ); + + sscanf + ( + (char *)data, "H%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f", + &Pitch, &Yaw, &Roll, + &position.x, &position.y, &position.z, + &loudness, &averageLoudness, + &handPos.x, &handPos.y, &handPos.z + ); if (glm::length(handPos) > 0.0) hand->setPos(handPos); } diff --git a/interface/src/Head.h b/interface/src/Head.h index b5ae162c80..3e2f2fcc83 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -74,30 +74,26 @@ enum AvatarJoints enum AvatarBones { AVATAR_BONE_NULL = -1, - AVATAR_BONE_PELVIS_SPINE, // connects pelvis joint with torso joint (cannot be rotated) + 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 (cannot be rotated) + 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 (cannot be rotated) + 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 (cannot be rotated) + 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 (cannot be rotated) + 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 (cannot be rotated) + 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 @@ -108,20 +104,26 @@ enum AvatarBones struct AvatarBone { AvatarBones parent; - Vector3D position; - Vector3D defaultPosePosition; - Vector3D velocity; + glm::dvec3 worldPosition; + glm::dvec3 defaultPosePosition; + glm::dvec3 velocity; double yaw; double pitch; double roll; - Orientation orientation; + Orientation worldOrientation; double length; }; struct Avatar { - Vector3D position; - Vector3D velocity; + glm::dvec3 position; + glm::dvec3 velocity; + glm::dvec3 thrust; + double yaw; + double pitch; + double roll; + double yawDelta; + double maxArmLength; Orientation orientation; AvatarBone bone[ NUM_AVATAR_BONES ]; }; @@ -154,15 +156,19 @@ class Head : public AgentData { float getRoll() {return Roll;} float getYaw() {return Yaw;} float getLastMeasuredYaw() {return YawRate;} + + double getAvatarYaw(); void render(int faceToFace, int isMine); void setAvatarPosition( double, double, double ); - void renderAvatar(); + void renderBody(); + void renderHead( int faceToFace, int isMine ); void simulate(float); void setHandMovement( glm::dvec3 movement ); + void updateHandMovement(); // Send and receive network data int getBroadcastData(char * data); @@ -227,7 +233,7 @@ class Head : public AgentData { glm::vec3 velocity; glm::vec3 thrust; - Vector3D handOffset; + glm::dvec3 handOffset; int driveKeys[MAX_DRIVE_KEYS]; @@ -238,8 +244,8 @@ class Head : public AgentData { Avatar avatar; void initializeAvatar(); - void simulateAvatar( float deltaTime ); void updateAvatarSkeleton(); + void calculateBoneLengths(); void readSensors(); float renderYaw, renderPitch; // Pitch from view frustum when this is own head. diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 0c1fb05ebf..03ad9e7ed2 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -566,15 +566,32 @@ void display(void) glMateriali(GL_FRONT, GL_SHININESS, 96); //------------------------------------------------------------------------------------- - // set the caemra to third-person view + // set the camera to third-person view //------------------------------------------------------------------------------------- - myCamera.setTargetPosition ( (glm::dvec3)myHead.getPos() ); - myCamera.setYaw ( 0.0 ); - myCamera.setPitch ( 0.0 ); - myCamera.setRoll ( 0.0 ); - myCamera.setUp ( 0.15 ); - myCamera.setDistance ( 0.08 ); - myCamera.update(); + myCamera.setTargetPosition( (glm::dvec3)myHead.getPos() ); + myCamera.setPitch ( 0.0 ); + myCamera.setRoll ( 0.0 ); + + if ( display_head ) + //------------------------------------------------------------------------------------- + // set the camera to looking at my face + //------------------------------------------------------------------------------------- + { + myCamera.setYaw ( - myHead.getAvatarYaw() ); + myCamera.setUp ( 0.4 ); + myCamera.setDistance( 0.08 ); + myCamera.update(); + } + else + //------------------------------------------------------------------------------------- + // set the camera to third-person view + //------------------------------------------------------------------------------------- + { + myCamera.setYaw ( 180.0 - myHead.getAvatarYaw() ); + myCamera.setUp ( 0.15 ); + myCamera.setDistance( 0.08 ); + myCamera.update(); + } //------------------------------------------------------------------------------------- // transform to camera view @@ -582,7 +599,13 @@ void display(void) glRotatef ( myCamera.getPitch(), 1, 0, 0 ); glRotatef ( myCamera.getYaw(), 0, 1, 0 ); glRotatef ( myCamera.getRoll(), 0, 0, 1 ); + + //printf( "myCamera position = %f, %f, %f\n", myCamera.getPosition().x, myCamera.getPosition().y, myCamera.getPosition().z ); + glTranslatef( myCamera.getPosition().x, myCamera.getPosition().y, myCamera.getPosition().z ); + + // fixed view + //glTranslatef( 6.18, -0.15, 1.4 ); if (::starsOn) { // should be the first rendering pass - w/o depth buffer / lighting @@ -601,7 +624,7 @@ void display(void) // if (!display_head) cloud.render(); // Draw voxels -//voxels.render(); + voxels.render(); // Draw field vectors if (display_field) field.render(); @@ -624,11 +647,12 @@ void display(void) if (!display_head && stats_on) render_world_box(); + //--------------------------------- + // Render my own head + //--------------------------------- myHead.render( true, 1 ); - //myHead.renderAvatar(); /* - // Render my own head glPushMatrix(); glLoadIdentity(); glTranslatef(0.f, 0.f, -7.f); @@ -967,7 +991,7 @@ void idle(void) if ( mouse_pressed == 1 ) { double xOffset = ( mouse_x - mouse_start_x ) / (double)WIDTH; - double yOffset = ( mouse_y - mouse_start_y ) / (double)WIDTH; + double yOffset = ( mouse_y - mouse_start_y ) / (double)HEIGHT; double leftRight = xOffset; double downUp = yOffset; @@ -1001,6 +1025,8 @@ void idle(void) } } + + void reshape(int width, int height) { WIDTH = width; @@ -1018,6 +1044,8 @@ void reshape(int width, int height) glViewport(0, 0, width, height); } + + void mouseFunc( int button, int state, int x, int y ) { if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN ) From e6a4647852c0ac2ce012dfa2350e915342653f3a Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Mon, 8 Apr 2013 18:56:31 -0700 Subject: [PATCH 28/33] added a fix for other av rotation --- interface/src/Head.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index efd07bf8d6..2b1222c09d 100755 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -397,6 +397,7 @@ void Head::simulate(float deltaTime) avatar.yaw += avatar.yawDelta * deltaTime; + Yaw = avatar.yaw; const float TEST_YAW_DECAY = 5.0; avatar.yawDelta *= ( 1.0 - TEST_YAW_DECAY * deltaTime ); From 7480283dd42b0ced3f2ddd39b09360797e9b9a1b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Apr 2013 19:54:14 -0700 Subject: [PATCH 29/33] cleanup of packet header constants --- injector/src/injector.cpp | 4 +++- interface/src/Audio.cpp | 3 ++- interface/src/VoxelSystem.cpp | 6 +++--- interface/src/main.cpp | 9 ++++++--- mixer/src/main.cpp | 3 ++- shared/src/AgentList.cpp | 4 ++-- shared/src/PacketHeaders.h | 7 +++++++ shared/src/SharedUtil.cpp | 2 +- shared/src/VoxelTree.cpp | 2 +- tools/sendvoxels.php | 8 ++++---- voxel/src/main.cpp | 13 +++++++------ 11 files changed, 38 insertions(+), 23 deletions(-) diff --git a/injector/src/injector.cpp b/injector/src/injector.cpp index 3845370178..3f6bb7f689 100644 --- a/injector/src/injector.cpp +++ b/injector/src/injector.cpp @@ -20,6 +20,8 @@ #include "UDPSocket.h" #include "UDPSocket.cpp" #include +#include + char EC2_WEST_AUDIO_SERVER[] = "54.241.92.53"; const int AUDIO_UDP_LISTEN_PORT = 55443; @@ -121,7 +123,7 @@ void stream(void) int leadingBytes = 1 + (sizeof(float) * 4); unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes]; - dataPacket[0] = 'I'; + dataPacket[0] = PACKET_HEADER_INJECT_AUDIO; unsigned char *currentPacketPtr = dataPacket + 1; for (int p = 0; p < 4; p++) { diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index ce45670c45..e717d707a9 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include "Audio.h" #include "Util.h" @@ -150,7 +151,7 @@ int audioCallback (const void *inputBuffer, // + 12 for 3 floats for position + float for bearing + 1 attenuation byte unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes]; - dataPacket[0] = 'I'; + dataPacket[0] = PACKET_HEADER_INJECT_AUDIO; unsigned char *currentPacketPtr = dataPacket + 1; // memcpy the three float positions diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index f3eb8ec957..ca6bbee7b0 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -113,15 +113,15 @@ void VoxelSystem::parseData(void *data, int size) { unsigned char *voxelData = (unsigned char *) data + 1; switch(command) { - case 'V': + case PACKET_HEADER_VOXEL_DATA: // ask the VoxelTree to read the bitstream into the tree tree->readBitstreamToTree(voxelData, size - 1); break; - case 'R': + case PACKET_HEADER_ERASE_VOXEL: // ask the tree to read the "remove" bitstream tree->processRemoveVoxelBitstream((unsigned char*)data,size); break; - case 'Z': + 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 diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 64d4e774c5..e7f794e0b7 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -63,6 +63,7 @@ #include "SerialInterface.h" #include #include +#include using namespace std; @@ -553,7 +554,7 @@ void simulateHead(float frametime) ::paintingVoxel.y >= 0.0 && ::paintingVoxel.y <= 1.0 && ::paintingVoxel.z >= 0.0 && ::paintingVoxel.z <= 1.0) { - if (createVoxelEditMessage('I',0,1,&::paintingVoxel,bufferOut,sizeOut)){ + if (createVoxelEditMessage(PACKET_HEADER_SET_VOXEL,0,1,&::paintingVoxel,bufferOut,sizeOut)){ agentList.broadcastToAgents((char*)bufferOut, sizeOut,AgentList::AGENTS_OF_TYPE_VOXEL); delete bufferOut; } @@ -1003,10 +1004,12 @@ void *networkReceive(void *args) packetcount++; bytescount += bytesReceived; - if (incomingPacket[0] == 't') { + if (incomingPacket[0] == PACKET_HEADER_TRANSMITTER_DATA) { // Pass everything but transmitter data to the agent list myHead.hand->processTransmitterData(incomingPacket, bytesReceived); - } else if (incomingPacket[0] == 'V' || incomingPacket[0] == 'Z') { + } else if (incomingPacket[0] == PACKET_HEADER_VOXEL_DATA || + incomingPacket[0] == PACKET_HEADER_Z_COMMAND || + incomingPacket[0] == PACKET_HEADER_ERASE_VOXEL) { voxels.parseData(incomingPacket, bytesReceived); } else { agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived); diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index bb97dab353..80c2452e2f 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -20,6 +20,7 @@ #include #include #include "AudioRingBuffer.h" +#include "PacketHeaders.h" #ifdef _WIN32 #include "Syssocket.h" @@ -275,7 +276,7 @@ int main(int argc, const char * argv[]) while (true) { if(agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) { - if (packetData[0] == 'I') { + if (packetData[0] == PACKET_HEADER_INJECT_AUDIO) { // Compute and report standard deviation for jitter calculation if (firstSample) { diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index 729a88ca6d..e0d4491700 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -69,12 +69,12 @@ unsigned int AgentList::getSocketListenPort() { void AgentList::processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes) { switch (((char *)packetData)[0]) { - case 'D': { + case PACKET_HEADER_DOMAIN: { // list of agents from domain server updateList((unsigned char *)packetData, dataBytes); break; } - case 'H': { + case PACKET_HEADER_HEAD_DATA: { // head data from another agent updateAgentWithData(senderAddress, packetData, dataBytes); break; diff --git a/shared/src/PacketHeaders.h b/shared/src/PacketHeaders.h index 7c76c5d7f9..097a87604c 100644 --- a/shared/src/PacketHeaders.h +++ b/shared/src/PacketHeaders.h @@ -12,5 +12,12 @@ const char PACKET_HEADER_DOMAIN = 'D'; const char PACKET_HEADER_PING = 'P'; const char PACKET_HEADER_PING_REPLY = 'R'; +const char PACKET_HEADER_HEAD_DATA = 'H'; +const char PACKET_HEADER_Z_COMMAND = 'Z'; +const char PACKET_HEADER_INJECT_AUDIO = 'I'; +const char PACKET_HEADER_SET_VOXEL = 'S'; +const char PACKET_HEADER_ERASE_VOXEL = 'E'; +const char PACKET_HEADER_VOXEL_DATA = 'V'; +const char PACKET_HEADER_TRANSMITTER_DATA = 't'; #endif diff --git a/shared/src/SharedUtil.cpp b/shared/src/SharedUtil.cpp index be4d081c5a..60d3b1559f 100644 --- a/shared/src/SharedUtil.cpp +++ b/shared/src/SharedUtil.cpp @@ -131,7 +131,7 @@ bool cmdOptionExists(int argc, const char * argv[],const char* option) { // corresponding to the closest voxel which encloses a cube with // lower corners at x,y,z, having side of length S. // The input values x,y,z range 0.0 <= v < 1.0 -// message should be either 'I' for insert or 'R' for remove +// message should be either 'S' for SET or 'E' for ERASE // // IMPORTANT: The buffer is returned to you a buffer which you MUST delete when you are // done with it. diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index dfda1de2b5..8cefb45a11 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -309,7 +309,7 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer, if (strcmp((char *)stopOctalCode, (char *)currentVoxelNode->octalCode) == 0) { // this is is the root node for this packet // add the leading V - *(bitstreamBuffer++) = 'V'; + *(bitstreamBuffer++) = PACKET_HEADER_VOXEL_DATA; // add its octal code to the packet int octalCodeBytes = bytesRequiredForCodeLength(*currentVoxelNode->octalCode); diff --git a/tools/sendvoxels.php b/tools/sendvoxels.php index b71c50c8df..438c9a1b8a 100644 --- a/tools/sendvoxels.php +++ b/tools/sendvoxels.php @@ -68,15 +68,15 @@ if (empty($options['i']) && empty($options['zcommand'])) { $filename = $options['i']; $server = $options['s']; $port = empty($options['p']) ? 40106 : $options['p']; - $command = empty($options['c']) ? 'I' : $options['c']; + $command = empty($options['c']) ? 'S' : $options['c']; switch($command) { - case 'I': - case 'R': + case 'S': + case 'E': case 'Z': //$command is good break; default: - $command='I';// insert by default! + $command='S';// insert by default! } if ($options['testmode']) { diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index c3b955b22e..09834a2d3e 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -16,6 +16,7 @@ #include #include "VoxelAgentData.h" #include +#include #ifdef _WIN32 #include "Syssocket.h" @@ -293,8 +294,8 @@ int main(int argc, const char * argv[]) // loop to send to agents requesting data while (true) { if (agentList.getAgentSocket().receive(&agentPublicAddress, packetData, &receivedBytes)) { - // XXXBHG: Hacked in support for 'I' insert command - if (packetData[0] == 'I') { + // XXXBHG: Hacked in support for 'S' SET command + if (packetData[0] == PACKET_HEADER_SET_VOXEL) { unsigned short int itemNumber = (*((unsigned short int*)&packetData[1])); printf("got I - insert voxels - command from client receivedBytes=%ld itemNumber=%d\n", receivedBytes,itemNumber); @@ -335,10 +336,10 @@ int main(int argc, const char * argv[]) // after done inserting all these voxels, then reaverage colors randomTree.reaverageVoxelColors(randomTree.rootNode); } - if (packetData[0] == 'R') { + if (packetData[0] == PACKET_HEADER_ERASE_VOXEL) { // Send these bits off to the VoxelTree class to process them - printf("got Remove Voxels message, have voxel tree do the work... randomTree.processRemoveVoxelBitstream()\n"); + printf("got Erase Voxels message, have voxel tree do the work... randomTree.processRemoveVoxelBitstream()\n"); randomTree.processRemoveVoxelBitstream((unsigned char*)packetData,receivedBytes); // Now send this to the connected agents so they know to delete @@ -346,7 +347,7 @@ int main(int argc, const char * argv[]) agentList.broadcastToAgents(packetData,receivedBytes,AgentList::AGENTS_OF_TYPE_HEAD); } - if (packetData[0] == 'Z') { + if (packetData[0] == PACKET_HEADER_Z_COMMAND) { // the Z command is a special command that allows the sender to send the voxel server high level semantic // requests, like erase all, or add sphere scene @@ -373,7 +374,7 @@ int main(int argc, const char * argv[]) printf("rebroadcasting Z message to connected agents... agentList.broadcastToAgents()\n"); agentList.broadcastToAgents(packetData,receivedBytes,AgentList::AGENTS_OF_TYPE_HEAD); } - if (packetData[0] == 'H') { + if (packetData[0] == PACKET_HEADER_HEAD_DATA) { if (agentList.addOrUpdateAgent(&agentPublicAddress, &agentPublicAddress, packetData[0], From 17f4c5d18437d0af102a73c692e5b5d12f07f523 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Apr 2013 19:56:42 -0700 Subject: [PATCH 30/33] cleanup of packet header constants --- interface/src/VoxelSystem.cpp | 1 + shared/src/VoxelTree.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index ca6bbee7b0..d901a08ebd 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -11,6 +11,7 @@ #include // to load voxels from file #include // to load voxels from file #include +#include #include #include "VoxelSystem.h" diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index 8cefb45a11..1a48a690c2 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -10,6 +10,7 @@ #include #include #include "SharedUtil.h" +#include "PacketHeaders.h" #include "CounterStats.h" #include "OctalCode.h" #include "VoxelTree.h" From ec9bd5efb32f13a4e5f9ae87246151b543a72aea Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Apr 2013 19:59:58 -0700 Subject: [PATCH 31/33] hopefully fix build buster --- interface/src/Orientation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Orientation.h b/interface/src/Orientation.h index 217366f8ef..30979c48ff 100755 --- a/interface/src/Orientation.h +++ b/interface/src/Orientation.h @@ -8,7 +8,7 @@ #ifndef __interface__orientation__ #define __interface__orientation__ -#include "Math.h" +#include #include "Vector3D.h" enum Axis From 6079ec2d918d46bda66b966771c1d1e740ce3a91 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Apr 2013 20:02:10 -0700 Subject: [PATCH 32/33] hopefully fix build buster --- interface/src/Orientation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Orientation.h b/interface/src/Orientation.h index 30979c48ff..f9f6744fc2 100755 --- a/interface/src/Orientation.h +++ b/interface/src/Orientation.h @@ -8,7 +8,7 @@ #ifndef __interface__orientation__ #define __interface__orientation__ -#include +#include // with this work? "Math.h" #include "Vector3D.h" enum Axis From 6eb503f6d0a7833495c3e2571656e32210a226da Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Apr 2013 20:04:24 -0700 Subject: [PATCH 33/33] hopefully fix build buster --- interface/src/Vector3D.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Vector3D.cpp b/interface/src/Vector3D.cpp index 792d55c16a..0e6393ecac 100755 --- a/interface/src/Vector3D.cpp +++ b/interface/src/Vector3D.cpp @@ -6,7 +6,7 @@ //----------------------------------------------------------- #include "Vector3D.h" -#include "Math.h" +#include // "Math.h" //--------------------------------------- Vector3D::Vector3D()