Merge remote-tracking branch 'upstream/master' into conditional-ds

This commit is contained in:
Stephen Birarda 2013-06-10 14:01:54 -07:00
commit a8075e44ca
13 changed files with 884 additions and 745 deletions

View file

@ -1,106 +1,107 @@
#version 120
//
// 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
//
uniform vec3 v3CameraPos; // The camera's current position
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;
uniform vec3 v3LightPos;
uniform float g;
uniform float g2;
varying vec3 position;
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 = position;
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 * 0.99;
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
vec3 secondaryFrontColor = v3FrontColor * fKmESun;
vec3 frontColor = v3FrontColor * (v3InvWavelength * fKrESun);
vec3 v3Direction = v3CameraPos - v3Pos;
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.rgb = frontColor.rgb + fMiePhase * secondaryFrontColor.rgb;
gl_FragColor.a = gl_FragColor.b;
}
#version 120
//
// 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
//
uniform vec3 v3CameraPos; // The camera's current position
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;
uniform vec3 v3LightPos;
uniform float g;
uniform float g2;
varying vec3 position;
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 = position;
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 * 0.99;
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
vec3 secondaryFrontColor = v3FrontColor * fKmESun;
vec3 frontColor = v3FrontColor * (v3InvWavelength * fKrESun);
vec3 v3Direction = v3CameraPos - v3Pos;
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.rgb = frontColor.rgb + fMiePhase * secondaryFrontColor.rgb;
gl_FragColor.a = gl_FragColor.b;
gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0/2.2));
}

View file

@ -110,4 +110,5 @@ void main (void)
vec3 secondaryColor = v3FrontColor * fKmESun;
gl_FragColor.rgb = color + fMiePhase * secondaryColor;
gl_FragColor.a = gl_FragColor.b;
gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0/2.2));
}

File diff suppressed because it is too large Load diff

View file

@ -112,7 +112,6 @@ private slots:
void decreaseVoxelSize();
void increaseVoxelSize();
void chooseVoxelPaintColor();
void setAutosave(bool wantsAutosave);
void loadSettings(QSettings* set = NULL);
void saveSettings(QSettings* set = NULL);
void importSettings();
@ -132,6 +131,7 @@ private:
void initDisplay();
void init();
void update(float deltaTime);
void updateAvatar(float deltaTime);
void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum);
@ -176,10 +176,12 @@ private:
QAction* _mouseLook; // Whether the have the mouse near edge of screen move your view
QAction* _showHeadMouse; // Whether the have the mouse near edge of screen move your view
QAction* _transmitterDrives; // Whether to have Transmitter data move/steer the Avatar
QAction* _gravityUse; // Whether gravity is on or not
QAction* _renderVoxels; // Whether to render voxels
QAction* _renderVoxelTextures; // Whether to render noise textures on voxels
QAction* _renderStarsOn; // Whether to display the stars
QAction* _renderAtmosphereOn; // Whether to display the atmosphere
QAction* _renderGroundPlaneOn; // Whether to display the ground plane
QAction* _renderAvatarsOn; // Whether to render avatars
QAction* _renderStatsOn; // Whether to show onscreen text overlay with stats
QAction* _renderFrameTimerOn; // Whether to show onscreen text overlay with stats
@ -226,7 +228,7 @@ private:
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
enum FrustumDrawMode { FRUSTUM_DRAW_MODE_ALL, FRUSTUM_DRAW_MODE_VECTORS, FRUSTUM_DRAW_MODE_PLANES,
FRUSTUM_DRAW_MODE_NEAR_PLANE, FRUSTUM_DRAW_MODE_FAR_PLANE, FRUSTUM_DRAW_MODE_COUNT };
FRUSTUM_DRAW_MODE_NEAR_PLANE, FRUSTUM_DRAW_MODE_FAR_PLANE, FRUSTUM_DRAW_MODE_KEYHOLE, FRUSTUM_DRAW_MODE_COUNT };
FrustumDrawMode _frustumDrawingMode;
float _viewFrustumOffsetYaw; // the following variables control yaw, pitch, roll and distance form regular
@ -293,8 +295,6 @@ private:
int _packetsPerSecond;
int _bytesPerSecond;
int _bytesCount;
bool _autosave; // True if the autosave is on.
};
#endif /* defined(__interface__Application__) */

