Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jeffrey Ventrella 2013-05-09 11:22:55 -07:00
commit 7cfc9844a3
14 changed files with 474 additions and 388 deletions

View file

@ -22,7 +22,6 @@
#include <AgentTypes.h> #include <AgentTypes.h>
#include <SharedUtil.h> #include <SharedUtil.h>
#include <StdDev.h> #include <StdDev.h>
#include <Stacktrace.h>
#include "AudioRingBuffer.h" #include "AudioRingBuffer.h"
#include "PacketHeaders.h" #include "PacketHeaders.h"
@ -258,8 +257,7 @@ void attachNewBufferToAgent(Agent *newAgent) {
} }
} }
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
signal(SIGSEGV, printStacktrace);
setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stdout, NULL, _IOLBF, 0);
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AUDIO_MIXER, MIXER_LISTEN_PORT); AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AUDIO_MIXER, MIXER_LISTEN_PORT);

View file

@ -1,3 +1,5 @@
#!/usr/bin/env python
# #
# gen_stars.py # gen_stars.py
# interface # interface
@ -12,7 +14,7 @@ from random import random,randint
from math import sqrt, hypot, atan2, pi, fmod, degrees from math import sqrt, hypot, atan2, pi, fmod, degrees
from sys import argv,stderr from sys import argv,stderr
hemisphere_only, equator, meridians= False, 1000, 1000 hemisphere_only, equator, meridians= False, 0, 1000
n_random = 100000 n_random = 100000
if len(argv) > 1: if len(argv) > 1:
@ -50,10 +52,13 @@ for i in range(n_random):
g = max(0,min(255,w + randint(-20,60))) g = max(0,min(255,w + randint(-20,60)))
b = max(0,min(255,w + randint(-10,100))) b = max(0,min(255,w + randint(-10,100)))
# position # position
x,y,z = random()*2-1,random(),random()*2-1 while True:
if not hemisphere_only: x,y,z = random()*2-1,random(),random()*2-1
y = y*2-1 if not hemisphere_only:
l = sqrt(x*x + y*y + z*z) y = y*2-1
l = sqrt(x*x + y*y + z*z)
if l <= 1.0:
break
x /= l; y /= l; z /= l x /= l; y /= l; z /= l
xz = hypot(x,z) xz = hypot(x,z)

View file

@ -1257,6 +1257,11 @@ void Avatar::initializeBodySprings() {
} }
void Avatar::updateBodySprings(float deltaTime) { void Avatar::updateBodySprings(float deltaTime) {
// Check for a large repositioning, and re-initialize body springs if this has happened
const float BEYOND_BODY_SPRING_RANGE = 2.f;
if (glm::length(_position - _joint[AVATAR_JOINT_PELVIS].springyPosition) > BEYOND_BODY_SPRING_RANGE) {
initializeBodySprings();
}
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
glm::vec3 springVector(_joint[b].springyPosition); glm::vec3 springVector(_joint[b].springyPosition);

View file

@ -42,28 +42,23 @@ void SerialInterface::pair() {
int matchStatus; int matchStatus;
regex_t regex; regex_t regex;
if (_failedOpenAttempts < 2) { // for now this only works on OS X, where the usb serial shows up as /dev/tty.usb*
// if we've already failed to open the detected interface twice then don't try again if((devDir = opendir("/dev"))) {
while((entry = readdir(devDir))) {
// for now this only works on OS X, where the usb serial shows up as /dev/tty.usb* regcomp(&regex, "tty\\.usb", REG_EXTENDED|REG_NOSUB);
if((devDir = opendir("/dev"))) { matchStatus = regexec(&regex, entry->d_name, (size_t) 0, NULL, 0);
while((entry = readdir(devDir))) { if (matchStatus == 0) {
regcomp(&regex, "tty\\.usb", REG_EXTENDED|REG_NOSUB); char *serialPortname = new char[100];
matchStatus = regexec(&regex, entry->d_name, (size_t) 0, NULL, 0); sprintf(serialPortname, "/dev/%s", entry->d_name);
if (matchStatus == 0) {
char *serialPortname = new char[100]; initializePort(serialPortname, 115200);
sprintf(serialPortname, "/dev/%s", entry->d_name);
delete [] serialPortname;
initializePort(serialPortname, 115200);
delete [] serialPortname;
}
regfree(&regex);
} }
closedir(devDir); regfree(&regex);
} }
} closedir(devDir);
}
#endif #endif
} }
@ -76,7 +71,6 @@ void SerialInterface::initializePort(char* portname, int baud) {
if (_serialDescriptor == -1) { if (_serialDescriptor == -1) {
printLog("Failed.\n"); printLog("Failed.\n");
_failedOpenAttempts++;
return; return;
} }
struct termios options; struct termios options;
@ -123,6 +117,9 @@ void SerialInterface::initializePort(char* portname, int baud) {
// this disables streaming so there's no garbage data on reads // this disables streaming so there's no garbage data on reads
write(_serialDescriptor, "SD\n", 3); write(_serialDescriptor, "SD\n", 3);
// delay after disabling streaming
usleep(10000);
// flush whatever was produced by the last two commands // flush whatever was produced by the last two commands
tcflush(_serialDescriptor, TCIOFLUSH); tcflush(_serialDescriptor, TCIOFLUSH);
} }
@ -232,26 +229,38 @@ void SerialInterface::readData() {
int initialSamples = totalSamples; int initialSamples = totalSamples;
if (USING_INVENSENSE_MPU9150) { if (USING_INVENSENSE_MPU9150) {
unsigned char gyroBuffer[20]; unsigned char sensorBuffer[36];
// ask the invensense for raw gyro data // ask the invensense for raw gyro data
write(_serialDescriptor, "RD684306\n", 9); write(_serialDescriptor, "RD683B0E\n", 9);
read(_serialDescriptor, gyroBuffer, 20); read(_serialDescriptor, sensorBuffer, 36);
int accelXRate, accelYRate, accelZRate;
convertHexToInt(sensorBuffer + 6, accelXRate);
convertHexToInt(sensorBuffer + 10, accelYRate);
convertHexToInt(sensorBuffer + 14, accelZRate);
const float LSB_TO_METERS_PER_SECOND = 1.f / 16384.f;
_lastAccelX = ((float) accelXRate) * LSB_TO_METERS_PER_SECOND;
_lastAccelY = ((float) accelYRate) * LSB_TO_METERS_PER_SECOND;
_lastAccelZ = ((float) accelZRate) * LSB_TO_METERS_PER_SECOND;
int rollRate, yawRate, pitchRate; int rollRate, yawRate, pitchRate;
convertHexToInt(gyroBuffer + 6, rollRate); convertHexToInt(sensorBuffer + 22, rollRate);
convertHexToInt(gyroBuffer + 10, yawRate); convertHexToInt(sensorBuffer + 26, yawRate);
convertHexToInt(gyroBuffer + 14, pitchRate); convertHexToInt(sensorBuffer + 30, pitchRate);
// Convert the integer rates to floats // 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 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 const float PITCH_BIAS = 2.0; // Strangely, there is a small DC bias in the
// invensense pitch reading. Gravity? // invensense pitch reading. Gravity?
_lastRollRate = (float) rollRate * LSB_TO_DEGREES_PER_SECOND; _lastRollRate = ((float) rollRate) * LSB_TO_DEGREES_PER_SECOND;
_lastYawRate = (float) yawRate * LSB_TO_DEGREES_PER_SECOND; _lastYawRate = ((float) yawRate) * LSB_TO_DEGREES_PER_SECOND;
_lastPitchRate = (float) -pitchRate * LSB_TO_DEGREES_PER_SECOND + PITCH_BIAS; _lastPitchRate = ((float) -pitchRate) * LSB_TO_DEGREES_PER_SECOND + PITCH_BIAS;
totalSamples++; totalSamples++;
} else { } else {

View file

@ -37,7 +37,12 @@ extern const bool USING_INVENSENSE_MPU9150;
class SerialInterface { class SerialInterface {
public: public:
SerialInterface() : active(false), SerialInterface() : active(false),
_failedOpenAttempts(0) {} _lastAccelX(0),
_lastAccelY(0),
_lastAccelZ(0),
_lastYawRate(0),
_lastPitchRate(0),
_lastRollRate(0) {}
void pair(); void pair();
void readData(); void readData();
@ -69,10 +74,12 @@ private:
int totalSamples; int totalSamples;
timeval lastGoodRead; timeval lastGoodRead;
glm::vec3 gravity; glm::vec3 gravity;
float _lastAccelX;
float _lastAccelY;
float _lastAccelZ;
float _lastYawRate; // Rates are in degrees per second. float _lastYawRate; // Rates are in degrees per second.
float _lastPitchRate; float _lastPitchRate;
float _lastRollRate; float _lastRollRate;
int _failedOpenAttempts;
}; };
#endif #endif

View file

@ -679,3 +679,19 @@ void VoxelSystem::removeOutOfView() {
); );
} }
} }
bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
VoxelDetail& detail, float& distance, BoxFace& face) {
VoxelNode* node;
if (!_tree->findRayIntersection(origin, direction, node, distance, face)) {
return false;
}
detail.x = node->getCorner().x;
detail.y = node->getCorner().y;
detail.z = node->getCorner().z;
detail.s = node->getScale();
detail.red = node->getColor()[0];
detail.green = node->getColor()[1];
detail.blue = node->getColor()[2];
return true;
}

