Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jeffrey Ventrella 2013-05-08 19:24:07 -07:00
commit bbd85664d6
47 changed files with 1593 additions and 428 deletions

View file

@ -32,7 +32,7 @@ configure_file(InterfaceConfig.h.in ${PROJECT_BINARY_DIR}/includes/InterfaceConf
# grab the implementation and header files from src dirs
file(GLOB INTERFACE_SRCS src/*.cpp src/*.h)
foreach(SUBDIR ui)
foreach(SUBDIR ui renderer)
file(GLOB SUBDIR_SRCS src/${SUBDIR}/*.cpp src/${SUBDIR}/*.h)
set(INTERFACE_SRCS ${INTERFACE_SRCS} ${SUBDIR_SRCS})
endforeach(SUBDIR)

View file

@ -0,0 +1,48 @@
//
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
//
// NVIDIA Statement on the Software
//
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
// detailed.
//
// No Warranty
//
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
// Limitation of Liability
//
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
//
//
// Atmospheric scattering fragment shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//
#version 120
uniform vec3 v3LightPos;
uniform float g;
uniform float g2;
varying vec3 v3Direction;
void main (void)
{
float fCos = dot(v3LightPos, v3Direction) / length(v3Direction);
float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
gl_FragColor = gl_Color + fMiePhase * gl_SecondaryColor;
gl_FragColor.a = gl_FragColor.b;
}

View file

@ -0,0 +1,100 @@
//
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
//
// NVIDIA Statement on the Software
//
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
// detailed.
//
// No Warranty
//
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
// Limitation of Liability
//
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
//
//
// Atmospheric scattering vertex shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//
#version 120
uniform vec3 v3CameraPos; // The camera's current position
uniform vec3 v3LightPos; // The direction vector to the light source
uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels
uniform float fInnerRadius; // The inner (planetary) radius
uniform float fKrESun; // Kr * ESun
uniform float fKmESun; // Km * ESun
uniform float fKr4PI; // Kr * 4 * PI
uniform float fKm4PI; // Km * 4 * PI
uniform float fScale; // 1 / (fOuterRadius - fInnerRadius)
uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found)
uniform float fScaleOverScaleDepth; // fScale / fScaleDepth
const int nSamples = 2;
const float fSamples = 2.0;
varying vec3 v3Direction;
float scale(float fCos)
{
float x = 1.0 - fCos;
return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
}
void main(void)
{
// Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere)
vec3 v3Pos = gl_Vertex.xyz;
vec3 v3Ray = v3Pos - v3CameraPos;
float fFar = length(v3Ray);
v3Ray /= fFar;
// Calculate the ray's starting position, then calculate its scattering offset
vec3 v3Start = v3CameraPos;
float fHeight = length(v3Start);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fStartAngle = dot(v3Ray, v3Start) / fHeight;
float fStartOffset = fDepth * scale(fStartAngle);
// Initialize the scattering loop variables
//gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0);
float fSampleLength = fFar / fSamples;
float fScaledLength = fSampleLength * fScale;
vec3 v3SampleRay = v3Ray * fSampleLength;
vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;
// Now loop through the sample rays
vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);
for(int i=0; i<nSamples; i++)
{
float fHeight = length(v3SamplePoint);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fLightAngle = dot(v3LightPos, v3SamplePoint) / fHeight;
float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight;
float fScatter = (fStartOffset + fDepth * (scale(fLightAngle) - scale(fCameraAngle)));
vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay;
}
// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader
gl_FrontSecondaryColor.rgb = v3FrontColor * fKmESun;
gl_FrontColor.rgb = v3FrontColor * (v3InvWavelength * fKrESun);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
v3Direction = v3CameraPos - v3Pos;
}

View file

@ -0,0 +1,48 @@
//
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
//
// NVIDIA Statement on the Software
//
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
// detailed.
//
// No Warranty
//
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
// Limitation of Liability
//
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
//
//
// Atmospheric scattering fragment shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//
#version 120
uniform vec3 v3LightPos;
uniform float g;
uniform float g2;
varying vec3 v3Direction;
void main (void)
{
float fCos = dot(v3LightPos, v3Direction) / length(v3Direction);
float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
gl_FragColor = gl_Color + fMiePhase * gl_SecondaryColor;
gl_FragColor.a = gl_FragColor.b;
}

View file

@ -0,0 +1,109 @@
//
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
//
// NVIDIA Statement on the Software
//
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
// detailed.
//
// No Warranty
//
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
// Limitation of Liability
//
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
//
//
// Atmospheric scattering vertex shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//
#version 120
uniform vec3 v3CameraPos; // The camera's current position
uniform vec3 v3LightPos; // The direction vector to the light source
uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels
uniform float fCameraHeight2; // fCameraHeight^2
uniform float fOuterRadius; // The outer (atmosphere) radius
uniform float fOuterRadius2; // fOuterRadius^2
uniform float fInnerRadius; // The inner (planetary) radius
uniform float fKrESun; // Kr * ESun
uniform float fKmESun; // Km * ESun
uniform float fKr4PI; // Kr * 4 * PI
uniform float fKm4PI; // Km * 4 * PI
uniform float fScale; // 1 / (fOuterRadius - fInnerRadius)
uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found)
uniform float fScaleOverScaleDepth; // fScale / fScaleDepth
const int nSamples = 2;
const float fSamples = 2.0;
varying vec3 v3Direction;
float scale(float fCos)
{
float x = 1.0 - fCos;
return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
}
void main(void)
{
// Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)
vec3 v3Pos = gl_Vertex.xyz;
vec3 v3Ray = v3Pos - v3CameraPos;
float fFar = length(v3Ray);
v3Ray /= fFar;
// Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)
float B = 2.0 * dot(v3CameraPos, v3Ray);
float C = fCameraHeight2 - fOuterRadius2;
float fDet = max(0.0, B*B - 4.0 * C);
float fNear = 0.5 * (-B - sqrt(fDet));
// Calculate the ray's starting position, then calculate its scattering offset
vec3 v3Start = v3CameraPos + v3Ray * fNear;
fFar -= fNear;
float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius;
float fStartDepth = exp(-1.0 / fScaleDepth);
float fStartOffset = fStartDepth * scale(fStartAngle);
// Initialize the scattering loop variables
//gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0);
float fSampleLength = fFar / fSamples;
float fScaledLength = fSampleLength * fScale;
vec3 v3SampleRay = v3Ray * fSampleLength;
vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;
// Now loop through the sample rays
vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);
for(int i=0; i<nSamples; i++)
{
float fHeight = length(v3SamplePoint);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fLightAngle = dot(v3LightPos, v3SamplePoint) / fHeight;
float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight;
float fScatter = (fStartOffset + fDepth * (scale(fLightAngle) - scale(fCameraAngle)));
vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay;
}
// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader
gl_FrontSecondaryColor.rgb = v3FrontColor * fKmESun;
gl_FrontColor.rgb = v3FrontColor * (v3InvWavelength * fKrESun);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
v3Direction = v3CameraPos - v3Pos;
}

View file

@ -111,7 +111,8 @@ int audioCallback (const void *inputBuffer,
int16_t *inputLeft = ((int16_t **) inputBuffer)[0];
// printLog("Audio callback at %6.0f\n", usecTimestampNow()/1000);
// Add Procedural effects to input samples
data->addProceduralSounds(inputLeft, BUFFER_LENGTH_SAMPLES);
if (inputLeft != NULL) {

View file

@ -30,6 +30,9 @@ public:
void setWalkingState(bool newWalkState);
void setLastAcceleration(glm::vec3 a) { audioData->setLastAcceleration(a); };
void setLastVelocity(glm::vec3 v) { audioData->setLastVelocity(v); };
// terminates audio I/O
bool terminate();
private:

View file

@ -28,4 +28,20 @@ AudioData::~AudioData() {
delete audioSocket;
}
// Take a pointer to the acquired microphone input samples and add procedural sounds
void AudioData::addProceduralSounds(int16_t* inputBuffer, int numSamples) {
const float MAX_AUDIBLE_VELOCITY = 3.0;
const float MIN_AUDIBLE_VELOCITY = 0.1;
const float VOLUME = 200;
float speed = glm::length(_lastVelocity);
if ((speed > MIN_AUDIBLE_VELOCITY) && (speed < MAX_AUDIBLE_VELOCITY)) {
for (int i = 0; i < numSamples; i++) {
inputBuffer[i] += (int16_t) ((randFloat() - 0.5f) * VOLUME * speed) ;
}
}
return;
}
#endif

View file

@ -39,6 +39,17 @@ class AudioData {
bool mixerLoopbackFlag;
bool playWalkSound;
// Added avatar acceleration and velocity for procedural effects sounds from client
void setLastVelocity(glm::vec3 v) { _lastVelocity = v; };
void setLastAcceleration(glm::vec3 a) { _lastAcceleration = a; };
void addProceduralSounds(int16_t* inputBuffer, int numSamples);
private:
glm::vec3 _lastVelocity;
glm::vec3 _lastAcceleration;
};
#endif /* defined(__interface__AudioData__) */

View file

@ -262,32 +262,38 @@ void Avatar::reset() {
_head.leanForward = _head.leanSideways = 0;
}
// this pertains to moving the head with the glasses
// Using serial data, update avatar/render position and angles
// Update avatar head rotation with sensor data
void Avatar::UpdateGyros(float frametime, SerialInterface* serialInterface, glm::vec3* gravity) {
float measured_pitch_rate = 0.0f;
float measured_roll_rate = 0.0f;
float measuredPitchRate = 0.0f;
float measuredRollRate = 0.0f;
float measuredYawRate = 0.0f;
if (serialInterface->active && USING_INVENSENSE_MPU9150) {
measured_pitch_rate = serialInterface->getLastPitch();
_head.yawRate = serialInterface->getLastYaw();
measured_roll_rate = -1 * serialInterface->getLastRoll();
measuredPitchRate = serialInterface->getLastPitchRate();
measuredYawRate = serialInterface->getLastYawRate();
measuredRollRate = serialInterface->getLastRollRate();
} else {
measured_pitch_rate = serialInterface->getRelativeValue(HEAD_PITCH_RATE);
_head.yawRate = serialInterface->getRelativeValue(HEAD_YAW_RATE);
measured_roll_rate = serialInterface->getRelativeValue(HEAD_ROLL_RATE);
measuredPitchRate = serialInterface->getRelativeValue(HEAD_PITCH_RATE);
measuredYawRate = serialInterface->getRelativeValue(HEAD_YAW_RATE);
measuredRollRate = serialInterface->getRelativeValue(HEAD_ROLL_RATE);
}
// Update avatar head position based on measured gyro rates
const float MAX_PITCH = 45;
const float MIN_PITCH = -45;
const float MAX_YAW = 85;
const float MIN_YAW = -85;
const float MAX_ROLL = 50;
const float MIN_ROLL = -50;
if ((_headPitch < HEAD_MAX_PITCH) && (_headPitch > HEAD_MIN_PITCH)) {
addHeadPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime);
}
addHeadRoll(measured_roll_rate * HEAD_ROLL_SCALE * frametime);
addHeadPitch(measuredPitchRate * frametime);
addHeadYaw(measuredYawRate * frametime);
addHeadRoll(measuredRollRate * frametime);
if ((_headYaw < HEAD_MAX_YAW) && (_headYaw > HEAD_MIN_YAW)) {
addHeadYaw(_head.yawRate * HEAD_ROTATION_SCALE * frametime);
}
setHeadPitch(glm::clamp(getHeadPitch(), MIN_PITCH, MAX_PITCH));
setHeadYaw(glm::clamp(getHeadYaw(), MIN_YAW, MAX_YAW));
setHeadRoll(glm::clamp(getHeadRoll(), MIN_ROLL, MAX_ROLL));
}
float Avatar::getAbsoluteHeadYaw() const {
@ -514,6 +520,16 @@ void Avatar::updateHead(float deltaTime) {
_headRoll *= (1.0f - DECAY * _head.returnSpringScale * 2 * deltaTime);
}
// For invensense gyro, decay only slightly when roughly centered
if (USING_INVENSENSE_MPU9150) {
const float RETURN_RANGE = 5.0;
const float RETURN_STRENGTH = 1.0;
if (fabs(_headPitch) < RETURN_RANGE) { _headPitch *= (1.0f - RETURN_STRENGTH * deltaTime); }
if (fabs(_headYaw) < RETURN_RANGE) { _headYaw *= (1.0f - RETURN_STRENGTH * deltaTime); }
if (fabs(_headRoll) < RETURN_RANGE) { _headRoll *= (1.0f - RETURN_STRENGTH * deltaTime); }
}
if (_head.noise) {
// Move toward new target
_headPitch += (_head.pitchTarget - _headPitch) * 10 * deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ;

View file

@ -108,6 +108,7 @@ public:
const glm::vec3& getBodyUpDirection() const { return _orientation.getUp(); };
float getSpeed() const { return _speed; };
const glm::vec3& getVelocity() const { return _velocity; };
float getGirth();
float getHeight();

View file

@ -0,0 +1,117 @@
//
// Environment.cpp
// interface
//
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <QByteArray>
#include <SharedUtil.h>
#include "Camera.h"
#include "Environment.h"
#include "renderer/ProgramObject.h"
#include "renderer/ShaderObject.h"
#include "world.h"
void Environment::init() {
switchToResourcesParentIfRequired();
_skyFromAtmosphereProgram = createSkyProgram("Atmosphere", _skyFromAtmosphereUniformLocations);
_skyFromSpaceProgram = createSkyProgram("Space", _skyFromSpaceUniformLocations);
}
void Environment::renderAtmosphere(Camera& camera) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(getAtmosphereCenter().x, getAtmosphereCenter().y, getAtmosphereCenter().z);
// use the camera distance to reset the near and far distances to keep the atmosphere in the frustum
glMatrixMode(GL_PROJECTION);
glPushMatrix();
float projection[16];
glGetFloatv(GL_PROJECTION_MATRIX, projection);
glm::vec3 relativeCameraPos = camera.getPosition() - getAtmosphereCenter();
float height = glm::length(relativeCameraPos);
float near = camera.getNearClip(), far = height + getAtmosphereOuterRadius();
projection[10] = (far + near) / (near - far);
projection[14] = (2.0f * far * near) / (near - far);
glLoadMatrixf(projection);
// 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;
}
// 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->setUniform(locations[INV_WAVELENGTH_LOCATION],
1 / powf(getScatteringWavelengths().r, 4.0f),
1 / powf(getScatteringWavelengths().g, 4.0f),
1 / powf(getScatteringWavelengths().b, 4.0f));
program->setUniform(locations[CAMERA_HEIGHT2_LOCATION], height * height);
program->setUniform(locations[OUTER_RADIUS_LOCATION], getAtmosphereOuterRadius());
program->setUniform(locations[OUTER_RADIUS2_LOCATION], getAtmosphereOuterRadius() * getAtmosphereOuterRadius());
program->setUniform(locations[INNER_RADIUS_LOCATION], getAtmosphereInnerRadius());
program->setUniform(locations[KR_ESUN_LOCATION], getRayleighScattering() * getSunBrightness());
program->setUniform(locations[KM_ESUN_LOCATION], getMieScattering() * getSunBrightness());
program->setUniform(locations[KR_4PI_LOCATION], getRayleighScattering() * 4.0f * PIf);
program->setUniform(locations[KM_4PI_LOCATION], getMieScattering() * 4.0f * PIf);
program->setUniform(locations[SCALE_LOCATION], 1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius()));
program->setUniform(locations[SCALE_DEPTH_LOCATION], 0.25f);
program->setUniform(locations[SCALE_OVER_SCALE_DEPTH_LOCATION],
(1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius())) / 0.25f);
program->setUniform(locations[G_LOCATION], -0.990f);
program->setUniform(locations[G2_LOCATION], -0.990f * -0.990f);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glutSolidSphere(getAtmosphereOuterRadius(), 100, 50);
glDepthMask(GL_TRUE);
program->release();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
ProgramObject* Environment::createSkyProgram(const char* from, int* locations) {
ProgramObject* program = new ProgramObject();
QByteArray prefix = QByteArray("resources/shaders/SkyFrom") + from;
program->attachFromSourceFile(GL_VERTEX_SHADER_ARB, prefix + ".vert");
program->attachFromSourceFile(GL_FRAGMENT_SHADER_ARB, prefix + ".frag");
program->link();
locations[CAMERA_POS_LOCATION] = program->getUniformLocation("v3CameraPos");
locations[LIGHT_POS_LOCATION] = program->getUniformLocation("v3LightPos");
locations[INV_WAVELENGTH_LOCATION] = program->getUniformLocation("v3InvWavelength");
locations[CAMERA_HEIGHT2_LOCATION] = program->getUniformLocation("fCameraHeight2");
locations[OUTER_RADIUS_LOCATION] = program->getUniformLocation("fOuterRadius");
locations[OUTER_RADIUS2_LOCATION] = program->getUniformLocation("fOuterRadius2");
locations[INNER_RADIUS_LOCATION] = program->getUniformLocation("fInnerRadius");
locations[KR_ESUN_LOCATION] = program->getUniformLocation("fKrESun");
locations[KM_ESUN_LOCATION] = program->getUniformLocation("fKmESun");
locations[KR_4PI_LOCATION] = program->getUniformLocation("fKr4PI");
locations[KM_4PI_LOCATION] = program->getUniformLocation("fKm4PI");
locations[SCALE_LOCATION] = program->getUniformLocation("fScale");
locations[SCALE_DEPTH_LOCATION] = program->getUniformLocation("fScaleDepth");
locations[SCALE_OVER_SCALE_DEPTH_LOCATION] = program->getUniformLocation("fScaleOverScaleDepth");
locations[G_LOCATION] = program->getUniformLocation("g");
locations[G2_LOCATION] = program->getUniformLocation("g2");
return program;
}

