diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index f147ada803..829ccbff06 100755 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -99,10 +99,6 @@ find_package(OpenNI) find_package(UVCCameraControl) find_package(ZLIB) -# link the stk library -set(STK_ROOT_DIR ${ROOT_DIR}/externals/stk) -find_package(STK REQUIRED) - # let the source know that we have OpenNI/NITE for Kinect if (OPENNI_FOUND) add_definitions(-DHAVE_OPENNI) @@ -126,7 +122,6 @@ include_directories( ${LEAP_INCLUDE_DIRS} ${MOTIONDRIVER_INCLUDE_DIRS} ${OPENCV_INCLUDE_DIRS} - ${STK_INCLUDE_DIRS} ) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${OPENCV_INCLUDE_DIRS}") @@ -136,7 +131,6 @@ target_link_libraries( ${MOTIONDRIVER_LIBRARIES} ${OPENCV_LIBRARIES} ${ZLIB_LIBRARIES} - ${STK_LIBRARIES} fervor ) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp old mode 100755 new mode 100644 index 86b420f7f4..6f70c89f3b --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -73,6 +73,8 @@ using namespace std; static char STAR_FILE[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt"; static char STAR_CACHE_FILE[] = "cachedStars.txt"; +static const bool TESTING_PARTICLE_SYSTEM = false; + static const int BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH = 6; // farther dragged clicks are ignored const glm::vec3 START_LOCATION(4.f, 0.f, 5.f); // Where one's own node begins in the world @@ -2006,6 +2008,10 @@ void Application::update(float deltaTime) { _audio.setLastVelocity(_myAvatar.getVelocity()); _audio.eventuallyAnalyzePing(); #endif + + if (TESTING_PARTICLE_SYSTEM) { + _particleSystem.simulate(deltaTime); + } } void Application::updateAvatar(float deltaTime) { @@ -2449,6 +2455,10 @@ void Application::displaySide(Camera& whichCamera) { _myAvatar.render(_lookingInMirror->isChecked(), _renderAvatarBalls->isChecked()); _myAvatar.setDisplayingLookatVectors(_renderLookatOn->isChecked()); } + + if (TESTING_PARTICLE_SYSTEM) { + _particleSystem.render(); + } // Render the world box if (!_lookingInMirror->isChecked() && _renderStatsOn->isChecked()) { render_world_box(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index acb2263cbf..c6bbd4eec2 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -41,6 +41,7 @@ #include "ui/ChatEntry.h" #include "ToolsPalette.h" #include "Swatch.h" +#include "ParticleSystem.h" class QAction; class QActionGroup; @@ -366,6 +367,8 @@ private: GeometryCache _geometryCache; + ParticleSystem _particleSystem; + #ifndef _WIN32 Audio _audio; #endif diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index ab57d6d0df..88559ffdb1 100755 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -96,6 +96,8 @@ Avatar::Avatar(Node* owningNode) : _elapsedTimeMoving(0.0f), _elapsedTimeStopped(0.0f), _elapsedTimeSinceCollision(0.0f), + _speedBrakes(false), + _isThrustOn(false), _voxels(this) { // give the pointer to our head to inherited _headData variable from AvatarData @@ -420,8 +422,21 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { up; } } -} + // Update speed brake status + + const float MIN_SPEED_BRAKE_VELOCITY = 0.4f; + if ((glm::length(_thrust) == 0.0f) && _isThrustOn && (glm::length(_velocity) > MIN_SPEED_BRAKE_VELOCITY)) { + _speedBrakes = true; + } + + if (_speedBrakes && (glm::length(_velocity) < MIN_SPEED_BRAKE_VELOCITY)) { + _speedBrakes = false; + } + _isThrustOn = (glm::length(_thrust) > EPSILON); + +} + void Avatar::simulate(float deltaTime, Transmitter* transmitter) { glm::quat orientation = getOrientation(); @@ -559,9 +574,14 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { const float STATIC_FRICTION_STRENGTH = 20.f; applyStaticFriction(deltaTime, _velocity, MAX_STATIC_FRICTION_VELOCITY, STATIC_FRICTION_STRENGTH); - const float LINEAR_DAMPING_STRENGTH = 3.0f; + const float LINEAR_DAMPING_STRENGTH = 1.0f; + const float SPEED_BRAKE_POWER = 10.0f; const float SQUARED_DAMPING_STRENGTH = 0.2f; - applyDamping(deltaTime, _velocity, LINEAR_DAMPING_STRENGTH, SQUARED_DAMPING_STRENGTH); + if (_speedBrakes) { + applyDamping(deltaTime, _velocity, LINEAR_DAMPING_STRENGTH * SPEED_BRAKE_POWER, SQUARED_DAMPING_STRENGTH * SPEED_BRAKE_POWER); + } else { + applyDamping(deltaTime, _velocity, LINEAR_DAMPING_STRENGTH, SQUARED_DAMPING_STRENGTH); + } //pitch and roll the body as a function of forward speed and turning delta const float BODY_PITCH_WHILE_WALKING = -20.0; diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 777b4dca59..653971c3e5 100755 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -213,6 +213,8 @@ private: float _elapsedTimeMoving; // Timers to drive camera transitions when moving float _elapsedTimeStopped; float _elapsedTimeSinceCollision; + bool _speedBrakes; + bool _isThrustOn; AvatarVoxelSystem _voxels; diff --git a/interface/src/ParticleSystem.cpp b/interface/src/ParticleSystem.cpp new file mode 100644 index 0000000000..3c27f3a8df --- /dev/null +++ b/interface/src/ParticleSystem.cpp @@ -0,0 +1,183 @@ +// +// ParticleSystem.cpp +// hifi +// +// Created by Jeffrey on July 10, 2013 +// + +#include +#include "InterfaceConfig.h" +#include + +#include "ParticleSystem.h" + +ParticleSystem::ParticleSystem() { + + _numberOfParticles = 1500; + assert(_numberOfParticles <= MAX_PARTICLES); + + _bounce = 0.9f; + _timer = 0.0f; + _airFriction = 6.0f; + _jitter = 0.1f; + _homeAttraction = 0.0f; + _tornadoForce = 0.0f; + _neighborAttraction = 0.02f; + _neighborRepulsion = 0.9f; + _tornadoAxis = glm::normalize(glm::vec3(0.1f, 1.0f, 0.1f)); + _home = glm::vec3(5.0f, 1.0f, 5.0f); + + _TEST_bigSphereRadius = 0.5f; + _TEST_bigSpherePosition = glm::vec3( 5.0f, _TEST_bigSphereRadius, 5.0f); + + for (unsigned int p = 0; p < _numberOfParticles; p++) { + _particle[p].position = _home; + _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f); + + float radian = ((float)p / (float)_numberOfParticles) * PI_TIMES_TWO; + float wave = sinf(radian); + + float red = 0.5f + 0.5f * wave; + float green = 0.3f + 0.3f * wave; + float blue = 0.2f - 0.2f * wave; + + _particle[p].color = glm::vec3(red, green, blue); + _particle[p].age = 0.0f; + _particle[p].radius = 0.01f; + } +} + +void ParticleSystem::simulate(float deltaTime) { + + runSpecialEffectsTest(deltaTime); + + for (unsigned int p = 0; p < _numberOfParticles; p++) { + updateParticle(p, deltaTime); + } +} + + + +void ParticleSystem::runSpecialEffectsTest(float deltaTime) { + + _timer += deltaTime; + + _gravity = 0.01f + 0.01f * sinf( _timer * 0.52f ); + _airFriction = 3.0f + 2.0f * sinf( _timer * 0.32f ); + _jitter = 0.05f + 0.05f * sinf( _timer * 0.42f ); + _homeAttraction = 0.01f + 0.01f * cosf( _timer * 0.6f ); + _tornadoForce = 0.0f + 0.03f * sinf( _timer * 0.7f ); + _neighborAttraction = 0.1f + 0.1f * cosf( _timer * 0.8f ); + _neighborRepulsion = 0.4f + 0.3f * sinf( _timer * 0.4f ); + + _tornadoAxis = glm::vec3 + ( + 0.0f + 0.5f * sinf( _timer * 0.55f ), + 1.0f, + 0.0f + 0.5f * cosf( _timer * 0.75f ) + ); +} + + + +void ParticleSystem::updateParticle(int p, float deltaTime) { + + _particle[p].age += deltaTime; + + // apply random jitter + _particle[p].velocity += + glm::vec3 + ( + -_jitter * ONE_HALF + _jitter * randFloat(), + -_jitter * ONE_HALF + _jitter * randFloat(), + -_jitter * ONE_HALF + _jitter * randFloat() + ) * deltaTime; + + + // apply attraction to home position + glm::vec3 vectorToHome = _home - _particle[p].position; + _particle[p].velocity += vectorToHome * _homeAttraction * deltaTime; + + // apply neighbor attraction + int neighbor = p + 1; + if (neighbor == _numberOfParticles ) { + neighbor = 0; + } + glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position; + + _particle[p].velocity -= vectorToNeighbor * _neighborAttraction * deltaTime; + + float distanceToNeighbor = glm::length(vectorToNeighbor); + if (distanceToNeighbor > 0.0f) { + _particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * _neighborRepulsion * deltaTime; + } + + // apply tornado force + glm::vec3 tornadoDirection = glm::cross(vectorToHome, _tornadoAxis); + _particle[p].velocity += tornadoDirection * _tornadoForce * deltaTime; + + // apply air friction + float drag = 1.0 - _airFriction * deltaTime; + if (drag < 0.0f) { + _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f); + } else { + _particle[p].velocity *= drag; + } + + // apply gravity + _particle[p].velocity.y -= _gravity * deltaTime; + + // update position by velocity + _particle[p].position += _particle[p].velocity; + + // collision with ground + if (_particle[p].position.y < _particle[p].radius) { + _particle[p].position.y = _particle[p].radius; + + if (_particle[p].velocity.y < 0.0f) { + _particle[p].velocity.y *= -_bounce; + } + } + + // collision with sphere + glm::vec3 vectorToSphereCenter = _TEST_bigSpherePosition - _particle[p].position; + float distanceToSphereCenter = glm::length(vectorToSphereCenter); + float combinedRadius = _TEST_bigSphereRadius + _particle[p].radius; + if (distanceToSphereCenter < combinedRadius) { + + if (distanceToSphereCenter > 0.0f){ + glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter; + _particle[p].position = _TEST_bigSpherePosition - directionToSphereCenter * combinedRadius; + } + } +} + + +void ParticleSystem::render() { + + for (unsigned int p = 0; p < _numberOfParticles; p++) { + glColor3f(_particle[p].color.x, _particle[p].color.y, _particle[p].color.z); + glPushMatrix(); + glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z); + glutSolidSphere(_particle[p].radius, 6, 6); + glPopMatrix(); + + // render velocity lines + glColor4f( _particle[p].color.x, _particle[p].color.y, _particle[p].color.z, 0.5f); + glm::vec3 end = _particle[p].position - _particle[p].velocity * 2.0f; + glBegin(GL_LINES); + glVertex3f(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z); + glVertex3f(end.x, end.y, end.z); + + glEnd(); + + } +} + + + + + + + + diff --git a/interface/src/ParticleSystem.h b/interface/src/ParticleSystem.h new file mode 100644 index 0000000000..38eb0a1777 --- /dev/null +++ b/interface/src/ParticleSystem.h @@ -0,0 +1,59 @@ +// +// ParticleSystem.h +// hifi +// +// Created by Jeffrey on July 10, 2013 +// +// + +#ifndef hifi_ParticleSystem_h +#define hifi_ParticleSystem_h + +const int MAX_PARTICLES = 5000; +const int MAX_EMITTERS = 10; + +class ParticleSystem { +public: + ParticleSystem(); + + void simulate(float deltaTime); + void render(); + +private: + + struct Particle { + glm::vec3 position; + glm::vec3 velocity; + glm::vec3 color; + float age; + float radius; + }; + + struct Emitter { + glm::vec3 position; + glm::vec3 direction; + }; + + float _bounce; + float _gravity; + float _timer; + Emitter _emitter[MAX_EMITTERS]; + Particle _particle[MAX_PARTICLES]; + int _numberOfParticles; + glm::vec3 _home; + glm::vec3 _tornadoAxis; + float _airFriction; + float _jitter; + float _homeAttraction; + float _tornadoForce; + float _neighborAttraction; + float _neighborRepulsion; + float _TEST_bigSphereRadius; + glm::vec3 _TEST_bigSpherePosition; + + // private methods + void updateParticle(int index, float deltaTime); + void runSpecialEffectsTest(float deltaTime); +}; + +#endif diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 30a0427292..421c03f3b6 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -20,6 +20,8 @@ const glm::vec3 IDENTITY_RIGHT = glm::vec3( 1.0f, 0.0f, 0.0f); const glm::vec3 IDENTITY_UP = glm::vec3( 0.0f, 1.0f, 0.0f); const glm::vec3 IDENTITY_FRONT = glm::vec3( 0.0f, 0.0f,-1.0f); +const bool LOW_RES_MONO = false; // while in "low res mode" do voxels switch to monochrome + const int TREE_SCALE = 128; const int NUMBER_OF_CHILDREN = 8; diff --git a/voxel-server/src/VoxelNodeData.cpp b/voxel-server/src/VoxelNodeData.cpp index 2fba3e511b..971b6f8eaa 100644 --- a/voxel-server/src/VoxelNodeData.cpp +++ b/voxel-server/src/VoxelNodeData.cpp @@ -31,7 +31,7 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) : void VoxelNodeData::resetVoxelPacket() { // If we're moving, and the client asked for low res, then we force monochrome, otherwise, use // the clients requested color state. - _currentPacketIsColor = (getWantLowResMoving() && _viewFrustumChanging) ? false : getWantColor(); + _currentPacketIsColor = (LOW_RES_MONO && getWantLowResMoving() && _viewFrustumChanging) ? false : getWantColor(); PACKET_TYPE voxelPacketType = _currentPacketIsColor ? PACKET_TYPE_VOXEL_DATA : PACKET_TYPE_VOXEL_DATA_MONOCHROME; int numBytesPacketHeader = populateTypeAndVersion(_voxelPacket, voxelPacketType); _voxelPacketAt = _voxelPacket + numBytesPacketHeader; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 917031b317..cf59f226db 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -133,7 +133,7 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, // If we're starting a fresh packet, then... // If we're moving, and the client asked for low res, then we force monochrome, otherwise, use // the clients requested color state. - bool wantColor = ((nodeData->getWantLowResMoving() && viewFrustumChanged) ? false : nodeData->getWantColor()); + bool wantColor = LOW_RES_MONO && nodeData->getWantLowResMoving() && viewFrustumChanged ? false : nodeData->getWantColor(); // If we have a packet waiting, and our desired want color, doesn't match the current waiting packets color // then let's just send that waiting packet.