diff --git a/interface/src/Hair.cpp b/interface/src/Hair.cpp deleted file mode 100644 index c2d3f78b98..0000000000 --- a/interface/src/Hair.cpp +++ /dev/null @@ -1,256 +0,0 @@ -// -// Hair.cpp -// interface/src -// -// Created by Philip on June 26, 2014 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -// Creates single flexible verlet-integrated strands that can be used for hair/fur/grass - -#include - -#include "Util.h" -#include "world.h" - -#include "Hair.h" - - -const float HAIR_DAMPING = 0.99f; -const float CONSTRAINT_RELAXATION = 10.0f; -const float HAIR_ACCELERATION_COUPLING = 0.045f; -const float HAIR_ANGULAR_VELOCITY_COUPLING = 0.001f; -const float HAIR_ANGULAR_ACCELERATION_COUPLING = 0.001f; -const float HAIR_MAX_LINEAR_ACCELERATION = 4.0f; -const float HAIR_STIFFNESS = 0.00f; -const glm::vec3 HAIR_COLOR1(0.98f, 0.76f, 0.075f); -const glm::vec3 HAIR_COLOR2(0.912f, 0.184f, 0.101f); - -Hair::Hair(int strands, - int links, - float radius, - float linkLength, - float hairThickness) : - _strands(strands), - _links(links), - _linkLength(linkLength), - _hairThickness(hairThickness), - _radius(radius), - _acceleration(0.0f), - _angularVelocity(0.0f), - _angularAcceleration(0.0f), - _gravity(DEFAULT_GRAVITY), - _loudness(0.0f) -{ - _hairPosition = new glm::vec3[_strands * _links]; - _hairOriginalPosition = new glm::vec3[_strands * _links]; - _hairLastPosition = new glm::vec3[_strands * _links]; - _hairQuadDelta = new glm::vec3[_strands * _links]; - _hairNormals = new glm::vec3[_strands * _links]; - _hairColors = new glm::vec3[_strands * _links]; - _hairIsMoveable = new int[_strands * _links]; - _hairConstraints = new int[_strands * _links * HAIR_CONSTRAINTS]; // Hair can link to two others - glm::vec3 thisVertex; - for (int strand = 0; strand < _strands; strand++) { - float strandAngle = randFloat() * PI; - - float azimuth = (float)strand / (float)_strands * PI * 2.0f; - float elevation = 0.0f; - - glm::vec3 thisStrand(sinf(azimuth) * cosf(elevation), sinf(elevation), -cosf(azimuth) * cosf(elevation)); - thisStrand *= _radius; - - for (int link = 0; link < _links; link++) { - int vertexIndex = strand * _links + link; - // Clear constraints - for (int link2 = 0; link2 < HAIR_CONSTRAINTS; link2++) { - _hairConstraints[vertexIndex * HAIR_CONSTRAINTS + link2] = -1; - } - if (vertexIndex % _links == 0) { - // start of strand - thisVertex = thisStrand; - } else { - thisVertex+= glm::normalize(thisStrand) * _linkLength; - // Set constraints to vertex before and maybe vertex after in strand - _hairConstraints[vertexIndex * HAIR_CONSTRAINTS] = vertexIndex - 1; - if (link < (_links - 1)) { - _hairConstraints[vertexIndex * HAIR_CONSTRAINTS + 1] = vertexIndex + 1; - } - } - _hairOriginalPosition[vertexIndex] = _hairLastPosition[vertexIndex] = _hairPosition[vertexIndex] = thisVertex; - - _hairQuadDelta[vertexIndex] = glm::vec3(cos(strandAngle) * _hairThickness, 0.0f, sin(strandAngle) * _hairThickness); - _hairQuadDelta[vertexIndex] *= ((float)link / _links); - _hairNormals[vertexIndex] = glm::normalize(randVector()); - if (randFloat() < elevation / PI_OVER_TWO) { - _hairColors[vertexIndex] = HAIR_COLOR1 * ((float)(link + 1) / (float)_links); - } else { - _hairColors[vertexIndex] = HAIR_COLOR2 * ((float)(link + 1) / (float)_links); - } - } - } -} - -Hair::~Hair() { - delete[] _hairPosition; - delete[] _hairOriginalPosition; - delete[] _hairLastPosition; - delete[] _hairQuadDelta; - delete[] _hairNormals; - delete[] _hairColors; - delete[] _hairIsMoveable; - delete[] _hairConstraints; -} - -const float SOUND_THRESHOLD = 40.0f; - -void Hair::simulate(float deltaTime) { - deltaTime = glm::clamp(deltaTime, 0.0f, 1.0f / 30.0f); - glm::vec3 acceleration = _acceleration; - if (glm::length(acceleration) > HAIR_MAX_LINEAR_ACCELERATION) { - acceleration = glm::normalize(acceleration) * HAIR_MAX_LINEAR_ACCELERATION; - } - - for (int strand = 0; strand < _strands; strand++) { - for (int link = 0; link < _links; link++) { - int vertexIndex = strand * _links + link; - if (vertexIndex % _links == 0) { - // Base Joint - no integration - } else { - // - // Vertlet Integration - // - // Add velocity from last position, with damping - glm::vec3 thisPosition = _hairPosition[vertexIndex]; - glm::vec3 diff = thisPosition - _hairLastPosition[vertexIndex]; - _hairPosition[vertexIndex] += diff * HAIR_DAMPING; - - /* - // Resolve collisions with sphere - if (glm::length(_hairPosition[vertexIndex]) < _radius) { - _hairPosition[vertexIndex] += glm::normalize(_hairPosition[vertexIndex]) * - (_radius - glm::length(_hairPosition[vertexIndex])); - } */ - - // Collide with a conical body descending from the root of the hair - glm::vec3 thisVertex = _hairPosition[vertexIndex]; - float depth = -thisVertex.y; - thisVertex.y = 0.0f; - const float BODY_CONE_ANGLE = 0.30; - if (glm::length(thisVertex) < depth * BODY_CONE_ANGLE) { - _hairPosition[vertexIndex] += glm::normalize(thisVertex) * (depth * BODY_CONE_ANGLE - glm::length(thisVertex)); - } - - // Add random thing driven by loudness - float loudnessFactor = (_loudness > SOUND_THRESHOLD) ? logf(_loudness - SOUND_THRESHOLD) / 2000.0f : 0.0f; - - const float QUIESCENT_LOUDNESS = 0.0f; - _hairPosition[vertexIndex] += randVector() * (QUIESCENT_LOUDNESS + loudnessFactor) * ((float)link / (float)_links); - - // Add gravity - const float SCALE_GRAVITY = 0.001f; - _hairPosition[vertexIndex] += _gravity * deltaTime * SCALE_GRAVITY; - - // Add linear acceleration - _hairPosition[vertexIndex] -= acceleration * HAIR_ACCELERATION_COUPLING * deltaTime; - - // Add stiffness to return to original position - _hairPosition[vertexIndex] += (_hairOriginalPosition[vertexIndex] - _hairPosition[vertexIndex]) - * powf(1.0f - (float)link / _links, 2.0f) * HAIR_STIFFNESS; - - // Add angular acceleration - const float ANGULAR_VELOCITY_MIN = 0.001f; - if (glm::length(_angularVelocity) > ANGULAR_VELOCITY_MIN) { - glm::vec3 yawVector = _hairPosition[vertexIndex]; - glm::vec3 angularVelocity = _angularVelocity * HAIR_ANGULAR_VELOCITY_COUPLING; - glm::vec3 angularAcceleration = _angularAcceleration * HAIR_ANGULAR_ACCELERATION_COUPLING; - yawVector.y = 0.0f; - if (glm::length(yawVector) > EPSILON) { - float radius = glm::length(yawVector); - yawVector = glm::normalize(yawVector); - float angle = atan2f(yawVector.x, -yawVector.z) + PI; - glm::vec3 delta = glm::vec3(-1.0f, 0.0f, 0.0f) * glm::angleAxis(angle, glm::vec3(0, 1, 0)); - _hairPosition[vertexIndex] -= delta * radius * (angularVelocity.y - angularAcceleration.y) * deltaTime; - } - glm::vec3 pitchVector = _hairPosition[vertexIndex]; - pitchVector.x = 0.0f; - if (glm::length(pitchVector) > EPSILON) { - float radius = glm::length(pitchVector); - pitchVector = glm::normalize(pitchVector); - float angle = atan2f(pitchVector.y, -pitchVector.z) + PI; - glm::vec3 delta = glm::vec3(0.0f, 1.0f, 0.0f) * glm::angleAxis(angle, glm::vec3(1, 0, 0)); - _hairPosition[vertexIndex] -= delta * radius * (angularVelocity.x - angularAcceleration.x) * deltaTime; - } - glm::vec3 rollVector = _hairPosition[vertexIndex]; - rollVector.z = 0.0f; - if (glm::length(rollVector) > EPSILON) { - float radius = glm::length(rollVector); - pitchVector = glm::normalize(rollVector); - float angle = atan2f(rollVector.x, rollVector.y) + PI; - glm::vec3 delta = glm::vec3(-1.0f, 0.0f, 0.0f) * glm::angleAxis(angle, glm::vec3(0, 0, 1)); - _hairPosition[vertexIndex] -= delta * radius * (angularVelocity.z - angularAcceleration.z) * deltaTime; - } - } - - // Impose link constraints - for (int link = 0; link < HAIR_CONSTRAINTS; link++) { - if (_hairConstraints[vertexIndex * HAIR_CONSTRAINTS + link] > -1) { - // If there is a constraint, try to enforce it - glm::vec3 vectorBetween = _hairPosition[_hairConstraints[vertexIndex * HAIR_CONSTRAINTS + link]] - _hairPosition[vertexIndex]; - _hairPosition[vertexIndex] += glm::normalize(vectorBetween) * (glm::length(vectorBetween) - _linkLength) * CONSTRAINT_RELAXATION * deltaTime; - } - } - - // Store start position for next verlet pass - _hairLastPosition[vertexIndex] = thisPosition; - } - } - } -} - -void Hair::render() { - // - // Before calling this function, translate/rotate to the origin of the owning object - // - float loudnessFactor = (_loudness > SOUND_THRESHOLD) ? logf(_loudness - SOUND_THRESHOLD) / 16.0f : 0.0f; - const int SPARKLE_EVERY = 5; - const float HAIR_SETBACK = 0.0f; - int sparkleIndex = (int) (randFloat() * SPARKLE_EVERY); - glPushMatrix(); - glTranslatef(0.0f, 0.0f, HAIR_SETBACK); - glBegin(GL_QUADS); - for (int strand = 0; strand < _strands; strand++) { - for (int link = 0; link < _links - 1; link++) { - int vertexIndex = strand * _links + link; - glm::vec3 thisColor = _hairColors[vertexIndex]; - if (sparkleIndex % SPARKLE_EVERY == 0) { - thisColor.x += (1.0f - thisColor.x) * loudnessFactor; - thisColor.y += (1.0f - thisColor.y) * loudnessFactor; - thisColor.z += (1.0f - thisColor.z) * loudnessFactor; - } - glColor3fv(&thisColor.x); - glNormal3fv(&_hairNormals[vertexIndex].x); - glVertex3f(_hairPosition[vertexIndex].x - _hairQuadDelta[vertexIndex].x, - _hairPosition[vertexIndex].y - _hairQuadDelta[vertexIndex].y, - _hairPosition[vertexIndex].z - _hairQuadDelta[vertexIndex].z); - glVertex3f(_hairPosition[vertexIndex].x + _hairQuadDelta[vertexIndex].x, - _hairPosition[vertexIndex].y + _hairQuadDelta[vertexIndex].y, - _hairPosition[vertexIndex].z + _hairQuadDelta[vertexIndex].z); - - glVertex3f(_hairPosition[vertexIndex + 1].x + _hairQuadDelta[vertexIndex].x, - _hairPosition[vertexIndex + 1].y + _hairQuadDelta[vertexIndex].y, - _hairPosition[vertexIndex + 1].z + _hairQuadDelta[vertexIndex].z); - glVertex3f(_hairPosition[vertexIndex + 1].x - _hairQuadDelta[vertexIndex].x, - _hairPosition[vertexIndex + 1].y - _hairQuadDelta[vertexIndex].y, - _hairPosition[vertexIndex + 1].z - _hairQuadDelta[vertexIndex].z); - sparkleIndex++; - } - } - glEnd(); - glPopMatrix(); -} - - - diff --git a/interface/src/Hair.h b/interface/src/Hair.h deleted file mode 100644 index 436c6b836a..0000000000 --- a/interface/src/Hair.h +++ /dev/null @@ -1,70 +0,0 @@ -// -// Hair.h -// interface/src -// -// Created by Philip on June 26, 2014 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Hair_h -#define hifi_Hair_h - -#include - -#include -#include - -#include "GeometryUtil.h" -#include "InterfaceConfig.h" -#include "Util.h" - -const int HAIR_CONSTRAINTS = 2; - -const int DEFAULT_HAIR_STRANDS = 20; -const int DEFAULT_HAIR_LINKS = 11; -const float DEFAULT_HAIR_RADIUS = 0.075f; -const float DEFAULT_HAIR_LINK_LENGTH = 0.1f; -const float DEFAULT_HAIR_THICKNESS = 0.07f; -const glm::vec3 DEFAULT_GRAVITY(0.0f, -9.8f, 0.0f); - -class Hair { -public: - Hair(int strands = DEFAULT_HAIR_STRANDS, - int links = DEFAULT_HAIR_LINKS, - float radius = DEFAULT_HAIR_RADIUS, - float linkLength = DEFAULT_HAIR_LINK_LENGTH, - float hairThickness = DEFAULT_HAIR_THICKNESS); - ~Hair(); - void simulate(float deltaTime); - void render(); - void setAcceleration(const glm::vec3& acceleration) { _acceleration = acceleration; } - void setAngularVelocity(const glm::vec3& angularVelocity) { _angularVelocity = angularVelocity; } - void setAngularAcceleration(const glm::vec3& angularAcceleration) { _angularAcceleration = angularAcceleration; } - void setLoudness(const float loudness) { _loudness = loudness; } - -private: - int _strands; - int _links; - float _linkLength; - float _hairThickness; - float _radius; - glm::vec3* _hairPosition; - glm::vec3* _hairOriginalPosition; - glm::vec3* _hairLastPosition; - glm::vec3* _hairQuadDelta; - glm::vec3* _hairNormals; - glm::vec3* _hairColors; - int* _hairIsMoveable; - int* _hairConstraints; - glm::vec3 _acceleration; - glm::vec3 _angularVelocity; - glm::vec3 _angularAcceleration; - glm::vec3 _gravity; - float _loudness; - - }; - -#endif // hifi_Hair_h diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 2147dd9220..3e9bdde1ff 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -635,9 +635,6 @@ Menu::Menu() : connect(appInstance->getAudio(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled())); - QMenu* experimentalOptionsMenu = developerMenu->addMenu("Experimental"); - addCheckableActionToQMenuAndActionHash(experimentalOptionsMenu, MenuOption::StringHair, 0, false); - addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel, Qt::CTRL | Qt::SHIFT | Qt::Key_V, this, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 27e57983af..a3e32b3682 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -475,7 +475,6 @@ namespace MenuOption { const QString Stats = "Stats"; const QString StereoAudio = "Stereo Audio"; const QString StopAllScripts = "Stop All Scripts"; - const QString StringHair = "String Hair"; const QString SuppressShortTimings = "Suppress Timings Less than 10ms"; const QString TestPing = "Test Ping"; const QString ToolWindow = "Tool Window"; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 6b6316f578..3e57fc7dba 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -191,14 +191,6 @@ void Avatar::simulate(float deltaTime) { head->setScale(_scale); head->simulate(deltaTime, false, _shouldRenderBillboard); } - if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) { - PerformanceTimer perfTimer("hair"); - _hair.setAcceleration(getAcceleration() * getHead()->getFinalOrientationInWorldFrame()); - _hair.setAngularVelocity((getAngularVelocity() + getHead()->getAngularVelocity()) * getHead()->getFinalOrientationInWorldFrame()); - _hair.setAngularAcceleration(getAngularAcceleration() * getHead()->getFinalOrientationInWorldFrame()); - _hair.setLoudness((float) getHeadData()->getAudioLoudness()); - _hair.simulate(deltaTime); - } } // update animation for display name fade in/out @@ -543,18 +535,6 @@ void Avatar::renderBody(RenderMode renderMode, bool postLighting, float glowLeve } } getHead()->render(1.0f, modelRenderMode, postLighting); - - if (!postLighting && Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) { - // Render Hair - glPushMatrix(); - glm::vec3 headPosition = getHead()->getPosition(); - glTranslatef(headPosition.x, headPosition.y, headPosition.z); - const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame(); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - _hair.render(); - glPopMatrix(); - } } bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index d862e042c2..f4727de94c 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -19,7 +19,6 @@ #include -#include "Hair.h" #include "Hand.h" #include "Head.h" #include "InterfaceConfig.h" @@ -34,10 +33,6 @@ static const float RESCALING_TOLERANCE = .02f; extern const float CHAT_MESSAGE_SCALE; extern const float CHAT_MESSAGE_HEIGHT; -const int HAIR_STRANDS = 150; // Number of strands of hair -const int HAIR_LINKS = 10; // Number of links in a hair strand -const int HAIR_MAX_CONSTRAINTS = 2; // Hair verlet is connected to at most how many others - enum DriveKeys { FWD = 0, BACK, @@ -187,7 +182,6 @@ signals: void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision); protected: - Hair _hair; SkeletonModel _skeletonModel; glm::vec3 _skeletonOffset; QVector _attachmentModels; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4e3a9c4ff4..81d00bae74 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -225,17 +225,6 @@ void MyAvatar::simulate(float deltaTime) { head->simulate(deltaTime, true); } - { - PerformanceTimer perfTimer("hair"); - if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) { - _hair.setAcceleration(getAcceleration() * getHead()->getFinalOrientationInWorldFrame()); - _hair.setAngularVelocity((getAngularVelocity() + getHead()->getAngularVelocity()) * getHead()->getFinalOrientationInWorldFrame()); - _hair.setAngularAcceleration(getAngularAcceleration() * getHead()->getFinalOrientationInWorldFrame()); - _hair.setLoudness((float)getHeadData()->getAudioLoudness()); - _hair.simulate(deltaTime); - } - } - { PerformanceTimer perfTimer("physics"); const float minError = 0.00001f; @@ -1139,18 +1128,6 @@ void MyAvatar::renderBody(RenderMode renderMode, bool postLighting, float glowLe const glm::vec3 cameraPos = camera->getPosition(); if (shouldRenderHead(cameraPos, renderMode)) { getHead()->render(1.0f, modelRenderMode, postLighting); - - if (!postLighting && Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) { - // Render Hair - glPushMatrix(); - glm::vec3 headPosition = getHead()->getPosition(); - glTranslatef(headPosition.x, headPosition.y, headPosition.z); - const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame(); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - _hair.render(); - glPopMatrix(); - } } if (postLighting) { getHand()->render(true, modelRenderMode);