View file

@ -0,0 +1,55 @@
//
// Environment.h
// interface
//
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__Environment__
#define __interface__Environment__
#include "EnvironmentData.h"
#include "InterfaceConfig.h"
class Camera;
class ProgramObject;
class Environment : public EnvironmentData {
public:
void init();
void renderAtmosphere(Camera& camera);
private:
ProgramObject* createSkyProgram(const char* from, int* locations);
ProgramObject* _skyFromAtmosphereProgram;
ProgramObject* _skyFromSpaceProgram;
enum {
CAMERA_POS_LOCATION,
LIGHT_POS_LOCATION,
INV_WAVELENGTH_LOCATION,
CAMERA_HEIGHT2_LOCATION,
OUTER_RADIUS_LOCATION,
OUTER_RADIUS2_LOCATION,
INNER_RADIUS_LOCATION,
KR_ESUN_LOCATION,
KM_ESUN_LOCATION,
KR_4PI_LOCATION,
KM_4PI_LOCATION,
SCALE_LOCATION,
SCALE_DEPTH_LOCATION,
SCALE_OVER_SCALE_DEPTH_LOCATION,
G_LOCATION,
G2_LOCATION,
LOCATION_COUNT
};
int _skyFromAtmosphereUniformLocations[LOCATION_COUNT];
int _skyFromSpaceUniformLocations[LOCATION_COUNT];
};
#endif /* defined(__interface__Environment__) */

View file

@ -173,12 +173,12 @@ void SerialInterface::renderLevels(int width, int height) {
const int LEVEL_CORNER_X = 10;
const int LEVEL_CORNER_Y = 200;
// Draw the text values
sprintf(val, "Yaw %d", _lastYaw);
// Draw the numeric degree/sec values from the gyros
sprintf(val, "Yaw %4.1f", _lastYawRate);
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y, 0.10, 0, 1.0, 1, val, 0, 1, 0);
sprintf(val, "Pitch %d", _lastPitch);
sprintf(val, "Pitch %4.1f", _lastPitchRate);
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 15, 0.10, 0, 1.0, 1, val, 0, 1, 0);
sprintf(val, "Roll %d", _lastRoll);
sprintf(val, "Roll %4.1f", _lastRollRate);
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 30, 0.10, 0, 1.0, 1, val, 0, 1, 0);
// Draw the levels as horizontal lines
@ -187,11 +187,11 @@ void SerialInterface::renderLevels(int width, int height) {
glColor4f(1, 1, 1, 1);
glBegin(GL_LINES);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y - 3);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastYaw, LEVEL_CORNER_Y - 3);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastYawRate, LEVEL_CORNER_Y - 3);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 12);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastPitch, LEVEL_CORNER_Y + 12);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastPitchRate, LEVEL_CORNER_Y + 12);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 27);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastRoll, LEVEL_CORNER_Y + 27);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastRollRate, LEVEL_CORNER_Y + 27);
glEnd();
// Draw green vertical centerline
glColor4f(0, 1, 0, 0.5);
@ -238,9 +238,20 @@ void SerialInterface::readData() {
write(_serialDescriptor, "RD684306\n", 9);
read(_serialDescriptor, gyroBuffer, 20);
convertHexToInt(gyroBuffer + 6, _lastYaw);
convertHexToInt(gyroBuffer + 10, _lastRoll);
convertHexToInt(gyroBuffer + 14, _lastPitch);
int rollRate, yawRate, pitchRate;
convertHexToInt(gyroBuffer + 6, rollRate);
convertHexToInt(gyroBuffer + 10, yawRate);
convertHexToInt(gyroBuffer + 14, pitchRate);
// Convert the integer rates to floats
const float LSB_TO_DEGREES_PER_SECOND = 1.f / 16.4f; // From MPU-9150 register map, 2000 deg/sec.
const float PITCH_BIAS = 2.0; // Strangely, there is a small DC bias in the
// invensense pitch reading. Gravity?
_lastRollRate = (float) rollRate * LSB_TO_DEGREES_PER_SECOND;
_lastYawRate = (float) yawRate * LSB_TO_DEGREES_PER_SECOND;
_lastPitchRate = (float) -pitchRate * LSB_TO_DEGREES_PER_SECOND + PITCH_BIAS;
totalSamples++;
} else {

View file

@ -42,9 +42,9 @@ public:
void pair();
void readData();
int getLastYaw() const { return _lastYaw; }
int getLastPitch() const { return _lastPitch; }
int getLastRoll() const { return _lastRoll; }
float getLastYawRate() const { return _lastYawRate; }
float getLastPitchRate() const { return _lastPitchRate; }
float getLastRollRate() const { return _lastRollRate; }
int getLED() {return LED;};
int getNumSamples() {return samplesAveraged;};
@ -69,9 +69,9 @@ private:
int totalSamples;
timeval lastGoodRead;
glm::vec3 gravity;
int _lastYaw;
int _lastPitch;
int _lastRoll;
float _lastYawRate; // Rates are in degrees per second.
float _lastPitchRate;
float _lastRollRate;
int _failedOpenAttempts;
};

View file

