cleanup of Avatar:: and MyAvatar::render()

MyAvatar now calls Avatar::render() which does most of the work.
Also, made ::renderBody() a proper virtual function
This commit is contained in:
Andrew Meadows 2014-03-17 10:22:02 -07:00
parent d4c7e25f8e
commit 68ba2201df
6 changed files with 55 additions and 104 deletions

View file

@ -189,55 +189,60 @@ static TextRenderer* textRenderer(TextRendererType type) {
return displayNameRenderer;
}
void Avatar::render(bool forShadowMap) {
void Avatar::render(const glm::vec3& cameraPosition, bool forShadowMap) {
// simple frustum check
float boundingRadius = getBillboardSize();
if (Application::getInstance()->getViewFrustum()->sphereInFrustum(_position, boundingRadius) == ViewFrustum::OUTSIDE) {
if (Application::getInstance()->getViewFrustum()->sphereInFrustum(cameraPosition, boundingRadius) == ViewFrustum::OUTSIDE) {
return;
}
glm::vec3 toTarget = _position - Application::getInstance()->getAvatar()->getPosition();
float lengthToTarget = glm::length(toTarget);
glm::vec3 toTarget = cameraPosition - Application::getInstance()->getAvatar()->getPosition();
float distanceToTarget = glm::length(toTarget);
{
// glow when moving in the distance
// glow when moving far away
const float GLOW_DISTANCE = 20.0f;
Glower glower(_moving && lengthToTarget > GLOW_DISTANCE && !forShadowMap ? 1.0f : 0.0f);
Glower glower(_moving && distanceToTarget > GLOW_DISTANCE && !forShadowMap ? 1.0f : 0.0f);
// render body
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
renderBody(forShadowMap);
}
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) {
_skeletonModel.renderCollisionProxies(0.7f);
}
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionProxies)) {
getHead()->getFaceModel().renderCollisionProxies(0.7f);
}
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
renderBody();
}
// render voice intensity sphere for avatars that are farther away
const float MAX_SPHERE_ANGLE = 10.f * RADIANS_PER_DEGREE;
const float MIN_SPHERE_ANGLE = 1.f * RADIANS_PER_DEGREE;
const float MIN_SPHERE_SIZE = 0.01f;
const float SPHERE_LOUDNESS_SCALING = 0.0005f;
const float SPHERE_COLOR[] = { 0.5f, 0.8f, 0.8f };
float height = getSkeletonHeight();
glm::vec3 delta = height * (getHead()->getCameraOrientation() * IDENTITY_UP) / 2.f;
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING;
if (!forShadowMap && (sphereRadius > MIN_SPHERE_SIZE) && (angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
glColor4f(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.f - angle / MAX_SPHERE_ANGLE);
glPushMatrix();
glTranslatef(_position.x, _position.y, _position.z);
glScalef(height, height, height);
glutSolidSphere(sphereRadius, 15, 15);
glPopMatrix();
// quick check before falling into the code below:
// (a 10 degree breadth of an almost 2 meter avatar kicks in at about 12m)
const float MIN_VOICE_SPHERE_DISTANCE = 12.f;
if (distanceToTarget > MIN_VOICE_SPHERE_DISTANCE) {
// render voice intensity sphere for avatars that are farther away
const float MAX_SPHERE_ANGLE = 10.f * RADIANS_PER_DEGREE;
const float MIN_SPHERE_ANGLE = 1.f * RADIANS_PER_DEGREE;
const float MIN_SPHERE_SIZE = 0.01f;
const float SPHERE_LOUDNESS_SCALING = 0.0005f;
const float SPHERE_COLOR[] = { 0.5f, 0.8f, 0.8f };
float height = getSkeletonHeight();
glm::vec3 delta = height * (getHead()->getCameraOrientation() * IDENTITY_UP) / 2.f;
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING;
if (!forShadowMap && (sphereRadius > MIN_SPHERE_SIZE) && (angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
glColor4f(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.f - angle / MAX_SPHERE_ANGLE);
glPushMatrix();
glTranslatef(_position.x, _position.y, _position.z);
glScalef(height, height, height);
glutSolidSphere(sphereRadius, 15, 15);
glPopMatrix();
}
}
}
const float DISPLAYNAME_DISTANCE = 10.0f;
setShowDisplayName(!forShadowMap && lengthToTarget < DISPLAYNAME_DISTANCE);
setShowDisplayName(!forShadowMap && distanceToTarget < DISPLAYNAME_DISTANCE);
if (forShadowMap) {
return;
}
@ -257,7 +262,6 @@ void Avatar::render(bool forShadowMap) {
glm::vec3 chatAxis = glm::axis(chatRotation);
glRotatef(glm::degrees(glm::angle(chatRotation)), chatAxis.x, chatAxis.y, chatAxis.z);
glColor3f(0.f, 0.8f, 0.f);
glRotatef(180.f, 0.f, 1.f, 0.f);
glRotatef(180.f, 0.f, 0.f, 1.f);
@ -302,9 +306,12 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
return glm::angleAxis(angle * proportion, axis);
}
void Avatar::renderBody() {
void Avatar::renderBody(bool forShadowMap) {
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
// render the billboard until both models are loaded
if (forShadowMap) {
return;
}
renderBillboard();
return;
}

View file

@ -74,7 +74,7 @@ public:
void init();
void simulate(float deltaTime);
void render(bool forShadowMap = false);
virtual void render(const glm::vec3& cameraPosition, bool forShadowMap);
//setters
void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); }
@ -181,6 +181,7 @@ protected:
float getPelvisToHeadLength() const;
void renderDisplayName();
virtual void renderBody(bool forShadowMap);
private:
@ -189,7 +190,6 @@ private:
bool _shouldRenderBillboard;
bool _modelsDirty;
void renderBody();
void renderBillboard();
float getBillboardSize() const;

View file

@ -77,7 +77,7 @@ void AvatarManager::renderAvatars(bool forShadowMapOrMirror, bool selfAvatarOnly
"Application::renderAvatars()");
bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors);
glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
if (!selfAvatarOnly) {
foreach (const AvatarSharedPointer& avatarPointer, _avatarHash) {
@ -85,17 +85,13 @@ void AvatarManager::renderAvatars(bool forShadowMapOrMirror, bool selfAvatarOnly
if (!avatar->isInitialized()) {
continue;
}
if (avatar == static_cast<Avatar*>(_myAvatar.data())) {
_myAvatar->render(forShadowMapOrMirror);
} else {
avatar->render(forShadowMapOrMirror);
}
avatar->render(cameraPosition, forShadowMapOrMirror);
avatar->setDisplayingLookatVectors(renderLookAtVectors);
}
renderAvatarFades(forShadowMapOrMirror);
renderAvatarFades(cameraPosition, forShadowMapOrMirror);
} else {
// just render myAvatar
_myAvatar->render(forShadowMapOrMirror);
_myAvatar->render(cameraPosition, forShadowMapOrMirror);
_myAvatar->setDisplayingLookatVectors(renderLookAtVectors);
}
}
@ -118,13 +114,15 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
}
}
void AvatarManager::renderAvatarFades(bool forShadowMap) {
void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, bool forShadowMap) {
// render avatar fades
Glower glower(forShadowMap ? 0.0f : 1.0f);
foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) {
Avatar* avatar = static_cast<Avatar*>(fadingAvatar.data());
avatar->render(forShadowMap);
if (avatar != static_cast<Avatar*>(_myAvatar.data())) {
avatar->render(cameraPosition, forShadowMap);
}
}
}