View file

@ -11,6 +11,7 @@
#include "InterfaceConfig.h" #include "InterfaceConfig.h"
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <SharedUtil.h>
#include <UDPSocket.h> #include <UDPSocket.h>
#include <AgentData.h> #include <AgentData.h>
#include <VoxelTree.h> #include <VoxelTree.h>
@ -64,6 +65,9 @@ public:
void removeOutOfView(); void removeOutOfView();
bool hasViewChanged(); bool hasViewChanged();
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
VoxelDetail& detail, float& distance, BoxFace& face);
private: private:
int _callsToTreesToArrays; int _callsToTreesToArrays;
VoxelNodeBag _removedVoxels; VoxelNodeBag _removedVoxels;

View file

@ -70,7 +70,6 @@
#include "Oscilloscope.h" #include "Oscilloscope.h"
#include "UDPSocket.h" #include "UDPSocket.h"
#include "SerialInterface.h" #include "SerialInterface.h"
#include <SharedUtil.h>
#include <PacketHeaders.h> #include <PacketHeaders.h>
#include <AvatarData.h> #include <AvatarData.h>
#include <PerfStat.h> #include <PerfStat.h>
@ -148,15 +147,15 @@ bool renderStarsOn = true; // Whether to display the stars
bool renderAtmosphereOn = true; // Whether to display the atmosphere bool renderAtmosphereOn = true; // Whether to display the atmosphere
bool renderAvatarsOn = true; // Whether to render avatars bool renderAvatarsOn = true; // Whether to render avatars
bool paintOn = false; // Whether to paint voxels as you fly around bool paintOn = false; // Whether to paint voxels as you fly around
VoxelDetail paintingVoxel; // The voxel we're painting if we're painting VoxelDetail paintingVoxel; // The voxel we're painting if we're painting
unsigned char dominantColor = 0; // The dominant color of the voxel we're painting unsigned char dominantColor = 0; // The dominant color of the voxel we're painting
bool perfStatsOn = false; // Do we want to display perfStats? bool perfStatsOn = false; // Do we want to display perfStats?
bool logOn = true; // Whether to show on-screen log bool logOn = true; // Whether to show on-screen log
bool wantToKillLocalVoxels = false; bool wantToKillLocalVoxels = false;
int noiseOn = 0; // Whether to add random noise int noiseOn = 0; // Whether to add random noise
float noise = 1.0; // Overall magnitude scaling for random noise levels float noise = 1.0; // Overall magnitude scaling for random noise levels
bool gyroLook = true; // Whether to allow the gyro data from head to move your view bool gyroLook = true; // Whether to allow the gyro data from head to move your view
@ -211,11 +210,11 @@ void Timer(int extra) {
FPS = (float)frameCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f); FPS = (float)frameCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f);
packetsPerSecond = (float)packetCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f); packetsPerSecond = (float)packetCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f);
bytesPerSecond = (float)bytesCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f); bytesPerSecond = (float)bytesCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f);
frameCount = 0; frameCount = 0;
packetCount = 0; packetCount = 0;
bytesCount = 0; bytesCount = 0;
glutTimerFunc(1000,Timer,0); glutTimerFunc(1000,Timer,0);
gettimeofday(&timerStart, NULL); gettimeofday(&timerStart, NULL);
// if we haven't detected gyros, check for them now // if we haven't detected gyros, check for them now
@ -240,27 +239,27 @@ void displayStats(void) {
voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered() / 1000.f << "K Updated: " << voxels.getVoxelsUpdated()/1000.f << "K"; voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered() / 1000.f << "K Updated: " << voxels.getVoxelsUpdated()/1000.f << "K";
drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
voxelStats.str(""); voxelStats.str("");
voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() / 1000.f << "K (" << voxels.getVoxelsCreatedPerSecondAverage() / 1000.f voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() / 1000.f << "K (" << voxels.getVoxelsCreatedPerSecondAverage() / 1000.f
<< "Kps) "; << "Kps) ";
drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
voxelStats.str(""); voxelStats.str("");
voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() / 1000.f << "K (" << voxels.getVoxelsColoredPerSecondAverage() / 1000.f voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() / 1000.f << "K (" << voxels.getVoxelsColoredPerSecondAverage() / 1000.f
<< "Kps) "; << "Kps) ";
drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
voxelStats.str(""); voxelStats.str("");
voxelStats << "Voxel Bits Read: " << voxels.getVoxelsBytesRead() * 8.f / 1000000.f voxelStats << "Voxel Bits Read: " << voxels.getVoxelsBytesRead() * 8.f / 1000000.f
<< "M (" << voxels.getVoxelsBytesReadPerSecondAverage() * 8.f / 1000000.f << " Mbps)"; << "M (" << voxels.getVoxelsBytesReadPerSecondAverage() * 8.f / 1000000.f << " Mbps)";
drawtext(10, statsVerticalOffset + 290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); drawtext(10, statsVerticalOffset + 290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
voxelStats.str(""); voxelStats.str("");
float voxelsBytesPerColored = voxels.getVoxelsColored() float voxelsBytesPerColored = voxels.getVoxelsColored()
? ((float) voxels.getVoxelsBytesRead() / voxels.getVoxelsColored()) ? ((float) voxels.getVoxelsBytesRead() / voxels.getVoxelsColored())
: 0; : 0;
voxelStats << "Voxels Bits per Colored: " << voxelsBytesPerColored * 8; voxelStats << "Voxels Bits per Colored: " << voxelsBytesPerColored * 8;
drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER); Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
@ -276,19 +275,19 @@ void displayStats(void) {
drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, avatarMixerStats); drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, avatarMixerStats);
if (::perfStatsOn) { if (::perfStatsOn) {
// Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups // Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups
char** perfStatLinesArray = new char*[PerfStat::getGroupCount()+1]; char** perfStatLinesArray = new char*[PerfStat::getGroupCount()+1];
int lines = PerfStat::DumpStats(perfStatLinesArray); int lines = PerfStat::DumpStats(perfStatLinesArray);
int atZ = 150; // arbitrary place on screen that looks good int atZ = 150; // arbitrary place on screen that looks good
for (int line=0; line < lines; line++) { for (int line=0; line < lines; line++) {
drawtext(10, statsVerticalOffset + atZ, 0.10f, 0, 1.0, 0, perfStatLinesArray[line]); drawtext(10, statsVerticalOffset + atZ, 0.10f, 0, 1.0, 0, perfStatLinesArray[line]);
delete perfStatLinesArray[line]; // we're responsible for cleanup delete perfStatLinesArray[line]; // we're responsible for cleanup
perfStatLinesArray[line]=NULL; perfStatLinesArray[line]=NULL;
atZ+=20; // height of a line atZ+=20; // height of a line
} }
delete []perfStatLinesArray; // we're responsible for cleanup delete []perfStatLinesArray; // we're responsible for cleanup
} }
} }
void initDisplay(void) { void initDisplay(void) {
@ -321,9 +320,9 @@ void init(void) {
myAvatar.setNoise(noise); myAvatar.setNoise(noise);
} }
myAvatar.setPosition(start_location); myAvatar.setPosition(start_location);
myCamera.setPosition(start_location); myCamera.setPosition(start_location);
#ifdef MARKER_CAPTURE #ifdef MARKER_CAPTURE
if(marker_capture_enabled){ if(marker_capture_enabled){
marker_capturer.position_updated(&position_updated); marker_capturer.position_updated(&position_updated);
@ -472,25 +471,25 @@ void updateAvatar(float deltaTime) {
// If I'm in paint mode, send a voxel out to VOXEL server agents. // If I'm in paint mode, send a voxel out to VOXEL server agents.
if (::paintOn) { if (::paintOn) {
glm::vec3 avatarPos = myAvatar.getPosition(); glm::vec3 avatarPos = myAvatar.getPosition();
// For some reason, we don't want to flip X and Z here. // For some reason, we don't want to flip X and Z here.
::paintingVoxel.x = avatarPos.x / 10.0; ::paintingVoxel.x = avatarPos.x / 10.0;
::paintingVoxel.y = avatarPos.y / 10.0; ::paintingVoxel.y = avatarPos.y / 10.0;
::paintingVoxel.z = avatarPos.z / 10.0; ::paintingVoxel.z = avatarPos.z / 10.0;
unsigned char* bufferOut; unsigned char* bufferOut;
int sizeOut; int sizeOut;
if (::paintingVoxel.x >= 0.0 && ::paintingVoxel.x <= 1.0 && if (::paintingVoxel.x >= 0.0 && ::paintingVoxel.x <= 1.0 &&
::paintingVoxel.y >= 0.0 && ::paintingVoxel.y <= 1.0 && ::paintingVoxel.y >= 0.0 && ::paintingVoxel.y <= 1.0 &&
::paintingVoxel.z >= 0.0 && ::paintingVoxel.z <= 1.0) { ::paintingVoxel.z >= 0.0 && ::paintingVoxel.z <= 1.0) {
if (createVoxelEditMessage(PACKET_HEADER_SET_VOXEL, 0, 1, &::paintingVoxel, bufferOut, sizeOut)){ if (createVoxelEditMessage(PACKET_HEADER_SET_VOXEL, 0, 1, &::paintingVoxel, bufferOut, sizeOut)){
AgentList::getInstance()->broadcastToAgents(bufferOut, sizeOut, &AGENT_TYPE_VOXEL, 1); AgentList::getInstance()->broadcastToAgents(bufferOut, sizeOut, &AGENT_TYPE_VOXEL, 1);
delete bufferOut; delete bufferOut;
} }
} }
} }
} }
@ -498,7 +497,7 @@ void updateAvatar(float deltaTime) {
// loadViewFrustum() // loadViewFrustum()
// //
// Description: this will load the view frustum bounds for EITHER the head // Description: this will load the view frustum bounds for EITHER the head
// or the "myCamera". // or the "myCamera".
// //
// These global scoped variables are used by our loadViewFrustum() and renderViewFrustum functions below, but are also // These global scoped variables are used by our loadViewFrustum() and renderViewFrustum functions below, but are also
@ -515,19 +514,19 @@ float viewFrustumOffsetDistance = 25.0;
float viewFrustumOffsetUp = 0.0; float viewFrustumOffsetUp = 0.0;
void loadViewFrustum(ViewFrustum& viewFrustum) { void loadViewFrustum(ViewFrustum& viewFrustum) {
// We will use these below, from either the camera or head vectors calculated above // We will use these below, from either the camera or head vectors calculated above
glm::vec3 position; glm::vec3 position;
glm::vec3 direction; glm::vec3 direction;
glm::vec3 up; glm::vec3 up;
glm::vec3 right; glm::vec3 right;
float fov, nearClip, farClip; float fov, nearClip, farClip;
// Camera or Head? // Camera or Head?
if (::cameraFrustum) { if (::cameraFrustum) {
position = ::myCamera.getPosition(); position = ::myCamera.getPosition();
} else { } else {
position = ::myAvatar.getHeadPosition(); position = ::myAvatar.getHeadPosition();
} }
fov = ::myCamera.getFieldOfView(); fov = ::myCamera.getFieldOfView();
nearClip = ::myCamera.getNearClip(); nearClip = ::myCamera.getNearClip();
@ -550,7 +549,7 @@ void loadViewFrustum(ViewFrustum& viewFrustum) {
printf("farClip=%f\n", farClip); printf("farClip=%f\n", farClip);
*/ */
// Set the viewFrustum up with the correct position and orientation of the camera // Set the viewFrustum up with the correct position and orientation of the camera
viewFrustum.setPosition(position); viewFrustum.setPosition(position);
viewFrustum.setOrientation(direction,up,right); viewFrustum.setOrientation(direction,up,right);
@ -567,7 +566,7 @@ void loadViewFrustum(ViewFrustum& viewFrustum) {
// renderViewFrustum() // renderViewFrustum()
// //
// Description: this will render the view frustum bounds for EITHER the head // Description: this will render the view frustum bounds for EITHER the head
// or the "myCamera". // or the "myCamera".
// //
// Frustum rendering mode. For debug purposes, we allow drawing the frustum in a couple of different ways. // Frustum rendering mode. For debug purposes, we allow drawing the frustum in a couple of different ways.
// We can draw it with each of these parts: // We can draw it with each of these parts:
@ -594,102 +593,102 @@ void renderViewFrustum(ViewFrustum& viewFrustum) {
// Load it with the latest details! // Load it with the latest details!
loadViewFrustum(viewFrustum); loadViewFrustum(viewFrustum);
glm::vec3 position = viewFrustum.getPosition(); glm::vec3 position = viewFrustum.getPosition();
glm::vec3 direction = viewFrustum.getDirection(); glm::vec3 direction = viewFrustum.getDirection();
glm::vec3 up = viewFrustum.getUp(); glm::vec3 up = viewFrustum.getUp();
glm::vec3 right = viewFrustum.getRight(); glm::vec3 right = viewFrustum.getRight();
// Get ready to draw some lines // Get ready to draw some lines
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
glColor4f(1.0, 1.0, 1.0, 1.0); glColor4f(1.0, 1.0, 1.0, 1.0);
glLineWidth(1.0); glLineWidth(1.0);
glBegin(GL_LINES); glBegin(GL_LINES);
if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_VECTORS) { if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_VECTORS) {
// Calculate the origin direction vectors // Calculate the origin direction vectors
glm::vec3 lookingAt = position + (direction * 0.2f); glm::vec3 lookingAt = position + (direction * 0.2f);
glm::vec3 lookingAtUp = position + (up * 0.2f); glm::vec3 lookingAtUp = position + (up * 0.2f);
glm::vec3 lookingAtRight = position + (right * 0.2f); glm::vec3 lookingAtRight = position + (right * 0.2f);
// Looking At = white // Looking At = white
glColor3f(1,1,1); glColor3f(1,1,1);
glVertex3f(position.x, position.y, position.z); glVertex3f(position.x, position.y, position.z);
glVertex3f(lookingAt.x, lookingAt.y, lookingAt.z); glVertex3f(lookingAt.x, lookingAt.y, lookingAt.z);
// Looking At Up = purple // Looking At Up = purple
glColor3f(1,0,1); glColor3f(1,0,1);
glVertex3f(position.x, position.y, position.z); glVertex3f(position.x, position.y, position.z);
glVertex3f(lookingAtUp.x, lookingAtUp.y, lookingAtUp.z); glVertex3f(lookingAtUp.x, lookingAtUp.y, lookingAtUp.z);
// Looking At Right = cyan // Looking At Right = cyan
glColor3f(0,1,1); glColor3f(0,1,1);
glVertex3f(position.x, position.y, position.z); glVertex3f(position.x, position.y, position.z);
glVertex3f(lookingAtRight.x, lookingAtRight.y, lookingAtRight.z); glVertex3f(lookingAtRight.x, lookingAtRight.y, lookingAtRight.z);
} }
if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES
|| ::frustumDrawingMode == FRUSTUM_DRAW_MODE_NEAR_PLANE) { || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_NEAR_PLANE) {
// Drawing the bounds of the frustum // Drawing the bounds of the frustum
// viewFrustum.getNear plane - bottom edge // viewFrustum.getNear plane - bottom edge
glColor3f(1,0,0); glColor3f(1,0,0);
glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z); glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z);
glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z); glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z);
// viewFrustum.getNear plane - top edge // viewFrustum.getNear plane - top edge
glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z); glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z);
glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z); glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z);
// viewFrustum.getNear plane - right edge // viewFrustum.getNear plane - right edge
glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z); glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z);
glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z); glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z);
// viewFrustum.getNear plane - left edge // viewFrustum.getNear plane - left edge
glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z); glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z);
glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z); glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z);
} }
if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES
|| ::frustumDrawingMode == FRUSTUM_DRAW_MODE_FAR_PLANE) { || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_FAR_PLANE) {
// viewFrustum.getFar plane - bottom edge // viewFrustum.getFar plane - bottom edge
glColor3f(0,1,0); // GREEN!!! glColor3f(0,1,0); // GREEN!!!
glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z); glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z);
glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z); glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z);
// viewFrustum.getFar plane - top edge // viewFrustum.getFar plane - top edge
glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z); glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z);
glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z); glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z);
// viewFrustum.getFar plane - right edge // viewFrustum.getFar plane - right edge
glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z); glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z);
glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z); glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z);
// viewFrustum.getFar plane - left edge // viewFrustum.getFar plane - left edge
glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z); glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z);
glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z); glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z);
} }
if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES) { if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES) {
// RIGHT PLANE IS CYAN // RIGHT PLANE IS CYAN
// right plane - bottom edge - viewFrustum.getNear to distant // right plane - bottom edge - viewFrustum.getNear to distant
glColor3f(0,1,1); glColor3f(0,1,1);
glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z); glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z);
glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z); glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z);
// right plane - top edge - viewFrustum.getNear to distant // right plane - top edge - viewFrustum.getNear to distant
glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z); glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z);
glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z); glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z);
// LEFT PLANE IS BLUE // LEFT PLANE IS BLUE
// left plane - bottom edge - viewFrustum.getNear to distant // left plane - bottom edge - viewFrustum.getNear to distant
glColor3f(0,0,1); glColor3f(0,0,1);
glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z); glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z);
glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z); glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z);
// left plane - top edge - viewFrustum.getNear to distant // left plane - top edge - viewFrustum.getNear to distant
glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z); glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z);
glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z); glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z);
} }
glEnd(); glEnd();
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
@ -716,7 +715,7 @@ void displaySide(Camera& whichCamera) {
} }
// finally render the starfield // finally render the starfield
stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip(), alpha); stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip(), alpha);
} }
// draw the sky dome // draw the sky dome
@ -727,8 +726,8 @@ void displaySide(Camera& whichCamera) {
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
// draw a red sphere // draw a red sphere
float sphereRadius = 0.25f; float sphereRadius = 0.25f;
glColor3f(1,0,0); glColor3f(1,0,0);
glPushMatrix(); glPushMatrix();
glutSolidSphere(sphereRadius, 15, 15); glutSolidSphere(sphereRadius, 15, 15);
@ -736,12 +735,12 @@ void displaySide(Camera& whichCamera) {
//draw a grid ground plane.... //draw a grid ground plane....
drawGroundPlaneGrid(10.f); drawGroundPlaneGrid(10.f);
// Draw voxels // Draw voxels
if (renderVoxels) { if (renderVoxels) {
voxels.render(); voxels.render();
} }
if (::renderAvatarsOn) { if (::renderAvatarsOn) {
// Render avatars of other agents // Render avatars of other agents
AgentList* agentList = AgentList::getInstance(); AgentList* agentList = AgentList::getInstance();
@ -763,8 +762,8 @@ void displaySide(Camera& whichCamera) {
// brad's frustum for debugging // brad's frustum for debugging
if (::frustumOn) renderViewFrustum(::viewFrustum); if (::frustumOn) renderViewFrustum(::viewFrustum);
glPopMatrix(); glPopMatrix();
} }
// this shader is an adaptation (HLSL -> GLSL, removed conditional) of the one in the Oculus sample // this shader is an adaptation (HLSL -> GLSL, removed conditional) of the one in the Oculus sample
@ -986,11 +985,11 @@ void displayOverlay() {
if (::paintOn) { if (::paintOn) {
char paintMessage[100]; char paintMessage[100];
sprintf(paintMessage,"Painting (%.3f,%.3f,%.3f/%.3f/%d,%d,%d)", sprintf(paintMessage,"Painting (%.3f,%.3f,%.3f/%.3f/%d,%d,%d)",
::paintingVoxel.x,::paintingVoxel.y,::paintingVoxel.z,::paintingVoxel.s, ::paintingVoxel.x,::paintingVoxel.y,::paintingVoxel.z,::paintingVoxel.s,
(unsigned int)::paintingVoxel.red,(unsigned int)::paintingVoxel.green,(unsigned int)::paintingVoxel.blue); (unsigned int)::paintingVoxel.red,(unsigned int)::paintingVoxel.green,(unsigned int)::paintingVoxel.blue);
drawtext(WIDTH-350,50, 0.10, 0, 1.0, 0, paintMessage, 1, 1, 0); drawtext(WIDTH-350,50, 0.10, 0, 1.0, 0, paintMessage, 1, 1, 0);
} }
glPopMatrix(); glPopMatrix();
@ -998,7 +997,7 @@ void displayOverlay() {
void display(void) void display(void)
{ {
PerfStat("display"); PerfStat("display");
glEnable(GL_LINE_SMOOTH); glEnable(GL_LINE_SMOOTH);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -1007,22 +1006,6 @@ void display(void)
glPushMatrix(); { glPushMatrix(); {
glLoadIdentity(); glLoadIdentity();
// Setup 3D lights
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
GLfloat light_position0[] = { 1.0, 1.0, 0.0, 0.0 };
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
GLfloat ambient_color[] = { 0.7, 0.7, 0.8 };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color);
GLfloat diffuse_color[] = { 0.8, 0.7, 0.7 };
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color);
GLfloat specular_color[] = { 1.0, 1.0, 1.0, 1.0};
glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color);
glMateriali(GL_FRONT, GL_SHININESS, 96);
// camera settings // camera settings
if (::lookingInMirror) { if (::lookingInMirror) {
// set the camera to looking at my own face // set the camera to looking at my own face
@ -1030,10 +1013,10 @@ void display(void)
myCamera.setTargetYaw (myAvatar.getBodyYaw() - 180.0f); // 180 degrees from body yaw myCamera.setTargetYaw (myAvatar.getBodyYaw() - 180.0f); // 180 degrees from body yaw
myCamera.setPitch (0.0); myCamera.setPitch (0.0);
myCamera.setRoll (0.0); myCamera.setRoll (0.0);
myCamera.setUpShift (0.0); myCamera.setUpShift (0.0);
myCamera.setDistance (0.2); myCamera.setDistance (0.2);
myCamera.setTightness (100.0f); myCamera.setTightness (100.0f);
} else { } else {
//float firstPersonPitch = 20.0f; //float firstPersonPitch = 20.0f;
//float firstPersonUpShift = 0.0f; //float firstPersonUpShift = 0.0f;
@ -1063,7 +1046,7 @@ void display(void)
} }
} }
myCamera.setPitch (thirdPersonPitch + ff * (firstPersonPitch - thirdPersonPitch )); myCamera.setPitch (thirdPersonPitch + ff * (firstPersonPitch - thirdPersonPitch ));
myCamera.setUpShift (thirdPersonUpShift + ff * (firstPersonUpShift - thirdPersonUpShift )); myCamera.setUpShift (thirdPersonUpShift + ff * (firstPersonUpShift - thirdPersonUpShift ));
myCamera.setDistance (thirdPersonDistance + ff * (firstPersonDistance - thirdPersonDistance )); myCamera.setDistance (thirdPersonDistance + ff * (firstPersonDistance - thirdPersonDistance ));
myCamera.setTightness (thirdPersonTightness + ff * (firstPersonTightness - thirdPersonTightness)); myCamera.setTightness (thirdPersonTightness + ff * (firstPersonTightness - thirdPersonTightness));
@ -1077,7 +1060,7 @@ void display(void)
} }
//printf("myCamera.getModeShift() = %f\n", myCamera.getModeShift()); //printf("myCamera.getModeShift() = %f\n", myCamera.getModeShift());
myCamera.setPitch (thirdPersonPitch + myCamera.getModeShift() * (firstPersonPitch - thirdPersonPitch )); myCamera.setPitch (thirdPersonPitch + myCamera.getModeShift() * (firstPersonPitch - thirdPersonPitch ));
myCamera.setUpShift (thirdPersonUpShift + myCamera.getModeShift() * (firstPersonUpShift - thirdPersonUpShift )); myCamera.setUpShift (thirdPersonUpShift + myCamera.getModeShift() * (firstPersonUpShift - thirdPersonUpShift ));
myCamera.setDistance (thirdPersonDistance + myCamera.getModeShift() * (firstPersonDistance - thirdPersonDistance )); myCamera.setDistance (thirdPersonDistance + myCamera.getModeShift() * (firstPersonDistance - thirdPersonDistance ));
myCamera.setTightness (thirdPersonTightness + myCamera.getModeShift() * (firstPersonTightness - thirdPersonTightness)); myCamera.setTightness (thirdPersonTightness + myCamera.getModeShift() * (firstPersonTightness - thirdPersonTightness));
@ -1087,7 +1070,7 @@ void display(void)
} }
//printf("myCamera.getModeShift() = %f\n", myCamera.getModeShift()); //printf("myCamera.getModeShift() = %f\n", myCamera.getModeShift());
myCamera.setPitch (firstPersonPitch + myCamera.getModeShift() * (thirdPersonPitch - firstPersonPitch )); myCamera.setPitch (firstPersonPitch + myCamera.getModeShift() * (thirdPersonPitch - firstPersonPitch ));
myCamera.setUpShift (firstPersonUpShift + myCamera.getModeShift() * (thirdPersonUpShift - firstPersonUpShift )); myCamera.setUpShift (firstPersonUpShift + myCamera.getModeShift() * (thirdPersonUpShift - firstPersonUpShift ));
myCamera.setDistance (firstPersonDistance + myCamera.getModeShift() * (thirdPersonDistance - firstPersonDistance )); myCamera.setDistance (firstPersonDistance + myCamera.getModeShift() * (thirdPersonDistance - firstPersonDistance ));
myCamera.setTightness (firstPersonTightness + myCamera.getModeShift() * (thirdPersonTightness - firstPersonTightness)); myCamera.setTightness (firstPersonTightness + myCamera.getModeShift() * (thirdPersonTightness - firstPersonTightness));
@ -1104,7 +1087,7 @@ void display(void)
myCamera.setTargetPosition(myAvatar.getHeadPosition()); myCamera.setTargetPosition(myAvatar.getHeadPosition());
myCamera.setTargetYaw (myAvatar.getBodyYaw()); myCamera.setTargetYaw (myAvatar.getBodyYaw());
myCamera.setRoll (0.0); myCamera.setRoll (0.0);
} }
// important... // important...
@ -1120,19 +1103,19 @@ void display(void)
glPopMatrix(); glPopMatrix();
*/ */
// Note: whichCamera is used to pick between the normal camera myCamera for our // Note: whichCamera is used to pick between the normal camera myCamera for our
// main camera, vs, an alternate camera. The alternate camera we support right now // main camera, vs, an alternate camera. The alternate camera we support right now
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism // is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
// to add other cameras. // to add other cameras.
// //
// Why have two cameras? Well, one reason is that because in the case of the renderViewFrustum() // Why have two cameras? Well, one reason is that because in the case of the renderViewFrustum()
// code, we want to keep the state of "myCamera" intact, so we can render what the view frustum of // code, we want to keep the state of "myCamera" intact, so we can render what the view frustum of
// myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera // myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera
Camera whichCamera = myCamera; Camera whichCamera = myCamera;
Camera viewFrustumOffsetCamera = myCamera; Camera viewFrustumOffsetCamera = myCamera;
if (::viewFrustumFromOffset && ::frustumOn) { if (::viewFrustumFromOffset && ::frustumOn) {
// set the camera to third-person view but offset so we can see the frustum // set the camera to third-person view but offset so we can see the frustum
viewFrustumOffsetCamera.setTargetYaw(::viewFrustumOffsetYaw + myAvatar.getBodyYaw()); viewFrustumOffsetCamera.setTargetYaw(::viewFrustumOffsetYaw + myAvatar.getBodyYaw());
@ -1142,19 +1125,35 @@ void display(void)
viewFrustumOffsetCamera.setDistance (::viewFrustumOffsetDistance); viewFrustumOffsetCamera.setDistance (::viewFrustumOffsetDistance);
viewFrustumOffsetCamera.update(1.f/FPS); viewFrustumOffsetCamera.update(1.f/FPS);
whichCamera = viewFrustumOffsetCamera; whichCamera = viewFrustumOffsetCamera;
} }
// transform view according to whichCamera // transform view according to whichCamera
// could be myCamera (if in normal mode) // could be myCamera (if in normal mode)
// or could be viewFrustumOffsetCamera if in offset mode // or could be viewFrustumOffsetCamera if in offset mode
// I changed the ordering here - roll is FIRST (JJV) // I changed the ordering here - roll is FIRST (JJV)
glRotatef ( whichCamera.getRoll(), IDENTITY_FRONT.x, IDENTITY_FRONT.y, IDENTITY_FRONT.z); glRotatef ( whichCamera.getRoll(), IDENTITY_FRONT.x, IDENTITY_FRONT.y, IDENTITY_FRONT.z);
glRotatef ( whichCamera.getPitch(), IDENTITY_RIGHT.x, IDENTITY_RIGHT.y, IDENTITY_RIGHT.z); glRotatef ( whichCamera.getPitch(), IDENTITY_RIGHT.x, IDENTITY_RIGHT.y, IDENTITY_RIGHT.z);
glRotatef (180.0 - whichCamera.getYaw(), IDENTITY_UP.x, IDENTITY_UP.y, IDENTITY_UP.z ); glRotatef (180.0 - whichCamera.getYaw(), IDENTITY_UP.x, IDENTITY_UP.y, IDENTITY_UP.z );
glTranslatef(-whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z); glTranslatef(-whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z);
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
GLfloat light_position0[] = { 1.0, 1.0, 0.0, 0.0 };
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
GLfloat ambient_color[] = { 0.7, 0.7, 0.8 };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color);
GLfloat diffuse_color[] = { 0.8, 0.7, 0.7 };
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color);
GLfloat specular_color[] = { 1.0, 1.0, 1.0, 1.0};
glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color);
glMateriali(GL_FRONT, GL_SHININESS, 96);
if (::oculusOn) { if (::oculusOn) {
displayOculus(whichCamera); displayOculus(whichCamera);
@ -1312,7 +1311,7 @@ int quitApp(int state) {
int setFrustumRenderMode(int state) { int setFrustumRenderMode(int state) {
if (state == MENU_ROW_PICKED) { if (state == MENU_ROW_PICKED) {
::frustumDrawingMode = (::frustumDrawingMode+1)%FRUSTUM_DRAW_MODE_COUNT; ::frustumDrawingMode = (::frustumDrawingMode+1)%FRUSTUM_DRAW_MODE_COUNT;
} }
return ::frustumDrawingMode; return ::frustumDrawingMode;
} }
@ -1369,25 +1368,25 @@ const char* modeNear = " - Near ";
const char* modeFar = " - Far "; const char* modeFar = " - Far ";
const char* getFrustumRenderModeName(int state) { const char* getFrustumRenderModeName(int state) {
const char * mode; const char * mode;
switch (state) { switch (state) {
case FRUSTUM_DRAW_MODE_ALL: case FRUSTUM_DRAW_MODE_ALL:
mode = modeAll; mode = modeAll;
break; break;
case FRUSTUM_DRAW_MODE_VECTORS: case FRUSTUM_DRAW_MODE_VECTORS:
mode = modeVectors; mode = modeVectors;
break; break;
case FRUSTUM_DRAW_MODE_PLANES: case FRUSTUM_DRAW_MODE_PLANES:
mode = modePlanes; mode = modePlanes;
break; break;
case FRUSTUM_DRAW_MODE_NEAR_PLANE: case FRUSTUM_DRAW_MODE_NEAR_PLANE:
mode = modeNear; mode = modeNear;
break; break;
case FRUSTUM_DRAW_MODE_FAR_PLANE: case FRUSTUM_DRAW_MODE_FAR_PLANE:
mode = modeFar; mode = modeFar;
break; break;
} }
return mode; return mode;
} }
void initMenu() { void initMenu() {
@ -1433,55 +1432,117 @@ void initMenu() {
} }
void testPointToVoxel() { void testPointToVoxel() {
float y=0; float y=0;
float z=0; float z=0;
float s=0.1; float s=0.1;
for (float x=0; x<=1; x+= 0.05) { for (float x=0; x<=1; x+= 0.05) {
printLog(" x=%f"); printLog(" x=%f");
unsigned char red = 200; //randomColorValue(65); unsigned char red = 200; //randomColorValue(65);
unsigned char green = 200; //randomColorValue(65); unsigned char green = 200; //randomColorValue(65);
unsigned char blue = 200; //randomColorValue(65); unsigned char blue = 200; //randomColorValue(65);
unsigned char* voxelCode = pointToVoxel(x, y, z, s,red,green,blue); unsigned char* voxelCode = pointToVoxel(x, y, z, s,red,green,blue);
printVoxelCode(voxelCode); printVoxelCode(voxelCode);
delete voxelCode; delete voxelCode;
printLog("\n"); printLog("\n");
} }
} }
void sendVoxelServerEraseAll() { void sendVoxelServerEraseAll() {
char message[100]; char message[100];
sprintf(message,"%c%s",'Z',"erase all"); sprintf(message,"%c%s",'Z',"erase all");
int messageSize = strlen(message) + 1; int messageSize = strlen(message) + 1;
AgentList::getInstance()->broadcastToAgents((unsigned char*) message, messageSize, &AGENT_TYPE_VOXEL, 1); AgentList::getInstance()->broadcastToAgents((unsigned char*) message, messageSize, &AGENT_TYPE_VOXEL, 1);
} }
void sendVoxelServerAddScene() { void sendVoxelServerAddScene() {
char message[100]; char message[100];
sprintf(message,"%c%s",'Z',"add scene"); sprintf(message,"%c%s",'Z',"add scene");
int messageSize = strlen(message) + 1; int messageSize = strlen(message) + 1;
AgentList::getInstance()->broadcastToAgents((unsigned char*)message, messageSize, &AGENT_TYPE_VOXEL, 1); AgentList::getInstance()->broadcastToAgents((unsigned char*)message, messageSize, &AGENT_TYPE_VOXEL, 1);
} }
void shiftPaintingColor() void shiftPaintingColor()
{ {
// About the color of the paintbrush... first determine the dominant color // About the color of the paintbrush... first determine the dominant color
::dominantColor = (::dominantColor+1)%3; // 0=red,1=green,2=blue ::dominantColor = (::dominantColor+1)%3; // 0=red,1=green,2=blue
::paintingVoxel.red = (::dominantColor==0)?randIntInRange(200,255):randIntInRange(40,100); ::paintingVoxel.red = (::dominantColor==0)?randIntInRange(200,255):randIntInRange(40,100);
::paintingVoxel.green = (::dominantColor==1)?randIntInRange(200,255):randIntInRange(40,100); ::paintingVoxel.green = (::dominantColor==1)?randIntInRange(200,255):randIntInRange(40,100);
::paintingVoxel.blue = (::dominantColor==2)?randIntInRange(200,255):randIntInRange(40,100); ::paintingVoxel.blue = (::dominantColor==2)?randIntInRange(200,255):randIntInRange(40,100);
} }
void setupPaintingVoxel() { void setupPaintingVoxel() {
glm::vec3 avatarPos = myAvatar.getPosition(); glm::vec3 avatarPos = myAvatar.getPosition();
::paintingVoxel.x = avatarPos.z/-10.0; // voxel space x is negative z head space ::paintingVoxel.x = avatarPos.z/-10.0; // voxel space x is negative z head space
::paintingVoxel.y = avatarPos.y/-10.0; // voxel space y is negative y head space ::paintingVoxel.y = avatarPos.y/-10.0; // voxel space y is negative y head space
::paintingVoxel.z = avatarPos.x/-10.0; // voxel space z is negative x head space ::paintingVoxel.z = avatarPos.x/-10.0; // voxel space z is negative x head space
::paintingVoxel.s = 1.0/256; ::paintingVoxel.s = 1.0/256;
shiftPaintingColor(); shiftPaintingColor();
}
void addVoxelUnderCursor() {
glm::vec3 origin, direction;
viewFrustum.computePickRay(mouseX / (float)WIDTH, mouseY / (float)HEIGHT, origin, direction);
VoxelDetail detail;
float distance;
BoxFace face;
if (voxels.findRayIntersection(origin, direction, detail, distance, face)) {
// use the face to determine the side on which to create a neighbor
switch (face) {
case MIN_X_FACE:
detail.x -= detail.s;
break;
case MAX_X_FACE:
detail.x += detail.s;
break;
case MIN_Y_FACE:
detail.y -= detail.s;
break;
case MAX_Y_FACE:
detail.y += detail.s;
break;
case MIN_Z_FACE:
detail.z -= detail.s;
break;
case MAX_Z_FACE:
detail.z += detail.s;
break;
}
unsigned char* bufferOut;
int sizeOut;
if (createVoxelEditMessage(PACKET_HEADER_SET_VOXEL, 0, 1, &detail, bufferOut, sizeOut)){
AgentList::getInstance()->broadcastToAgents(bufferOut, sizeOut, &AGENT_TYPE_VOXEL, 1);
delete bufferOut;
}
}
}
void deleteVoxelUnderCursor() {
glm::vec3 origin, direction;
viewFrustum.computePickRay(mouseX / (float)WIDTH, mouseY / (float)HEIGHT, origin, direction);
VoxelDetail detail;
float distance;
BoxFace face;
if (voxels.findRayIntersection(origin, direction, detail, distance, face)) {
unsigned char* bufferOut;
int sizeOut;
if (createVoxelEditMessage(PACKET_HEADER_ERASE_VOXEL, 0, 1, &detail, bufferOut, sizeOut)){
AgentList::getInstance()->broadcastToAgents(bufferOut, sizeOut, &AGENT_TYPE_VOXEL, 1);
delete bufferOut;
}
}
} }
const float KEYBOARD_YAW_RATE = 0.8; const float KEYBOARD_YAW_RATE = 0.8;
@ -1566,42 +1627,44 @@ void key(unsigned char k, int x, int y) {
return; return;
} }
// Process keypresses // Process keypresses
if (k == 'q' || k == 'Q') ::terminate(); if (k == 'q' || k == 'Q') ::terminate();
if (k == '/') ::renderStatsOn = !::renderStatsOn; // toggle stats if (k == '/') ::renderStatsOn = !::renderStatsOn; // toggle stats
if (k == '*') ::renderStarsOn = !::renderStarsOn; // toggle stars if (k == '*') ::renderStarsOn = !::renderStarsOn; // toggle stars
if (k == 'V' || k == 'v') ::renderVoxels = !::renderVoxels; // toggle voxels if (k == 'V' || k == 'v') ::renderVoxels = !::renderVoxels; // toggle voxels
if (k == 'A') ::renderAtmosphereOn = !::renderAtmosphereOn; if (k == 'A') ::renderAtmosphereOn = !::renderAtmosphereOn;
if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging
if (k == 'C') ::cameraFrustum = !::cameraFrustum; // toggle which frustum to look at 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 if (k == 'O' || k == 'G') setFrustumOffset(MENU_ROW_PICKED); // toggle view frustum offset debugging
if (k == 'f') setFullscreen(!::fullscreen); if (k == 'f') setFullscreen(!::fullscreen);
if (k == 'o') setOculus(!::oculusOn); if (k == 'o') setOculus(!::oculusOn);
if (k == '[') ::viewFrustumOffsetYaw -= 0.5; if (k == '[') ::viewFrustumOffsetYaw -= 0.5;
if (k == ']') ::viewFrustumOffsetYaw += 0.5; if (k == ']') ::viewFrustumOffsetYaw += 0.5;
if (k == '{') ::viewFrustumOffsetPitch -= 0.5; if (k == '{') ::viewFrustumOffsetPitch -= 0.5;
if (k == '}') ::viewFrustumOffsetPitch += 0.5; if (k == '}') ::viewFrustumOffsetPitch += 0.5;
if (k == '(') ::viewFrustumOffsetRoll -= 0.5; if (k == '(') ::viewFrustumOffsetRoll -= 0.5;
if (k == ')') ::viewFrustumOffsetRoll += 0.5; if (k == ')') ::viewFrustumOffsetRoll += 0.5;
if (k == '<') ::viewFrustumOffsetDistance -= 0.5; if (k == '<') ::viewFrustumOffsetDistance -= 0.5;
if (k == '>') ::viewFrustumOffsetDistance += 0.5; if (k == '>') ::viewFrustumOffsetDistance += 0.5;
if (k == ',') ::viewFrustumOffsetUp -= 0.05; if (k == ',') ::viewFrustumOffsetUp -= 0.05;
if (k == '.') ::viewFrustumOffsetUp += 0.05; if (k == '.') ::viewFrustumOffsetUp += 0.05;
// if (k == '|') ViewFrustum::fovAngleAdust -= 0.05; // if (k == '|') ViewFrustum::fovAngleAdust -= 0.05;
// if (k == '\\') ViewFrustum::fovAngleAdust += 0.05; // if (k == '\\') ViewFrustum::fovAngleAdust += 0.05;
if (k == 'R') setFrustumRenderMode(MENU_ROW_PICKED); if (k == 'R') setFrustumRenderMode(MENU_ROW_PICKED);
if (k == '&') { if (k == '&') {
::paintOn = !::paintOn; // toggle paint ::paintOn = !::paintOn; // toggle paint
::setupPaintingVoxel(); // also randomizes colors ::setupPaintingVoxel(); // also randomizes colors
} }
if (k == '^') ::shiftPaintingColor(); // shifts randomize color between R,G,B dominant if (k == '^') ::shiftPaintingColor(); // shifts randomize color between R,G,B dominant
if (k == '-') ::sendVoxelServerEraseAll(); // sends erase all command to voxel server if (k == '-') ::sendVoxelServerEraseAll(); // sends erase all command to voxel server
if (k == '%') ::sendVoxelServerAddScene(); // sends add scene command to voxel server if (k == '%') ::sendVoxelServerAddScene(); // sends add scene command to voxel server
if (k == 'n' || k == 'N') if (k == '1') ::addVoxelUnderCursor();
if (k == '2') ::deleteVoxelUnderCursor();
if (k == 'n' || k == 'N')
{ {
noiseOn = !noiseOn; // Toggle noise noiseOn = !noiseOn; // Toggle noise
if (noiseOn) if (noiseOn)
@ -1695,15 +1758,15 @@ void idle(void) {
// Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time // Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time
if (diffclock(&lastTimeIdle, &check) > IDLE_SIMULATE_MSECS) { if (diffclock(&lastTimeIdle, &check) > IDLE_SIMULATE_MSECS) {
float deltaTime = 1.f/FPS; float deltaTime = 1.f/FPS;
// update behaviors for avatar hand movement: handControl takes mouse values as input, // update behaviors for avatar hand movement: handControl takes mouse values as input,
// and gives back 3D values modulated for smooth transitioning between interaction modes. // and gives back 3D values modulated for smooth transitioning between interaction modes.
handControl.update(mouseX, mouseY); handControl.update(mouseX, mouseY);
myAvatar.setHandMovementValues(handControl.getValues()); myAvatar.setHandMovementValues(handControl.getValues());
// tell my avatar if the mouse is being pressed... // tell my avatar if the mouse is being pressed...
if (mousePressed) { if (mousePressed) {
myAvatar.setMousePressed(mousePressed); myAvatar.setMousePressed(mousePressed);
} }
@ -1711,7 +1774,7 @@ void idle(void) {
// walking triggers the handControl to stop // walking triggers the handControl to stop
if (myAvatar.getMode() == AVATAR_MODE_WALKING) { if (myAvatar.getMode() == AVATAR_MODE_WALKING) {
handControl.stop(); handControl.stop();
} }
// Read serial port interface devices // Read serial port interface devices
if (serialPort.active && USING_INVENSENSE_MPU9150) { if (serialPort.active && USING_INVENSENSE_MPU9150) {
@ -1724,8 +1787,8 @@ void idle(void) {
// read incoming packets from network // read incoming packets from network
if (!enableNetworkThread) { if (!enableNetworkThread) {
networkReceive(0); networkReceive(0);
} }
//loop through all the remote avatars and simulate them... //loop through all the remote avatars and simulate them...
AgentList* agentList = AgentList::getInstance(); AgentList* agentList = AgentList::getInstance();
agentList->lock(); agentList->lock();
@ -1836,19 +1899,19 @@ void mouseFunc(int button, int state, int x, int y) {
mouseY = y; mouseY = y;
mousePressed = 0; mousePressed = 0;
} }
} }
} }
void motionFunc(int x, int y) { void motionFunc(int x, int y) {
mouseX = x; mouseX = x;
mouseY = y; mouseY = y;
} }
void mouseoverFunc(int x, int y){ void mouseoverFunc(int x, int y){
menu.mouseOver(x, y); menu.mouseOver(x, y);
mouseX = x; mouseX = x;
mouseY = y; mouseY = y;
} }
void attachNewHeadToAgent(Agent *newAgent) { void attachNewHeadToAgent(Agent *newAgent) {
@ -1884,14 +1947,14 @@ int main(int argc, const char * argv[]) {
gettimeofday(&applicationStartupTime, NULL); gettimeofday(&applicationStartupTime, NULL);
const char* domainIP = getCmdOption(argc, argv, "--domain"); const char* domainIP = getCmdOption(argc, argv, "--domain");
if (domainIP) { if (domainIP) {
strcpy(DOMAIN_IP,domainIP); strcpy(DOMAIN_IP,domainIP);
} }
// Handle Local Domain testing with the --local command line // Handle Local Domain testing with the --local command line
if (cmdOptionExists(argc, argv, "--local")) { if (cmdOptionExists(argc, argv, "--local")) {
printLog("Local Domain MODE!\n"); printLog("Local Domain MODE!\n");
int ip = getLocalAddress(); int ip = getLocalAddress();
sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
} }
// the callback for our instance of AgentList is attachNewHeadToAgent // the callback for our instance of AgentList is attachNewHeadToAgent
@ -1940,30 +2003,30 @@ int main(int argc, const char * argv[]) {
glutDisplayFunc(display); glutDisplayFunc(display);
glutReshapeFunc(reshape); glutReshapeFunc(reshape);
glutKeyboardFunc(key); glutKeyboardFunc(key);
glutKeyboardUpFunc(keyUp); glutKeyboardUpFunc(keyUp);
glutSpecialFunc(specialkey); glutSpecialFunc(specialkey);
glutSpecialUpFunc(specialkeyUp); glutSpecialUpFunc(specialkeyUp);
glutMotionFunc(motionFunc); glutMotionFunc(motionFunc);
glutPassiveMotionFunc(mouseoverFunc); glutPassiveMotionFunc(mouseoverFunc);
glutMouseFunc(mouseFunc); glutMouseFunc(mouseFunc);
glutIdleFunc(idle); glutIdleFunc(idle);
init(); init();
printLog( "Init() complete.\n" ); printLog( "Init() complete.\n" );
// Check to see if the user passed in a command line option for randomizing colors // Check to see if the user passed in a command line option for randomizing colors
if (cmdOptionExists(argc, argv, "--NoColorRandomizer")) { if (cmdOptionExists(argc, argv, "--NoColorRandomizer")) {
wantColorRandomizer = false; wantColorRandomizer = false;
} }
// Check to see if the user passed in a command line option for loading a local // Check to see if the user passed in a command line option for loading a local
// Voxel File. If so, load it now. // Voxel File. If so, load it now.
const char* voxelsFilename = getCmdOption(argc, argv, "-i"); const char* voxelsFilename = getCmdOption(argc, argv, "-i");
if (voxelsFilename) { if (voxelsFilename) {
voxels.loadVoxelsFile(voxelsFilename,wantColorRandomizer); voxels.loadVoxelsFile(voxelsFilename,wantColorRandomizer);
printLog("Local Voxel File loaded.\n"); printLog("Local Voxel File loaded.\n");
} }
// create thread for receipt of data via UDP // create thread for receipt of data via UDP
if (enableNetworkThread) { if (enableNetworkThread) {

View file

@ -1,28 +0,0 @@
//
// Stacktrace.cpp
// hifi
//
// Created by Stephen Birarda on 5/6/13.
//
//
#include <signal.h>
#include <stdio.h>
#include <execinfo.h>
#include <cstdlib>
#include "Stacktrace.h"
const int NUMBER_OF_STACK_ENTRIES = 20;
void printStacktrace(int signal) {
void* array[NUMBER_OF_STACK_ENTRIES];
// get void*'s for all entries on the stack
size_t size = backtrace(array, NUMBER_OF_STACK_ENTRIES);
// print out all the frames to stderr
fprintf(stderr, "Error: signal %d:\n", signal);
backtrace_symbols_fd(array, size, 2);
exit(1);
}

View file

@ -1,16 +0,0 @@
//
// Stacktrace.h
// hifi
//
// Created by Stephen Birarda on 5/6/13.
//
//
#ifndef __hifi__Stacktrace__
#define __hifi__Stacktrace__
#include <iostream>
void printStacktrace(int signal);
#endif /* defined(__hifi__Stacktrace__) */

View file

@ -95,7 +95,7 @@ static bool findIntersection(float origin, float direction, float corner, float
return false; return false;
} }
bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const {
// handle the trivial case where the box contains the origin // handle the trivial case where the box contains the origin
if (contains(origin)) { if (contains(origin)) {
distance = 0; distance = 0;
@ -105,14 +105,23 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
float axisDistance; float axisDistance;
if ((findIntersection(origin.x, direction.x, _corner.x, _size.x, axisDistance) && axisDistance >= 0 && if ((findIntersection(origin.x, direction.x, _corner.x, _size.x, axisDistance) && axisDistance >= 0 &&
isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) && isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) &&
isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z)) || isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z))) {
(findIntersection(origin.y, direction.y, _corner.y, _size.y, axisDistance) && axisDistance >= 0 && distance = axisDistance;
face = direction.x > 0 ? MIN_X_FACE : MAX_X_FACE;
return true;
}
if ((findIntersection(origin.y, direction.y, _corner.y, _size.y, axisDistance) && axisDistance >= 0 &&
isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x) && isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x) &&
isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z)) || isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z))) {
(findIntersection(origin.z, direction.z, _corner.z, _size.z, axisDistance) && axisDistance >= 0 && distance = axisDistance;
face = direction.y > 0 ? MIN_Y_FACE : MAX_Y_FACE;
return true;
}
if ((findIntersection(origin.z, direction.z, _corner.z, _size.z, axisDistance) && axisDistance >= 0 &&
isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) && isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) &&
isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x))) { isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x))) {
distance = axisDistance; distance = axisDistance;
face = direction.z > 0 ? MIN_Z_FACE : MAX_Z_FACE;
return true; return true;
} }
return false; return false;

View file

@ -13,6 +13,15 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
enum BoxFace {
MIN_X_FACE,
MAX_X_FACE,
MIN_Y_FACE,
MAX_Y_FACE,
MIN_Z_FACE,
MAX_Z_FACE
};
class AABox class AABox
{ {
@ -37,7 +46,7 @@ public:
const glm::vec3& getCenter() const { return _center; }; const glm::vec3& getCenter() const { return _center; };
bool contains(const glm::vec3& point) const; bool contains(const glm::vec3& point) const;
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
private: private:
glm::vec3 _corner; glm::vec3 _corner;

View file

@ -605,6 +605,7 @@ public:
glm::vec3 direction; glm::vec3 direction;
VoxelNode*& node; VoxelNode*& node;
float& distance; float& distance;
BoxFace& face;
bool found; bool found;
}; };
@ -612,7 +613,8 @@ bool findRayOperation(VoxelNode* node, void* extraData) {
RayArgs* args = static_cast<RayArgs*>(extraData); RayArgs* args = static_cast<RayArgs*>(extraData);
AABox box = node->getAABox(); AABox box = node->getAABox();
float distance; float distance;
if (!box.findRayIntersection(args->origin, args->direction, distance)) { BoxFace face;
if (!box.findRayIntersection(args->origin, args->direction, distance, face)) {
return false; return false;
} }
if (!node->isLeaf()) { if (!node->isLeaf()) {
@ -621,14 +623,16 @@ bool findRayOperation(VoxelNode* node, void* extraData) {
if (!args->found || distance < args->distance) { if (!args->found || distance < args->distance) {
args->node = node; args->node = node;
args->distance = distance; args->distance = distance;
args->face = face;
args->found = true; args->found = true;
} }
return false; return false;
} }
bool VoxelTree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelNode*& node, float& distance) bool VoxelTree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
VoxelNode*& node, float& distance, BoxFace& face)
{ {
RayArgs args = { origin / (float)TREE_SCALE, direction, node, distance }; RayArgs args = { origin / (float)TREE_SCALE, direction, node, distance, face };
recurseTreeWithOperation(findRayOperation, &args); recurseTreeWithOperation(findRayOperation, &args);
return args.found; return args.found;
} }

View file

@ -63,7 +63,8 @@ public:
void clearDirtyBit() { _isDirty = false; }; void clearDirtyBit() { _isDirty = false; };
unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; }; unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; };
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelNode*& node, float& distance); bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
VoxelNode*& node, float& distance, BoxFace& face);
// Note: this assumes the fileFormat is the HIO individual voxels code files // Note: this assumes the fileFormat is the HIO individual voxels code files
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer); void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);