Merge remote-tracking branch 'upstream/master' into agentlist-array

This commit is contained in:
Stephen Birarda 2013-04-25 15:27:40 -07:00
commit 5ddd9a9f4f
16 changed files with 429 additions and 482 deletions

View file

@ -123,8 +123,7 @@ int main(int argc, const char* argv[]) {
// put her hand out so somebody can shake it // put her hand out so somebody can shake it
eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2, eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2,
0.25, 0.25,
eve.getPosition()[2] + 0.1)); eve.getPosition()[2] + 0.1));
// read eve's audio data // read eve's audio data
AudioInjector eveAudioInjector("eve.raw"); AudioInjector eveAudioInjector("eve.raw");
@ -139,6 +138,8 @@ int main(int argc, const char* argv[]) {
// int numIterationsLeftBeforeAudioSend = 0; // int numIterationsLeftBeforeAudioSend = 0;
// pthread_t injectAudioThread; // pthread_t injectAudioThread;
int handStateTimer = 0;
while (true) { while (true) {
// update the thisSend timeval to the current time // update the thisSend timeval to the current time
gettimeofday(&thisSend, NULL); gettimeofday(&thisSend, NULL);
@ -170,7 +171,19 @@ int main(int argc, const char* argv[]) {
// sleep for the correct amount of time to have data send be consistently timed // sleep for the correct amount of time to have data send be consistently timed
if ((numMicrosecondsSleep = (DATA_SEND_INTERVAL_MSECS * 1000) - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) { if ((numMicrosecondsSleep = (DATA_SEND_INTERVAL_MSECS * 1000) - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {
usleep(numMicrosecondsSleep); usleep(numMicrosecondsSleep);
} }
// simulate the effect of pressing and un-pressing the mouse button/pad
handStateTimer++;
if ( handStateTimer == 100 ) {
eve.setHandState(1);
}
if ( handStateTimer == 150 ) {
eve.setHandState(0);
}
if ( handStateTimer >= 200 ) {
handStateTimer = 0;
}
} }
// stop the receive agent data thread // stop the receive agent data thread

View file

@ -42,7 +42,7 @@ void usage(void)
std::cout << " -c FLOAT,FLOAT,FLOAT,FLOAT X,Y,Z,YAW position in universe where audio will be originating from and direction. Defaults to 0,0,0,0" << std::endl; std::cout << " -c FLOAT,FLOAT,FLOAT,FLOAT X,Y,Z,YAW position in universe where audio will be originating from and direction. Defaults to 0,0,0,0" << std::endl;
std::cout << " -a 0-255 Attenuation curve modifier, defaults to 255" << std::endl; std::cout << " -a 0-255 Attenuation curve modifier, defaults to 255" << std::endl;
std::cout << " -f FILENAME Name of audio source file. Required - RAW format, 22050hz 16bit signed mono" << std::endl; std::cout << " -f FILENAME Name of audio source file. Required - RAW format, 22050hz 16bit signed mono" << std::endl;
}; }
bool processParameters(int parameterCount, char* parameterData[]) bool processParameters(int parameterCount, char* parameterData[])
{ {
@ -91,9 +91,9 @@ bool processParameters(int parameterCount, char* parameterData[])
} }
} }
return true; return true;
};_Position };
int main(int argc, const char* argv[]) { int main(int argc, char* argv[]) {
srand(time(0)); srand(time(0));
int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1)); int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1));

View file