View file

@ -45,7 +45,7 @@ private:
void processKillAvatar(const QByteArray& datagram);
void simulateAvatarFades(float deltaTime);
void renderAvatarFades(bool forShadowMap);
void renderAvatarFades(const glm::vec3& cameraPosition, bool forShadowMap);
// virtual override
AvatarHash::iterator erase(const AvatarHash::iterator& iterator);

View file

@ -453,68 +453,14 @@ void MyAvatar::renderDebugBodyPoints() {
}
void MyAvatar::render(bool forShadowMapOrMirror) {
// virtual
void MyAvatar::render(const glm::vec3& cameraPosition, bool forShadowMapOrMirror) {
// don't render if we've been asked to disable local rendering
if (!_shouldRender) {
return; // exit early
}
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
renderBody(forShadowMapOrMirror);
}
// render body
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) {
_skeletonModel.renderCollisionProxies(0.8f);
}
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionProxies)) {
getHead()->getFaceModel().renderCollisionProxies(0.8f);
}
setShowDisplayName(!forShadowMapOrMirror);
if (forShadowMapOrMirror) {
return;
}
renderDisplayName();
if (!_chatMessage.empty()) {
int width = 0;
int lastWidth = 0;
for (string::iterator it = _chatMessage.begin(); it != _chatMessage.end(); it++) {
width += (lastWidth = textRenderer()->computeWidth(*it));
}
glPushMatrix();
glm::vec3 chatPosition = getHead()->getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale;
glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z);
glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation();
glm::vec3 chatAxis = glm::axis(chatRotation);
glRotatef(glm::degrees(glm::angle(chatRotation)), chatAxis.x, chatAxis.y, chatAxis.z);
glColor3f(0.f, 0.8f, 0.f);
glRotatef(180.f, 0.f, 1.f, 0.f);
glRotatef(180.f, 0.f, 0.f, 1.f);
glScalef(_scale * CHAT_MESSAGE_SCALE, _scale * CHAT_MESSAGE_SCALE, 1.0f);
glDisable(GL_LIGHTING);
glDepthMask(false);
if (_keyState == NO_KEY_DOWN) {
textRenderer()->draw(-width / 2.0f, 0, _chatMessage.c_str());
} else {
// rather than using substr and allocating a new string, just replace the last
// character with a null, then restore it
int lastIndex = _chatMessage.size() - 1;
char lastChar = _chatMessage[lastIndex];
_chatMessage[lastIndex] = '\0';
textRenderer()->draw(-width / 2.0f, 0, _chatMessage.c_str());
_chatMessage[lastIndex] = lastChar;
glColor3f(0.f, 1.f, 0.f);
textRenderer()->draw(width / 2.0f - lastWidth, 0, _chatMessage.c_str() + lastIndex);
}
glEnable(GL_LIGHTING);
glDepthMask(true);
glPopMatrix();
}
Avatar::render(cameraPosition, forShadowMapOrMirror);
}
void MyAvatar::renderHeadMouse() const {

View file

@ -35,7 +35,8 @@ public:
void simulate(float deltaTime);
void updateFromGyros(float deltaTime);
void render(bool forShadowMapOrMirror = false);
void render(const glm::vec3& cameraPosition, bool forShadowMapOrMirror = false);
void renderBody(bool forceRenderHead);
void renderDebugBodyPoints();
void renderHeadMouse() const;
@ -120,7 +121,6 @@ private:
bool _billboardValid;
// private methods
void renderBody(bool forceRenderHead);
void updateThrust(float deltaTime);
void updateHandMovementAndTouching(float deltaTime);
void updateCollisionWithAvatars(float deltaTime);