@ -34,7 +34,7 @@ float Stars::changeLOD(float fraction, float overalloc, float realloc) {
return float(_ptrController->changeLOD(fraction, overalloc, realloc));
}
void Stars::render(float fovY, float aspect, float nearZ) {
void Stars::render(float fovY, float aspect, float nearZ, float alpha) {
// determine length of screen diagonal from quadrant height and aspect ratio
float quadrantHeight = nearZ * tan(angleConvert<Degrees,Radians>(fovY) * 0.5f);
@ -46,7 +46,7 @@ void Stars::render(float fovY, float aspect, float nearZ) {
// 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), alpha);
}

View file

@ -37,7 +37,7 @@ class Stars {
// Renders the starfield from a local viewer's perspective.
// The parameters specifiy the field of view.
//
void render(float fovY, float aspect, float nearZ);
void render(float fovY, float aspect, float nearZ, float alpha);
//
// Sets the resolution for FOV culling.

View file

@ -63,11 +63,6 @@ void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer)
setupNewVoxelsForDrawing();
}
void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) {
_tree->createSphere(r, xc, yc, zc, s, solid, wantColorRandomizer);
setupNewVoxelsForDrawing();
}
long int VoxelSystem::getVoxelsCreated() {
return _tree->voxelsCreated;
}
@ -144,22 +139,22 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
double start = usecTimestampNow();
double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000.0;
if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed,SIXTY_FPS_IN_MILLISECONDS)) {
if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) {
return; // bail early, it hasn't been long enough since the last time we ran
}
double sinceLastViewCulling = (start - _lastViewCulling) / 1000.0;
// If the view frustum has changed, since last time, then remove nodes that are out of view
if ((sinceLastViewCulling >= VIEW_CULLING_RATE_IN_MILLISECONDS) && hasViewChanged()) {
if ((sinceLastViewCulling >= std::max(_lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) && hasViewChanged()) {
_lastViewCulling = start;
removeOutOfView();
double endViewCulling = usecTimestampNow();
_lastViewCullingElapsed = (endViewCulling - start) / 1000.0;
}
if (_tree->isDirty()) {
PerformanceWarning warn(_renderWarningsOn, "calling... newTreeToArrays()");
_callsToTreesToArrays++;
if (_alwaysRenderFullVBO) {
_voxelsInWriteArrays = 0; // reset our VBO
}
@ -176,7 +171,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
copyWrittenDataToReadArrays();
double end = usecTimestampNow();
double elapsedmsec = (end - start)/1000.0;
double elapsedmsec = (end - start) / 1000.0;
_setupNewVoxelsForDrawingLastFinished = end;
_setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
}
@ -225,6 +220,11 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) {
}
int VoxelSystem::newway__updateNodeInArray(VoxelNode* node) {
// If we've run out of room, then just bail...
if (_voxelsInWriteArrays >= MAX_VOXELS_PER_SYSTEM) {
return 0;
}
if (node->getShouldRender()) {
glm::vec3 startVertex = node->getCorner();
float voxelScale = node->getScale();
@ -299,7 +299,7 @@ void VoxelSystem::init() {
_callsToTreesToArrays = 0;
_setupNewVoxelsForDrawingLastFinished = 0;
_setupNewVoxelsForDrawingLastElapsed = 0;
_lastViewCulling = 0;
_lastViewCullingElapsed = _lastViewCulling = 0;
// When we change voxels representations in the arrays, we'll update this
_voxelsDirty = false;
@ -508,6 +508,7 @@ bool VoxelSystem::trueColorizeOperation(VoxelNode* node, void* extraData) {
}
void VoxelSystem::trueColorize() {
PerformanceWarning warn(true, "trueColorize()",true);
_nodeCount = 0;
_tree->recurseTreeWithOperation(trueColorizeOperation);
printLog("setting true color for %d nodes\n", _nodeCount);
@ -587,17 +588,71 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) {
setupNewVoxelsForDrawing();
}
// combines the removeOutOfView args into a single class
class removeOutOfViewArgs {
public:
VoxelSystem* thisVoxelSystem;
VoxelNodeBag dontRecurseBag;
unsigned long nodesScanned;
unsigned long nodesRemoved;
unsigned long nodesInside;
unsigned long nodesIntersect;
unsigned long nodesOutside;
removeOutOfViewArgs(VoxelSystem* voxelSystem) :
thisVoxelSystem(voxelSystem),
dontRecurseBag(),
nodesScanned(0),
nodesRemoved(0),
nodesInside(0),
nodesIntersect(0),
nodesOutside(0)
{ }
};
// "Remove" voxels from the tree that are not in view. We don't actually delete them,
// we remove them from the tree and place them into a holding area for later deletion
bool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) {
VoxelSystem* thisVoxelSystem = (VoxelSystem*) extraData;
_nodeCount++;
removeOutOfViewArgs* args = (removeOutOfViewArgs*)extraData;
// If our node was previously added to the don't recurse bag, then return false to
// stop the further recursion. This means that the whole node and it's children are
// known to be in view, so don't recurse them
if (args->dontRecurseBag.contains(node)) {
args->dontRecurseBag.remove(node);
return false; // stop recursion
}
VoxelSystem* thisVoxelSystem = args->thisVoxelSystem;
args->nodesScanned++;
// Need to operate on our child nodes, so we can remove them
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
VoxelNode* childNode = node->getChildAtIndex(i);
if (childNode && !childNode->isInView(*thisVoxelSystem->_viewFrustum)) {
node->removeChildAtIndex(i);
thisVoxelSystem->_removedVoxels.insert(childNode);
if (childNode) {
ViewFrustum::location inFrustum = childNode->inFrustum(*thisVoxelSystem->_viewFrustum);
switch (inFrustum) {
case ViewFrustum::OUTSIDE: {
args->nodesOutside++;
args->nodesRemoved++;
node->removeChildAtIndex(i);
thisVoxelSystem->_removedVoxels.insert(childNode);
// by removing the child, it will not get recursed!
} break;
case ViewFrustum::INSIDE: {
// if the child node is fully INSIDE the view, then there's no need to recurse it
// because we know all it's children will also be in the view, so we want to
// tell the caller to NOT recurse this child
args->nodesInside++;
args->dontRecurseBag.insert(childNode);
} break;
case ViewFrustum::INTERSECT: {
// if the child node INTERSECTs the view, then we don't want to remove it because
// it is at least partially in view. But we DO want to recurse the children because
// some of them may not be in view... nothing specifically to do, just keep iterating
// the children
args->nodesIntersect++;
} break;
}
}
}
return true; // keep going!
@ -613,7 +668,14 @@ bool VoxelSystem::hasViewChanged() {
}
void VoxelSystem::removeOutOfView() {
PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()"); // would like to include removedCount, _nodeCount, _removedVoxels.count()
_nodeCount = 0;
_tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)this);
PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()");
removeOutOfViewArgs args(this);
_tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args);
if (_renderWarningsOn) {
printLog("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld bag.count()=%d \n",
args.nodesScanned, args.nodesRemoved, args.nodesInside,
args.nodesIntersect, args.nodesOutside, args.dontRecurseBag.count()
);
}
}

View file

@ -42,7 +42,6 @@ public:
void setViewerAvatar(Avatar *newViewerAvatar) { _viewerAvatar = newViewerAvatar; };
void setCamera(Camera* newCamera) { _camera = newCamera; };
void loadVoxelsFile(const char* fileName,bool wantColorRandomizer);
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer);
long int getVoxelsCreated();
long int getVoxelsColored();
@ -105,6 +104,7 @@ private:
double _setupNewVoxelsForDrawingLastElapsed;
double _setupNewVoxelsForDrawingLastFinished;
double _lastViewCulling;
double _lastViewCullingElapsed;
GLuint _vboVerticesID;
GLuint _vboNormalsID;

View file

