mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 14:24:22 +02:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
bbd85664d6
47 changed files with 1593 additions and 428 deletions
|
@ -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)
|
||||
|
|
48
interface/resources/shaders/SkyFromAtmosphere.frag
Normal file
48
interface/resources/shaders/SkyFromAtmosphere.frag
Normal 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;
|
||||
}
|
100
interface/resources/shaders/SkyFromAtmosphere.vert
Normal file
100
interface/resources/shaders/SkyFromAtmosphere.vert
Normal 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;
|
||||
}
|
48
interface/resources/shaders/SkyFromSpace.frag
Normal file
48
interface/resources/shaders/SkyFromSpace.frag
Normal 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;
|
||||
}
|
109
interface/resources/shaders/SkyFromSpace.vert
Normal file
109
interface/resources/shaders/SkyFromSpace.vert
Normal 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;
|
||||
}
|
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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 + ;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
117
interface/src/Environment.cpp
Normal file
117
interface/src/Environment.cpp
Normal 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;
|
||||
}
|
55
interface/src/Environment.h
Normal file
55
interface/src/Environment.h
Normal 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__) */
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
119
interface/src/renderer/ProgramObject.cpp
Normal file
119
interface/src/renderer/ProgramObject.cpp
Normal 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);
|
||||
}
|
66
interface/src/renderer/ProgramObject.h
Normal file
66
interface/src/renderer/ProgramObject.h
Normal 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__) */
|
39
interface/src/renderer/ShaderObject.cpp
Normal file
39
interface/src/renderer/ShaderObject.cpp
Normal 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;
|
||||
}
|
36
interface/src/renderer/ShaderObject.h
Normal file
36
interface/src/renderer/ShaderObject.h
Normal 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__) */
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
|
90
libraries/voxels/src/EnvironmentData.cpp
Normal file
90
libraries/voxels/src/EnvironmentData.cpp
Normal 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;
|
||||
}
|
||||
|
57
libraries/voxels/src/EnvironmentData.h
Normal file
57
libraries/voxels/src/EnvironmentData.h
Normal 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__) */
|
106
libraries/voxels/src/SceneUtils.cpp
Normal file
106
libraries/voxels/src/SceneUtils.cpp
Normal 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");
|
||||
}
|
20
libraries/voxels/src/SceneUtils.h
Normal file
20
libraries/voxels/src/SceneUtils.h
Normal 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__) */
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) +
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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--;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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; };
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
BIN
voxel-server/resources/voxels.hio2
Normal file
BIN
voxel-server/resources/voxels.hio2
Normal file
Binary file not shown.
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue