mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 13:09:52 +02:00
Merge remote-tracking branch 'upstream/master' into agentlist-array
This commit is contained in:
commit
5ddd9a9f4f
16 changed files with 429 additions and 482 deletions
|
@ -124,7 +124,6 @@ int main(int argc, const char* argv[]) {
|
||||||
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);
|
||||||
|
@ -171,6 +172,18 @@ int main(int argc, const char* argv[]) {
|
||||||
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
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
@ -73,9 +71,6 @@ Head::Head(bool isMine) {
|
||||||
_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.pitch = 0.0;
|
|
||||||
//_head.roll = 0.0;
|
|
||||||
_head.pitchRate = 0.0;
|
_head.pitchRate = 0.0;
|
||||||
_head.yawRate = 0.0;
|
_head.yawRate = 0.0;
|
||||||
_head.rollRate = 0.0;
|
_head.rollRate = 0.0;
|
||||||
|
@ -108,15 +103,15 @@ Head::Head(bool isMine) {
|
||||||
_head.lastLoudness = 0.0;
|
_head.lastLoudness = 0.0;
|
||||||
_head.browAudioLift = 0.0;
|
_head.browAudioLift = 0.0;
|
||||||
_head.noise = 0;
|
_head.noise = 0;
|
||||||
|
|
||||||
_movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 );
|
_movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 );
|
||||||
_usingBodySprings = true;
|
_usingBodySprings = true;
|
||||||
_springForce = 6.0f;
|
_springForce = 6.0f;
|
||||||
_springVelocityDecay = 16.0f;
|
_springVelocityDecay = 16.0f;
|
||||||
_renderYaw = 0.0;
|
_renderYaw = 0.0;
|
||||||
_renderPitch = 0.0;
|
_renderPitch = 0.0;
|
||||||
|
|
||||||
_sphere = NULL;
|
_sphere = NULL;
|
||||||
|
_interactingOther = NULL;
|
||||||
|
_interactingOtherIsNearby = false;
|
||||||
|
|
||||||
_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,19 +124,16 @@ 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;
|
||||||
|
@ -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
|
// check for collisions with other avatars and respond
|
||||||
//------------------------------------------------------
|
|
||||||
updateAvatarCollisionDetectionAndResponse
|
updateAvatarCollisionDetectionAndResponse
|
||||||
(
|
(
|
||||||
otherAvatar->getPosition(),
|
otherAvatar->getBonePosition( AVATAR_BONE_PELVIS_SPINE ),
|
||||||
otherAvatar->getGirth(),
|
0.2,
|
||||||
otherAvatar->getHeight(),
|
0.2,
|
||||||
otherAvatar->getBodyUpDirection(),
|
otherAvatar->getBodyUpDirection(),
|
||||||
deltaTime
|
deltaTime
|
||||||
);
|
);
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// test other avatar hand position for proximity
|
// test other avatar hand position for proximity
|
||||||
//------------------------------------------------
|
|
||||||
glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position );
|
glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position );
|
||||||
v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND );
|
v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND );
|
||||||
|
|
||||||
float distance = glm::length( v );
|
float distance = glm::length( v );
|
||||||
if ( distance < _maxArmLength ) {
|
if ( distance < _maxArmLength ) {
|
||||||
if ( distance < closestDistance ) {
|
|
||||||
|
//if ( distance < closestDistance ) { // perhaps I don't need this if we want to allow multi-avatar interactions
|
||||||
|
{
|
||||||
closestDistance = distance;
|
closestDistance = distance;
|
||||||
_nearOtherAvatar = true;
|
_interactingOther = otherAvatar;
|
||||||
_otherAvatar.handPosition = otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND );
|
_interactingOtherIsNearby = true;
|
||||||
_otherAvatar.handState = (int)otherAvatar->getHandState();
|
|
||||||
|
// if I am holding hands with another avatar, a force is applied
|
||||||
|
if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) {
|
||||||
|
glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHolding.position;
|
||||||
|
glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position;
|
||||||
|
|
||||||
|
_handHolding.velocity *= 0.7;
|
||||||
|
_handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime;
|
||||||
|
_handHolding.position += _handHolding.velocity;
|
||||||
|
|
||||||
|
_bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the vector we send for hand position to other people to be our right hand
|
||||||
|
setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position);
|
||||||
|
|
||||||
}//if ( _isMine )
|
}//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
|
|
||||||
//------------------------
|
|
||||||
updateSkeleton();
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// reset hand and arm positions according to hand movement
|
|
||||||
//------------------------------------------------------------
|
|
||||||
if (_usingBodySprings) {
|
|
||||||
updateHandMovement( deltaTime );
|
|
||||||
updateBodySprings( 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)
|
// driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely)
|
||||||
//-------------------------------------------------
|
if ( _isMine ) {
|
||||||
// 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]) {
|
||||||
|
@ -428,8 +431,6 @@ void Head::simulate(float 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,26 +634,19 @@ 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 );
|
||||||
|
@ -686,20 +656,16 @@ void Head::render(bool lookingInMirror) {
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Avatar::renderHead(bool lookingInMirror) {
|
||||||
void Head::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...
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
if (( getHandState() == 1 )
|
|
||||||
|| ( _otherAvatar.handState == 1 )) {
|
|
||||||
if ( _nearOtherAvatar ) {
|
|
||||||
|
|
||||||
glm::vec3 vectorToOtherHand = _otherAvatar.handPosition - _handHolding.position;
|
void Avatar::updateArmIKAndConstraints( float deltaTime ) {
|
||||||
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,
|
|
@ -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();
|
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,47 +25,47 @@ 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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
|
||||||
logger.render(WIDTH, HEIGHT);
|
if (::statsOn) { displayStats(); }
|
||||||
}
|
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) {
|
||||||
|
@ -1197,6 +1204,7 @@ 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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
bool deferred(Tile*& cursor) {
|
if (c.current == c.firstInRow) {
|
||||||
|
c.current = c.firstInRow + _refRenderer._objTiling.getAzimuthalTiles();
|
||||||
|
}
|
||||||
|
c.current -= 1;
|
||||||
|
}
|
||||||
|
void up(Cursor& c) const {
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 >
|
||||||
|
|
Loading…
Reference in a new issue