From fd98982fa6658e10f87069d8a7abd6b54ba44762 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 21 May 2013 21:33:08 -0700 Subject: [PATCH] Support for multiple environments, collisions with notional planet surfaces. --- interface/src/Application.cpp | 40 ++--- interface/src/Application.h | 1 + interface/src/Avatar.cpp | 39 +++-- interface/src/Avatar.h | 2 + interface/src/Environment.cpp | 182 +++++++++++++++++------ interface/src/Environment.h | 21 ++- libraries/shared/CMakeLists.txt | 8 +- libraries/shared/src/UDPSocket.cpp | 6 +- libraries/shared/src/UDPSocket.h | 2 +- libraries/voxels/src/EnvironmentData.cpp | 20 ++- libraries/voxels/src/EnvironmentData.h | 12 +- libraries/voxels/src/GeometryUtil.cpp | 23 +++ libraries/voxels/src/GeometryUtil.h | 16 ++ libraries/voxels/src/VoxelTree.cpp | 16 +- voxel-server/src/main.cpp | 42 ++++-- 15 files changed, 300 insertions(+), 130 deletions(-) create mode 100644 libraries/voxels/src/GeometryUtil.cpp create mode 100644 libraries/voxels/src/GeometryUtil.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index aa9a5880bb..f3a636fee4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -389,7 +389,8 @@ void Application::paintGL() { glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glm::vec3 relativeSunLoc = glm::normalize(_environment.getSunLocation() - whichCamera.getPosition()); + glm::vec3 relativeSunLoc = glm::normalize(_environment.getClosestData(whichCamera.getPosition()).getSunLocation() - + whichCamera.getPosition()); GLfloat light_position0[] = { relativeSunLoc.x, relativeSunLoc.y, relativeSunLoc.z, 0.0 }; glLightfv(GL_LIGHT0, GL_POSITION, light_position0); GLfloat ambient_color[] = { 0.7, 0.7, 0.8 }; @@ -829,26 +830,6 @@ static glm::vec3 getFaceVector(BoxFace face) { } } -//Find and return the gravity vector at this location -static glm::vec3 getGravity(const glm::vec3& pos) { - // - // For now, we'll test this with a simple global lookup, but soon we will add getting this - // from the domain/voxelserver (or something similar) - // - if ((pos.x > 0.f) && - (pos.x < 10.f) && - (pos.z > 0.f) && - (pos.z < 10.f) && - (pos.y > 0.f) && - (pos.y < 3.f)) { - // If above ground plane, turn gravity on - return glm::vec3(0.f, -1.f, 0.f); - } else { - // If flying in space, turn gravity OFF - return glm::vec3(0.f, 0.f, 0.f); - } -} - void Application::idle() { timeval check; gettimeofday(&check, NULL); @@ -983,7 +964,7 @@ void Application::idle() { agentList->unlock(); // Simulate myself - _myAvatar.setGravity(getGravity(_myAvatar.getPosition())); + _myAvatar.setGravity(_environment.getGravity(_myAvatar.getPosition())); if (_transmitterDrives->isChecked() && _myTransmitter.isConnected()) { _myAvatar.simulate(deltaTime, &_myTransmitter); } else { @@ -1653,13 +1634,14 @@ void Application::displaySide(Camera& whichCamera) { // compute starfield alpha based on distance from atmosphere float alpha = 1.0f; if (_renderAtmosphereOn->isChecked()) { - float height = glm::distance(whichCamera.getPosition(), _environment.getAtmosphereCenter()); - if (height < _environment.getAtmosphereInnerRadius()) { + const EnvironmentData& closestData = _environment.getClosestData(whichCamera.getPosition()); + float height = glm::distance(whichCamera.getPosition(), closestData.getAtmosphereCenter()); + if (height < closestData.getAtmosphereInnerRadius()) { alpha = 0.0f; - } else if (height < _environment.getAtmosphereOuterRadius()) { - alpha = (height - _environment.getAtmosphereInnerRadius()) / - (_environment.getAtmosphereOuterRadius() - _environment.getAtmosphereInnerRadius()); + } else if (height < closestData.getAtmosphereOuterRadius()) { + alpha = (height - closestData.getAtmosphereInnerRadius()) / + (closestData.getAtmosphereOuterRadius() - closestData.getAtmosphereInnerRadius()); } } @@ -1669,7 +1651,7 @@ void Application::displaySide(Camera& whichCamera) { // draw the sky dome if (_renderAtmosphereOn->isChecked()) { - _environment.renderAtmosphere(whichCamera); + _environment.renderAtmospheres(whichCamera); } glEnable(GL_LIGHTING); @@ -2142,7 +2124,7 @@ void* Application::networkReceive(void* args) { app->_voxels.parseData(app->_incomingPacket, bytesReceived); break; case PACKET_HEADER_ENVIRONMENT_DATA: - app->_environment.parseData(app->_incomingPacket, bytesReceived); + app->_environment.parseData(&senderAddress, app->_incomingPacket, bytesReceived); break; case PACKET_HEADER_BULK_AVATAR_DATA: AgentList::getInstance()->processBulkAgentData(&senderAddress, diff --git a/interface/src/Application.h b/interface/src/Application.h index 8c9818eebe..01b6f9c4b9 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -63,6 +63,7 @@ public: Avatar* getAvatar() { return &_myAvatar; } VoxelSystem* getVoxels() { return &_voxels; } + Environment* getEnvironment() { return &_environment; } private slots: diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 451172b45b..d7a09619df 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -239,12 +239,9 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // apply gravity and collision with the ground/floor if (_isMine && USING_AVATAR_GRAVITY) { - if (_position.y > _pelvisStandingHeight + 0.01f) { - _velocity += _gravity * (GRAVITY_SCALE * deltaTime); - } else if (_position.y < _pelvisStandingHeight) { - _position.y = _pelvisStandingHeight; - _velocity.y = -_velocity.y * BOUNCE; - } + _velocity += _gravity * (GRAVITY_SCALE * deltaTime); + + updateCollisionWithEnvironment(deltaTime); } // update body springs @@ -589,20 +586,34 @@ void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float d } } -void Avatar::updateCollisionWithVoxels(float deltaTime) { - VoxelSystem* voxels = Application::getInstance()->getVoxels(); +void Avatar::updateCollisionWithEnvironment(float deltaTime) { float radius = _height * 0.125f; glm::vec3 halfVector = glm::vec3(0.0f, _height * ONE_HALF - radius, 0.0f); glm::vec3 penetration; - if (voxels->findCapsulePenetration(_position - halfVector, _position + halfVector, radius, penetration)) { - _position += penetration; - - // reflect the velocity component in the direction of penetration - glm::vec3 direction = glm::normalize(penetration); - _velocity -= 2.0f * glm::dot(_velocity, direction) * direction * BOUNCE; + if (Application::getInstance()->getEnvironment()->findCapsulePenetration( + _position - halfVector, _position + halfVector, radius, penetration)) { + applyCollisionWithScene(penetration, deltaTime); } } +void Avatar::updateCollisionWithVoxels(float deltaTime) { + float radius = _height * 0.125f; + glm::vec3 halfVector = glm::vec3(0.0f, _height * ONE_HALF - radius, 0.0f); + glm::vec3 penetration; + if (Application::getInstance()->getVoxels()->findCapsulePenetration( + _position - halfVector, _position + halfVector, radius, penetration)) { + applyCollisionWithScene(penetration, deltaTime); + } +} + +void Avatar::applyCollisionWithScene(const glm::vec3& penetration, float deltaTime) { + _position += penetration; + + // reflect the velocity component in the direction of penetration + glm::vec3 direction = glm::normalize(penetration); + //_velocity -= 2.0f * glm::dot(_velocity, direction) * direction * BOUNCE; +} + void Avatar::updateAvatarCollisions(float deltaTime) { // Reset detector for nearest avatar diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index cc2192ad52..7aaee288da 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -194,7 +194,9 @@ private: void updateHandMovementAndTouching(float deltaTime); void updateAvatarCollisions(float deltaTime); void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime ); + void updateCollisionWithEnvironment(float deltaTime); void updateCollisionWithVoxels(float deltaTime); + void applyCollisionWithScene(const glm::vec3& penetration, float deltaTime); void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime ); void setHeadFromGyros(glm::vec3 * eulerAngles, glm::vec3 * angularVelocity, float deltaTime, float smoothingTime); void checkForMouseRayTouching(); diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 81d983d635..b589d59c2d 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -6,7 +6,9 @@ // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. #include +#include +#include #include #include "Camera.h" @@ -14,64 +16,94 @@ #include "renderer/ProgramObject.h" #include "world.h" +uint qHash(const sockaddr& address) { + const sockaddr_in* inetAddress = reinterpret_cast(&address); + if (inetAddress->sin_family != AF_INET) { + return 0; // shouldn't happen, but if it does, zero is a perfectly valid hash + } + return inetAddress->sin_port + qHash(QByteArray::fromRawData( + reinterpret_cast(&inetAddress->sin_addr), sizeof(in_addr))); +} + +bool operator== (const sockaddr& addr1, const sockaddr& addr2) { + return socketMatch(&addr1, &addr2); +} + void Environment::init() { switchToResourcesParentIfRequired(); _skyFromAtmosphereProgram = createSkyProgram("Atmosphere", _skyFromAtmosphereUniformLocations); _skyFromSpaceProgram = createSkyProgram("Space", _skyFromSpaceUniformLocations); + + // start off with a default-constructed environment data + _data[sockaddr()][0]; } -void Environment::renderAtmosphere(Camera& camera) { - glPushMatrix(); - glTranslatef(getAtmosphereCenter().x, getAtmosphereCenter().y, getAtmosphereCenter().z); - - glm::vec3 relativeCameraPos = camera.getPosition() - getAtmosphereCenter(); - float height = glm::length(relativeCameraPos); - - // use the appropriate shader depending on whether we're inside or outside - ProgramObject* program; - int* locations; - if (height < getAtmosphereOuterRadius()) { - program = _skyFromAtmosphereProgram; - locations = _skyFromAtmosphereUniformLocations; - - } else { - program = _skyFromSpaceProgram; - locations = _skyFromSpaceUniformLocations; +void Environment::renderAtmospheres(Camera& camera) { + foreach (const ServerData& serverData, _data) { + foreach (const EnvironmentData& environmentData, serverData) { + renderAtmosphere(camera, environmentData); + } } +} + +glm::vec3 Environment::getGravity (const glm::vec3& position) const { + glm::vec3 gravity; + foreach (const ServerData& serverData, _data) { + foreach (const EnvironmentData& environmentData, serverData) { + glm::vec3 vector = environmentData.getAtmosphereCenter() - position; + if (glm::length(vector) < environmentData.getAtmosphereOuterRadius()) { + gravity += glm::normalize(vector) * environmentData.getGravity(); + } + } + } + return gravity; +} + +const EnvironmentData& Environment::getClosestData(const glm::vec3& position) const { + const EnvironmentData* closest; + float closestDistance = FLT_MAX; + foreach (const ServerData& serverData, _data) { + foreach (const EnvironmentData& environmentData, serverData) { + float distance = glm::distance(position, environmentData.getAtmosphereCenter()) - + environmentData.getAtmosphereOuterRadius(); + if (distance < closestDistance) { + closest = &environmentData; + closestDistance = distance; + } + } + } + return *closest; +} + +bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, + float radius, glm::vec3& penetration) const { + bool found = false; + penetration = glm::vec3(0.0f, 0.0f, 0.0f); + foreach (const ServerData& serverData, _data) { + foreach (const EnvironmentData& environmentData, serverData) { + glm::vec3 vector = computeVectorFromPointToSegment(environmentData.getAtmosphereCenter(), start, end); + float vectorLength = glm::length(vector); + float distance = vectorLength - environmentData.getAtmosphereInnerRadius() - radius; + if (distance < 0.0f) { + penetration += vector * (-distance / vectorLength); + found = true; + } + } + } + return found; +} + +int Environment::parseData(sockaddr *senderAddress, unsigned char* sourceBuffer, int numBytes) { + EnvironmentData newData; + int bytesRead = newData.parseData(sourceBuffer, numBytes); - // the constants here are from Sean O'Neil's GPU Gems entry - // (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), GameEngine.cpp - program->bind(); - program->setUniform(locations[CAMERA_POS_LOCATION], relativeCameraPos); - glm::vec3 lightDirection = glm::normalize(getSunLocation()); - program->setUniform(locations[LIGHT_POS_LOCATION], lightDirection); - program->setUniformValue(locations[INV_WAVELENGTH_LOCATION], - 1 / powf(getScatteringWavelengths().r, 4.0f), - 1 / powf(getScatteringWavelengths().g, 4.0f), - 1 / powf(getScatteringWavelengths().b, 4.0f)); - program->setUniformValue(locations[CAMERA_HEIGHT2_LOCATION], height * height); - program->setUniformValue(locations[OUTER_RADIUS_LOCATION], getAtmosphereOuterRadius()); - program->setUniformValue(locations[OUTER_RADIUS2_LOCATION], getAtmosphereOuterRadius() * getAtmosphereOuterRadius()); - program->setUniformValue(locations[INNER_RADIUS_LOCATION], getAtmosphereInnerRadius()); - program->setUniformValue(locations[KR_ESUN_LOCATION], getRayleighScattering() * getSunBrightness()); - program->setUniformValue(locations[KM_ESUN_LOCATION], getMieScattering() * getSunBrightness()); - program->setUniformValue(locations[KR_4PI_LOCATION], getRayleighScattering() * 4.0f * PIf); - program->setUniformValue(locations[KM_4PI_LOCATION], getMieScattering() * 4.0f * PIf); - program->setUniformValue(locations[SCALE_LOCATION], 1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius())); - program->setUniformValue(locations[SCALE_DEPTH_LOCATION], 0.25f); - program->setUniformValue(locations[SCALE_OVER_SCALE_DEPTH_LOCATION], - (1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius())) / 0.25f); - program->setUniformValue(locations[G_LOCATION], -0.990f); - program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f); + // update the mapping by address/ID + _data[*senderAddress][newData.getID()] = newData; - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glutSolidSphere(getAtmosphereOuterRadius(), 100, 50); - glDepthMask(GL_TRUE); + // remove the default mapping, if any + _data.remove(sockaddr()); - program->release(); - - glPopMatrix(); + return bytesRead; } ProgramObject* Environment::createSkyProgram(const char* from, int* locations) { @@ -100,3 +132,57 @@ ProgramObject* Environment::createSkyProgram(const char* from, int* locations) { return program; } + +void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) { + glPushMatrix(); + glTranslatef(data.getAtmosphereCenter().x, data.getAtmosphereCenter().y, data.getAtmosphereCenter().z); + + glm::vec3 relativeCameraPos = camera.getPosition() - data.getAtmosphereCenter(); + float height = glm::length(relativeCameraPos); + + // use the appropriate shader depending on whether we're inside or outside + ProgramObject* program; + int* locations; + if (height < data.getAtmosphereOuterRadius()) { + program = _skyFromAtmosphereProgram; + locations = _skyFromAtmosphereUniformLocations; + + } else { + program = _skyFromSpaceProgram; + locations = _skyFromSpaceUniformLocations; + } + + // the constants here are from Sean O'Neil's GPU Gems entry + // (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), GameEngine.cpp + program->bind(); + program->setUniform(locations[CAMERA_POS_LOCATION], relativeCameraPos); + glm::vec3 lightDirection = glm::normalize(data.getSunLocation()); + program->setUniform(locations[LIGHT_POS_LOCATION], lightDirection); + program->setUniformValue(locations[INV_WAVELENGTH_LOCATION], + 1 / powf(data.getScatteringWavelengths().r, 4.0f), + 1 / powf(data.getScatteringWavelengths().g, 4.0f), + 1 / powf(data.getScatteringWavelengths().b, 4.0f)); + program->setUniformValue(locations[CAMERA_HEIGHT2_LOCATION], height * height); + program->setUniformValue(locations[OUTER_RADIUS_LOCATION], data.getAtmosphereOuterRadius()); + program->setUniformValue(locations[OUTER_RADIUS2_LOCATION], data.getAtmosphereOuterRadius() * data.getAtmosphereOuterRadius()); + program->setUniformValue(locations[INNER_RADIUS_LOCATION], data.getAtmosphereInnerRadius()); + program->setUniformValue(locations[KR_ESUN_LOCATION], data.getRayleighScattering() * data.getSunBrightness()); + program->setUniformValue(locations[KM_ESUN_LOCATION], data.getMieScattering() * data.getSunBrightness()); + program->setUniformValue(locations[KR_4PI_LOCATION], data.getRayleighScattering() * 4.0f * PIf); + program->setUniformValue(locations[KM_4PI_LOCATION], data.getMieScattering() * 4.0f * PIf); + program->setUniformValue(locations[SCALE_LOCATION], 1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())); + program->setUniformValue(locations[SCALE_DEPTH_LOCATION], 0.25f); + program->setUniformValue(locations[SCALE_OVER_SCALE_DEPTH_LOCATION], + (1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())) / 0.25f); + program->setUniformValue(locations[G_LOCATION], -0.990f); + program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f); + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glutSolidSphere(data.getAtmosphereOuterRadius(), 100, 50); + glDepthMask(GL_TRUE); + + program->release(); + + glPopMatrix(); +} diff --git a/interface/src/Environment.h b/interface/src/Environment.h index 9c68b5c3e5..95112806e5 100644 --- a/interface/src/Environment.h +++ b/interface/src/Environment.h @@ -9,22 +9,35 @@ #ifndef __interface__Environment__ #define __interface__Environment__ +#include + +#include + #include "EnvironmentData.h" #include "InterfaceConfig.h" class Camera; class ProgramObject; -class Environment : public EnvironmentData { +class Environment { public: void init(); - void renderAtmosphere(Camera& camera); + void renderAtmospheres(Camera& camera); + + glm::vec3 getGravity (const glm::vec3& position) const; + const EnvironmentData& getClosestData(const glm::vec3& position) const; + + bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const; + + int parseData(sockaddr *senderAddress, unsigned char* sourceBuffer, int numBytes); private: ProgramObject* createSkyProgram(const char* from, int* locations); + void renderAtmosphere(Camera& camera, const EnvironmentData& data); + ProgramObject* _skyFromAtmosphereProgram; ProgramObject* _skyFromSpaceProgram; @@ -50,6 +63,10 @@ private: int _skyFromAtmosphereUniformLocations[LOCATION_COUNT]; int _skyFromSpaceUniformLocations[LOCATION_COUNT]; + + typedef QHash ServerData; + + QHash _data; }; #endif /* defined(__interface__Environment__) */ diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index 00b99b69db..8026aa01de 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -1,5 +1,8 @@ cmake_minimum_required(VERSION 2.8) +set(ROOT_DIR ../..) +set(MACRO_DIR ${ROOT_DIR}/cmake/macros) + set(TARGET_NAME shared) project(${TARGET_NAME}) @@ -12,6 +15,9 @@ set(HIFI_SHARED_LIBRARY ${TARGET_NAME}) set(EXTERNAL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external) +include(${MACRO_DIR}/IncludeGLM.cmake) +include_glm(${TARGET_NAME} ${ROOT_DIR}) + if (WIN32) # include headers for external libraries and InterfaceConfig. include_directories(${EXTERNAL_ROOT_DIR}) @@ -25,4 +31,4 @@ endif (WIN32) if (UNIX AND NOT APPLE) find_package(Threads REQUIRED) target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT}) -endif (UNIX AND NOT APPLE) \ No newline at end of file +endif (UNIX AND NOT APPLE) diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index 88930d4af4..f46eb2952d 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -27,7 +27,7 @@ using shared_lib::printLog; sockaddr_in destSockaddr, senderAddress; -bool socketMatch(sockaddr* first, sockaddr* second) { +bool socketMatch(const sockaddr* first, const sockaddr* second) { if (first != NULL && second != NULL) { // utility function that indicates if two sockets are equivalent @@ -38,8 +38,8 @@ bool socketMatch(sockaddr* first, sockaddr* second) { // not the same family, can't be equal return false; } else if (first->sa_family == AF_INET) { - sockaddr_in *firstIn = (sockaddr_in *) first; - sockaddr_in *secondIn = (sockaddr_in *) second; + const sockaddr_in *firstIn = (const sockaddr_in *) first; + const sockaddr_in *secondIn = (const sockaddr_in *) second; return firstIn->sin_addr.s_addr == secondIn->sin_addr.s_addr && firstIn->sin_port == secondIn->sin_port; diff --git a/libraries/shared/src/UDPSocket.h b/libraries/shared/src/UDPSocket.h index d246d9e512..b56a1cc0cf 100644 --- a/libraries/shared/src/UDPSocket.h +++ b/libraries/shared/src/UDPSocket.h @@ -34,7 +34,7 @@ private: bool blocking; }; -bool socketMatch(sockaddr* first, sockaddr* second); +bool socketMatch(const sockaddr* first, const sockaddr* second); int packSocket(unsigned char* packStore, in_addr_t inAddress, in_port_t networkOrderPort); int packSocket(unsigned char* packStore, sockaddr* socketToPack); int unpackSocket(unsigned char* packedData, sockaddr* unpackDestSocket); diff --git a/libraries/voxels/src/EnvironmentData.cpp b/libraries/voxels/src/EnvironmentData.cpp index c08489bf67..4142a00ae6 100644 --- a/libraries/voxels/src/EnvironmentData.cpp +++ b/libraries/voxels/src/EnvironmentData.cpp @@ -11,8 +11,10 @@ #include "PacketHeaders.h" // initial values from Sean O'Neil's GPU Gems entry (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), -// GameEngine.cpp (and the radius of the earth) -EnvironmentData::EnvironmentData() : +// GameEngine.cpp +EnvironmentData::EnvironmentData(int id) : + _id(id), + _gravity(1.0f), _atmosphereCenter(0, -1000, 0), _atmosphereInnerRadius(1000), _atmosphereOuterRadius(1025), @@ -27,7 +29,13 @@ int EnvironmentData::getBroadcastData(unsigned char* destinationBuffer) const { unsigned char* bufferStart = destinationBuffer; *destinationBuffer++ = PACKET_HEADER_ENVIRONMENT_DATA; - + + memcpy(destinationBuffer, &_id, sizeof(_id)); + destinationBuffer += sizeof(_id); + + memcpy(destinationBuffer, &_gravity, sizeof(_gravity)); + destinationBuffer += sizeof(_gravity); + memcpy(destinationBuffer, &_atmosphereCenter, sizeof(_atmosphereCenter)); destinationBuffer += sizeof(_atmosphereCenter); @@ -61,6 +69,12 @@ int EnvironmentData::parseData(unsigned char* sourceBuffer, int numBytes) { unsigned char* startPosition = sourceBuffer; + memcpy(&_id, sourceBuffer, sizeof(_id)); + sourceBuffer += sizeof(_id); + + memcpy(&_gravity, sourceBuffer, sizeof(_gravity)); + sourceBuffer += sizeof(_gravity); + memcpy(&_atmosphereCenter, sourceBuffer, sizeof(_atmosphereCenter)); sourceBuffer += sizeof(_atmosphereCenter); diff --git a/libraries/voxels/src/EnvironmentData.h b/libraries/voxels/src/EnvironmentData.h index b4de3498c6..b801caba96 100644 --- a/libraries/voxels/src/EnvironmentData.h +++ b/libraries/voxels/src/EnvironmentData.h @@ -14,7 +14,13 @@ class EnvironmentData { public: - EnvironmentData(); + EnvironmentData(int id = 0); + + void setID(int id) { _id = id; } + int getID() const { return _id; } + + void setGravity(float gravity) { _gravity = gravity; } + float getGravity() const { return _gravity; } void setAtmosphereCenter(const glm::vec3& center) { _atmosphereCenter = center; } void setAtmosphereInnerRadius(float radius) { _atmosphereInnerRadius = radius; } @@ -41,6 +47,10 @@ public: private: + int _id; + + float _gravity; + glm::vec3 _atmosphereCenter; float _atmosphereInnerRadius; float _atmosphereOuterRadius; diff --git a/libraries/voxels/src/GeometryUtil.cpp b/libraries/voxels/src/GeometryUtil.cpp new file mode 100644 index 0000000000..46e83018cd --- /dev/null +++ b/libraries/voxels/src/GeometryUtil.cpp @@ -0,0 +1,23 @@ +// +// GeometryUtil.cpp +// interface +// +// Created by Andrzej Kapolka on 5/21/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. + +#include "GeometryUtil.h" + +glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) { + // compute the projection of the point vector onto the segment vector + glm::vec3 segmentVector = end - start; + float proj = glm::dot(point - start, segmentVector) / glm::dot(segmentVector, segmentVector); + if (proj <= 0.0f) { // closest to the start + return start - point; + + } else if (proj >= 1.0f) { // closest to the end + return end - point; + + } else { // closest to the middle + return start + segmentVector*proj - point; + } +} diff --git a/libraries/voxels/src/GeometryUtil.h b/libraries/voxels/src/GeometryUtil.h new file mode 100644 index 0000000000..f0c63e5a86 --- /dev/null +++ b/libraries/voxels/src/GeometryUtil.h @@ -0,0 +1,16 @@ +// +// GeometryUtil.h +// interface +// +// Created by Andrzej Kapolka on 5/21/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__GeometryUtil__ +#define __interface__GeometryUtil__ + +#include + +glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end); + +#endif /* defined(__interface__GeometryUtil__) */ diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index cf8615bd3b..33d0395345 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -16,6 +16,7 @@ #include "voxels_Log.h" #include "PacketHeaders.h" #include "OctalCode.h" +#include "GeometryUtil.h" #include "VoxelTree.h" #include "VoxelNodeBag.h" #include "ViewFrustum.h" @@ -725,21 +726,6 @@ public: bool found; }; -glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) { - // compute the projection of the point vector onto the segment vector - glm::vec3 segmentVector = end - start; - float proj = glm::dot(point - start, segmentVector) / glm::dot(segmentVector, segmentVector); - if (proj <= 0.0f) { // closest to the start - return start - point; - - } else if (proj >= 1.0f) { // closest to the end - return end - point; - - } else { // closest to the middle - return start + segmentVector*proj - point; - } -} - bool findCapsulePenetrationOp(VoxelNode* node, void* extraData) { CapsuleArgs* args = static_cast(extraData); diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index c268031e74..b7e8695fa0 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -60,7 +60,7 @@ bool shouldShowAnimationDebug = false; -EnvironmentData environmentData; +EnvironmentData environmentData[3]; void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { @@ -162,7 +162,8 @@ void resInVoxelDistributor(AgentList* agentList, int trueBytesSent = 0; double start = usecTimestampNow(); - while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - 1) { + int environmentPacketCount = sizeof(environmentData) / sizeof(environmentData[0]); + while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - environmentPacketCount) { if (!agentData->nodeBag.isEmpty()) { VoxelNode* subTree = agentData->nodeBag.extract(); bytesWritten = randomTree.encodeTreeBitstream(agentData->getMaxSearchLevel(), subTree, @@ -193,11 +194,13 @@ void resInVoxelDistributor(AgentList* agentList, packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left } } - // send the environment packet - int envPacketLength = environmentData.getBroadcastData(tempOutputBuffer); - agentList->getAgentSocket()->send(agent->getActiveSocket(), tempOutputBuffer, envPacketLength); - trueBytesSent += envPacketLength; - truePacketsSent++; + // send the environment packets + for (int i = 0; i < environmentPacketCount; i++) { + int envPacketLength = environmentData[i].getBroadcastData(tempOutputBuffer); + agentList->getAgentSocket()->send(agent->getActiveSocket(), tempOutputBuffer, envPacketLength); + trueBytesSent += envPacketLength; + truePacketsSent++; + } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; @@ -282,7 +285,8 @@ void deepestLevelVoxelDistributor(AgentList* agentList, int trueBytesSent = 0; double start = usecTimestampNow(); - while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - 1) { + int environmentPacketCount = sizeof(environmentData) / sizeof(environmentData[0]); + while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - environmentPacketCount) { if (!agentData->nodeBag.isEmpty()) { VoxelNode* subTree = agentData->nodeBag.extract(); bytesWritten = randomTree.encodeTreeBitstream(INT_MAX, subTree, @@ -313,11 +317,13 @@ void deepestLevelVoxelDistributor(AgentList* agentList, packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left } } - // send the environment packet - int envPacketLength = environmentData.getBroadcastData(tempOutputBuffer); - agentList->getAgentSocket()->send(agent->getActiveSocket(), tempOutputBuffer, envPacketLength); - trueBytesSent += envPacketLength; - truePacketsSent++; + // send the environment packets + for (int i = 0; i < environmentPacketCount; i++) { + int envPacketLength = environmentData[i].getBroadcastData(tempOutputBuffer); + agentList->getAgentSocket()->send(agent->getActiveSocket(), tempOutputBuffer, envPacketLength); + trueBytesSent += envPacketLength; + truePacketsSent++; + } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; @@ -517,6 +523,16 @@ int main(int argc, const char * argv[]) addSphereScene(&randomTree); } + // for now, initialize the environments with fixed values + environmentData[1].setID(1); + environmentData[1].setAtmosphereCenter(glm::vec3(0.5, 0.5, (0.25 - 0.06125)) * (float)TREE_SCALE); + environmentData[1].setAtmosphereInnerRadius(0.030625f * TREE_SCALE); + environmentData[1].setAtmosphereOuterRadius(0.030625f * TREE_SCALE * 1.025f); + environmentData[2].setID(2); + environmentData[2].setAtmosphereCenter(glm::vec3(0.5f, 0.5f, 0.5f) * (float)TREE_SCALE); + environmentData[2].setAtmosphereInnerRadius(0.1875f * TREE_SCALE); + environmentData[2].setAtmosphereOuterRadius(0.1875f * TREE_SCALE * 1.025f); + pthread_t sendVoxelThread; pthread_create(&sendVoxelThread, NULL, distributeVoxelsToListeners, NULL);