diff --git a/Source/Audio.cpp b/Source/Audio.cpp index d008aa3993..7699dd9a0e 100644 --- a/Source/Audio.cpp +++ b/Source/Audio.cpp @@ -28,14 +28,18 @@ const float AMPLITUDE_RATIO_AT_90 = 0.5; const short RING_BUFFER_FRAMES = 5; const short RING_BUFFER_SIZE_SAMPLES = RING_BUFFER_FRAMES * BUFFER_LENGTH_SAMPLES; -const short JITTER_BUFFER_LENGTH_MSECS = 3; +const short JITTER_BUFFER_LENGTH_MSECS = 1; const int SAMPLE_RATE = 22050; const short NUM_AUDIO_SOURCES = 2; const short ECHO_SERVER_TEST = 1; +char WORKCLUB_AUDIO_SERVER[] = "192.168.1.19"; +char EC2_WEST_AUDIO_SERVER[] = "54.241.92.53"; + const int AUDIO_UDP_LISTEN_PORT = 55444; + #define LOG_SAMPLE_DELAY 1 bool Audio::initialized; diff --git a/Source/Head.cpp b/Source/Head.cpp index 77c3054d90..8a66d11128 100644 --- a/Source/Head.cpp +++ b/Source/Head.cpp @@ -47,10 +47,12 @@ Head::Head() EyeballYaw[0] = EyeballYaw[1] = 0; PitchTarget = YawTarget = 0; NoiseEnvelope = 1.0; - PupilConverge = 5.0; + PupilConverge = 10.0; leanForward = 0.0; leanSideways = 0.0; - setNoise(0); + eyeContact = 1; + eyeContactTarget = LEFT_EYE; + setNoise(1); } void Head::reset() @@ -69,18 +71,18 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea float measured_roll_rate = serialInterface->getRelativeValue(ROLL_RATE); // Update avatar head position based on measured gyro rates - const float HEAD_ROTATION_SCALE = 0.20; - const float HEAD_ROLL_SCALE = 0.50; - const float HEAD_LEAN_SCALE = 0.02; + const float HEAD_ROTATION_SCALE = 0.80; + const float HEAD_ROLL_SCALE = 0.80; + const float HEAD_LEAN_SCALE = 0.01; if (head_mirror) { - addYaw(measured_yaw_rate * HEAD_ROTATION_SCALE * frametime); + addYaw(-measured_yaw_rate * HEAD_ROTATION_SCALE * frametime); addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); - addRoll(measured_roll_rate * HEAD_ROLL_SCALE * frametime); - addLean(measured_lateral_accel * frametime * HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); + addRoll(-measured_roll_rate * HEAD_ROLL_SCALE * frametime); + addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } else { addYaw(measured_yaw_rate * -HEAD_ROTATION_SCALE * frametime); addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); - addRoll(measured_roll_rate * HEAD_ROLL_SCALE * frametime); + addRoll(-measured_roll_rate * HEAD_ROLL_SCALE * frametime); addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } } @@ -111,28 +113,69 @@ void Head::simulate(float deltaTime) } else { // Move toward new target - Pitch += (PitchTarget - Pitch)*22*deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ; - Yaw += (YawTarget - Yaw)*22*deltaTime; // (1.f - DECAY*deltaTime); + Pitch += (PitchTarget - Pitch)*10*deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ; + Yaw += (YawTarget - Yaw)*10*deltaTime; // (1.f - DECAY*deltaTime); Roll *= (1.f - DECAY*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 + if (randFloat() < 0.005) { + eyeContact = !eyeContact; + eyeContact = 1; + if (!eyeContact) { + // If we just stopped making eye contact,move the eyes markedly away + EyeballPitch[0] = EyeballPitch[1] = EyeballPitch[0] + 5.0 + (randFloat() - 0.5)*10; + EyeballYaw[0] = EyeballYaw[1] = EyeballYaw[0] + 5.0 + (randFloat()- 0.5)*5; + } else { + // If now making eye contact, turn head to look right at viewer + SetNewHeadTarget(0,0); + } + } + + const float DEGREES_BETWEEN_VIEWER_EYES = 3; + const float DEGREES_TO_VIEWER_MOUTH = 7; + + if (eyeContact) { + // Should we pick a new eye contact target? + if (randFloat() < 0.01) { + // Choose where to look next + if (randFloat() < 0.1) { + eyeContactTarget = MOUTH; + } else { + if (randFloat() < 0.5) eyeContactTarget = LEFT_EYE; else eyeContactTarget = RIGHT_EYE; + } + } + } + + if (noise) { - Pitch += (randFloat() - 0.5)*0.05*NoiseEnvelope; - Yaw += (randFloat() - 0.5)*0.1*NoiseEnvelope; - PupilSize += (randFloat() - 0.5)*0.001*NoiseEnvelope; + Pitch += (randFloat() - 0.5)*0.2*NoiseEnvelope; + Yaw += (randFloat() - 0.5)*0.3*NoiseEnvelope; + //PupilSize += (randFloat() - 0.5)*0.001*NoiseEnvelope; if (randFloat() < 0.005) MouthWidth = MouthWidthChoices[rand()%3]; - //if (randFloat() < 0.005) Pitch = (randFloat() - 0.5)*45; - //if (randFloat() < 0.005) Yaw = (randFloat() - 0.5)*45; - //if (randFloat() < 0.001) Roll = (randFloat() - 0.5)*45; - //if (randFloat() < 0.003) PupilSize = ((randFloat() - 0.5)*0.25+1)*NominalPupilSize; - if (randFloat() < 0.01) EyeballPitch[0] = EyeballPitch[1] = (randFloat() - 0.5)*20; - if (randFloat() < 0.01) EyeballYaw[0] = EyeballYaw[1] = (randFloat()- 0.5)*10; + if (!eyeContact) { + if (randFloat() < 0.01) EyeballPitch[0] = EyeballPitch[1] = (randFloat() - 0.5)*20; + if (randFloat() < 0.01) EyeballYaw[0] = EyeballYaw[1] = (randFloat()- 0.5)*10; + } else { + float eye_target_yaw_adjust = 0; + float eye_target_pitch_adjust = 0; + if (eyeContactTarget == LEFT_EYE) eye_target_yaw_adjust = DEGREES_BETWEEN_VIEWER_EYES; + if (eyeContactTarget == RIGHT_EYE) eye_target_yaw_adjust = -DEGREES_BETWEEN_VIEWER_EYES; + if (eyeContactTarget == MOUTH) eye_target_pitch_adjust = DEGREES_TO_VIEWER_MOUTH; + + EyeballPitch[0] = EyeballPitch[1] = -Pitch + eye_target_pitch_adjust; + EyeballYaw[0] = EyeballYaw[1] = -Yaw + eye_target_yaw_adjust; + } + + if ((randFloat() < 0.005) && (fabs(PitchTarget - Pitch) < 1.0) && (fabs(YawTarget - Yaw) < 1.0)) { @@ -220,7 +263,6 @@ void Head::render() glPopMatrix(); glTranslatef(0, 1.0, 0); - glTranslatef(-interPupilDistance/2.0,-0.68,0.7); // Right Eye @@ -235,12 +277,14 @@ void Head::render() } glPopMatrix(); // Right Pupil - glPushMatrix(); + glPushMatrix(); glRotatef(EyeballPitch[1], 1, 0, 0); glRotatef(EyeballYaw[1] + PupilConverge, 0, 1, 0); - glTranslatef(0,0,.25); - glColor3f(0,0,0); - glutSolidSphere(PupilSize, 15, 15); + glTranslatef(0,0,.35); + if (!eyeContact) glColor3f(0,0,0); else glColor3f(0.1,0.1,1.0); + //glRotatef(90,0,1,0); + glutSolidSphere(PupilSize, 15, 15); + glPopMatrix(); // Left Eye glColor3fv(eyeColor); @@ -257,9 +301,10 @@ void Head::render() glPushMatrix(); glRotatef(EyeballPitch[0], 1, 0, 0); glRotatef(EyeballYaw[0] - PupilConverge, 0, 1, 0); - glTranslatef(0,0,.25); - glColor3f(0,0,0); - glutSolidSphere(PupilSize, 15, 15); + glTranslatef(0,0,.35); + if (!eyeContact) glColor3f(0,0,0); else glColor3f(0.1,0.1,1.0); + //glRotatef(90,0,1,0); + glutSolidSphere(PupilSize, 15, 15); glPopMatrix(); } diff --git a/Source/Head.h b/Source/Head.h index a3c8ddbc3c..910e41463f 100644 --- a/Source/Head.h +++ b/Source/Head.h @@ -15,6 +15,8 @@ #include #include "SerialInterface.h" +enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH}; + class Head { float noise; float Pitch; @@ -39,17 +41,15 @@ class Head { float MouthHeight; float leanForward; float leanSideways; - float PitchTarget; float YawTarget; - float NoiseEnvelope; - float PupilConverge; - glm::vec3 position; - + int eyeContact; + eyeContactTargets eyeContactTarget; void readSensors(); + public: Head(void); diff --git a/Source/SerialInterface.cpp b/Source/SerialInterface.cpp index 755e97082b..3037cbf1b1 100644 --- a/Source/SerialInterface.cpp +++ b/Source/SerialInterface.cpp @@ -22,6 +22,8 @@ char serial_buffer[MAX_BUFFER]; int serial_buffer_pos = 0; int samples_total = 0; +const int ZERO_OFFSET = 2048; + // Init the serial port to the specified values int SerialInterface::init(char * portname, int baud) { @@ -79,6 +81,7 @@ void SerialInterface::renderLevels(int width, int height) { char val[10]; for(i = 0; i < NUM_CHANNELS; i++) { + // Actual value glLineWidth(2.0); glColor4f(1, 1, 1, 1); @@ -93,12 +96,14 @@ void SerialInterface::renderLevels(int width, int height) { glVertex2f(disp_x + 2, height*(0.25 + 0.75f*getTrailingValue(i)/4096)); glEnd(); + /* glColor3f(1,0,0); glBegin(GL_LINES); - glLineWidth(2.0); - glVertex2f(disp_x - 10, height*0.5 - getRelativeValue(i)); - glVertex2f(disp_x + 10, height*0.5 - getRelativeValue(i)); + glLineWidth(4.0); + glVertex2f(disp_x - 10, height*0.5 - getValue(i)/4096); + glVertex2f(disp_x + 10, height*0.5 - getValue(i)/4096); glEnd(); + */ sprintf(val, "%d", getValue(i)); drawtext(disp_x-GAP/2, (height*0.95)+2, 0.08, 90, 1.0, 0, val, 0, 1, 0); @@ -120,7 +125,7 @@ void SerialInterface::renderLevels(int width, int height) { void SerialInterface::readData() { // This array sets the rate of trailing averaging for each channel. // If the sensor rate is 100Hz, 0.001 will make the long term average a 10-second average - const float AVG_RATE[] = {0.001, 0.001, 0.001, 0.001, 0.001, 0.001}; + const float AVG_RATE[] = {0.01, 0.01, 0.01, 0.01, 0.01, 0.01}; char bufchar[1]; while (read(serial_fd, bufchar, 1) > 0) { diff --git a/Source/SerialInterface.h b/Source/SerialInterface.h index 39070d344e..82d35f85d7 100644 --- a/Source/SerialInterface.h +++ b/Source/SerialInterface.h @@ -20,13 +20,13 @@ #define NUM_CHANNELS 6 // Acceleration sensors, in screen/world coord system (X = left/right, Y = Up/Down, Z = fwd/back) -#define ACCEL_X 4 -#define ACCEL_Y 5 -#define ACCEL_Z 3 +#define ACCEL_X 3 +#define ACCEL_Y 4 +#define ACCEL_Z 5 // Gyro sensors, in coodinate system of head/airplane -#define PITCH_RATE 0 -#define YAW_RATE 1 +#define PITCH_RATE 1 +#define YAW_RATE 0 #define ROLL_RATE 2 class SerialInterface { diff --git a/Source/hardware/head_hand/head_hand.pde b/Source/hardware/head_hand/head_hand.pde index 8618674cc3..844f352e56 100644 --- a/Source/hardware/head_hand/head_hand.pde +++ b/Source/hardware/head_hand/head_hand.pde @@ -1,23 +1,26 @@ -/* -Read a set of analog input lines and echo their readings over the serial port with averaging -*/ - -// ADC PIN MAPPINGS // -// 15,16 = Head Pitch, Yaw gyro -// 17,18,19 = Head Accelerometer - +// Read Gyro and accelerometer data, send over serialUSB to computer for processing. +// +// Written by Philip, 2012, for High Fidelity, Inc. +// +// PIN WIRING: Connect input sensors to the channels in following manner +// +// AIN 10: Yaw Gyro (shaking your head 'no') +// AIN 16: Pitch Gyro (nodding your head 'yes') +// AIN 17: Roll Gyro (looking quizzical, tilting your head) +// AIN 18: Lateral acceleration (moving from side-to-side in front of your monitor) +// AIN 19: Up/Down acceleration (sitting up/ducking in front of your monitor) +// AIN 20: Forward/Back acceleration (Toward or away from your monitor) #define NUM_CHANNELS 6 -#define MSECS_PER_SAMPLE 15 +#define MSECS_PER_SAMPLE 10 #define LED_PIN 12 -int inputPins[NUM_CHANNELS] = {19,20,18,15,16,17}; - -int LED_on = 0; -unsigned int total_count = 0; +int inputPins[NUM_CHANNELS] = {10,16,17,18,19,20}; +int LED = 0; +unsigned int samplesSent = 0; unsigned int time; int measured[NUM_CHANNELS]; @@ -42,30 +45,34 @@ void loop() { int i; sampleCount++; - total_count++; - if (total_count % 20172 == 0) { - LED_on = !LED_on; - if (LED_on) digitalWrite(LED_PIN, HIGH); - else digitalWrite(LED_PIN, LOW); - } for (i = 0; i < NUM_CHANNELS; i++) { accumulate[i] += analogRead(inputPins[i]); } if ((millis() - time) >= MSECS_PER_SAMPLE) { + samplesSent++; time = millis(); for (i = 0; i < NUM_CHANNELS; i++) { measured[i] = accumulate[i] / sampleCount; SerialUSB.print(measured[i]); SerialUSB.print(" "); accumulate[i] = 0; - } + } + + if ((samplesSent % 100 == 0) && (samplesSent % 150 == 0)) { + LED = !LED; + digitalWrite(LED_PIN, LED); + digitalWrite(BOARD_LED_PIN, LED); + } + SerialUSB.print(sampleCount); SerialUSB.print(" "); - if (LED_on) SerialUSB.print("1"); - else SerialUSB.print("0"); + if (LED) + SerialUSB.print("1"); + else + SerialUSB.print("0"); + SerialUSB.println(""); - sampleCount = 0; } }