View file

@ -1225,6 +1225,8 @@ void Avatar::loadData(QSettings* set) {
_position.y = set->value("position_y", _position.y).toFloat();
_position.z = set->value("position_z", _position.z).toFloat();
_voxels.setVoxelURL(set->value("voxelURL").toUrl());
set->endGroup();
}
@ -1244,6 +1246,8 @@ void Avatar::saveData(QSettings* set) {
set->setValue("position_y", _position.y);
set->setValue("position_z", _position.z);
set->setValue("voxelURL", _voxels.getVoxelURL());
set->endGroup();
}

View file

@ -71,7 +71,7 @@ void Camera::updateFollowMode(float deltaTime) {
_distance = _previousDistance * (1.0f - _modeShift) + _newDistance * _modeShift;
_tightness = _previousTightness * (1.0f - _modeShift) + _newTightness * _modeShift;
if (_linearModeShift > 1.0f ) {
if (_needsToInitialize || _linearModeShift > 1.0f) {
_linearModeShift = 1.0f;
_modeShift = 1.0f;
_upShift = _newUpShift;

View file

@ -27,7 +27,7 @@ public:
static unsigned const TEXT_COLOR = 0xb299ff; // text foreground color (bytes, RGB)
static FILE* const DEFAULT_STREAM; // = stdout; // stream to also log to (defined in .cpp)
static unsigned const DEFAULT_CHAR_WIDTH = 7; // width of a single character
static unsigned const DEFAULT_CHAR_WIDTH = 5; // width of a single character
static unsigned const DEFAULT_CHAR_HEIGHT = 16; // height of a single character
static unsigned const DEFAULT_CONSOLE_WIDTH = 400; // width of the (right-aligned) log console

View file

@ -24,28 +24,29 @@ enum BoxFace {
const int FACE_COUNT = 6;
class AABox
class AABox
{
public:
AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(x,y,z) { };
AABox(const glm::vec3& corner, const glm::vec3& size) : _corner(corner), _size(size) { };
AABox(const glm::vec3& corner, float size) : _corner(corner), _size(size, size, size) { };
AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(x, y, z) { };
AABox(const glm::vec3& corner, const glm::vec3& size) : _corner(corner), _size(size) { };
AABox() : _corner(0,0,0), _size(0,0,0) { }
~AABox() { }
void setBox(const glm::vec3& corner, float x, float y, float z) { setBox(corner,glm::vec3(x,y,z)); };
void setBox(const glm::vec3& corner, const glm::vec3& size);
void setBox(const glm::vec3& corner, float x, float y, float z) { setBox(corner,glm::vec3(x,y,z)); };
void setBox(const glm::vec3& corner, const glm::vec3& size);
// for use in frustum computations
glm::vec3 getVertexP(const glm::vec3& normal) const;
glm::vec3 getVertexN(const glm::vec3& normal) const;
void scale(float scale);
const glm::vec3& getCorner() const { return _corner; };
const glm::vec3& getSize() const { return _size; };
const glm::vec3& getCenter() const { return _center; };
// for use in frustum computations
glm::vec3 getVertexP(const glm::vec3& normal) const;
glm::vec3 getVertexN(const glm::vec3& normal) const;
void scale(float scale);
const glm::vec3& getCorner() const { return _corner; };
const glm::vec3& getSize() const { return _size; };
const glm::vec3& getCenter() const { return _center; };
bool contains(const glm::vec3& point) const;
bool expandedContains(const glm::vec3& point, float expansion) const;
@ -55,16 +56,16 @@ public:
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
private:
glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const;
glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const;
glm::vec4 getPlane(BoxFace face) const;
static BoxFace getOppositeFace(BoxFace face);
glm::vec3 _corner;
glm::vec3 _center;
glm::vec3 _size;
glm::vec3 _corner;
glm::vec3 _center;
glm::vec3 _size;
};

View file

@ -29,6 +29,7 @@ ViewFrustum::ViewFrustum() :
_aspectRatio(1.0),
_nearClip(0.1),
_farClip(500.0),
_keyholeRadius(DEFAULT_KEYHOLE_RADIUS),
_farTopLeft(0,0,0),
_farTopRight(0,0,0),
_farBottomLeft(0,0,0),
@ -36,7 +37,9 @@ ViewFrustum::ViewFrustum() :
_nearTopLeft(0,0,0),
_nearTopRight(0,0,0),
_nearBottomLeft(0,0,0),
_nearBottomRight(0,0,0) { }
_nearBottomRight(0,0,0)
{
}
void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) {
_orientation = orientationAsQuaternion;
@ -114,42 +117,6 @@ void ViewFrustum::calculate() {
}
void ViewFrustum::dump() const {
printLog("position.x=%f, position.y=%f, position.z=%f\n", _position.x, _position.y, _position.z);
printLog("direction.x=%f, direction.y=%f, direction.z=%f\n", _direction.x, _direction.y, _direction.z);
printLog("up.x=%f, up.y=%f, up.z=%f\n", _up.x, _up.y, _up.z);
printLog("right.x=%f, right.y=%f, right.z=%f\n", _right.x, _right.y, _right.z);
printLog("farDist=%f\n", _farClip);
printLog("nearDist=%f\n", _nearClip);
printLog("eyeOffsetPosition=%f,%f,%f\n", _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z);
printLog("eyeOffsetOrientation=%f,%f,%f,%f\n", _eyeOffsetOrientation.x, _eyeOffsetOrientation.y,
_eyeOffsetOrientation.z, _eyeOffsetOrientation.w);
printLog("farTopLeft.x=%f, farTopLeft.y=%f, farTopLeft.z=%f\n",
_farTopLeft.x, _farTopLeft.y, _farTopLeft.z);
printLog("farTopRight.x=%f, farTopRight.y=%f, farTopRight.z=%f\n",
_farTopRight.x, _farTopRight.y, _farTopRight.z);
printLog("farBottomLeft.x=%f, farBottomLeft.y=%f, farBottomLeft.z=%f\n",
_farBottomLeft.x, _farBottomLeft.y, _farBottomLeft.z);
printLog("farBottomRight.x=%f, farBottomRight.y=%f, farBottomRight.z=%f\n",
_farBottomRight.x, _farBottomRight.y, _farBottomRight.z);
printLog("nearTopLeft.x=%f, nearTopLeft.y=%f, nearTopLeft.z=%f\n",
_nearTopLeft.x, _nearTopLeft.y, _nearTopLeft.z);
printLog("nearTopRight.x=%f, nearTopRight.y=%f, nearTopRight.z=%f\n",
_nearTopRight.x, _nearTopRight.y, _nearTopRight.z);
printLog("nearBottomLeft.x=%f, nearBottomLeft.y=%f, nearBottomLeft.z=%f\n",
_nearBottomLeft.x, _nearBottomLeft.y, _nearBottomLeft.z);
printLog("nearBottomRight.x=%f, nearBottomRight.y=%f, nearBottomRight.z=%f\n",
_nearBottomRight.x, _nearBottomRight.y, _nearBottomRight.z);
}
//enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
const char* ViewFrustum::debugPlaneName (int plane) const {
switch (plane) {
@ -163,52 +130,147 @@ const char* ViewFrustum::debugPlaneName (int plane) const {
return "Unknown";
}
ViewFrustum::location ViewFrustum::pointInSphere(const glm::vec3& point, const glm::vec3& center, float radius ) 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();
ViewFrustum::location result = INSIDE;
for(int i=0; i < 6; i++) {
float distance = _planes[i].distance(point);
//printf("plane[%d] %s -- distance=%f \n",i,debugPlaneName(i),distance);
ViewFrustum::location result = INTERSECT;
if (distance < 0) {
return OUTSIDE;
float distance = glm::distance(point, center);
if (distance > radius) {
result = OUTSIDE;
} else if (distance < radius) {
result = INSIDE;
}
return result;
}
// To determine if two spheres intersect, simply calculate the distance between the centers of the two spheres.
// If the distance is greater than the sum of the two sphere radii, they dont intersect. Otherwise they intersect.
// If the distance plus the radius of sphere A is less than the radius of sphere B then, sphere A is inside of sphere B
ViewFrustum::location ViewFrustum::sphereInSphere(const glm::vec3& centerA, float radiusA,
const glm::vec3& centerB, float radiusB ) const {
ViewFrustum::location result = INTERSECT;
float distanceFromAtoB = glm::distance(centerA, centerB);
if (distanceFromAtoB > (radiusA + radiusB)) {
result = OUTSIDE;
} else if ((distanceFromAtoB + radiusA) < radiusB) {
result = INSIDE;
}
return result;
}
// A box is inside a sphere if all of its corners are inside the sphere
// A box intersects a sphere if any of its edges (as rays) interesect the sphere
// A box is outside a sphere if none of its edges (as rays) interesect the sphere
ViewFrustum::location ViewFrustum::boxInSphere(const AABox& box, const glm::vec3& center, float radius) const {
glm::vec3 penetration;
bool intersects = box.findSpherePenetration(center, radius, penetration);
ViewFrustum::location result = OUTSIDE;
// if the box intersects the sphere, then it may also be inside... calculate further
if (intersects) {
result = INTERSECT;
// test all the corners, if they are all inside the sphere, the entire box is in the sphere
glm::vec3 testPoint = box.getCorner();
glm::vec3 size = box.getSize();
if (pointInSphere(testPoint, center, radius)) {
testPoint = box.getCorner() + glm::vec3(size.x, 0.0f, 0.0f);
if (pointInSphere(testPoint, center, radius)) {
testPoint = box.getCorner() + glm::vec3(0.0f, 0.0f, size.z);
if (pointInSphere(testPoint, center, radius)) {
testPoint = box.getCorner() + glm::vec3(size.x, 0.0f, size.z);
if (pointInSphere(testPoint, center, radius)) {
testPoint = box.getCorner() + glm::vec3(0.0f, size.y, 0.0f);
if (pointInSphere(testPoint, center, radius)) {
testPoint = box.getCorner() + glm::vec3(size.x, size.y, 0.0f);
if (pointInSphere(testPoint, center, radius)) {
testPoint = box.getCorner() + glm::vec3(0.0f, size.y, size.z);
if (pointInSphere(testPoint, center, radius)) {
testPoint = box.getCorner() + glm::vec3(size.x, size.y, size.z);
if (pointInSphere(testPoint, center, radius)) {
result = INSIDE;
}
}
}
}
}
}
}
}
}
return(result);
return result;
}
ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const {
ViewFrustum::location regularResult = INSIDE;
ViewFrustum::location keyholeResult = OUTSIDE;
// If we have a keyholeRadius, check that first, since it's cheaper
if (_keyholeRadius >= 0.0f) {
keyholeResult = pointInSphere(point, _position, _keyholeRadius);
}
if (keyholeResult == INSIDE) {
return keyholeResult;
}
// If we're not known to be INSIDE the keyhole, then check the regular frustum
for(int i=0; i < 6; i++) {
float distance = _planes[i].distance(point);
if (distance < 0) {
return keyholeResult; // escape early will be the value from checking the keyhole
}
}
return regularResult;
}
ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
ViewFrustum::location result = INSIDE;
ViewFrustum::location regularResult = INSIDE;
ViewFrustum::location keyholeResult = OUTSIDE;
// If we have a keyholeRadius, check that first, since it's cheaper
if (_keyholeRadius >= 0.0f) {
keyholeResult = sphereInSphere(center, radius, _position, _keyholeRadius);
}
if (keyholeResult == INSIDE) {
return keyholeResult;
}
float distance;
for(int i=0; i < 6; i++) {
distance = _planes[i].distance(center);
if (distance < -radius)
return OUTSIDE;
else if (distance < radius)
result = INTERSECT;
if (distance < -radius) {
// This is outside the regular frustum, so just return the value from checking the keyhole
return keyholeResult;
} else if (distance < radius) {
regularResult = INTERSECT;
}
}
return(result);
return regularResult;
}
ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
ViewFrustum::location regularResult = INSIDE;
ViewFrustum::location keyholeResult = OUTSIDE;
// If we have a keyholeRadius, check that first, since it's cheaper
if (_keyholeRadius >= 0.0f) {
keyholeResult = boxInSphere(box, _position, _keyholeRadius);
}
if (keyholeResult == INSIDE) {
return keyholeResult;
}
//printf("ViewFrustum::boxInFrustum() box.corner=%f,%f,%f x=%f\n",
// box.getCorner().x,box.getCorner().y,box.getCorner().z,box.getSize().x);
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,
// _planes[i].getPoint().x, _planes[i].getPoint().y, _planes[i].getPoint().z,
// _planes[i].getNormal().x, _planes[i].getNormal().y, _planes[i].getNormal().z,
// _planes[i].getDCoefficient()
//);
glm::vec3 normal = _planes[i].getNormal();
glm::vec3 boxVertexP = box.getVertexP(normal);
float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP);
@ -216,19 +278,14 @@ ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
glm::vec3 boxVertexN = box.getVertexN(normal);
float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN);
//printf("plane[%d] normal=(%f,%f,%f) bVertexP=(%f,%f,%f) planeToBoxVertexPDistance=%f boxVertexN=(%f,%f,%f) planeToBoxVertexNDistance=%f\n",i,
// normal.x,normal.y,normal.z,
// boxVertexP.x,boxVertexP.y,boxVertexP.z,planeToBoxVertexPDistance,
// boxVertexN.x,boxVertexN.y,boxVertexN.z,planeToBoxVertexNDistance
// );
if (planeToBoxVertexPDistance < 0) {
return OUTSIDE;
// This is outside the regular frustum, so just return the value from checking the keyhole
return keyholeResult;
} else if (planeToBoxVertexNDistance < 0) {
result = INTERSECT;
regularResult = INTERSECT;
}
}
return(result);
return regularResult;
}
bool testMatches(glm::quat lhs, glm::quat rhs) {

View file

@ -16,44 +16,9 @@
#include "Plane.h"
#include "AABox.h"
const float DEFAULT_KEYHOLE_RADIUS = 2.0f;
class ViewFrustum {
private:
// camera location/orientation attributes
glm::vec3 _position;
glm::quat _orientation;
// calculated for orientation
glm::vec3 _direction;
glm::vec3 _up;
glm::vec3 _right;
// Lens attributes
float _fieldOfView;
float _aspectRatio;
float _nearClip;
float _farClip;
glm::vec3 _eyeOffsetPosition;
glm::quat _eyeOffsetOrientation;
// Calculated values
glm::vec3 _offsetPosition;
glm::vec3 _offsetDirection;
glm::vec3 _offsetUp;
glm::vec3 _offsetRight;
glm::vec3 _farTopLeft;
glm::vec3 _farTopRight;
glm::vec3 _farBottomLeft;
glm::vec3 _farBottomRight;
glm::vec3 _nearTopLeft;
glm::vec3 _nearTopRight;
glm::vec3 _nearBottomLeft;
glm::vec3 _nearBottomRight;
enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
Plane _planes[6]; // How will this be used?
const char* debugPlaneName (int plane) const;
public:
// setters for camera attributes
void setPosition (const glm::vec3& p) { _position = p; };
@ -74,7 +39,6 @@ public:
void setEyeOffsetPosition (const glm::vec3& p) { _eyeOffsetPosition = p; };
void setEyeOffsetOrientation (const glm::quat& o) { _eyeOffsetOrientation = o; };
// getters for lens attributes
float getFieldOfView() const { return _fieldOfView; };
float getAspectRatio() const { return _aspectRatio; };
@ -98,12 +62,14 @@ public:
const glm::vec3& getNearBottomLeft() const { return _nearBottomLeft; };
const glm::vec3& getNearBottomRight() const { return _nearBottomRight;};
// get/set for keyhole attribute
void setKeyholeRadius(float keyholdRadius) { _keyholeRadius = keyholdRadius; };
float getKeyholeRadius() const { return _keyholeRadius; };
void calculate();
ViewFrustum();
void dump() const;
typedef enum {OUTSIDE, INTERSECT, INSIDE} location;
ViewFrustum::location pointInFrustum(const glm::vec3& point) const;
@ -120,6 +86,53 @@ public:
glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
void printDebugDetails() const;
private:
// Used for keyhole calculations
ViewFrustum::location pointInSphere(const glm::vec3& point, const glm::vec3& center, float radius) const;
ViewFrustum::location sphereInSphere(const glm::vec3& centerA, float radiusA, const glm::vec3& centerB, float radiusB) const;
ViewFrustum::location boxInSphere(const AABox& box, const glm::vec3& center, float radius) const;
// camera location/orientation attributes
glm::vec3 _position;
glm::quat _orientation;
// calculated for orientation
glm::vec3 _direction;
glm::vec3 _up;
glm::vec3 _right;
// Lens attributes
float _fieldOfView;
float _aspectRatio;
float _nearClip;
float _farClip;
glm::vec3 _eyeOffsetPosition;
glm::quat _eyeOffsetOrientation;
// keyhole attributes
float _keyholeRadius;
// Calculated values
glm::vec3 _offsetPosition;
glm::vec3 _offsetDirection;
glm::vec3 _offsetUp;
glm::vec3 _offsetRight;
glm::vec3 _farTopLeft;
glm::vec3 _farTopRight;
glm::vec3 _farBottomLeft;
glm::vec3 _farBottomRight;
glm::vec3 _nearTopLeft;
glm::vec3 _nearTopRight;
glm::vec3 _nearBottomLeft;
glm::vec3 _nearBottomRight;
enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
Plane _planes[6]; // How will this be used?
const char* debugPlaneName (int plane) const;
};

View file

@ -35,7 +35,7 @@ void VoxelNode::init(unsigned char * octalCode) {
_currentColor[0] = _currentColor[1] = _currentColor[2] = _currentColor[3] = 0;
#endif
_trueColor[0] = _trueColor[1] = _trueColor[2] = _trueColor[3] = 0;
_density = 0.0f;
// default pointers to child nodes to NULL
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
@ -161,10 +161,10 @@ void VoxelNode::safeDeepDeleteChildAtIndex(int childIndex, bool& stagedForDeleti
}
}
// will average the child colors...
void VoxelNode::setColorFromAverageOfChildren() {
int colorArray[4] = {0,0,0,0};
float density = 0.0f;
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
if (_children[i] && !_children[i]->isStagedForDeletion() && _children[i]->isColored()) {
for (int j = 0; j < 3; j++) {
@ -172,11 +172,24 @@ void VoxelNode::setColorFromAverageOfChildren() {
}
colorArray[3]++;
}
if (_children[i]) {
density += _children[i]->getDensity();
}
}
density /= (float) NUMBER_OF_CHILDREN;
//
// The VISIBLE_ABOVE_DENSITY sets the density of matter above which an averaged color voxel will
// be set. It is an important physical constant in our universe. A number below 0.5 will cause
// things to get 'fatter' at a distance, because upward averaging will make larger voxels out of
// less data, which is (probably) going to be preferable because it gives a sense that there is
// something out there to go investigate. A number above 0.5 would cause the world to become
// more 'empty' at a distance. Exactly 0.5 would match the physical world, at least for materials
// that are not shiny and have equivalent ambient reflectance.
//
const float VISIBLE_ABOVE_DENSITY = 0.10f;
nodeColor newColor = { 0, 0, 0, 0};
if (colorArray[3] > 4) {
// we need at least 4 colored children to have an average color value
// or if we have none we generate random values
if (density > VISIBLE_ABOVE_DENSITY) {
// The density of material in the space of the voxel sets whether it is actually colored
for (int c = 0; c < 3; c++) {
// set the average color value
newColor[c] = colorArray[c] / colorArray[3];
@ -184,10 +197,9 @@ void VoxelNode::setColorFromAverageOfChildren() {
// set the alpha to 1 to indicate that this isn't transparent
newColor[3] = 1;
}
// actually set our color, note, if we didn't have enough children
// this will be the default value all zeros, and therefore be marked as
// transparent with a 4th element of 0
// Set the color from the average of the child colors, and update the density
setColor(newColor);
setDensity(density);
}
// Note: !NO_FALSE_COLOR implementations of setFalseColor(), setFalseColored(), and setColor() here.
@ -214,20 +226,21 @@ void VoxelNode::setFalseColored(bool isFalseColored) {
_falseColored = isFalseColored;
_isDirty = true;
markWithChangedTime();
_density = 1.0f; // If color set, assume leaf, re-averaging will update density if needed.
}
};
void VoxelNode::setColor(const nodeColor& color) {
if (_trueColor[0] != color[0] || _trueColor[1] != color[1] || _trueColor[2] != color[2]) {
//printLog("VoxelNode::setColor() was: (%d,%d,%d) is: (%d,%d,%d)\n",
// _trueColor[0],_trueColor[1],_trueColor[2],color[0],color[1],color[2]);
memcpy(&_trueColor,&color,sizeof(nodeColor));
if (!_falseColored) {
memcpy(&_currentColor,&color,sizeof(nodeColor));
}
_isDirty = true;
markWithChangedTime();
_density = 1.0f; // If color set, assume leaf, re-averaging will update density if needed.
}
}
#endif

View file

@ -36,6 +36,7 @@ private:
unsigned char* _octalCode;
VoxelNode* _children[8];
int _childCount;
float _density; // If leaf: density = 1, if internal node: 0-1 density of voxels inside
void calculateAABox();
@ -102,11 +103,14 @@ public:
void setColor(const nodeColor& color);
const nodeColor& getTrueColor() const { return _trueColor; };
const nodeColor& getColor() const { return _currentColor; };
void setDensity(const float density) { _density = density; };
const float getDensity() const { return _density; };
#else
void setFalseColor(colorPart red, colorPart green, colorPart blue) { /* no op */ };
void setFalseColored(bool isFalseColored) { /* no op */ };
bool getFalseColored() { return false; };
void setColor(const nodeColor& color) { memcpy(_trueColor,color,sizeof(nodeColor)); };
void setDensity(const float density) { _density = density; };
const nodeColor& getTrueColor() const { return _trueColor; };
const nodeColor& getColor() const { return _trueColor; };
#endif

View file

@ -387,16 +387,6 @@ void persistVoxelsWhenDirty() {
// check the dirty bit and persist here...
if (::wantVoxelPersist && ::serverTree.isDirty() && sinceLastTime > VOXEL_PERSIST_INTERVAL) {
{
PerformanceWarning warn(::shouldShowAnimationDebug,
"persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug);
// after done inserting all these voxels, then reaverage colors
serverTree.reaverageVoxelColors(serverTree.rootNode);
}
{
PerformanceWarning warn(::shouldShowAnimationDebug,
"persistVoxelsWhenDirty() - writeToSVOFile()", ::shouldShowAnimationDebug);
@ -505,6 +495,15 @@ int main(int argc, const char * argv[]) {
if (::wantVoxelPersist) {
printf("loading voxels from file...\n");
persistantFileRead = ::serverTree.readFromSVOFile(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE);
if (persistantFileRead) {
PerformanceWarning warn(::shouldShowAnimationDebug,
"persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug);
// after done inserting all these voxels, then reaverage colors
serverTree.reaverageVoxelColors(serverTree.rootNode);
printf("Voxels reAveraged\n");
}
::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it
printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead));
unsigned long nodeCount = ::serverTree.getVoxelCount();