@ -58,12 +58,15 @@
#include "ui/MenuColumn.h"
#include "ui/Menu.h"
#include "ui/TextRenderer.h"
#include "renderer/ProgramObject.h"
#include "renderer/ShaderObject.h"
#include "Camera.h"
#include "Avatar.h"
#include <AgentList.h>
#include <AgentTypes.h>
#include "VoxelSystem.h"
#include "Environment.h"
#include "Oscilloscope.h"
#include "UDPSocket.h"
#include "SerialInterface.h"
@ -120,29 +123,32 @@ char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
char starCacheFile[] = "cachedStars.txt";
Stars stars;
bool showingVoxels = true;
glm::vec3 box(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);
VoxelSystem voxels;
bool wantToKillLocalVoxels = false;
Environment environment;
#ifndef _WIN32
Audio audio(&audioScope, &myAvatar);
#endif
#define IDLE_SIMULATE_MSECS 16 // How often should call simulate and other stuff
// in the idle loop?
// in the idle loop? (60 FPS is default)
// Where one's own agent begins in the world (needs to become a dynamic thing passed to the program)
glm::vec3 start_location(6.1f, 0, 1.4f);
glm::vec3 start_location(6.1f, 0, 1.4f); // Where one's own agent begins in the world
// (will be overwritten if avatar data file is found)
bool renderWarningsOn = false; // Whether to show render pipeline warnings
bool statsOn = false; // Whether to show onscreen text overlay with stats
bool starsOn = false; // Whether to display the stars
bool renderStatsOn = false; // Whether to show onscreen text overlay with stats
bool renderVoxels = true; // Whether to render voxels
bool renderStarsOn = true; // Whether to display the stars
bool renderAtmosphereOn = true; // Whether to display the atmosphere
bool renderAvatarsOn = true; // Whether to render avatars
bool paintOn = false; // Whether to paint voxels as you fly around
VoxelDetail paintingVoxel; // The voxel we're painting if we're painting
unsigned char dominantColor = 0; // The dominant color of the voxel we're painting
@ -177,7 +183,7 @@ bool chatEntryOn = false; // Whether to show the chat entry
bool oculusOn = false; // Whether to configure the display for the Oculus Rift
GLuint oculusTextureID = 0; // The texture to which we render for Oculus distortion
GLhandleARB oculusProgramID = 0; // The GLSL program containing the distortion shader
ProgramObject* oculusProgram = 0; // The GLSL program containing the distortion shader
float oculusDistortionScale = 1.25; // Controls the Oculus field of view
//
@ -302,6 +308,8 @@ void init(void) {
voxels.setViewerAvatar(&myAvatar);
voxels.setCamera(&myCamera);
environment.init();
handControl.setScreenDimensions(WIDTH, HEIGHT);
headMouseX = WIDTH/2;
@ -678,13 +686,31 @@ void renderViewFrustum(ViewFrustum& viewFrustum) {
void displaySide(Camera& whichCamera) {
glPushMatrix();
if (::starsOn) {
if (::renderStarsOn) {
// should be the first rendering pass - w/o depth buffer / lighting
// compute starfield alpha based on distance from atmosphere
float alpha = 1.0f;
if (::renderAtmosphereOn) {
float height = glm::distance(whichCamera.getPosition(), environment.getAtmosphereCenter());
if (height < environment.getAtmosphereInnerRadius()) {
alpha = 0.0f;
} else if (height < environment.getAtmosphereOuterRadius()) {
alpha = (height - environment.getAtmosphereInnerRadius()) /
(environment.getAtmosphereOuterRadius() - environment.getAtmosphereInnerRadius());
}
}
// finally render the starfield
stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip());
stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip(), alpha);
}
// draw the sky dome
if (::renderAtmosphereOn) {
environment.renderAtmosphere(whichCamera);
}
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
@ -699,23 +725,28 @@ void displaySide(Camera& whichCamera) {
drawGroundPlaneGrid(10.f);
// Draw voxels
if (showingVoxels) {
if (renderVoxels) {
voxels.render();
}
// Render avatars of other agents
AgentList* agentList = AgentList::getInstance();
agentList->lock();
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
Avatar *avatar = (Avatar *)agent->getLinkedData();
avatar->render(0, ::myCamera.getPosition());
if (::renderAvatarsOn) {
// Render avatars of other agents
AgentList* agentList = AgentList::getInstance();
agentList->lock();
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
Avatar *avatar = (Avatar *)agent->getLinkedData();
avatar->render(0, ::myCamera.getPosition());
}
}
agentList->unlock();
// Render my own Avatar
myAvatar.render(::lookingInMirror, ::myCamera.getPosition());
}
agentList->unlock();
// Render the world box
if (!::lookingInMirror && ::statsOn) { render_world_box(); }
if (!::lookingInMirror && ::renderStatsOn) { render_world_box(); }
// brad's frustum for debugging
if (::frustumOn) renderViewFrustum(::viewFrustum);
@ -806,18 +837,16 @@ void displayOculus(Camera& whichCamera) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GLhandleARB shaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
glShaderSourceARB(shaderID, 1, &DISTORTION_FRAGMENT_SHADER, 0);
glCompileShaderARB(shaderID);
::oculusProgramID = glCreateProgramObjectARB();
glAttachObjectARB(::oculusProgramID, shaderID);
glLinkProgramARB(::oculusProgramID);
textureLocation = glGetUniformLocationARB(::oculusProgramID, "texture");
lensCenterLocation = glGetUniformLocationARB(::oculusProgramID, "lensCenter");
screenCenterLocation = glGetUniformLocationARB(::oculusProgramID, "screenCenter");
scaleLocation = glGetUniformLocationARB(::oculusProgramID, "scale");
scaleInLocation = glGetUniformLocationARB(::oculusProgramID, "scaleIn");
hmdWarpParamLocation = glGetUniformLocationARB(::oculusProgramID, "hmdWarpParam");
::oculusProgram = new ProgramObject();
::oculusProgram->attachFromSourceCode(GL_FRAGMENT_SHADER_ARB, DISTORTION_FRAGMENT_SHADER);
::oculusProgram->link();
textureLocation = ::oculusProgram->getUniformLocation("texture");
lensCenterLocation = ::oculusProgram->getUniformLocation("lensCenter");
screenCenterLocation = ::oculusProgram->getUniformLocation("screenCenter");
scaleLocation = ::oculusProgram->getUniformLocation("scale");
scaleInLocation = ::oculusProgram->getUniformLocation("scaleIn");
hmdWarpParamLocation = ::oculusProgram->getUniformLocation("hmdWarpParam");
} else {
glBindTexture(GL_TEXTURE_2D, ::oculusTextureID);
@ -837,13 +866,13 @@ void displayOculus(Camera& whichCamera) {
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glUseProgramObjectARB(::oculusProgramID);
glUniform1iARB(textureLocation, 0);
glUniform2fARB(lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
glUniform2fARB(screenCenterLocation, 0.25, 0.5);
glUniform2fARB(scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio);
glUniform2fARB(scaleInLocation, 4, 2 / aspectRatio);
glUniform4fARB(hmdWarpParamLocation, 1.0, 0.22, 0.24, 0);
::oculusProgram->bind();
::oculusProgram->setUniform(textureLocation, 0);
::oculusProgram->setUniform(lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
::oculusProgram->setUniform(screenCenterLocation, 0.25, 0.5);
::oculusProgram->setUniform(scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio);
::oculusProgram->setUniform(scaleInLocation, 4, 2 / aspectRatio);
::oculusProgram->setUniform(hmdWarpParamLocation, 1.0, 0.22, 0.24, 0);
glColor3f(1, 0, 1);
glBegin(GL_QUADS);
@ -857,8 +886,8 @@ void displayOculus(Camera& whichCamera) {
glVertex2f(0, HEIGHT);
glEnd();
glUniform2fARB(lensCenterLocation, 0.787994, 0.5);
glUniform2fARB(screenCenterLocation, 0.75, 0.5);
::oculusProgram->setUniform(lensCenterLocation, 0.787994, 0.5);
::oculusProgram->setUniform(screenCenterLocation, 0.75, 0.5);
glBegin(GL_QUADS);
glTexCoord2f(0.5, 0);
@ -874,7 +903,7 @@ void displayOculus(Camera& whichCamera) {
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgramObjectARB(0);
::oculusProgram->release();
glPopMatrix();
}
@ -895,7 +924,7 @@ void displayOverlay() {
//noiseTest(WIDTH, HEIGHT);
if (displayHeadMouse && !::lookingInMirror && statsOn) {
if (displayHeadMouse && !::lookingInMirror && renderStatsOn) {
// Display small target box at center or head mouse target that can also be used to measure LOD
glColor3f(1.0, 1.0, 1.0);
glDisable(GL_LINE_SMOOTH);
@ -917,7 +946,7 @@ void displayOverlay() {
glLineWidth(1.0f);
glPointSize(1.0f);
if (::statsOn) { displayStats(); }
if (::renderStatsOn) { displayStats(); }
if (::logOn) { logger.render(WIDTH, HEIGHT); }
// Show menu
@ -1202,13 +1231,23 @@ int setFullscreen(int state) {
}
int setVoxels(int state) {
return setValue(state, &::showingVoxels);
return setValue(state, &::renderVoxels);
}
int setStars(int state) {
return setValue(state, &::starsOn);
return setValue(state, &::renderStarsOn);
}
int setAtmosphere(int state) {
return setValue(state, &::renderAtmosphereOn);
}
int setRenderAvatars(int state) {
return setValue(state, &::renderAvatarsOn);
}
int setOculus(int state) {
bool wasOn = ::oculusOn;
int value = setValue(state, &::oculusOn);
@ -1219,7 +1258,7 @@ int setOculus(int state) {
}
int setStats(int state) {
return setValue(state, &::statsOn);
return setValue(state, &::renderStatsOn);
}
int setMenu(int state) {
@ -1354,6 +1393,8 @@ void initMenu() {
menuColumnRender = menu.addColumn("Render");
menuColumnRender->addRow("Voxels (V)", setVoxels);
menuColumnRender->addRow("Stars (*)", setStars);
menuColumnRender->addRow("Atmosphere (A)", setAtmosphere);
menuColumnRender->addRow("Avatars", setRenderAvatars);
menuColumnRender->addRow("Oculus (o)", setOculus);
// Tools
@ -1432,23 +1473,6 @@ void setupPaintingVoxel() {
shiftPaintingColor();
}
void addRandomSphere(bool wantColorRandomizer) {
float r = randFloatInRange(0.05,0.1);
float xc = randFloatInRange(r,(1-r));
float yc = randFloatInRange(r,(1-r));
float zc = randFloatInRange(r,(1-r));
float s = 0.001; // size of voxels to make up surface of sphere
bool solid = false;
printLog("random sphere\n");
printLog("radius=%f\n",r);
printLog("xc=%f\n",xc);
printLog("yc=%f\n",yc);
printLog("zc=%f\n",zc);
voxels.createSphere(r,xc,yc,zc,s,solid,wantColorRandomizer);
}
const float KEYBOARD_YAW_RATE = 0.8;
const float KEYBOARD_PITCH_RATE = 0.6;
const float KEYBOARD_STRAFE_RATE = 0.03;
@ -1533,9 +1557,10 @@ void key(unsigned char k, int x, int y) {
// Process keypresses
if (k == 'q' || k == 'Q') ::terminate();
if (k == '/') ::statsOn = !::statsOn; // toggle stats
if (k == '*') ::starsOn = !::starsOn; // toggle stars
if (k == 'V' || k == 'v') ::showingVoxels = !::showingVoxels; // toggle voxels
if (k == '/') ::renderStatsOn = !::renderStatsOn; // toggle stats
if (k == '*') ::renderStarsOn = !::renderStarsOn; // toggle stars
if (k == 'V' || k == 'v') ::renderVoxels = !::renderVoxels; // toggle voxels
if (k == 'A') ::renderAtmosphereOn = !::renderAtmosphereOn;
if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging
if (k == 'C') ::cameraFrustum = !::cameraFrustum; // toggle which frustum to look at
if (k == 'O' || k == 'G') setFrustumOffset(MENU_ROW_PICKED); // toggle view frustum offset debugging
@ -1629,6 +1654,9 @@ void* networkReceive(void* args) {
case PACKET_HEADER_ERASE_VOXEL:
voxels.parseData(incomingPacket, bytesReceived);
break;
case PACKET_HEADER_ENVIRONMENT_DATA:
environment.parseData(incomingPacket, bytesReceived);
break;
case PACKET_HEADER_BULK_AVATAR_DATA:
AgentList::getInstance()->processBulkAgentData(&senderAddress,
incomingPacket,
@ -1674,6 +1702,7 @@ void idle(void) {
handControl.stop();
}
// Read serial port interface devices
if (serialPort.active && USING_INVENSENSE_MPU9150) {
serialPort.readData();
}
@ -1699,7 +1728,11 @@ void idle(void) {
myAvatar.setGravity(getGravity(myAvatar.getPosition()));
myAvatar.simulate(deltaTime);
// Update audio stats for procedural sounds
audio.setLastAcceleration(myAvatar.getThrust());
audio.setLastVelocity(myAvatar.getVelocity());
glutPostRedisplay();
lastTimeIdle = check;
}
@ -1733,6 +1766,7 @@ void reshape(int width, int height) {
glBindTexture(GL_TEXTURE_2D, 0);
}
} else {
camera.setAspectRatio(aspectRatio);
camera.setFieldOfView(fov = 60);
}

View file

@ -0,0 +1,119 @@
//
// ProgramObject.cpp
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include "ProgramObject.h"
#include "ShaderObject.h"
ProgramObject::ProgramObject() : _handle(glCreateProgramObjectARB()) {
}
ProgramObject::~ProgramObject() {
glDeleteObjectARB(_handle);
}
void ProgramObject::attach(ShaderObject* shader) {
glAttachObjectARB(_handle, shader->getHandle());
}
bool ProgramObject::attachFromSourceCode(int type, const char* source) {
ShaderObject* shader = new ShaderObject(type);
if (shader->compileSourceCode(source)) {
attach(shader);
return true;
} else {
delete shader;
return false;
}
}
bool ProgramObject::attachFromSourceFile(int type, const char* filename) {
ShaderObject* shader = new ShaderObject(type);
if (shader->compileSourceFile(filename)) {
attach(shader);
return true;
} else {
delete shader;
return false;
}
}
bool ProgramObject::link() {
glLinkProgramARB(_handle);
int status;
glGetObjectParameterivARB(_handle, GL_OBJECT_LINK_STATUS_ARB, &status);
return status;
}
QByteArray ProgramObject::getLog() const {
int length;
glGetObjectParameterivARB(_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
QByteArray log(length, 0);
glGetInfoLogARB(_handle, length, 0, log.data());
return log;
}
void ProgramObject::bind() const {
glUseProgramObjectARB(_handle);
}
void ProgramObject::release() const {
glUseProgramObjectARB(0);
}
int ProgramObject::getUniformLocation(const char* name) const {
return glGetUniformLocationARB(_handle, name);
}
void ProgramObject::setUniform(int location, int value) {
glUniform1iARB(location, value);
}
void ProgramObject::setUniform(const char* name, int value) {
setUniform(getUniformLocation(name), value);
}
void ProgramObject::setUniform(int location, float value) {
glUniform1fARB(location, value);
}
void ProgramObject::setUniform(const char* name, float value) {
setUniform(getUniformLocation(name), value);
}
void ProgramObject::setUniform(int location, float x, float y) {
glUniform2fARB(location, x, y);
}
void ProgramObject::setUniform(const char* name, float x, float y) {
setUniform(getUniformLocation(name), x, y);
}
void ProgramObject::setUniform(int location, const glm::vec3& value) {
glUniform3fARB(location, value.x, value.y, value.z);
}
void ProgramObject::setUniform(const char* name, const glm::vec3& value) {
setUniform(getUniformLocation(name), value);
}
void ProgramObject::setUniform(int location, float x, float y, float z) {
glUniform3fARB(location, x, y, z);
}
void ProgramObject::setUniform(const char* name, float x, float y, float z) {
setUniform(getUniformLocation(name), x, y, z);
}
void ProgramObject::setUniform(int location, float x, float y, float z, float w) {
glUniform4fARB(location, x, y, z, w);
}
void ProgramObject::setUniform(const char* name, float x, float y, float z, float w) {
setUniform(getUniformLocation(name), x, y, z, w);
}

View file

@ -0,0 +1,66 @@
//
// ProgramObject.h
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__ProgramObject__
#define __interface__ProgramObject__
#include <QObject>
#include <glm/glm.hpp>
#include "InterfaceConfig.h"
class ShaderObject;
class ProgramObject {
public:
ProgramObject();
~ProgramObject();
GLhandleARB getHandle() const { return _handle; }
void attach(ShaderObject* shader);
bool attachFromSourceCode(int type, const char* source);
bool attachFromSourceFile(int type, const char* filename);
bool link();
QByteArray getLog() const;
void bind() const;
void release() const;
int getUniformLocation(const char* name) const;
void setUniform(int location, int value);
void setUniform(const char* name, int value);
void setUniform(int location, float value);
void setUniform(const char* name, float value);
void setUniform(int location, float x, float y);
void setUniform(const char* name, float x, float y);
void setUniform(int location, const glm::vec3& value);
void setUniform(const char* name, const glm::vec3& value);
void setUniform(int location, float x, float y, float z);
void setUniform(const char* name, float x, float y, float z);
void setUniform(int location, float x, float y, float z, float w);
void setUniform(const char* name, float x, float y, float z, float w);
private:
Q_DISABLE_COPY(ProgramObject)
GLhandleARB _handle;
};
#endif /* defined(__interface__ProgramObject__) */

View file

@ -0,0 +1,39 @@
//
// ShaderObject.cpp
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <QFile>
#include "ShaderObject.h"
ShaderObject::ShaderObject(int type)
: _handle(glCreateShaderObjectARB(type)) {
}
ShaderObject::~ShaderObject() {
glDeleteObjectARB(_handle);
}
bool ShaderObject::compileSourceCode(const char* data) {
glShaderSourceARB(_handle, 1, &data, 0);
glCompileShaderARB(_handle);
int status;
glGetObjectParameterivARB(_handle, GL_OBJECT_COMPILE_STATUS_ARB, &status);
return status;
}
bool ShaderObject::compileSourceFile(const char* filename) {
QFile file(filename);
return file.open(QIODevice::ReadOnly) && compileSourceCode(file.readAll().constData());
}
QByteArray ShaderObject::getLog() const {
int length;
glGetObjectParameterivARB(_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
QByteArray log(length, 0);
glGetInfoLogARB(_handle, length, 0, log.data());
return log;
}

View file

@ -0,0 +1,36 @@
//
// ShaderObject.h
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__ShaderObject__
#define __interface__ShaderObject__
#include <QObject>
#include "InterfaceConfig.h"
class ShaderObject {
public:
ShaderObject(int type);
~ShaderObject();
GLhandleARB getHandle() const { return _handle; }
bool compileSourceCode(const char* data);
bool compileSourceFile(const char* filename);
QByteArray getLog() const;
private:
Q_DISABLE_COPY(ShaderObject)
GLhandleARB _handle;
};
#endif /* defined(__interface__ShaderObject__) */

View file

@ -361,7 +361,7 @@ namespace starfield {
public:
void render(float perspective, float angle, mat4 const& orientation) {
void render(float perspective, float angle, mat4 const& orientation, float alpha) {
#if STARFIELD_MULTITHREADING
// check out renderer
@ -377,7 +377,7 @@ namespace starfield {
#else
BrightnessLevel b = _valLodBrightness;
#endif
renderer->render(perspective, angle, orientation, b);
renderer->render(perspective, angle, orientation, b, alpha);
}
#if STARFIELD_MULTITHREADING

View file

@ -13,6 +13,8 @@
#error "This is an implementation file - not intended for direct inclusion."
#endif
#include "renderer/ProgramObject.h"
#include "starfield/Config.h"
#include "starfield/data/InputVertex.h"
#include "starfield/data/BrightnessLevel.h"
@ -70,7 +72,8 @@ namespace starfield {
GLint* _arrBatchOffs;
GLsizei* _arrBatchCount;
GLuint _hndVertexArray;
OGlProgram _objProgram;
ProgramObject _objProgram;
int _alphaLocation;
Tiling _objTiling;
@ -123,7 +126,8 @@ namespace starfield {
void render(float perspective,
float aspect,
mat4 const& orientation,
BrightnessLevel minBright) {
BrightnessLevel minBright,
float alpha) {
// printLog("
// Stars.cpp: rendering at minimal brightness %d\n", minBright);
@ -186,7 +190,7 @@ namespace starfield {
# define matrix matrix_debug
#endif
this->glBatch(glm::value_ptr(matrix), prepareBatch(
(unsigned*) _arrBatchOffs, _itrOutIndex) );
(unsigned*) _arrBatchOffs, _itrOutIndex), alpha);
#if STARFIELD_DEBUG_CULLING
# undef matrix
@ -463,24 +467,26 @@ namespace starfield {
GLchar const* const VERTEX_SHADER =
"#version 120\n"
"uniform float alpha;\n"
"void main(void) {\n"
" vec3 c = gl_Color.rgb * 1.0125;\n"
" float s = max(1.0, dot(c, c) * 0.7);\n"
" gl_Position = ftransform();\n"
" gl_FrontColor= gl_Color;\n"
" gl_FrontColor= gl_Color * alpha;\n"
" gl_PointSize = s;\n"
"}\n";
_objProgram.addShader(GL_VERTEX_SHADER, VERTEX_SHADER);
_objProgram.attachFromSourceCode(GL_VERTEX_SHADER, VERTEX_SHADER);
GLchar const* const FRAGMENT_SHADER =
"#version 120\n"
"void main(void) {\n"
" gl_FragColor = gl_Color;\n"
"}\n";
_objProgram.addShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
_objProgram.attachFromSourceCode(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
_objProgram.link();
_alphaLocation = _objProgram.getUniformLocation("alpha");
glGenBuffersARB(1, & _hndVertexArray);
}
@ -499,7 +505,7 @@ namespace starfield {
glBindBufferARB(GL_ARRAY_BUFFER, 0);
}
void glBatch(GLfloat const* matrix, GLsizei n_ranges) {
void glBatch(GLfloat const* matrix, GLsizei n_ranges, float alpha) {
// printLog("Stars.cpp: rendering %d-multibatch\n", n_ranges);
@ -527,7 +533,8 @@ namespace starfield {
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
// select shader and vertex array
_objProgram.activate();
_objProgram.bind();
_objProgram.setUniform(_alphaLocation, alpha);
glBindBufferARB(GL_ARRAY_BUFFER, _hndVertexArray);
glInterleavedArrays(GL_C4UB_V3F, sizeof(GpuVertex), 0l);
@ -537,7 +544,7 @@ namespace starfield {
// restore state
glBindBufferARB(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
_objProgram.release();
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
glDisable(GL_POINT_SMOOTH);
glPopMatrix();

View file

@ -25,6 +25,7 @@ const PACKET_HEADER PACKET_HEADER_ERASE_VOXEL = 'E';
const PACKET_HEADER PACKET_HEADER_VOXEL_DATA = 'V';
const PACKET_HEADER PACKET_HEADER_BULK_AVATAR_DATA = 'X';
const PACKET_HEADER PACKET_HEADER_TRANSMITTER_DATA = 't';
const PACKET_HEADER PACKET_HEADER_ENVIRONMENT_DATA = 'e';
const PACKET_HEADER PACKET_HEADER_DOMAIN_LIST_REQUEST = 'L';
const PACKET_HEADER PACKET_HEADER_DOMAIN_RFD = 'C';

View file

@ -108,15 +108,16 @@ int PerfStat::DumpStats(char** array) {
PerformanceWarning::~PerformanceWarning() {
double end = usecTimestampNow();
double elapsedmsec = (end - _start) / 1000.0;
if (_renderWarningsOn && elapsedmsec > 1) {
if ((_alwaysDisplay || _renderWarningsOn) && elapsedmsec > 1) {
if (elapsedmsec > 1000) {
double elapsedsec = (end - _start) / 1000000.0;
printLog("WARNING! %s took %lf seconds\n", _message, elapsedsec);
} else {
printLog("WARNING! %s took %lf milliseconds\n", _message, elapsedmsec);
}
} else if (_alwaysDisplay) {
printLog("WARNING! %s took %lf milliseconds\n", _message, elapsedmsec);
}
};

View file

@ -87,11 +87,13 @@ private:
double _start;
const char* _message;
bool _renderWarningsOn;
bool _alwaysDisplay;
public:
PerformanceWarning(bool renderWarnings, const char* message) :
PerformanceWarning(bool renderWarnings, const char* message, bool alwaysDisplay = false) :
_start(usecTimestampNow()),
_message(message),
_renderWarningsOn(renderWarnings) { };
_renderWarningsOn(renderWarnings),
_alwaysDisplay(alwaysDisplay) { };
~PerformanceWarning();
};

View file

@ -170,7 +170,7 @@ bool cmdOptionExists(int argc, const char * argv[],const char* option) {
// Complaints: Brad :)
#define GUESS_OF_VOXELCODE_SIZE 10
#define MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE 1500
#define SIZE_OF_COLOR_DATA 3
#define SIZE_OF_COLOR_DATA sizeof(rgbColor)
bool createVoxelEditMessage(unsigned char command, short int sequence,
int voxelCount, VoxelDetail* voxelDetails, unsigned char*& bufferOut, int& sizeOut) {
@ -231,27 +231,26 @@ bool createVoxelEditMessage(unsigned char command, short int sequence,
unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r, unsigned char g, unsigned char b ) {
float xTest, yTest, zTest, sTest;
xTest = yTest = zTest = sTest = 0.5;
xTest = yTest = zTest = sTest = 0.5f;
// First determine the voxelSize that will properly encode a
// voxel of size S.
int voxelSizeInBits = 0;
unsigned int voxelSizeInOctets = 1;
while (sTest > s) {
sTest /= 2.0;
voxelSizeInBits+=3;
voxelSizeInOctets++;
}
unsigned int voxelSizeInBytes = (voxelSizeInBits/8)+1;
unsigned int voxelSizeInOctets = (voxelSizeInBits/3);
unsigned int voxelBufferSize = voxelSizeInBytes+1+3; // 1 for size, 3 for color
unsigned int voxelSizeInBytes = bytesRequiredForCodeLength(voxelSizeInOctets); // (voxelSizeInBits/8)+1;
unsigned int voxelBufferSize = voxelSizeInBytes + sizeof(rgbColor); // 3 for color
// allocate our resulting buffer
unsigned char* voxelOut = new unsigned char[voxelBufferSize];
// first byte of buffer is always our size in octets
voxelOut[0]=voxelSizeInOctets;
sTest = 0.5; // reset sTest so we can do this again.
sTest = 0.5f; // reset sTest so we can do this again.
unsigned char byte = 0; // we will be adding coding bits here
int bitInByteNDX = 0; // keep track of where we are in byte as we go
@ -260,7 +259,7 @@ unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r,
// Now we actually fill out the voxel code
while (octetsDone < voxelSizeInOctets) {
if (x > xTest) {
if (x >= xTest) {
//<write 1 bit>
byte = (byte << 1) | true;
xTest += sTest/2.0;
@ -272,14 +271,14 @@ unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r,
bitInByteNDX++;
// If we've reached the last bit of the byte, then we want to copy this byte
// into our buffer. And get ready to start on a new byte
if (bitInByteNDX > 7) {
if (bitInByteNDX == 8) {
voxelOut[byteNDX]=byte;
byteNDX++;
bitInByteNDX=0;
byte=0;
}
if (y > yTest) {
if (y >= yTest) {
//<write 1 bit>
byte = (byte << 1) | true;
yTest += sTest/2.0;
@ -291,14 +290,14 @@ unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r,
bitInByteNDX++;
// If we've reached the last bit of the byte, then we want to copy this byte
// into our buffer. And get ready to start on a new byte
if (bitInByteNDX > 7) {
if (bitInByteNDX == 8) {
voxelOut[byteNDX]=byte;
byteNDX++;
bitInByteNDX=0;
byte=0;
}
if (z > zTest) {
if (z >= zTest) {
//<write 1 bit>
byte = (byte << 1) | true;
zTest += sTest/2.0;
@ -310,7 +309,7 @@ unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r,
bitInByteNDX++;
// If we've reached the last bit of the byte, then we want to copy this byte
// into our buffer. And get ready to start on a new byte
if (bitInByteNDX > 7) {
if (bitInByteNDX == 8) {
voxelOut[byteNDX]=byte;
byteNDX++;
bitInByteNDX=0;
@ -323,13 +322,13 @@ unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r,
// If we've got here, and we didn't fill the last byte, we need to zero pad this
// byte before we copy it into our buffer.
if (bitInByteNDX > 0 && bitInByteNDX < 7) {
if (bitInByteNDX > 0 && bitInByteNDX < 8) {
// Pad the last byte
while (bitInByteNDX <= 7) {
while (bitInByteNDX < 8) {
byte = (byte << 1) | false;
bitInByteNDX++;
}
// Copy it into our output buffer
voxelOut[byteNDX]=byte;
byteNDX++;

View file

@ -18,6 +18,8 @@
#include <sys/time.h>
#endif
typedef unsigned char rgbColor[3];
static const float ZERO = 0.0f;
static const float ONE = 1.0f;
static const float ONE_HALF = 0.5f;

View file

@ -0,0 +1,90 @@
//
// EnvironmentData.cpp
// interface
//
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <cstring>
#include "EnvironmentData.h"
#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() :
_atmosphereCenter(0, -1000, 0),
_atmosphereInnerRadius(1000),
_atmosphereOuterRadius(1025),
_rayleighScattering(0.0025f),
_mieScattering(0.0010f),
_scatteringWavelengths(0.650f, 0.570f, 0.475f),
_sunLocation(1000, 1000, 0),
_sunBrightness(20.0f) {
}
int EnvironmentData::getBroadcastData(unsigned char* destinationBuffer) const {
unsigned char* bufferStart = destinationBuffer;
*destinationBuffer++ = PACKET_HEADER_ENVIRONMENT_DATA;
memcpy(destinationBuffer, &_atmosphereCenter, sizeof(_atmosphereCenter));
destinationBuffer += sizeof(_atmosphereCenter);
memcpy(destinationBuffer, &_atmosphereInnerRadius, sizeof(_atmosphereInnerRadius));
destinationBuffer += sizeof(_atmosphereInnerRadius);
memcpy(destinationBuffer, &_atmosphereOuterRadius, sizeof(_atmosphereOuterRadius));
destinationBuffer += sizeof(_atmosphereOuterRadius);
memcpy(destinationBuffer, &_rayleighScattering, sizeof(_rayleighScattering));
destinationBuffer += sizeof(_rayleighScattering);
memcpy(destinationBuffer, &_mieScattering, sizeof(_mieScattering));
destinationBuffer += sizeof(_mieScattering);
memcpy(destinationBuffer, &_scatteringWavelengths, sizeof(_scatteringWavelengths));
destinationBuffer += sizeof(_scatteringWavelengths);
memcpy(destinationBuffer, &_sunLocation, sizeof(_sunLocation));
destinationBuffer += sizeof(_sunLocation);
memcpy(destinationBuffer, &_sunBrightness, sizeof(_sunBrightness));
destinationBuffer += sizeof(_sunBrightness);
return destinationBuffer - bufferStart;
}
int EnvironmentData::parseData(unsigned char* sourceBuffer, int numBytes) {
// increment to push past the packet header
sourceBuffer++;
unsigned char* startPosition = sourceBuffer;
memcpy(&_atmosphereCenter, sourceBuffer, sizeof(_atmosphereCenter));
sourceBuffer += sizeof(_atmosphereCenter);
memcpy(&_atmosphereInnerRadius, sourceBuffer, sizeof(_atmosphereInnerRadius));
sourceBuffer += sizeof(_atmosphereInnerRadius);
memcpy(&_atmosphereOuterRadius, sourceBuffer, sizeof(_atmosphereOuterRadius));
sourceBuffer += sizeof(_atmosphereOuterRadius);
memcpy(&_rayleighScattering, sourceBuffer, sizeof(_rayleighScattering));
sourceBuffer += sizeof(_rayleighScattering);
memcpy(&_mieScattering, sourceBuffer, sizeof(_mieScattering));
sourceBuffer += sizeof(_mieScattering);
memcpy(&_scatteringWavelengths, sourceBuffer, sizeof(_scatteringWavelengths));
sourceBuffer += sizeof(_scatteringWavelengths);
memcpy(&_sunLocation, sourceBuffer, sizeof(_sunLocation));
sourceBuffer += sizeof(_sunLocation);
memcpy(&_sunBrightness, sourceBuffer, sizeof(_sunBrightness));
sourceBuffer += sizeof(_sunBrightness);
return sourceBuffer - startPosition;
}

View file

@ -0,0 +1,57 @@
//
// EnvironmentData.h
// interface
//
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__EnvironmentData__
#define __interface__EnvironmentData__
#include <glm/glm.hpp>
class EnvironmentData {
public:
EnvironmentData();
void setAtmosphereCenter(const glm::vec3& center) { _atmosphereCenter = center; }
void setAtmosphereInnerRadius(float radius) { _atmosphereInnerRadius = radius; }
void setAtmosphereOuterRadius(float radius) { _atmosphereOuterRadius = radius; }
const glm::vec3& getAtmosphereCenter() const { return _atmosphereCenter; }
float getAtmosphereInnerRadius() const { return _atmosphereInnerRadius; }
float getAtmosphereOuterRadius() const { return _atmosphereOuterRadius; }
void setRayleighScattering(float scattering) { _rayleighScattering = scattering; }
void setMieScattering(float scattering) { _mieScattering = scattering; }
float getRayleighScattering() const { return _rayleighScattering; }
float getMieScattering() const { return _mieScattering; }
void setScatteringWavelengths(const glm::vec3& wavelengths) { _scatteringWavelengths = wavelengths; }
const glm::vec3& getScatteringWavelengths() const { return _scatteringWavelengths; }
void setSunLocation(const glm::vec3& location) { _sunLocation = location; }
void setSunBrightness(float brightness) { _sunBrightness = brightness; }
const glm::vec3& getSunLocation() const { return _sunLocation; }
float getSunBrightness() const { return _sunBrightness; }
int getBroadcastData(unsigned char* destinationBuffer) const;
int parseData(unsigned char* sourceBuffer, int numBytes);
private:
glm::vec3 _atmosphereCenter;
float _atmosphereInnerRadius;
float _atmosphereOuterRadius;
float _rayleighScattering;
float _mieScattering;
glm::vec3 _scatteringWavelengths;
glm::vec3 _sunLocation;
float _sunBrightness;
};
#endif /* defined(__interface__EnvironmentData__) */

View file

@ -0,0 +1,106 @@
//
// SceneUtils.cpp
// hifi
//
// Created by Brad Hefta-Gaub on 5/7/2013.
//
//
#include "SceneUtils.h"
#include <glm/gtc/noise.hpp>
void addCornersAndAxisLines(VoxelTree* tree) {
// We want our corner voxels to be about 1/2 meter high, and our TREE_SCALE is in meters, so...
float voxelSize = 0.5f / TREE_SCALE;
// Now some more examples... a little more complex
printf("creating corner points...\n");
tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255);
tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 );
tree->createVoxel(0 , 1.0 - voxelSize, 0 , voxelSize, 0 , 255 ,0 );
tree->createVoxel(0 , 0 , 1.0 - voxelSize, voxelSize, 0 , 0 ,255);
tree->createVoxel(1.0 - voxelSize, 0 , 1.0 - voxelSize, voxelSize, 255, 0 ,255);
tree->createVoxel(0 , 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 0 , 255 ,255);
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 0 , voxelSize, 255, 255 ,0 );
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 255, 255 ,255);
printf("DONE creating corner points...\n");
// Now some more examples... creating some lines using the line primitive
printf("creating voxel lines...\n");
// We want our line voxels to be about 1/32 meter high, and our TREE_SCALE is in meters, so...
float lineVoxelSize = 1.f / (32 * TREE_SCALE);
rgbColor red = {255, 0, 0};
rgbColor green = {0, 255, 0};
rgbColor blue = {0, 0, 255};
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 0, 1), lineVoxelSize, blue);
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(1, 0, 0), lineVoxelSize, red);
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 1, 0), lineVoxelSize, green);
printf("DONE creating lines...\n");
}
void addSphereScene(VoxelTree * tree) {
printf("adding sphere scene...\n");
// Now some more examples... creating some spheres using the sphere primitive
// We want the smallest unit of our spheres to be about 1/16th of a meter tall
float sphereVoxelSize = 1.f / (8 * TREE_SCALE);
printf("creating spheres... sphereVoxelSize=%f\n",sphereVoxelSize);
tree->createSphere(0.030625, 0.5, 0.5, (0.25 - 0.06125), sphereVoxelSize, true, NATURAL);
printf("1 spheres added... sphereVoxelSize=%f\n",sphereVoxelSize);
tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), (0.75 - 0.06125), sphereVoxelSize, true, GRADIENT);
printf("2 spheres added... sphereVoxelSize=%f\n",sphereVoxelSize);
tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), 0.06125, sphereVoxelSize, true, RANDOM);
printf("3 spheres added... sphereVoxelSize=%f\n",sphereVoxelSize);
tree->createSphere(0.030625, (0.75 - 0.030625), 0.06125, (0.75 - 0.06125), sphereVoxelSize, true, GRADIENT);
printf("4 spheres added... sphereVoxelSize=%f\n",sphereVoxelSize);
tree->createSphere(0.06125, 0.125, 0.125, (0.75 - 0.125), sphereVoxelSize, true, GRADIENT);
/**
float radius = 0.0125f;
printf("5 spheres added...\n");
tree->createSphere(radius, 0.25, radius * 5.0f, 0.25, sphereVoxelSize, true, GRADIENT);
printf("6 spheres added...\n");
tree->createSphere(radius, 0.125, radius * 5.0f, 0.25, sphereVoxelSize, true, RANDOM);
printf("7 spheres added...\n");
tree->createSphere(radius, 0.075, radius * 5.0f, 0.25, sphereVoxelSize, true, GRADIENT);
printf("8 spheres added...\n");
tree->createSphere(radius, 0.05, radius * 5.0f, 0.25, sphereVoxelSize, true, RANDOM);
printf("9 spheres added...\n");
tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, sphereVoxelSize, true, GRADIENT);
printf("10 spheres added...\n");
*/
float largeRadius = 0.1875f;
tree->createSphere(largeRadius, 0.5, 0.5, 0.5, sphereVoxelSize, true, NATURAL);
printf("11 - last large sphere added... largeRadius=%f sphereVoxelSize=%f\n", largeRadius, sphereVoxelSize);
printf("DONE adding scene of spheres...\n");
}
void addSurfaceScene(VoxelTree * tree) {
printf("adding surface scene...\n");
float voxelSize = 1.f / (8 * TREE_SCALE);
// color 1= blue, color 2=green
unsigned char r1, g1, b1, r2, g2, b2, red, green, blue;
r1 = r2 = b2 = g1 = 0;
b1 = g2 = 255;
for (float x = 0.0; x < 1.0; x += voxelSize) {
for (float z = 0.0; z < 1.0; z += voxelSize) {
glm::vec2 position = glm::vec2(x, z);
float perlin = glm::perlin(position) + .25f * glm::perlin(position * 4.f) + .125f * glm::perlin(position * 16.f);
float gradient = (1.0f + perlin)/ 2.0f;
red = (unsigned char)std::min(255, std::max(0, (int)(r1 + ((r2 - r1) * gradient))));
green = (unsigned char)std::min(255, std::max(0, (int)(g1 + ((g2 - g1) * gradient))));
blue = (unsigned char)std::min(255, std::max(0, (int)(b1 + ((b2 - b1) * gradient))));
int height = (4 * gradient)+1; // make it at least 4 thick, so we get some averaging
for (int i = 0; i < height; i++) {
tree->createVoxel(x, ((i+1) * voxelSize) , z, voxelSize, red, green, blue);
}
}
}
printf("DONE adding surface scene...\n");
}

View file

@ -0,0 +1,20 @@
//
// SceneUtils.h
// hifi
//
// Created by Brad Hefta-Gaub on 5/7/2013.
//
//
#ifndef __hifi__SceneUtil__
#define __hifi__SceneUtil__
#include "VoxelTree.h"
#include <SharedUtil.h>
void addCornersAndAxisLines(VoxelTree* tree);
void addSphereScene(VoxelTree * tree);
void addSurfaceScene(VoxelTree * tree);
#endif /* defined(__hifi__SceneUtil__) */

View file

@ -158,12 +158,12 @@ const char* ViewFrustum::debugPlaneName (int plane) const {
}
int ViewFrustum::pointInFrustum(const glm::vec3& point) const {
ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const {
//printf("ViewFrustum::pointInFrustum() point=%f,%f,%f\n",point.x,point.y,point.z);
//dump();
int result = INSIDE;
ViewFrustum::location result = INSIDE;
for(int i=0; i < 6; i++) {
float distance = _planes[i].distance(point);
@ -176,8 +176,8 @@ int ViewFrustum::pointInFrustum(const glm::vec3& point) const {
return(result);
}
int ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
int result = INSIDE;
ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
ViewFrustum::location result = INSIDE;
float distance;
for(int i=0; i < 6; i++) {
distance = _planes[i].distance(center);
@ -190,11 +190,11 @@ int ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
}
int ViewFrustum::boxInFrustum(const AABox& box) const {
ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
//printf("ViewFrustum::boxInFrustum() box.corner=%f,%f,%f x=%f\n",
// box.getCorner().x,box.getCorner().y,box.getCorner().z,box.getSize().x);
int result = INSIDE;
ViewFrustum::location result = INSIDE;
for(int i=0; i < 6; i++) {
//printf("plane[%d] -- point(%f,%f,%f) normal(%f,%f,%f) d=%f \n",i,

View file

@ -94,9 +94,9 @@ public:
typedef enum {OUTSIDE, INTERSECT, INSIDE} location;
int pointInFrustum(const glm::vec3& point) const;
int sphereInFrustum(const glm::vec3& center, float radius) const;
int boxInFrustum(const AABox& box) const;
ViewFrustum::location pointInFrustum(const glm::vec3& point) const;
ViewFrustum::location sphereInFrustum(const glm::vec3& center, float radius) const;
ViewFrustum::location boxInFrustum(const AABox& box) const;
// some frustum comparisons
bool matches(const ViewFrustum& compareTo) const;

View file

@ -14,12 +14,12 @@
#include <limits.h>
const int TREE_SCALE = 100;
const int TREE_SCALE = 128;
const int NUMBER_OF_CHILDREN = 8;
const int MAX_VOXEL_PACKET_SIZE = 1492;
const int MAX_TREE_SLICE_BYTES = 26;
const int MAX_VOXELS_PER_SYSTEM = 250000;
const int MAX_VOXELS_PER_SYSTEM = 200000;
const int VERTICES_PER_VOXEL = 24;
const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
const int INDICES_PER_VOXEL = 3 * 12;

View file

@ -123,7 +123,6 @@ void VoxelNode::setColorFromAverageOfChildren() {
colorArray[3]++;
}
}
nodeColor newColor = { 0, 0, 0, 0};
if (colorArray[3] > 4) {
// we need at least 4 colored children to have an average color value
@ -179,9 +178,7 @@ void VoxelNode::setColor(const nodeColor& color) {
if (!_falseColored) {
memcpy(&_currentColor,&color,sizeof(nodeColor));
}
//if (_shouldRender) {
_isDirty = true;
//}
_isDirty = true;
}
}
#endif
@ -262,6 +259,12 @@ bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const {
return inView;
}
ViewFrustum::location VoxelNode::inFrustum(const ViewFrustum& viewFrustum) const {
AABox box = _box; // use temporary box so we can scale it
box.scale(TREE_SCALE);
return viewFrustum.boxInFrustum(box);
}
float VoxelNode::distanceToCamera(const ViewFrustum& viewFrustum) const {
glm::vec3 center = _box.getCenter() * (float)TREE_SCALE;
float distanceToVoxelCenter = sqrtf(powf(viewFrustum.getPosition().x - center.x, 2) +

View file

@ -57,6 +57,7 @@ public:
bool isColored() const { return (_trueColor[3]==1); };
bool isInView(const ViewFrustum& viewFrustum) const;
ViewFrustum::location inFrustum(const ViewFrustum& viewFrustum) const;
float distanceToCamera(const ViewFrustum& viewFrustum) const;
bool isLeaf() const;
void printDebugDetails(const char* label) const;

View file

@ -82,3 +82,39 @@ VoxelNode* VoxelNodeBag::extract() {
}
return NULL;
}
bool VoxelNodeBag::contains(VoxelNode* node) {
for (int i = 0; i < _elementsInUse; i++) {
// just compare the pointers... that's good enough
if (_bagElements[i] == node) {
return true; // exit early!!
}
// if we're past where it should be, then it's not here!
if (_bagElements[i] > node) {
return false;
}
}
// if we made it through the entire bag, it's not here!
return false;
}
void VoxelNodeBag::remove(VoxelNode* node) {
int foundAt = -1;
for (int i = 0; i < _elementsInUse; i++) {
// just compare the pointers... that's good enough
if (_bagElements[i] == node) {
foundAt = i;
break;
}
// if we're past where it should be, then it's not here!
if (_bagElements[i] > node) {
break;
}
}
// if we found it, then we need to remove it....
if (foundAt != -1) {
memmove(&_bagElements[foundAt], &_bagElements[foundAt + 1], (_elementsInUse - foundAt) * sizeof(VoxelNode*));
_elementsInUse--;
}
}

View file

@ -28,6 +28,8 @@ public:
void insert(VoxelNode* node); // put a node into the bag
VoxelNode* extract(); // pull a node out of the bag (could come in any order)
bool contains(VoxelNode* node); // is this node in the bag?
void remove(VoxelNode* node); // remove a specific item from the bag
bool isEmpty() const { return (_elementsInUse == 0); };
int count() const { return _elementsInUse; };

View file

@ -22,10 +22,12 @@
#include <fstream> // to load voxels from file
#include "VoxelConstants.h"
#include <glm/gtc/noise.hpp>
using voxels_lib::printLog;
int boundaryDistanceForRenderLevel(unsigned int renderLevel) {
float voxelSizeScale = 500.0*TREE_SCALE;
float voxelSizeScale = 50000.0f;
return voxelSizeScale / powf(2, renderLevel);
}
@ -113,9 +115,7 @@ VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char
}
}
int VoxelTree::readNodeData(VoxelNode* destinationNode,
unsigned char* nodeData,
int bytesLeftToRead) {
int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, int bytesLeftToRead) {
// instantiate variable for bytes already read
int bytesRead = 1;
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
@ -457,87 +457,136 @@ void VoxelTree::createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, r
}
void VoxelTree::createSphere(float radius, float xc, float yc, float zc, float voxelSize,
bool solid, bool wantColorRandomizer, bool debug) {
bool solid, creationMode mode, bool debug) {
// About the color of the sphere... we're going to make this sphere be a gradient
// between two RGB colors. We will do the gradient along the phi spectrum
unsigned char dominantColor1 = randIntInRange(1, 3); //1=r, 2=g, 3=b dominant
unsigned char dominantColor2 = randIntInRange(1, 3);
bool wantColorRandomizer = (mode == RANDOM);
bool wantNaturalSurface = (mode == NATURAL);
bool wantNaturalColor = (mode == NATURAL);
if (dominantColor1 == dominantColor2) {
dominantColor2 = dominantColor1 + 1 % 3;
// About the color of the sphere... we're going to make this sphere be a mixture of two colors
// in NATURAL mode, those colors will be green dominant and blue dominant. In GRADIENT mode we
// will randomly pick which color family red, green, or blue to be dominant. In RANDOM mode we
// ignore these dominant colors and make every voxel a completely random color.
unsigned char r1, g1, b1, r2, g2, b2;
if (wantNaturalColor) {
r1 = r2 = b2 = g1 = 0;
b1 = g2 = 255;
} else if (!wantColorRandomizer) {
unsigned char dominantColor1 = randIntInRange(1, 3); //1=r, 2=g, 3=b dominant
unsigned char dominantColor2 = randIntInRange(1, 3);
if (dominantColor1 == dominantColor2) {
dominantColor2 = dominantColor1 + 1 % 3;
}
r1 = (dominantColor1 == 1) ? randIntInRange(200, 255) : randIntInRange(40, 100);
g1 = (dominantColor1 == 2) ? randIntInRange(200, 255) : randIntInRange(40, 100);
b1 = (dominantColor1 == 3) ? randIntInRange(200, 255) : randIntInRange(40, 100);
r2 = (dominantColor2 == 1) ? randIntInRange(200, 255) : randIntInRange(40, 100);
g2 = (dominantColor2 == 2) ? randIntInRange(200, 255) : randIntInRange(40, 100);
b2 = (dominantColor2 == 3) ? randIntInRange(200, 255) : randIntInRange(40, 100);
}
unsigned char r1 = (dominantColor1 == 1) ? randIntInRange(200, 255) : randIntInRange(40, 100);
unsigned char g1 = (dominantColor1 == 2) ? randIntInRange(200, 255) : randIntInRange(40, 100);
unsigned char b1 = (dominantColor1 == 3) ? randIntInRange(200, 255) : randIntInRange(40, 100);
unsigned char r2 = (dominantColor2 == 1) ? randIntInRange(200, 255) : randIntInRange(40, 100);
unsigned char g2 = (dominantColor2 == 2) ? randIntInRange(200, 255) : randIntInRange(40, 100);
unsigned char b2 = (dominantColor2 == 3) ? randIntInRange(200, 255) : randIntInRange(40, 100);
// We initialize our rgb to be either "grey" in case of randomized surface, or
// the average of the gradient, in the case of the gradient sphere.
// We initialize our rgb to be either "grey" in case of randomized surface, or
// the average of the gradient, in the case of the gradient sphere.
unsigned char red = wantColorRandomizer ? 128 : (r1 + r2) / 2; // average of the colors
unsigned char green = wantColorRandomizer ? 128 : (g1 + g2) / 2;
unsigned char blue = wantColorRandomizer ? 128 : (b1 + b2) / 2;
// Psuedocode for creating a sphere:
//
// for (theta from 0 to 2pi):
// for (phi from 0 to pi):
// x = xc+r*cos(theta)*sin(phi)
// y = yc+r*sin(theta)*sin(phi)
// z = zc+r*cos(phi)
// assume solid for now
float thisRadius = 0.0;
float thisVoxelSize = radius / 4.0f;
if (!solid) {
thisRadius = radius; // just the outer surface
thisVoxelSize = voxelSize;
}
// If you also iterate form the interior of the sphere to the radius, makeing
// larger and larger sphere'voxelSize you'd end up with a solid sphere. And lots of voxels!
while (thisRadius <= (radius + (voxelSize / 2.0))) {
if (debug) {
printLog("radius: thisRadius=%f thisVoxelSize=%f thisRadius+thisVoxelSize=%f (radius+(voxelSize/2.0))=%f\n",
thisRadius, thisVoxelSize, thisRadius+thisVoxelSize, (radius + (voxelSize / 2.0)));
}
// I want to do something smart like make these inside circles with bigger voxels, but this doesn't seem to work.
float thisVoxelSize = voxelSize; // radius / 2.0f;
float thisRadius = 0.0;
if (!solid) {
thisRadius = radius; // just the outer surface
thisVoxelSize = voxelSize;
}
// If you also iterate form the interior of the sphere to the radius, making
// larger and larger spheres you'd end up with a solid sphere. And lots of voxels!
bool lastLayer = false;
while (!lastLayer) {
lastLayer = (thisRadius + (voxelSize * 2.0) >= radius);
// We want to make sure that as we "sweep" through our angles we use a delta angle that voxelSize
// small enough to not skip any voxels we can calculate theta from our desired arc length
// lenArc = ndeg/360deg * 2pi*R ---> lenArc = theta/2pi * 2pi*R
// lenArc = theta*R ---> theta = lenArc/R ---> theta = g/r
float angleDelta = (thisVoxelSize / thisRadius);
for (float theta=0.0; theta <= 2 * M_PI; theta += angleDelta) {
for (float phi=0.0; phi <= M_PI; phi += angleDelta) {
float x = xc + thisRadius * cos(theta) * sin(phi);
float y = yc + thisRadius * sin(theta) * sin(phi);
float z = zc + thisRadius * cos(phi);
// gradient color data
float gradient = (phi / M_PI);
// only use our actual desired color on the outer edge, otherwise
// use our "average" color
if (thisRadius + (voxelSize * 2.0) >= radius) {
//printLog("painting candy shell radius: thisRadius=%f radius=%f\n",thisRadius,radius);
red = wantColorRandomizer ? randomColorValue(165) : r1 + ((r2 - r1) * gradient);
green = wantColorRandomizer ? randomColorValue(165) : g1 + ((g2 - g1) * gradient);
blue = wantColorRandomizer ? randomColorValue(165) : b1 + ((b2 - b1) * gradient);
}
unsigned char* voxelData = pointToVoxel(x, y, z, thisVoxelSize, red, green, blue);
this->readCodeColorBufferToTree(voxelData);
delete voxelData;
}
}
if (debug) {
int percentComplete = 100 * (thisRadius/radius);
printLog("percentComplete=%d\n",percentComplete);
}
for (float theta=0.0; theta <= 2 * M_PI; theta += angleDelta) {
for (float phi=0.0; phi <= M_PI; phi += angleDelta) {
bool naturalSurfaceRendered = false;
float x = xc + thisRadius * cos(theta) * sin(phi);
float y = yc + thisRadius * sin(theta) * sin(phi);
float z = zc + thisRadius * cos(phi);
// if we're on the outer radius, then we do a couple of things differently.
// 1) If we're in NATURAL mode we will actually draw voxels from our surface outward (from the surface) up
// some random height. This will give our sphere some contours.
// 2) In all modes, we will use our "outer" color to draw the voxels. Otherwise we will use the average color
if (lastLayer) {
if (false && debug) {
printLog("adding candy shell: theta=%f phi=%f thisRadius=%f radius=%f\n",
theta, phi, thisRadius,radius);
}
switch (mode) {
case RANDOM: {
red = randomColorValue(165);
green = randomColorValue(165);
blue = randomColorValue(165);
} break;
case GRADIENT: {
float gradient = (phi / M_PI);
red = r1 + ((r2 - r1) * gradient);
green = g1 + ((g2 - g1) * gradient);
blue = b1 + ((b2 - b1) * gradient);
} break;
case NATURAL: {
glm::vec3 position = glm::vec3(theta,phi,radius);
float perlin = glm::perlin(position) + .25f * glm::perlin(position * 4.f)
+ .125f * glm::perlin(position * 16.f);
float gradient = (1.0f + perlin)/ 2.0f;
red = (unsigned char)std::min(255, std::max(0, (int)(r1 + ((r2 - r1) * gradient))));
green = (unsigned char)std::min(255, std::max(0, (int)(g1 + ((g2 - g1) * gradient))));
blue = (unsigned char)std::min(255, std::max(0, (int)(b1 + ((b2 - b1) * gradient))));
if (debug) {
printLog("perlin=%f gradient=%f color=(%d,%d,%d)\n",perlin, gradient, red, green, blue);
}
} break;
}
if (wantNaturalSurface) {
// for natural surfaces, we will render up to 16 voxel's above the surface of the sphere
glm::vec3 position = glm::vec3(theta,phi,radius);
float perlin = glm::perlin(position) + .25f * glm::perlin(position * 4.f)
+ .125f * glm::perlin(position * 16.f);
float gradient = (1.0f + perlin)/ 2.0f;
int height = (4 * gradient)+1; // make it at least 4 thick, so we get some averaging
float subVoxelScale = thisVoxelSize;
for (int i = 0; i < height; i++) {
x = xc + (thisRadius + i * subVoxelScale) * cos(theta) * sin(phi);
y = yc + (thisRadius + i * subVoxelScale) * sin(theta) * sin(phi);
z = zc + (thisRadius + i * subVoxelScale) * cos(phi);
this->createVoxel(x, y, z, subVoxelScale, red, green, blue);
}
naturalSurfaceRendered = true;
}
}
if (!naturalSurfaceRendered) {
this->createVoxel(x, y, z, thisVoxelSize, red, green, blue);
}
}
}
thisRadius += thisVoxelSize;
thisVoxelSize = std::max(voxelSize, thisVoxelSize / 2.0f);
}
this->reaverageVoxelColors(this->rootNode);
thisVoxelSize = std::max(voxelSize, thisVoxelSize / 2.0f);
}
this->reaverageVoxelColors(this->rootNode);
}
int VoxelTree::searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag) {
@ -884,7 +933,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
bool VoxelTree::readFromFileV2(const char* fileName) {
std::ifstream file(fileName, std::ios::in|std::ios::binary|std::ios::ate);
if(file.is_open()) {
printLog("loading file...\n");
printLog("loading file %s...\n", fileName);
// get file length....
unsigned long fileLength = file.tellg();
@ -907,6 +956,8 @@ void VoxelTree::writeToFileV2(const char* fileName) const {
std::ofstream file(fileName, std::ios::out|std::ios::binary);
if(file.is_open()) {
printLog("saving to file %s...\n", fileName);
VoxelNodeBag nodeBag;
nodeBag.insert(rootNode);
@ -923,3 +974,13 @@ void VoxelTree::writeToFileV2(const char* fileName) const {
file.close();
}
unsigned long VoxelTree::getVoxelCount() {
unsigned long nodeCount = 0;
recurseTreeWithOperation(countVoxelsOperation, &nodeCount);
return nodeCount;
}
bool VoxelTree::countVoxelsOperation(VoxelNode* node, void* extraData) {
(*(unsigned long*)extraData)++;
return true; // keep going
}

View file

@ -17,6 +17,7 @@
// Callback function, for recuseTreeWithOperation
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData);
typedef enum {GRADIENT, RANDOM, NATURAL} creationMode;
class VoxelTree {
public:
@ -49,7 +50,7 @@ public:
VoxelNode* getVoxelAt(float x, float y, float z, float s) const;
void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue);
void createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color);
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer, bool debug = false);
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, creationMode mode, bool debug = false);
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
@ -70,6 +71,8 @@ public:
// these will read/write files that match the wireformat, excluding the 'V' leading
void writeToFileV2(const char* filename) const;
bool readFromFileV2(const char* filename);
unsigned long getVoxelCount();
private:
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
@ -79,6 +82,8 @@ private:
int searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel,
VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag);
static bool countVoxelsOperation(VoxelNode* node, void* extraData);
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData);
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const;
VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate);

View file

@ -8,6 +8,7 @@
#include <VoxelTree.h>
#include <SharedUtil.h>
#include <SceneUtils.h>
VoxelTree myTree;
@ -19,12 +20,16 @@ bool countVoxelsOperation(VoxelNode* node, void* extraData) {
return true; // keep going
}
void addScene(VoxelTree * tree) {
void addLandscape(VoxelTree * tree) {
printf("Adding Landscape...\n");
}
void voxelTutorial(VoxelTree * tree) {
printf("adding scene...\n");
// We want our corner voxels to be about 1/2 meter high, and our TREE_SCALE is in meters, so...
float voxelSize = 0.5f / TREE_SCALE;
// Here's an example of how to create a voxel.
printf("creating corner points...\n");
tree->createVoxel(0, 0, 0, voxelSize, 255, 255 ,255);
@ -47,72 +52,8 @@ void addScene(VoxelTree * tree) {
} else {
printf("corner point 0,0,0 does not exists...\n");
}
// Now some more examples... a little more complex
printf("creating corner points...\n");
tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255);
tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 );
tree->createVoxel(0 , 1.0 - voxelSize, 0 , voxelSize, 0 , 255 ,0 );
tree->createVoxel(0 , 0 , 1.0 - voxelSize, voxelSize, 0 , 0 ,255);
tree->createVoxel(1.0 - voxelSize, 0 , 1.0 - voxelSize, voxelSize, 255, 0 ,255);
tree->createVoxel(0 , 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 0 , 255 ,255);
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 0 , voxelSize, 255, 255 ,0 );
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 255, 255 ,255);
printf("DONE creating corner points...\n");
// Now some more examples... creating some lines using the line primitive
printf("creating voxel lines...\n");
// We want our line voxels to be about 1/32 meter high, and our TREE_SCALE is in meters, so...
float lineVoxelSize = 1.f / (32 * TREE_SCALE);
rgbColor red = {255, 0, 0};
rgbColor green = {0, 255, 0};
rgbColor blue = {0, 0, 255};
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 0, 1), lineVoxelSize, blue);
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(1, 0, 0), lineVoxelSize, red);
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 1, 0), lineVoxelSize, green);
printf("DONE creating lines...\n");
// Now some more examples... creating some spheres using the sphere primitive
// We want the smallest unit of our spheres to be about 1/16th of a meter tall
float sphereVoxelSize = 1.f / (16 * TREE_SCALE);
printf("creating spheres... sphereVoxelSize=%f\n",sphereVoxelSize);
tree->createSphere(0.25, 0.5, 0.5, 0.5, sphereVoxelSize, true, false, true);
printf("one sphere added... sphereVoxelSize=%f\n",sphereVoxelSize);
tree->createSphere(0.030625, 0.5, 0.5, (0.25 - 0.06125), sphereVoxelSize, true, true);
printf("two spheres added... sphereVoxelSize=%f\n",sphereVoxelSize);
tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), (0.75 - 0.06125), sphereVoxelSize, true, true);
printf("three spheres added... sphereVoxelSize=%f\n",sphereVoxelSize);
tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), 0.06125, sphereVoxelSize, true, true);
printf("four spheres added... sphereVoxelSize=%f\n",sphereVoxelSize);
tree->createSphere(0.030625, (0.75 - 0.030625), 0.06125, (0.75 - 0.06125), sphereVoxelSize, true, true);
printf("five spheres added... sphereVoxelSize=%f\n",sphereVoxelSize);
tree->createSphere(0.06125, 0.125, 0.125, (0.75 - 0.125), sphereVoxelSize, true, true);
float radius = 0.0125f;
printf("6 spheres added...\n");
tree->createSphere(radius, 0.25, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
printf("7 spheres added...\n");
tree->createSphere(radius, 0.125, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
printf("8 spheres added...\n");
tree->createSphere(radius, 0.075, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
printf("9 spheres added...\n");
tree->createSphere(radius, 0.05, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
printf("10 spheres added...\n");
tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
printf("11 spheres added...\n");
printf("DONE creating spheres...\n");
// Here's an example of how to recurse the tree and do some operation on the nodes as you recurse them.
// This one is really simple, it just couts them...
// Look at the function countVoxelsOperation() for an example of how you could use this function
_nodeCount=0;
tree->recurseTreeWithOperation(countVoxelsOperation);
printf("Nodes after adding scene %d nodes\n", _nodeCount);
printf("DONE adding scene of spheres...\n");
}
int main(int argc, const char * argv[])
{
const char* SAY_HELLO = "--sayHello";
@ -127,8 +68,32 @@ int main(int argc, const char * argv[])
printf("You asked us not to create a scene file, so we will not.\n");
} else {
printf("Creating Scene File...\n");
addScene(&myTree);
const char* RUN_TUTORIAL = "--runTutorial";
if (cmdOptionExists(argc, argv, RUN_TUTORIAL)) {
voxelTutorial(&myTree);
}
const char* ADD_CORNERS_AND_AXIS_LINES = "--addCornersAndAxisLines";
if (cmdOptionExists(argc, argv, ADD_CORNERS_AND_AXIS_LINES)) {
addCornersAndAxisLines(&myTree);
}
const char* ADD_SPHERE_SCENE = "--addSphereScene";
if (cmdOptionExists(argc, argv, ADD_SPHERE_SCENE)) {
addSphereScene(&myTree);
}
const char* ADD_SURFACE_SCENE = "--addSurfaceScene";
if (cmdOptionExists(argc, argv, ADD_SURFACE_SCENE)) {
addSurfaceScene(&myTree);
}
unsigned long nodeCount = myTree.getVoxelCount();
printf("Nodes after adding scenes: %ld nodes\n", nodeCount);
myTree.writeToFileV2("voxels.hio2");
}
return 0;
}

Binary file not shown.

View file

@ -13,10 +13,12 @@
#include <OctalCode.h>
#include <AgentList.h>
#include <AgentTypes.h>
#include <EnvironmentData.h>
#include <VoxelTree.h>
#include "VoxelAgentData.h"
#include <SharedUtil.h>
#include <PacketHeaders.h>
#include <SceneUtils.h>
#ifdef _WIN32
#include "Syssocket.h"
@ -27,6 +29,9 @@
#include <ifaddrs.h>
#endif
const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.hio2";
const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.hio2";
const int VOXEL_LISTEN_PORT = 40106;
@ -44,102 +49,13 @@ const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
VoxelTree randomTree;
bool wantVoxelPersist = true;
bool wantLocalDomain = false;
bool wantColorRandomizer = false;
bool debugVoxelSending = false;
void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) {
float r = random ? randFloatInRange(0.05,0.1) : 0.25;
float xc = random ? randFloatInRange(r,(1-r)) : 0.5;
float yc = random ? randFloatInRange(r,(1-r)) : 0.5;
float zc = random ? randFloatInRange(r,(1-r)) : 0.5;
float s = (1.0/256); // size of voxels to make up surface of sphere
bool solid = true;
printf("adding sphere:");
if (random)
printf(" random");
printf("\nradius=%f\n",r);
printf("xc=%f\n",xc);
printf("yc=%f\n",yc);
printf("zc=%f\n",zc);
tree->createSphere(r,xc,yc,zc,s,solid,wantColorRandomizer);
}
int _nodeCount=0;
bool countVoxelsOperation(VoxelNode* node, void* extraData) {
if (node->isColored()){
_nodeCount++;
}
return true; // keep going
}
void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) {
printf("adding scene...\n");
float voxelSize = 1.f/32;
printf("creating corner points...\n");
tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255);
tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 );
tree->createVoxel(0 , 1.0 - voxelSize, 0 , voxelSize, 0 , 255 ,0 );
tree->createVoxel(0 , 0 , 1.0 - voxelSize, voxelSize, 0 , 0 ,255);
tree->createVoxel(1.0 - voxelSize, 0 , 1.0 - voxelSize, voxelSize, 255, 0 ,255);
tree->createVoxel(0 , 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 0 , 255 ,255);
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 0 , voxelSize, 255, 255 ,0 );
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 255, 255 ,255);
printf("DONE creating corner points...\n");
printf("creating voxel lines...\n");
float lineVoxelSize = 0.99f/256;
rgbColor red = {255,0,0};
rgbColor green = {0,255,0};
rgbColor blue = {0,0,255};
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 0, 1), lineVoxelSize, blue);
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(1, 0, 0), lineVoxelSize, red);
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 1, 0), lineVoxelSize, green);
printf("DONE creating lines...\n");
int sphereBaseSize = 512;
printf("creating spheres...\n");
tree->createSphere(0.25, 0.5, 0.5, 0.5, (1.0 / sphereBaseSize), true, wantColorRandomizer);
printf("one sphere added...\n");
tree->createSphere(0.030625, 0.5, 0.5, (0.25-0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
printf("two spheres added...\n");
tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
printf("three spheres added...\n");
tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), 0.06125, (1.0 / (sphereBaseSize * 2)), true, true);
printf("four spheres added...\n");
tree->createSphere(0.030625, (0.75 - 0.030625), 0.06125, (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
printf("five spheres added...\n");
tree->createSphere(0.06125, 0.125, 0.125, (0.75 - 0.125), (1.0 / (sphereBaseSize * 2)), true, true);
float radius = 0.0125f;
printf("6 spheres added...\n");
tree->createSphere(radius, 0.25, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
printf("7 spheres added...\n");
tree->createSphere(radius, 0.125, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
printf("8 spheres added...\n");
tree->createSphere(radius, 0.075, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
printf("9 spheres added...\n");
tree->createSphere(radius, 0.05, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
printf("10 spheres added...\n");
tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
printf("11 spheres added...\n");
printf("DONE creating spheres...\n");
_nodeCount=0;
tree->recurseTreeWithOperation(countVoxelsOperation);
printf("Nodes after adding scene %d nodes\n", _nodeCount);
printf("DONE adding scene of spheres...\n");
}
EnvironmentData environmentData;
void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) {
@ -237,7 +153,7 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
int trueBytesSent = 0;
double start = usecTimestampNow();
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL) {
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - 1) {
if (!agentData->nodeBag.isEmpty()) {
VoxelNode* subTree = agentData->nodeBag.extract();
bytesWritten = randomTree.encodeTreeBitstream(agentData->getMaxSearchLevel(), subTree,
@ -267,6 +183,12 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
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++;
double end = usecTimestampNow();
double elapsedmsec = (end - start)/1000.0;
if (elapsedmsec > 100) {
@ -298,7 +220,7 @@ void persistVoxelsWhenDirty() {
// check the dirty bit and persist here...
if (::wantVoxelPersist && ::randomTree.isDirty()) {
printf("saving voxels to file...\n");
randomTree.writeToFileV2("voxels.hio2");
randomTree.writeToFileV2(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE);
randomTree.clearDirtyBit(); // tree is clean after saving
printf("DONE saving voxels to file...\n");
}
@ -361,8 +283,8 @@ int main(int argc, const char * argv[])
// Handle Local Domain testing with the --local command line
const char* local = "--local";
bool wantLocalDomain = cmdOptionExists(argc, argv,local);
if (wantLocalDomain) {
::wantLocalDomain = cmdOptionExists(argc, argv,local);
if (::wantLocalDomain) {
printf("Local Domain MODE!\n");
int ip = getLocalAddress();
sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
@ -393,12 +315,11 @@ int main(int argc, const char * argv[])
bool persistantFileRead = false;
if (::wantVoxelPersist) {
printf("loading voxels from file...\n");
persistantFileRead = ::randomTree.readFromFileV2("voxels.hio2");
persistantFileRead = ::randomTree.readFromFileV2(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE);
::randomTree.clearDirtyBit(); // the tree is clean since we just loaded it
printf("DONE loading voxels from file...\n");
_nodeCount=0;
::randomTree.recurseTreeWithOperation(countVoxelsOperation);
printf("Nodes after loading scene %d nodes\n", _nodeCount);
printf("DONE loading voxels from file... fileRead=%s\n", persistantFileRead ? "yes" : "no" );
unsigned long nodeCount = ::randomTree.getVoxelCount();
printf("Nodes after loading scene %ld nodes\n", nodeCount);
}
// Check to see if the user passed in a command line option for loading an old style local
@ -427,14 +348,6 @@ int main(int argc, const char * argv[])
randomlyFillVoxelTree(MAX_VOXEL_TREE_DEPTH_LEVELS, randomTree.rootNode);
}
const char* ADD_SPHERE = "--AddSphere";
const char* ADD_RANDOM_SPHERE = "--AddRandomSphere";
if (cmdOptionExists(argc, argv, ADD_SPHERE)) {
addSphere(&randomTree,false,wantColorRandomizer);
} else if (cmdOptionExists(argc, argv, ADD_RANDOM_SPHERE)) {
addSphere(&randomTree,true,wantColorRandomizer);
}
const char* ADD_SCENE = "--AddScene";
bool addScene = cmdOptionExists(argc, argv, ADD_SCENE);
const char* NO_ADD_SCENE = "--NoAddScene";
@ -447,9 +360,11 @@ int main(int argc, const char * argv[])
// 1) we attempted to load a persistant file and it wasn't there
// 2) you asked us to add a scene
// HOWEVER -- we will NEVER add a scene if you explicitly tell us not to!
bool actuallyAddScene = !noAddScene && (addScene || (::wantVoxelPersist && !persistantFileRead));
//
// TEMPORARILY DISABLED!!!
bool actuallyAddScene = false; // !noAddScene && (addScene || (::wantVoxelPersist && !persistantFileRead));
if (actuallyAddScene) {
addSphereScene(&randomTree,wantColorRandomizer);
addSphereScene(&randomTree);
}
pthread_t sendVoxelThread;
@ -535,7 +450,7 @@ int main(int argc, const char * argv[])
}
if (0==strcmp(command,(char*)"add scene")) {
printf("got Z message == add scene\n");
addSphereScene(&randomTree,false);
addSphereScene(&randomTree);
}
totalLength += commandLength+1;
}
@ -559,4 +474,4 @@ int main(int argc, const char * argv[])
pthread_join(sendVoxelThread, NULL);
return 0;
}
}