@ -157,7 +157,7 @@ int audioCallback (const void *inputBuffer,
// memcpy the three float positions // memcpy the three float positions
for (int p = 0; p < 3; p++) { for (int p = 0; p < 3; p++) {
memcpy(currentPacketPtr, &data->linkedHead->getPosition()[p], sizeof(float)); memcpy(currentPacketPtr, &data->linkedAvatar->getPosition()[p], sizeof(float));
currentPacketPtr += sizeof(float); currentPacketPtr += sizeof(float);
} }
@ -165,7 +165,7 @@ int audioCallback (const void *inputBuffer,
*(currentPacketPtr++) = 255; *(currentPacketPtr++) = 255;
// memcpy the corrected render yaw // memcpy the corrected render yaw
float correctedYaw = fmodf(data->linkedHead->getRenderYaw(), 360); float correctedYaw = fmodf(data->linkedAvatar->getRenderYaw(), 360);
if (correctedYaw > 180) { if (correctedYaw > 180) {
correctedYaw -= 360; correctedYaw -= 360;
@ -259,7 +259,7 @@ int audioCallback (const void *inputBuffer,
// rotation of the head relative to body, this may effect flange effect! // rotation of the head relative to body, this may effect flange effect!
// //
// //
int lastYawMeasured = fabsf(data->linkedHead->getLastMeasuredHeadYaw()); int lastYawMeasured = fabsf(data->linkedAvatar->getLastMeasuredHeadYaw());
if (!samplesLeftForFlange && lastYawMeasured > MIN_FLANGE_EFFECT_THRESHOLD) { if (!samplesLeftForFlange && lastYawMeasured > MIN_FLANGE_EFFECT_THRESHOLD) {
// we should flange for one second // we should flange for one second
@ -448,7 +448,7 @@ void Audio::setWalkingState(bool newWalkState) {
* @return Returns true if successful or false if an error occurred. * @return Returns true if successful or false if an error occurred.
Use Audio::getError() to retrieve the error code. Use Audio::getError() to retrieve the error code.
*/ */
Audio::Audio(Oscilloscope *s, Head *linkedHead) Audio::Audio(Oscilloscope *s, Avatar *linkedAvatar)
{ {
// read the walking sound from the raw file and store it // read the walking sound from the raw file and store it
// in the in memory array // in the in memory array
@ -472,7 +472,7 @@ Audio::Audio(Oscilloscope *s, Head *linkedHead)
audioData = new AudioData(); audioData = new AudioData();
audioData->linkedHead = linkedHead; audioData->linkedAvatar = linkedAvatar;
// setup a UDPSocket // setup a UDPSocket
audioData->audioSocket = new UDPSocket(AUDIO_UDP_LISTEN_PORT); audioData->audioSocket = new UDPSocket(AUDIO_UDP_LISTEN_PORT);

View file

@ -12,12 +12,12 @@
#include <portaudio.h> #include <portaudio.h>
#include "AudioData.h" #include "AudioData.h"
#include "Oscilloscope.h" #include "Oscilloscope.h"
#include "Head.h" #include "Avatar.h"
class Audio { class Audio {
public: public:
// initializes audio I/O // initializes audio I/O
Audio(Oscilloscope *s, Head *linkedHead); Audio(Oscilloscope *s, Avatar *linkedAvatar);
void render(); void render();
void render(int screenWidth, int screenHeight); void render(int screenWidth, int screenHeight);

View file

@ -13,7 +13,7 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "AudioRingBuffer.h" #include "AudioRingBuffer.h"
#include "UDPSocket.h" #include "UDPSocket.h"
#include "Head.h" #include "Avatar.h"
class AudioData { class AudioData {
public: public:
@ -23,7 +23,7 @@ class AudioData {
UDPSocket *audioSocket; UDPSocket *audioSocket;
Head *linkedHead; Avatar *linkedAvatar;
// store current mixer address and port // store current mixer address and port
in_addr_t mixerAddress; in_addr_t mixerAddress;

View file

@ -1,5 +1,5 @@
// //
// Head.cpp // Avatar.cpp
// interface // interface
// //
// Created by Philip Rosedale on 9/11/12. // Created by Philip Rosedale on 9/11/12.
@ -11,7 +11,7 @@
#include <vector> #include <vector>
#include <lodepng.h> #include <lodepng.h>
#include <SharedUtil.h> #include <SharedUtil.h>
#include "Head.h" #include "Avatar.h"
#include "Log.h" #include "Log.h"
#include <AgentList.h> #include <AgentList.h>
#include <AgentTypes.h> #include <AgentTypes.h>
@ -41,14 +41,13 @@ vector<unsigned char> iris_texture;
unsigned int iris_texture_width = 512; unsigned int iris_texture_width = 512;
unsigned int iris_texture_height = 256; unsigned int iris_texture_height = 256;
Head::Head(bool isMine) { Avatar::Avatar(bool isMine) {
_orientation.setToIdentity(); _orientation.setToIdentity();
_velocity = glm::vec3( 0.0, 0.0, 0.0 ); _velocity = glm::vec3( 0.0, 0.0, 0.0 );
_thrust = glm::vec3( 0.0, 0.0, 0.0 ); _thrust = glm::vec3( 0.0, 0.0, 0.0 );
_rotation = glm::quat( 0.0f, 0.0f, 0.0f, 0.0f ); _rotation = glm::quat( 0.0f, 0.0f, 0.0f, 0.0f );
_nearOtherAvatar = false;
_bodyYaw = -90.0; _bodyYaw = -90.0;
_bodyPitch = 0.0; _bodyPitch = 0.0;
_bodyRoll = 0.0; _bodyRoll = 0.0;
@ -60,7 +59,6 @@ Head::Head(bool isMine) {
//_transmitterTimer = 0; //_transmitterTimer = 0;
_transmitterHz = 0.0; _transmitterHz = 0.0;
_transmitterPackets = 0; _transmitterPackets = 0;
//_numOtherAvatars = 0;
initializeSkeleton(); initializeSkeleton();
@ -69,54 +67,51 @@ Head::Head(bool isMine) {
for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false; for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false;
_head.pupilSize = 0.10; _head.pupilSize = 0.10;
_head.interPupilDistance = 0.6; _head.interPupilDistance = 0.6;
_head.interBrowDistance = 0.75; _head.interBrowDistance = 0.75;
_head.nominalPupilSize = 0.10; _head.nominalPupilSize = 0.10;
//_head.yaw = 0.0; _head.pitchRate = 0.0;
//_head.pitch = 0.0; _head.yawRate = 0.0;
//_head.roll = 0.0; _head.rollRate = 0.0;
_head.pitchRate = 0.0; _head.eyebrowPitch[0] = -30;
_head.yawRate = 0.0; _head.eyebrowPitch[1] = -30;
_head.rollRate = 0.0; _head.eyebrowRoll [0] = 20;
_head.eyebrowPitch[0] = -30; _head.eyebrowRoll [1] = -20;
_head.eyebrowPitch[1] = -30; _head.mouthPitch = 0;
_head.eyebrowRoll [0] = 20; _head.mouthYaw = 0;
_head.eyebrowRoll [1] = -20; _head.mouthWidth = 1.0;
_head.mouthPitch = 0; _head.mouthHeight = 0.2;
_head.mouthYaw = 0; _head.eyeballPitch[0] = 0;
_head.mouthWidth = 1.0; _head.eyeballPitch[1] = 0;
_head.mouthHeight = 0.2; _head.eyeballScaleX = 1.2;
_head.eyeballPitch[0] = 0; _head.eyeballScaleY = 1.5;
_head.eyeballPitch[1] = 0; _head.eyeballScaleZ = 1.0;
_head.eyeballScaleX = 1.2; _head.eyeballYaw[0] = 0;
_head.eyeballScaleY = 1.5; _head.eyeballYaw[1] = 0;
_head.eyeballScaleZ = 1.0; _head.pitchTarget = 0;
_head.eyeballYaw[0] = 0; _head.yawTarget = 0;
_head.eyeballYaw[1] = 0; _head.noiseEnvelope = 1.0;
_head.pitchTarget = 0; _head.pupilConverge = 10.0;
_head.yawTarget = 0; _head.leanForward = 0.0;
_head.noiseEnvelope = 1.0; _head.leanSideways = 0.0;
_head.pupilConverge = 10.0; _head.eyeContact = 1;
_head.leanForward = 0.0; _head.eyeContactTarget = LEFT_EYE;
_head.leanSideways = 0.0; _head.scale = 1.0;
_head.eyeContact = 1; _head.audioAttack = 0.0;
_head.eyeContactTarget = LEFT_EYE; _head.averageLoudness = 0.0;
_head.scale = 1.0; _head.lastLoudness = 0.0;
_head.audioAttack = 0.0; _head.browAudioLift = 0.0;
_head.averageLoudness = 0.0; _head.noise = 0;
_head.lastLoudness = 0.0; _movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 );
_head.browAudioLift = 0.0; _usingBodySprings = true;
_head.noise = 0; _springForce = 6.0f;
_springVelocityDecay = 16.0f;
_movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 ); _renderYaw = 0.0;
_usingBodySprings = true; _renderPitch = 0.0;
_springForce = 6.0f; _sphere = NULL;
_springVelocityDecay = 16.0f; _interactingOther = NULL;
_renderYaw = 0.0; _interactingOtherIsNearby = false;
_renderPitch = 0.0;
_sphere = NULL;
_handHolding.position = glm::vec3( 0.0, 0.0, 0.0 ); _handHolding.position = glm::vec3( 0.0, 0.0, 0.0 );
_handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 );
@ -129,38 +124,35 @@ Head::Head(bool isMine) {
printLog("error %u: %s\n", error, lodepng_error_text(error)); printLog("error %u: %s\n", error, lodepng_error_text(error));
} }
} }
_otherAvatar.handPosition = glm::vec3( 0.0f, 0.0f, 0.0f );
_otherAvatar.handState = 0;
} }
Head::Head(const Head &otherAvatar) { Avatar::Avatar(const Avatar &otherAvatar) {
_velocity = otherAvatar._velocity; _velocity = otherAvatar._velocity;
_thrust = otherAvatar._thrust; _thrust = otherAvatar._thrust;
_rotation = otherAvatar._rotation; _rotation = otherAvatar._rotation;
_nearOtherAvatar = otherAvatar._nearOtherAvatar; _interactingOtherIsNearby = otherAvatar._interactingOtherIsNearby;
_bodyYaw = otherAvatar._bodyYaw; _bodyYaw = otherAvatar._bodyYaw;
_bodyPitch = otherAvatar._bodyPitch; _bodyPitch = otherAvatar._bodyPitch;
_bodyRoll = otherAvatar._bodyRoll; _bodyRoll = otherAvatar._bodyRoll;
_bodyYawDelta = otherAvatar._bodyYawDelta; _bodyYawDelta = otherAvatar._bodyYawDelta;
_mousePressed = otherAvatar._mousePressed; _mousePressed = otherAvatar._mousePressed;
_mode = otherAvatar._mode; _mode = otherAvatar._mode;
_isMine = otherAvatar._isMine; _isMine = otherAvatar._isMine;
_renderYaw = otherAvatar._renderYaw; _renderYaw = otherAvatar._renderYaw;
_renderPitch = otherAvatar._renderPitch; _renderPitch = otherAvatar._renderPitch;
_maxArmLength = otherAvatar._maxArmLength; _maxArmLength = otherAvatar._maxArmLength;
_transmitterTimer = otherAvatar._transmitterTimer; _transmitterTimer = otherAvatar._transmitterTimer;
_transmitterHz = otherAvatar._transmitterHz; _transmitterHz = otherAvatar._transmitterHz;
_transmitterPackets = otherAvatar._transmitterPackets; _transmitterPackets = otherAvatar._transmitterPackets;
_TEST_bigSphereRadius = otherAvatar._TEST_bigSphereRadius; _TEST_bigSphereRadius = otherAvatar._TEST_bigSphereRadius;
_TEST_bigSpherePosition = otherAvatar._TEST_bigSpherePosition; _TEST_bigSpherePosition = otherAvatar._TEST_bigSpherePosition;
_movedHandOffset = otherAvatar._movedHandOffset; _movedHandOffset = otherAvatar._movedHandOffset;
_usingBodySprings = otherAvatar._usingBodySprings; _usingBodySprings = otherAvatar._usingBodySprings;
_springForce = otherAvatar._springForce; _springForce = otherAvatar._springForce;
_springVelocityDecay = otherAvatar._springVelocityDecay; _springVelocityDecay = otherAvatar._springVelocityDecay;
_orientation.set( otherAvatar._orientation ); _orientation.set( otherAvatar._orientation );
_sphere = NULL; _sphere = NULL;
@ -173,9 +165,6 @@ Head::Head(const Head &otherAvatar) {
_head.interPupilDistance = otherAvatar._head.interPupilDistance; _head.interPupilDistance = otherAvatar._head.interPupilDistance;
_head.interBrowDistance = otherAvatar._head.interBrowDistance; _head.interBrowDistance = otherAvatar._head.interBrowDistance;
_head.nominalPupilSize = otherAvatar._head.nominalPupilSize; _head.nominalPupilSize = otherAvatar._head.nominalPupilSize;
//_head.yaw = otherAvatar._head.yaw;
//_head.pitch = otherAvatar._head.pitch;
//_head.roll = otherAvatar._head.roll;
_head.yawRate = otherAvatar._head.yawRate; _head.yawRate = otherAvatar._head.yawRate;
_head.pitchRate = otherAvatar._head.pitchRate; _head.pitchRate = otherAvatar._head.pitchRate;
_head.rollRate = otherAvatar._head.rollRate; _head.rollRate = otherAvatar._head.rollRate;
@ -209,7 +198,6 @@ Head::Head(const Head &otherAvatar) {
_head.browAudioLift = otherAvatar._head.browAudioLift; _head.browAudioLift = otherAvatar._head.browAudioLift;
_head.noise = otherAvatar._head.noise; _head.noise = otherAvatar._head.noise;
if (iris_texture.size() == 0) { if (iris_texture.size() == 0) {
switchToResourcesParentIfRequired(); switchToResourcesParentIfRequired();
unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file); unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file);
@ -219,25 +207,24 @@ Head::Head(const Head &otherAvatar) {
} }
} }
Head::~Head() { Avatar::~Avatar() {
if (_sphere != NULL) { if (_sphere != NULL) {
gluDeleteQuadric(_sphere); gluDeleteQuadric(_sphere);
} }
} }
Head* Head::clone() const { Avatar* Avatar::clone() const {
return new Head(*this); return new Avatar(*this);
} }
void Head::reset() { void Avatar::reset() {
_headPitch = _headYaw = _headRoll = 0; _headPitch = _headYaw = _headRoll = 0;
_head.leanForward = _head.leanSideways = 0; _head.leanForward = _head.leanSideways = 0;
} }
//this pertains to moving the head with the glasses //this pertains to moving the head with the glasses
//--------------------------------------------------- void Avatar::UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity)
void Head::UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity)
// Using serial data, update avatar/render position and angles // Using serial data, update avatar/render position and angles
{ {
const float PITCH_ACCEL_COUPLING = 0.5; const float PITCH_ACCEL_COUPLING = 0.5;
@ -276,28 +263,41 @@ void Head::UpdateGyros(float frametime, SerialInterface * serialInterface, glm::
addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE); addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE);
} }
void Head::addLean(float x, float z) { void Avatar::addLean(float x, float z) {
// Add Body lean as impulse // Add Body lean as impulse
_head.leanSideways += x; _head.leanSideways += x;
_head.leanForward += z; _head.leanForward += z;
} }
void Head::setLeanForward(float dist){ void Avatar::setLeanForward(float dist){
_head.leanForward = dist; _head.leanForward = dist;
} }
void Head::setLeanSideways(float dist){ void Avatar::setLeanSideways(float dist){
_head.leanSideways = dist; _head.leanSideways = dist;
} }
void Head::setMousePressed( bool d ) { void Avatar::setMousePressed( bool d ) {
_mousePressed = d; _mousePressed = d;
} }
void Head::simulate(float deltaTime) { void Avatar::simulate(float deltaTime) {
// update avatar skeleton
updateSkeleton();
// reset hand and arm positions according to hand movement
updateHandMovement( deltaTime );
if ( !_interactingOtherIsNearby ) {
//initialize _handHolding
_handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position;
_handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 );
}
_interactingOtherIsNearby = false;
//-------------------------------------------------------------
// if the avatar being simulated is mine, then loop through // if the avatar being simulated is mine, then loop through
// all the other avatars to get information about them... // all the other avatars to get information about them...
//------------------------------------------------------------- //-------------------------------------------------------------
@ -315,46 +315,60 @@ void Head::simulate(float deltaTime) {
if ((*agent).getLinkedData() != NULL && (*agent).getType() == AGENT_TYPE_AVATAR) { if ((*agent).getLinkedData() != NULL && (*agent).getType() == AGENT_TYPE_AVATAR) {
Head *otherAvatar = (Head *)(*agent).getLinkedData(); Head *otherAvatar = (Head *)(*agent).getLinkedData();
// if ( _numOtherAvatars < MAX_OTHER_AVATARS ) // check for collisions with other avatars and respond
{ updateAvatarCollisionDetectionAndResponse
(
//------------------------------------------------------ otherAvatar->getBonePosition( AVATAR_BONE_PELVIS_SPINE ),
// check for collisions with other avatars and respond 0.2,
//------------------------------------------------------ 0.2,
updateAvatarCollisionDetectionAndResponse otherAvatar->getBodyUpDirection(),
( deltaTime
otherAvatar->getPosition(), );
otherAvatar->getGirth(),
otherAvatar->getHeight(), // test other avatar hand position for proximity
otherAvatar->getBodyUpDirection(), glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position );
deltaTime v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND );
);
float distance = glm::length( v );
//------------------------------------------------- if ( distance < _maxArmLength ) {
// test other avatar hand position for proximity
//------------------------------------------------ //if ( distance < closestDistance ) { // perhaps I don't need this if we want to allow multi-avatar interactions
glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); {
v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); closestDistance = distance;
_interactingOther = otherAvatar;
float distance = glm::length( v ); _interactingOtherIsNearby = true;
if ( distance < _maxArmLength ) {
if ( distance < closestDistance ) { // if I am holding hands with another avatar, a force is applied
closestDistance = distance; if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) {
_nearOtherAvatar = true; glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHolding.position;
_otherAvatar.handPosition = otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position;
_otherAvatar.handState = (int)otherAvatar->getHandState();
} _handHolding.velocity *= 0.7;
_handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime;
_handHolding.position += _handHolding.velocity;
_bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position;
}
} }
} }
} }
} }
}//if ( _isMine ) // Set the vector we send for hand position to other people to be our right hand
setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position);
}//if ( _isMine )
updateArmIKAndConstraints( deltaTime );
if (!_interactingOtherIsNearby) {
_interactingOther = NULL;
}
if ( usingBigSphereCollisionTest ) { if ( usingBigSphereCollisionTest ) {
//--------------------------------------------------------------
// test for avatar collision response (using a big sphere :) // test for avatar collision response (using a big sphere :)
//--------------------------------------------------------------
updateAvatarCollisionDetectionAndResponse updateAvatarCollisionDetectionAndResponse
( (
_TEST_bigSpherePosition, _TEST_bigSpherePosition,
@ -377,23 +391,12 @@ void Head::simulate(float deltaTime) {
} }
} }
//------------------------ // update body springs
// update avatar skeleton updateBodySprings( deltaTime );
//------------------------
updateSkeleton(); // driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely)
if ( _isMine ) {
//------------------------------------------------------------
// reset hand and arm positions according to hand movement
//------------------------------------------------------------
if (_usingBodySprings) {
updateHandMovement( deltaTime );
updateBodySprings( deltaTime );
}
if ( _isMine ) { // driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely)
//-------------------------------------------------
// this handles the avatar being driven around...
//-------------------------------------------------
_thrust = glm::vec3( 0.0, 0.0, 0.0 ); _thrust = glm::vec3( 0.0, 0.0, 0.0 );
if (_driveKeys[FWD]) { if (_driveKeys[FWD]) {
@ -427,9 +430,7 @@ void Head::simulate(float deltaTime) {
_bodyYawDelta += YAW_MAG * deltaTime; _bodyYawDelta += YAW_MAG * deltaTime;
} }
} }
//----------------------------------------------------------
float translationalSpeed = glm::length( _velocity ); float translationalSpeed = glm::length( _velocity );
float rotationalSpeed = fabs( _bodyYawDelta ); float rotationalSpeed = fabs( _bodyYawDelta );
if ( translationalSpeed + rotationalSpeed > 0.2 ) if ( translationalSpeed + rotationalSpeed > 0.2 )
@ -441,43 +442,27 @@ void Head::simulate(float deltaTime) {
_mode = AVATAR_MODE_INTERACTING; _mode = AVATAR_MODE_INTERACTING;
} }
//----------------------------------------------------------
// update body yaw by body yaw delta // update body yaw by body yaw delta
//----------------------------------------------------------
if (_isMine) { if (_isMine) {
_bodyYaw += _bodyYawDelta * deltaTime; _bodyYaw += _bodyYawDelta * deltaTime;
} }
//----------------------------------------------------------
// decay body yaw delta // decay body yaw delta
//----------------------------------------------------------
_bodyYawDelta *= (1.0 - TEST_YAW_DECAY * deltaTime); _bodyYawDelta *= (1.0 - TEST_YAW_DECAY * deltaTime);
//----------------------------------------------------------
// add thrust to velocity // add thrust to velocity
//----------------------------------------------------------
_velocity += glm::dvec3(_thrust * deltaTime); _velocity += glm::dvec3(_thrust * deltaTime);
//----------------------------------------------------------
// update position by velocity // update position by velocity
//----------------------------------------------------------
_position += (glm::vec3)_velocity * deltaTime; _position += (glm::vec3)_velocity * deltaTime;
//----------------------------------------------------------
// decay velocity // decay velocity
//----------------------------------------------------------
_velocity *= ( 1.0 - LIN_VEL_DECAY * deltaTime ); _velocity *= ( 1.0 - LIN_VEL_DECAY * deltaTime );
// //
// Update Head information // Update Head information
// //
// we will be eventually getting head rotation from elsewhere. For now, just setting it to body rotation
//_head.yaw = _bodyYaw;
//_head.pitch = _bodyPitch;
//_head.roll = _bodyRoll;
if (!_head.noise) { if (!_head.noise) {
// Decay back toward center // Decay back toward center
_headPitch *= (1.0f - DECAY * 2 * deltaTime); _headPitch *= (1.0f - DECAY * 2 * deltaTime);
@ -573,23 +558,21 @@ void Head::simulate(float deltaTime) {
} }
float Head::getGirth() { float Avatar::getGirth() {
return COLLISION_BODY_RADIUS; return COLLISION_BODY_RADIUS;
} }
float Head::getHeight() { float Avatar::getHeight() {
return COLLISION_HEIGHT; return COLLISION_HEIGHT;
} }
glm::vec3 Head::getBodyUpDirection() { glm::vec3 Avatar::getBodyUpDirection() {
return _orientation.getUp(); return _orientation.getUp();
} }
//--------------------------------------------------------------------------------
// This is a workspace for testing avatar body collision detection and response // This is a workspace for testing avatar body collision detection and response
//-------------------------------------------------------------------------------- void Avatar::updateAvatarCollisionDetectionAndResponse
void Head::updateAvatarCollisionDetectionAndResponse
( glm::vec3 collisionPosition, float collisionGirth, float collisionHeight, glm::vec3 collisionUpVector, float deltaTime ) { ( glm::vec3 collisionPosition, float collisionGirth, float collisionHeight, glm::vec3 collisionUpVector, float deltaTime ) {
float myBodyApproximateBoundingRadius = 1.0f; float myBodyApproximateBoundingRadius = 1.0f;
@ -630,14 +613,9 @@ void Head::updateAvatarCollisionDetectionAndResponse
} }
} }
void Avatar::render(bool lookingInMirror) {
void Head::render(bool lookingInMirror) {
//---------------------------------------------------
// show avatar position // show avatar position
//---------------------------------------------------
glColor4f( 0.5f, 0.5f, 0.5f, 0.6 ); glColor4f( 0.5f, 0.5f, 0.5f, 0.6 );
glPushMatrix(); glPushMatrix();
glTranslatef(_position.x, _position.y, _position.z); glTranslatef(_position.x, _position.y, _position.z);
@ -646,9 +624,8 @@ void Head::render(bool lookingInMirror) {
glPopMatrix(); glPopMatrix();
if ( usingBigSphereCollisionTest ) { if ( usingBigSphereCollisionTest ) {
//---------------------------------------------------
// show TEST big sphere // show TEST big sphere
//---------------------------------------------------
glColor4f( 0.5f, 0.6f, 0.8f, 0.7 ); glColor4f( 0.5f, 0.6f, 0.8f, 0.7 );
glPushMatrix(); glPushMatrix();
glTranslatef(_TEST_bigSpherePosition.x, _TEST_bigSpherePosition.y, _TEST_bigSpherePosition.z); glTranslatef(_TEST_bigSpherePosition.x, _TEST_bigSpherePosition.y, _TEST_bigSpherePosition.z);
@ -657,49 +634,38 @@ void Head::render(bool lookingInMirror) {
glPopMatrix(); glPopMatrix();
} }
//---------------------------------------------------
// render body // render body
//---------------------------------------------------
renderBody(); renderBody();
//---------------------------------------------------
// render head // render head
//---------------------------------------------------
renderHead(lookingInMirror); renderHead(lookingInMirror);
//--------------------------------------------------------------------------- // if this is my avatar, then render my interactions with the other avatar
// if this is my avatar, then render my interactions with the other avatars
//---------------------------------------------------------------------------
if ( _isMine ) if ( _isMine )
{ {
if (_usingBodySprings) { if ( _interactingOtherIsNearby ) {
if ( _nearOtherAvatar ) {
glm::vec3 v1( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); glm::vec3 v1( _bone[ AVATAR_BONE_RIGHT_HAND ].position );
glm::vec3 v2( _otherAvatar.handPosition ); glm::vec3 v2( _interactingOther->_handPosition );
glLineWidth( 8.0 ); glLineWidth( 8.0 );
glColor4f( 0.7f, 0.4f, 0.1f, 0.6 ); glColor4f( 0.7f, 0.4f, 0.1f, 0.6 );
glBegin( GL_LINE_STRIP ); glBegin( GL_LINE_STRIP );
glVertex3f( v1.x, v1.y, v1.z ); glVertex3f( v1.x, v1.y, v1.z );
glVertex3f( v2.x, v2.y, v2.z ); glVertex3f( v2.x, v2.y, v2.z );
glEnd(); glEnd();
}
} }
} }
} }
void Head::renderHead(bool lookingInMirror) { void Avatar::renderHead(bool lookingInMirror) {
int side = 0; int side = 0;
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_RESCALE_NORMAL); glEnable(GL_RESCALE_NORMAL);
//---------------------------------------------------
// show head orientation // show head orientation
//---------------------------------------------------
//renderOrientationDirections( _bone[ AVATAR_BONE_HEAD ].position, _bone[ AVATAR_BONE_HEAD ].orientation, 0.2f ); //renderOrientationDirections( _bone[ AVATAR_BONE_HEAD ].position, _bone[ AVATAR_BONE_HEAD ].orientation, 0.2f );
glPushMatrix(); glPushMatrix();
@ -855,7 +821,7 @@ void Head::renderHead(bool lookingInMirror) {
glPopMatrix(); glPopMatrix();
} }
void Head::startHandMovement() { void Avatar::startHandMovement() {
if (!_usingBodySprings) { if (!_usingBodySprings) {
initializeBodySprings(); initializeBodySprings();
@ -863,19 +829,19 @@ void Head::startHandMovement() {
} }
} }
void Head::stopHandMovement() { void Avatar::stopHandMovement() {
//_usingBodySprings = false; //_usingBodySprings = false;
} }
void Head::setHandMovementValues( glm::vec3 handOffset ) { void Avatar::setHandMovementValues( glm::vec3 handOffset ) {
_movedHandOffset = handOffset; _movedHandOffset = handOffset;
} }
AvatarMode Head::getMode() { AvatarMode Avatar::getMode() {
return _mode; return _mode;
} }
void Head::initializeSkeleton() { void Avatar::initializeSkeleton() {
for (int b=0; b<NUM_AVATAR_BONES; b++) { for (int b=0; b<NUM_AVATAR_BONES; b++) {
_bone[b].parent = AVATAR_BONE_NULL; _bone[b].parent = AVATAR_BONE_NULL;
@ -920,9 +886,7 @@ void Head::initializeSkeleton() {
_bone[ AVATAR_BONE_RIGHT_SHIN ].parent = AVATAR_BONE_RIGHT_THIGH; _bone[ AVATAR_BONE_RIGHT_SHIN ].parent = AVATAR_BONE_RIGHT_THIGH;
_bone[ AVATAR_BONE_RIGHT_FOOT ].parent = AVATAR_BONE_RIGHT_SHIN; _bone[ AVATAR_BONE_RIGHT_FOOT ].parent = AVATAR_BONE_RIGHT_SHIN;
//----------------------------------------------------------
// specify the default pose position // specify the default pose position
//----------------------------------------------------------
_bone[ AVATAR_BONE_PELVIS_SPINE ].defaultPosePosition = glm::vec3( 0.0, 0.3, 0.0 ); _bone[ AVATAR_BONE_PELVIS_SPINE ].defaultPosePosition = glm::vec3( 0.0, 0.3, 0.0 );
_bone[ AVATAR_BONE_MID_SPINE ].defaultPosePosition = glm::vec3( 0.0, 0.1, 0.0 ); _bone[ AVATAR_BONE_MID_SPINE ].defaultPosePosition = glm::vec3( 0.0, 0.1, 0.0 );
_bone[ AVATAR_BONE_CHEST_SPINE ].defaultPosePosition = glm::vec3( 0.0, 0.06, 0.0 ); _bone[ AVATAR_BONE_CHEST_SPINE ].defaultPosePosition = glm::vec3( 0.0, 0.06, 0.0 );
@ -972,18 +936,14 @@ void Head::initializeSkeleton() {
_bone[ AVATAR_BONE_RIGHT_SHIN ].radius = 0.015; _bone[ AVATAR_BONE_RIGHT_SHIN ].radius = 0.015;
_bone[ AVATAR_BONE_RIGHT_FOOT ].radius = 0.02; _bone[ AVATAR_BONE_RIGHT_FOOT ].radius = 0.02;
//----------------------------------------------------------------------------
// calculate bone length // calculate bone length
//----------------------------------------------------------------------------
calculateBoneLengths(); calculateBoneLengths();
//----------------------------------------------------------------------------
// generate world positions // generate world positions
//----------------------------------------------------------------------------
updateSkeleton(); updateSkeleton();
} }
void Head::calculateBoneLengths() { void Avatar::calculateBoneLengths() {
for (int b=0; b<NUM_AVATAR_BONES; b++) { for (int b=0; b<NUM_AVATAR_BONES; b++) {
_bone[b].length = glm::length( _bone[b].defaultPosePosition ); _bone[b].length = glm::length( _bone[b].defaultPosePosition );
} }
@ -994,16 +954,12 @@ void Head::calculateBoneLengths() {
+ _bone[ AVATAR_BONE_RIGHT_HAND ].length; + _bone[ AVATAR_BONE_RIGHT_HAND ].length;
} }
void Head::updateSkeleton() { void Avatar::updateSkeleton() {
//----------------------------------
// rotate body... // rotate body...
//----------------------------------
_orientation.setToIdentity(); _orientation.setToIdentity();
_orientation.yaw( _bodyYaw ); _orientation.yaw( _bodyYaw );
//------------------------------------------------------------------------
// calculate positions of all bones by traversing the skeleton tree: // calculate positions of all bones by traversing the skeleton tree:
//------------------------------------------------------------------------
for (int b=0; b<NUM_AVATAR_BONES; b++) { for (int b=0; b<NUM_AVATAR_BONES; b++) {
if ( _bone[b].parent == AVATAR_BONE_NULL ) { if ( _bone[b].parent == AVATAR_BONE_NULL ) {
_bone[b].orientation.set( _orientation ); _bone[b].orientation.set( _orientation );
@ -1014,9 +970,7 @@ void Head::updateSkeleton() {
_bone[b].position = _bone[ _bone[b].parent ].position; _bone[b].position = _bone[ _bone[b].parent ].position;
} }
//-------------------------------------------------------------------------------------
// if this is not my avatar, then hand position comes from transmitted data // if this is not my avatar, then hand position comes from transmitted data
//-------------------------------------------------------------------------------------
if ( ! _isMine ) { if ( ! _isMine ) {
_bone[ AVATAR_BONE_RIGHT_HAND ].position = _handPosition; _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handPosition;
} }
@ -1035,7 +989,7 @@ void Head::updateSkeleton() {
} }
} }
void Head::initializeBodySprings() { void Avatar::initializeBodySprings() {
for (int b=0; b<NUM_AVATAR_BONES; b++) { for (int b=0; b<NUM_AVATAR_BONES; b++) {
_bone[b].springyPosition = _bone[b].position; _bone[b].springyPosition = _bone[b].position;
_bone[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f ); _bone[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f );
@ -1043,7 +997,7 @@ void Head::initializeBodySprings() {
} }
void Head::updateBodySprings( float deltaTime ) { void Avatar::updateBodySprings( float deltaTime ) {
for (int b=0; b<NUM_AVATAR_BONES; b++) { for (int b=0; b<NUM_AVATAR_BONES; b++) {
glm::vec3 springVector( _bone[b].springyPosition ); glm::vec3 springVector( _bone[b].springyPosition );
@ -1083,7 +1037,7 @@ void Head::updateBodySprings( float deltaTime ) {
} }
} }
glm::vec3 Head::getHeadLookatDirection() { glm::vec3 Avatar::getHeadLookatDirection() {
return glm::vec3 return glm::vec3
( (
_orientation.getFront().x, _orientation.getFront().x,
@ -1092,7 +1046,7 @@ glm::vec3 Head::getHeadLookatDirection() {
); );
} }
glm::vec3 Head::getHeadLookatDirectionUp() { glm::vec3 Avatar::getHeadLookatDirectionUp() {
return glm::vec3 return glm::vec3
( (
_orientation.getUp().x, _orientation.getUp().x,
@ -1101,7 +1055,7 @@ glm::vec3 Head::getHeadLookatDirectionUp() {
); );
} }
glm::vec3 Head::getHeadLookatDirectionRight() { glm::vec3 Avatar::getHeadLookatDirectionRight() {
return glm::vec3 return glm::vec3
( (
_orientation.getRight().x, _orientation.getRight().x,
@ -1110,7 +1064,7 @@ glm::vec3 Head::getHeadLookatDirectionRight() {
); );
} }
glm::vec3 Head::getHeadPosition() { glm::vec3 Avatar::getHeadPosition() {
if ( _usingBodySprings ) { if ( _usingBodySprings ) {
return _bone[ AVATAR_BONE_HEAD ].springyPosition; return _bone[ AVATAR_BONE_HEAD ].springyPosition;
@ -1120,13 +1074,13 @@ glm::vec3 Head::getHeadPosition() {
} }
glm::vec3 Head::getBonePosition( AvatarBoneID b ) { glm::vec3 Avatar::getBonePosition( AvatarBoneID b ) {
return _bone[b].position; return _bone[b].position;
} }
void Head::updateHandMovement( float deltaTime ) { void Avatar::updateHandMovement( float deltaTime ) {
glm::vec3 transformedHandMovement; glm::vec3 transformedHandMovement;
transformedHandMovement transformedHandMovement
@ -1139,47 +1093,21 @@ void Head::updateHandMovement( float deltaTime ) {
if (_isMine) { if (_isMine) {
_handState = _mousePressed; _handState = _mousePressed;
} }
}
//---------------------------------------------------------------------
// if holding hands with another avatar, add a force to the hand...
//--------------------------------------------------------------------- void Avatar::updateArmIKAndConstraints( float deltaTime ) {
if (( getHandState() == 1 )
|| ( _otherAvatar.handState == 1 )) {
if ( _nearOtherAvatar ) {
glm::vec3 vectorToOtherHand = _otherAvatar.handPosition - _handHolding.position;
glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position;
_handHolding.velocity *= 0.7;
_handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime;
_handHolding.position += _handHolding.velocity;
_bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position;
}
}
else {
_handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position;
_handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 );
}
//-------------------------------------------------------------------------------
// determine the arm vector // determine the arm vector
//-------------------------------------------------------------------------------
glm::vec3 armVector = _bone[ AVATAR_BONE_RIGHT_HAND ].position; glm::vec3 armVector = _bone[ AVATAR_BONE_RIGHT_HAND ].position;
armVector -= _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; armVector -= _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position;
//-------------------------------------------------------------------------------
// test to see if right hand is being dragged beyond maximum arm length // test to see if right hand is being dragged beyond maximum arm length
//-------------------------------------------------------------------------------
float distance = glm::length( armVector ); float distance = glm::length( armVector );
//-------------------------------------------------------------------------------
// if right hand is being dragged beyond maximum arm length... // if right hand is being dragged beyond maximum arm length...
//-------------------------------------------------------------------------------
if ( distance > _maxArmLength ) { if ( distance > _maxArmLength ) {
//-------------------------------------------------------------------------------
// reset right hand to be constrained to maximum arm length // reset right hand to be constrained to maximum arm length
//-------------------------------------------------------------------------------
_bone[ AVATAR_BONE_RIGHT_HAND ].position = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; _bone[ AVATAR_BONE_RIGHT_HAND ].position = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position;
glm::vec3 armNormal = armVector / distance; glm::vec3 armNormal = armVector / distance;
armVector = armNormal * _maxArmLength; armVector = armNormal * _maxArmLength;
@ -1189,35 +1117,27 @@ void Head::updateHandMovement( float deltaTime ) {
_bone[ AVATAR_BONE_RIGHT_HAND ].position = constrainedPosition; _bone[ AVATAR_BONE_RIGHT_HAND ].position = constrainedPosition;
} }
//-----------------------------------------------------------------------------
// set elbow position // set elbow position
//-----------------------------------------------------------------------------
glm::vec3 newElbowPosition = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; glm::vec3 newElbowPosition = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position;
newElbowPosition += armVector * ONE_HALF; newElbowPosition += armVector * ONE_HALF;
glm::vec3 perpendicular = glm::cross( _orientation.getFront(), armVector ); glm::vec3 perpendicular = glm::cross( _orientation.getFront(), armVector );
newElbowPosition += perpendicular * ( 1.0f - ( _maxArmLength / distance ) ) * ONE_HALF; newElbowPosition += perpendicular * ( 1.0f - ( _maxArmLength / distance ) ) * ONE_HALF;
_bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position = newElbowPosition; _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position = newElbowPosition;
//-----------------------------------------------------------------------------
// set wrist position // set wrist position
//-----------------------------------------------------------------------------
glm::vec3 vv( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); glm::vec3 vv( _bone[ AVATAR_BONE_RIGHT_HAND ].position );
vv -= _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position; vv -= _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position;
glm::vec3 newWristPosition = _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position; glm::vec3 newWristPosition = _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position;
newWristPosition += vv * 0.7f; newWristPosition += vv * 0.7f;
_bone[ AVATAR_BONE_RIGHT_FOREARM ].position = newWristPosition; _bone[ AVATAR_BONE_RIGHT_FOREARM ].position = newWristPosition;
// Set the vector we send for hand position to other people to be our right hand
setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position);
} }
void Head::renderBody() {
//----------------------------------------- void Avatar::renderBody() {
// Render bone positions as spheres // Render bone positions as spheres
//-----------------------------------------
for (int b=0; b<NUM_AVATAR_BONES; b++) { for (int b=0; b<NUM_AVATAR_BONES; b++) {
//renderBoneAsBlock( (AvatarBoneID)b); //renderBoneAsBlock( (AvatarBoneID)b);
@ -1240,9 +1160,7 @@ void Head::renderBody() {
} }
} }
//-----------------------------------------------------
// Render lines connecting the bone positions // Render lines connecting the bone positions
//-----------------------------------------------------
if ( _usingBodySprings ) { if ( _usingBodySprings ) {
glColor3f( 0.4f, 0.5f, 0.6f ); glColor3f( 0.4f, 0.5f, 0.6f );
glLineWidth(3.0); glLineWidth(3.0);
@ -1270,9 +1188,7 @@ void Head::renderBody() {
} }
} }
//---------------------------------------------------------
// if the hand is grasping, show it... // if the hand is grasping, show it...
//---------------------------------------------------------
if (( _usingBodySprings ) && ( _handState == 1 )) { if (( _usingBodySprings ) && ( _handState == 1 )) {
glPushMatrix(); glPushMatrix();
glTranslatef glTranslatef
@ -1289,9 +1205,7 @@ void Head::renderBody() {
} }
} }
void Avatar::renderBoneAsBlock( AvatarBoneID b ) {
void Head::renderBoneAsBlock( AvatarBoneID b ) {
glColor3fv( skinColor ); glColor3fv( skinColor );
glPushMatrix(); glPushMatrix();
glTranslatef( _bone[b].springyPosition.x, _bone[b].springyPosition.y, _bone[b].springyPosition.z ); glTranslatef( _bone[b].springyPosition.x, _bone[b].springyPosition.y, _bone[b].springyPosition.z );
@ -1303,13 +1217,13 @@ void Head::renderBoneAsBlock( AvatarBoneID b ) {
glPopMatrix(); glPopMatrix();
} }
void Head::SetNewHeadTarget(float pitch, float yaw) { void Avatar::SetNewHeadTarget(float pitch, float yaw) {
_head.pitchTarget = pitch; _head.pitchTarget = pitch;
_head.yawTarget = yaw; _head.yawTarget = yaw;
} }
// getting data from Android transmitte app // getting data from Android transmitte app
void Head::processTransmitterData(unsigned char* packetData, int numBytes) { void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) {
// Read a packet from a transmitter app, process the data // Read a packet from a transmitter app, process the data
float accX, accY, accZ, float accX, accY, accZ,
graX, graY, graZ, graX, graY, graZ,

View file

@ -1,13 +1,13 @@
// //
// Head.h // Avatar.h
// interface // interface
// //
// Created by Philip Rosedale on 9/11/12. // Created by Philip Rosedale on 9/11/12.
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved. // Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
// //
#ifndef __interface__head__ #ifndef __interface__avatar__
#define __interface__head__ #define __interface__avatar__
#include <AvatarData.h> #include <AvatarData.h>
#include <Orientation.h> #include <Orientation.h>
@ -100,13 +100,6 @@ struct AvatarHandHolding
float force; float force;
}; };
struct OtherAvatar
{
glm::vec3 handPosition;
int handState;
};
struct AvatarBone struct AvatarBone
{ {
AvatarBoneID parent; // which bone is this bone connected to? AvatarBoneID parent; // which bone is this bone connected to?
@ -163,12 +156,12 @@ struct AvatarHead
}; };
class Head : public AvatarData { class Avatar : public AvatarData {
public: public:
Head(bool isMine); Avatar(bool isMine);
~Head(); ~Avatar();
Head(const Head &otherHead); Avatar(const Avatar &otherAvatar);
Head* clone() const; Avatar* clone() const;
void reset(); void reset();
void UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity); void UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
@ -191,7 +184,6 @@ class Head : public AvatarData {
glm::vec3 getHeadPosition(); glm::vec3 getHeadPosition();
glm::vec3 getBonePosition( AvatarBoneID b ); glm::vec3 getBonePosition( AvatarBoneID b );
glm::vec3 getBodyUpDirection(); glm::vec3 getBodyUpDirection();
//int getHandState();
float getGirth(); float getGirth();
float getHeight(); float getHeight();
@ -206,6 +198,7 @@ class Head : public AvatarData {
void stopHandMovement(); void stopHandMovement();
void setHandMovementValues( glm::vec3 movement ); void setHandMovementValues( glm::vec3 movement );
void updateHandMovement( float deltaTime ); void updateHandMovement( float deltaTime );
void updateArmIKAndConstraints( float deltaTime );
float getAverageLoudness() {return _head.averageLoudness;}; float getAverageLoudness() {return _head.averageLoudness;};
void setAverageLoudness(float al) {_head.averageLoudness = al;}; void setAverageLoudness(float al) {_head.averageLoudness = al;};
@ -230,10 +223,8 @@ class Head : public AvatarData {
bool _isMine; bool _isMine;
glm::vec3 _TEST_bigSpherePosition; glm::vec3 _TEST_bigSpherePosition;
float _TEST_bigSphereRadius; float _TEST_bigSphereRadius;
OtherAvatar _otherAvatar;
bool _mousePressed; bool _mousePressed;
float _bodyYawDelta; float _bodyYawDelta;
bool _nearOtherAvatar;
bool _usingBodySprings; bool _usingBodySprings;
glm::vec3 _movedHandOffset; glm::vec3 _movedHandOffset;
float _springVelocityDecay; float _springVelocityDecay;
@ -253,10 +244,10 @@ class Head : public AvatarData {
timeval _transmitterTimer; timeval _transmitterTimer;
float _transmitterHz; float _transmitterHz;
int _transmitterPackets; int _transmitterPackets;
Avatar* _interactingOther;
bool _interactingOtherIsNearby;
//-----------------------------
// private methods... // private methods...
//-----------------------------
void initializeSkeleton(); void initializeSkeleton();
void updateSkeleton(); void updateSkeleton();
void initializeBodySprings(); void initializeBodySprings();

View file

@ -55,7 +55,7 @@ class Log {
public: public:
explicit Log(FILE* tPipeTo = stdout, unsigned bufferedLines = 1024, explicit Log(FILE* tPipeTo = stdout, unsigned bufferedLines = 1024,
unsigned defaultLogWidth = 240, unsigned defaultCharWidth = 6, unsigned defaultCharHeight = 20); unsigned defaultLogWidth = 400, unsigned defaultCharWidth = 6, unsigned defaultCharHeight = 20);
~Log(); ~Log();
void setLogWidth(unsigned pixels); void setLogWidth(unsigned pixels);

View file

@ -34,7 +34,17 @@ float Stars::changeLOD(float fraction, float overalloc, float realloc) {
return float(_ptrController->changeLOD(fraction, overalloc, realloc)); return float(_ptrController->changeLOD(fraction, overalloc, realloc));
} }
void Stars::render(float fovDiagonal, float aspect, glm::mat4 const& view) { void Stars::render(float fovY, float aspect, float nearZ) {
// determine length of screen diagonal from quadrant height and aspect ratio
float quadrantHeight = nearZ * tan(angleConvert<Degrees,Radians>(fovY) * 0.5f);
float halfDiagonal = sqrt(quadrantHeight * quadrantHeight * (1.0f + aspect * aspect));
// determine fov angle in respect to the diagonal
float fovDiagonal = atan(halfDiagonal / nearZ) * 2.0f;
// pull the modelview matrix off the GL stack
glm::mat4 view; glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(view));
_ptrController->render(fovDiagonal, aspect, glm::affineInverse(view)); _ptrController->render(fovDiagonal, aspect, glm::affineInverse(view));
} }

View file

@ -13,9 +13,9 @@
namespace starfield { class Controller; } namespace starfield { class Controller; }
/** //
* Starfield rendering component. // Starfield rendering component.
*/ //
class Stars { class Stars {
starfield::Controller* _ptrController; starfield::Controller* _ptrController;
@ -25,49 +25,49 @@ class Stars {
Stars(); Stars();
~Stars(); ~Stars();
/** //
* Reads input file from URL. Returns true upon success. // Reads input file from URL. Returns true upon success.
* //
* The limit parameter allows to reduce the number of stars // The limit parameter allows to reduce the number of stars
* that are loaded, keeping the brightest ones. // that are loaded, keeping the brightest ones.
*/ //
bool readInput(const char* url, const char* cacheFile = 0l, unsigned limit = 200000); bool readInput(const char* url, const char* cacheFile = 0l, unsigned limit = 200000);
/** //
* Renders the starfield from a local viewer's perspective. // Renders the starfield from a local viewer's perspective.
* The parameter specifies the field of view. // The parameters specifiy the field of view.
*/ //
void render(float fovDiagonal, float aspect, glm::mat4 const& view); void render(float fovY, float aspect, float nearZ);
/** //
* Sets the resolution for FOV culling. // Sets the resolution for FOV culling.
* //
* The parameter determines the number of tiles in azimuthal // The parameter determines the number of tiles in azimuthal
* and altitudinal directions. // and altitudinal directions.
* //
* GPU resources are updated upon change in which case 'true' // GPU resources are updated upon change in which case 'true'
* is returned. // is returned.
*/ //
bool setResolution(unsigned k); bool setResolution(unsigned k);
/** //
* Allows to alter the number of stars to be rendered given a // Allows to alter the number of stars to be rendered given a
* factor. The least brightest ones are omitted first. // factor. The least brightest ones are omitted first.
* //
* The further parameters determine when GPU resources should // The further parameters determine when GPU resources should
* be reallocated. Its value is fractional in respect to the // be reallocated. Its value is fractional in respect to the
* last number of stars 'n' that caused 'n * (1+overalloc)' to // last number of stars 'n' that caused 'n * (1+overalloc)' to
* be allocated. When the next call to setLOD causes the total // be allocated. When the next call to setLOD causes the total
* number of stars that could be rendered to drop below 'n * // number of stars that could be rendered to drop below 'n *
* (1-realloc)' or rises above 'n * (1+realloc)' GPU resources // (1-realloc)' or rises above 'n * (1+realloc)' GPU resources
* are updated. Note that all parameters must be fractions, // are updated. Note that all parameters must be fractions,
* that is within the range [0;1] and that 'overalloc' must be // that is within the range [0;1] and that 'overalloc' must be
* greater than or equal to 'realloc'. // greater than or equal to 'realloc'.
* //
* The current level of detail is returned as a float in [0;1]. // The current level of detail is returned as a float in [0;1].
*/ //
float changeLOD(float factor, float changeLOD(float factor,
float overalloc = 0.25, float realloc = 0.15); float overalloc = 0.25, float realloc = 0.15);
private: private:
// don't copy/assign // don't copy/assign

View file

@ -60,8 +60,8 @@ VoxelSystem::~VoxelSystem() {
pthread_mutex_destroy(&bufferWriteLock); pthread_mutex_destroy(&bufferWriteLock);
} }
void VoxelSystem::setViewerHead(Head *newViewerHead) { void VoxelSystem::setViewerAvatar(Avatar *newViewerAvatar) {
viewerHead = newViewerHead; viewerAvatar = newViewerAvatar;
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -187,7 +187,7 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosi
int voxelsAdded = 0; int voxelsAdded = 0;
float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE); float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE);
glm::vec3 viewerPosition = viewerHead->getPosition(); glm::vec3 viewerPosition = viewerAvatar->getPosition();
// debug LOD code // debug LOD code
glm::vec3 debugNodePosition; glm::vec3 debugNodePosition;

View file

@ -15,7 +15,7 @@
#include <AgentData.h> #include <AgentData.h>
#include <VoxelTree.h> #include <VoxelTree.h>
#include <ViewFrustum.h> #include <ViewFrustum.h>
#include "Head.h" #include "Avatar.h"
#include "Util.h" #include "Util.h"
#include "world.h" #include "world.h"
@ -34,7 +34,7 @@ public:
void render(); void render();
void setVoxelsRendered(int v) {voxelsRendered = v;}; void setVoxelsRendered(int v) {voxelsRendered = v;};
int getVoxelsRendered() {return voxelsRendered;}; int getVoxelsRendered() {return voxelsRendered;};
void setViewerHead(Head *newViewerHead); void setViewerAvatar(Avatar *newViewerAvatar);
void loadVoxelsFile(const char* fileName,bool wantColorRandomizer); void loadVoxelsFile(const char* fileName,bool wantColorRandomizer);
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer); void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer);
@ -67,7 +67,7 @@ private:
static float _minDistance; static float _minDistance;
int voxelsRendered; int voxelsRendered;
Head *viewerHead; Avatar *viewerAvatar;
VoxelTree *tree; VoxelTree *tree;
GLfloat *readVerticesArray; GLfloat *readVerticesArray;
GLubyte *readColorsArray; GLubyte *readColorsArray;

View file

@ -64,7 +64,7 @@
#include "MenuColumn.h" #include "MenuColumn.h"
#include "Menu.h" #include "Menu.h"
#include "Camera.h" #include "Camera.h"
#include "Head.h" #include "Avatar.h"
#include "Particle.h" #include "Particle.h"
#include "Texture.h" #include "Texture.h"
#include "Cloud.h" #include "Cloud.h"
@ -107,7 +107,7 @@ Oscilloscope audioScope(256,200,true);
ViewFrustum viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum viewFrustum; // current state of view frustum, perspective, orientation, etc.
Head myAvatar(true); // The rendered avatar of oneself Avatar myAvatar(true); // The rendered avatar of oneself
Camera myCamera; // My view onto the world (sometimes on myself :) Camera myCamera; // My view onto the world (sometimes on myself :)
Camera viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode Camera viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
@ -157,6 +157,8 @@ VoxelDetail paintingVoxel; // The voxel we're painting if we're paintin
unsigned char dominantColor = 0; // The dominant color of the voxel we're painting unsigned char dominantColor = 0; // The dominant color of the voxel we're painting
bool perfStatsOn = false; // Do we want to display perfStats? bool perfStatsOn = false; // Do we want to display perfStats?
bool logOn = true; // Whether to show on-screen log
int noiseOn = 0; // Whether to add random noise int noiseOn = 0; // Whether to add random noise
float noise = 1.0; // Overall magnitude scaling for random noise levels float noise = 1.0; // Overall magnitude scaling for random noise levels
@ -382,7 +384,7 @@ void initDisplay(void)
void init(void) void init(void)
{ {
voxels.init(); voxels.init();
voxels.setViewerHead(&myAvatar); voxels.setViewerAvatar(&myAvatar);
myAvatar.setRenderYaw(startYaw); myAvatar.setRenderYaw(startYaw);
initializeHandController(); initializeHandController();
@ -862,9 +864,10 @@ void display(void)
if (::starsOn) { if (::starsOn) {
// should be the first rendering pass - w/o depth buffer / lighting // should be the first rendering pass - w/o depth buffer / lighting
glm::mat4 view;
glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(view)); // finally render the starfield
stars.render(angleConvert<Degrees,Radians>(whichCamera.getFieldOfView()), aspectRatio, view); stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip());
} }
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
@ -919,7 +922,7 @@ void display(void)
if ( !::lookingInMirror ) balls.render(); if ( !::lookingInMirror ) balls.render();
// Render the world box // Render the world box
if (!::lookingInMirror && statsOn) render_world_box(); if (!::lookingInMirror && ::statsOn) { render_world_box(); }
// brad's frustum for debugging // brad's frustum for debugging
if (::frustumOn) renderViewFrustum(::viewFrustum); if (::frustumOn) renderViewFrustum(::viewFrustum);
@ -961,13 +964,12 @@ void display(void)
// Show detected levels from the serial I/O ADC channel sensors // Show detected levels from the serial I/O ADC channel sensors
if (displayLevels) serialPort.renderLevels(WIDTH,HEIGHT); if (displayLevels) serialPort.renderLevels(WIDTH,HEIGHT);
// Display miscellaneous text stats onscreen // Display stats and log text onscreen
if (statsOn) { glLineWidth(1.0f);
glLineWidth(1.0f); glPointSize(1.0f);
glPointSize(1.0f);
displayStats(); if (::statsOn) { displayStats(); }
logger.render(WIDTH, HEIGHT); if (::logOn) { logger.render(WIDTH, HEIGHT); }
}
// Show menu // Show menu
if (::menuOn) { if (::menuOn) {
@ -1057,6 +1059,11 @@ int setNoise(int state) {
return iRet; return iRet;
} }
int setLog(int state) {
int iRet = setValue(state, &::logOn);
return iRet;
}
int setGyroLook(int state) { int setGyroLook(int state) {
int iRet = setValue(state, &::gyroLook); int iRet = setValue(state, &::gyroLook);
return iRet; return iRet;
@ -1071,7 +1078,7 @@ int setStars(int state) {
} }
int setStats(int state) { int setStats(int state) {
return setValue(state, &statsOn); return setValue(state, &::statsOn);
} }
int setMenu(int state) { int setMenu(int state) {
@ -1196,7 +1203,8 @@ void initMenu() {
// Tools // Tools
menuColumnTools = menu.addColumn("Tools"); menuColumnTools = menu.addColumn("Tools");
menuColumnTools->addRow("Stats (/)", setStats); menuColumnTools->addRow("Stats (/)", setStats);
menuColumnTools->addRow("Log ", setLog);
menuColumnTools->addRow("(M)enu", setMenu); menuColumnTools->addRow("(M)enu", setMenu);
// Frustum Options // Frustum Options
@ -1354,7 +1362,7 @@ void key(unsigned char k, int x, int y)
// Process keypresses // Process keypresses
if (k == 'q' || k == 'Q') ::terminate(); if (k == 'q' || k == 'Q') ::terminate();
if (k == '/') statsOn = !statsOn; // toggle stats if (k == '/') ::statsOn = !::statsOn; // toggle stats
if (k == '*') ::starsOn = !::starsOn; // toggle stars if (k == '*') ::starsOn = !::starsOn; // toggle stars
if (k == 'V' || k == 'v') ::showingVoxels = !::showingVoxels; // toggle voxels if (k == 'V' || k == 'v') ::showingVoxels = !::showingVoxels; // toggle voxels
if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging
@ -1603,7 +1611,7 @@ void mouseoverFunc( int x, int y)
void attachNewHeadToAgent(Agent *newAgent) { void attachNewHeadToAgent(Agent *newAgent) {
if (newAgent->getLinkedData() == NULL) { if (newAgent->getLinkedData() == NULL) {
newAgent->setLinkedData(new Head(false)); newAgent->setLinkedData(new Avatar(false));
} }
} }

View file

@ -130,17 +130,18 @@ namespace starfield {
float halfPersp = perspective * 0.5f; float halfPersp = perspective * 0.5f;
// determine dimensions based on a sought screen diagonal // define diagonal and near distance
// float halfDiag = std::sin(halfPersp);
// ww + hh = dd
// a = h / w => h = wa
// ww + ww aa = dd
// ww = dd / (1 + aa)
float diag = 2.0f * std::sin(halfPersp);
float nearClip = std::cos(halfPersp); float nearClip = std::cos(halfPersp);
float hw = 0.5f * sqrt(diag * diag / (1.0f + aspect * aspect)); // determine half dimensions based on the screen diagonal
float hh = hw * aspect; //
// ww + hh = dd
// a = w / h => w = ha
// hh + hh aa = dd
// hh = dd / (1 + aa)
float hh = sqrt(halfDiag * halfDiag / (1.0f + aspect * aspect));
float hw = hh * aspect;
// cancel all translation // cancel all translation
mat4 matrix = orientation; mat4 matrix = orientation;
@ -154,6 +155,9 @@ namespace starfield {
float azimuth = atan2(ahead.x,-ahead.z) + Radians::pi(); float azimuth = atan2(ahead.x,-ahead.z) + Radians::pi();
float altitude = atan2(-ahead.y, hypotf(ahead.x, ahead.z)); float altitude = atan2(-ahead.y, hypotf(ahead.x, ahead.z));
angleHorizontalPolar<Radians>(azimuth, altitude); angleHorizontalPolar<Radians>(azimuth, altitude);
float const eps = 0.002f;
altitude = glm::clamp(altitude,
-Radians::halfPi() + eps, Radians::halfPi() - eps);
#if STARFIELD_HEMISPHERE_ONLY #if STARFIELD_HEMISPHERE_ONLY
altitude = std::max(0.0f, altitude); altitude = std::max(0.0f, altitude);
#endif #endif
@ -162,24 +166,25 @@ namespace starfield {
// printLog("Stars.cpp: starting on tile #%d\n", tileIndex); // printLog("Stars.cpp: starting on tile #%d\n", tileIndex);
#if STARFIELD_DEBUG_CULLING #if STARFIELD_DEBUG_CULLING
mat4 matrix_debug = glm::translate( mat4 matrix_debug = glm::translate(glm::frustum(-hw, hw, -hh, hh, nearClip, 10.0f),
glm::frustum(-hw, hw, -hh, hh, nearClip, 10.0f), vec3(0.0f, 0.0f, -4.0f)) *
vec3(0.0f, 0.0f, -4.0f)) * glm::affineInverse(matrix); glm::affineInverse(matrix);
#endif #endif
matrix = glm::frustum(-hw,hw, -hh,hh, nearClip,10.0f) matrix = glm::frustum(-hw,hw, -hh,hh, nearClip,10.0f) * glm::affineInverse(matrix);
* glm::affineInverse(matrix);
this->_itrOutIndex = (unsigned*) _arrBatchOffs; this->_itrOutIndex = (unsigned*) _arrBatchOffs;
this->_vecWxform = vec3(row(matrix, 3)); this->_vecWxform = vec3(row(matrix, 3));
this->_valHalfPersp = halfPersp; this->_valHalfPersp = halfPersp;
this->_valMinBright = minBright; this->_valMinBright = minBright;
floodFill(_arrTile + tileIndex, TileSelection(*this, TileSelection::Cursor cursor;
_arrTile, _arrTile + _objTiling.getTileCount(), cursor.current = _arrTile + _objTiling.getTileIndex(azimuth, altitude);
(Tile**) _arrBatchCount)); cursor.firstInRow = _arrTile + _objTiling.getTileIndex(0.0f, altitude);
floodFill(cursor, TileSelection(*this, _arrTile, _arrTile + _objTiling.getTileCount(),
(TileSelection::Cursor*) _arrBatchCount));
#if STARFIELD_DEBUG_CULLING #if STARFIELD_DEBUG_CULLING
# define matrix matrix_debug # define matrix matrix_debug
@ -269,31 +274,35 @@ namespace starfield {
class TileSelection { class TileSelection {
public:
struct Cursor { Tile* current, * firstInRow; };
private:
Renderer& _refRenderer; Renderer& _refRenderer;
Tile** const _arrStack; Cursor* const _arrStack;
Tile** _itrStack; Cursor* _itrStack;
Tile const* const _arrTile; Tile const* const _arrTile;
Tile const* const _itrTilesEnd; Tile const* const _ptrTilesEnd;
public: public:
TileSelection(Renderer& renderer, Tile const* tiles, TileSelection(Renderer& renderer, Tile const* tiles,
Tile const* tiles_end, Tile** stack) : Tile const* tiles_end, Cursor* stack) :
_refRenderer(renderer), _refRenderer(renderer),
_arrStack(stack), _arrStack(stack),
_itrStack(stack), _itrStack(stack),
_arrTile(tiles), _arrTile(tiles),
_itrTilesEnd(tiles_end) { _ptrTilesEnd(tiles_end) {
} }
protected: protected:
// flood fill strategy // flood fill strategy
bool select(Tile* t) { bool select(Cursor const& c) {
Tile* t = c.current;
if (t < _arrTile || t >= _itrTilesEnd || if (t < _arrTile || t >= _ptrTilesEnd ||
!! (t->flags & Tile::checked)) { !! (t->flags & Tile::checked)) {
// out of bounds or been here already // out of bounds or been here already
@ -311,7 +320,8 @@ namespace starfield {
return false; return false;
} }
bool process(Tile* t) { bool process(Cursor const& c) {
Tile* t = c.current;
if (! (t->flags & Tile::visited)) { if (! (t->flags & Tile::visited)) {
@ -321,14 +331,39 @@ namespace starfield {
return false; return false;
} }
void right(Tile*& cursor) const { cursor += 1; } void right(Cursor& c) const {
void left(Tile*& cursor) const { cursor -= 1; }
void up(Tile*& cursor) const { cursor += yStride(); }
void down(Tile*& cursor) const { cursor -= yStride(); }
void defer(Tile* t) { *_itrStack++ = t; } c.current += 1;
if (c.current == c.firstInRow + _refRenderer._objTiling.getAzimuthalTiles()) {
c.current = c.firstInRow;
}
}
void left(Cursor& c) const {
if (c.current == c.firstInRow) {
c.current = c.firstInRow + _refRenderer._objTiling.getAzimuthalTiles();
}
c.current -= 1;
}
void up(Cursor& c) const {
bool deferred(Tile*& cursor) { unsigned d = _refRenderer._objTiling.getAzimuthalTiles();
c.current += d;
c.firstInRow += d;
}
void down(Cursor& c) const {
unsigned d = _refRenderer._objTiling.getAzimuthalTiles();
c.current -= d;
c.firstInRow -= d;
}
void defer(Cursor const& t) {
*_itrStack++ = t;
}
bool deferred(Cursor& cursor) {
if (_itrStack != _arrStack) { if (_itrStack != _arrStack) {
cursor = *--_itrStack; cursor = *--_itrStack;
@ -336,12 +371,6 @@ namespace starfield {
} }
return false; return false;
} }
private:
unsigned yStride() const {
return _refRenderer._objTiling.getAzimuthalTiles();
}
}; };
bool visitTile(Tile* t) { bool visitTile(Tile* t) {
@ -362,6 +391,7 @@ namespace starfield {
bool tileVisible(Tile* t, unsigned i) { bool tileVisible(Tile* t, unsigned i) {
float slice = _objTiling.getSliceAngle(); float slice = _objTiling.getSliceAngle();
float halfSlice = 0.5f * slice;
unsigned stride = _objTiling.getAzimuthalTiles(); unsigned stride = _objTiling.getAzimuthalTiles();
float azimuth = (i % stride) * slice; float azimuth = (i % stride) * slice;
float altitude = (i / stride) * slice - Radians::halfPi(); float altitude = (i / stride) * slice - Radians::halfPi();
@ -371,14 +401,13 @@ namespace starfield {
vec3 tileCenter = vec3(gx * exz, sin(altitude), gz * exz); vec3 tileCenter = vec3(gx * exz, sin(altitude), gz * exz);
float w = dot(_vecWxform, tileCenter); float w = dot(_vecWxform, tileCenter);
float halfSlice = 0.5f * slice; float daz = halfSlice * cos(std::max(0.0f, abs(altitude) - halfSlice));
float daz = halfSlice * cos(abs(altitude) - halfSlice);
float dal = halfSlice; float dal = halfSlice;
float adjustedNear = cos(_valHalfPersp + sqrt(daz * daz + dal * dal)); float adjustedNear = cos(_valHalfPersp + sqrt(daz * daz + dal * dal));
// printLog("Stars.cpp: checking tile #%d, w = %f, near = %f\n", i, w, nearClip); // printLog("Stars.cpp: checking tile #%d, w = %f, near = %f\n", i, w, nearClip);
return w > adjustedNear; return w >= adjustedNear;
} }
void updateVertexCount(Tile* t, BrightnessLevel minBright) { void updateVertexCount(Tile* t, BrightnessLevel minBright) {

View file

@ -1,5 +1,5 @@
// //
// starfield/renderer/ // starfield/renderer/Tiling.h
// interface // interface
// //
// Created by Tobias Schwinger on 3/22/13. // Created by Tobias Schwinger on 3/22/13.
@ -51,6 +51,7 @@ namespace starfield {
private: private:
unsigned discreteAngle(float unsigned_angle) const { unsigned discreteAngle(float unsigned_angle) const {
return unsigned(floor(unsigned_angle * _valRcpSlice + 0.5f)); return unsigned(floor(unsigned_angle * _valRcpSlice + 0.5f));
} }

View file

@ -9,32 +9,31 @@
#ifndef __hifi__FloodFill__ #ifndef __hifi__FloodFill__
#define __hifi__FloodFill__ #define __hifi__FloodFill__
/** //
* Line scanning, iterative flood fill algorithm. // Line scanning, iterative flood fill algorithm.
* //
* The strategy must obey the following contract: // The strategy must obey the following contract:
* //
* There is an associated cursor that represents a position on the image. // There is an associated cursor that represents a position on the image.
* The member functions 'left(C&)', 'right(C&)', 'up(C&)', and 'down(C&)' // The member functions 'left(C&)', 'right(C&)', 'up(C&)', and 'down(C&)'
* move it. // move it.
* The state of a cursor can be deferred to temporary storage (typically a // The state of a cursor can be deferred to temporary storage (typically a
* stack or a queue) using the 'defer(C const&)' member function. // stack or a queue) using the 'defer(C const&)' member function.
* Calling 'deferred(C&)' restores a cursor's state from temporary storage // Calling 'deferred(C&)' restores a cursor's state from temporary storage
* and removes it there. // and removes it there.
* The 'select(C const&)' and 'process(C const&)' functions control the // The 'select(C const&)' and 'process(C const&)' functions control the
* algorithm. The former is called to determine where to go. It may be // 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 // 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 // '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 // overuse, otherwise). The latter will never be called for a given pixel
* unless previously selected. It may be called multiple times, in which // unless previously selected. It may be called multiple times, in which
* case it should return 'true' upon successful processing and 'false' // case it should return 'true' upon successful processing and 'false'
* when an already processed pixel has been visited. // when an already processed pixel has been visited.
* //
* Note: The terms "image" and "pixel" are used for illustratory purposes // Note: The terms "image" and "pixel" are used for illustratory purposes
* and mean "undirected graph with 4-connected 2D grid topology" and "node", // and mean "undirected graph with 4-connected 2D grid topology" and "node",
* respectively. // respectively.
* //
*/
template< class Strategy, typename Cursor > template< class Strategy, typename Cursor >
void floodFill(Cursor const& position, void floodFill(Cursor const& position,
Strategy const& strategy = Strategy()); Strategy const& strategy = Strategy());
@ -63,57 +62,39 @@ struct floodFill_impl : Strategy {
} }
Cursor higher, lower, h,l, i; Cursor higher, lower, h,l, i;
bool higherFound, lowerFound, hf, lf;
do { do {
if (! process(position)) { if (! process(position)) {
continue; continue;
} }
higher = position; higherFound = false; higher = position;
up(higher); yTest(higher, higherFound); up(higher);
lower = position; lowerFound = false; if (select(higher)) { defer(higher); }
down(lower); yTest(lower, lowerFound);
lower = position;
down(lower);
if (select(lower)) { defer(lower); }
i = position, h = higher, l = lower; i = position, h = higher, l = lower;
hf = higherFound, lf = lowerFound;
do { do {
right(i), right(h), right(l); yTest(h,hf); yTest(l,lf);
} while (selectAndProcess(i)); right(i), right(h), right(l);
if (select(h)) { defer(h); }
if (select(l)) { defer(l); }
} while (select(i) && process(i));
i = position, h = higher, l = lower; i = position, h = higher, l = lower;
hf = higherFound, lf = lowerFound;
do { do {
left(i); left(h); left(l); yTest(h,hf); yTest(l,lf); left(i); left(h); left(l);
if (select(h)) { defer(h); }
if (select(l)) { defer(l); }
} while (selectAndProcess(i)); } while (select(i) && process(i));
} while (deferred(position)); } while (deferred(position));
} }
bool selectAndProcess(Cursor const& i) {
if (select(i)) {
process(i);
return true;
}
return false;
}
void yTest(Cursor const& i, bool& state) {
if (! select(i)) {
state = false;
} else if (! state) {
state = true;
defer(i);
}
}
}; };
template< class Strategy, typename Cursor > template< class Strategy, typename Cursor >