mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 17:41:12 +02:00
Merge branch 'master' of https://github.com/worklist/hifi
This commit is contained in:
commit
a864a6f8c6
32 changed files with 681 additions and 16986 deletions
|
@ -29,35 +29,42 @@
|
||||||
# (To distribute this file outside of CMake, substitute the full
|
# (To distribute this file outside of CMake, substitute the full
|
||||||
# License text for the above reference.)
|
# License text for the above reference.)
|
||||||
|
|
||||||
# default search dirs
|
IF (GLM_INCLUDE_DIR)
|
||||||
SET(_glm_HEADER_SEARCH_DIRS
|
set(GLM_INCLUDE_DIRS "${GLM_INCLUDE_DIR}")
|
||||||
"/usr/include"
|
SET(GLM_FOUND TRUE)
|
||||||
"/usr/local/include")
|
ELSE (GLM_INCLUDE_DIR)
|
||||||
|
# default search dirs
|
||||||
|
SET(_glm_HEADER_SEARCH_DIRS
|
||||||
|
"/usr/include"
|
||||||
|
"/usr/local/include")
|
||||||
|
|
||||||
# check environment variable
|
# check environment variable
|
||||||
SET(_glm_ENV_ROOT_DIR "$ENV{GLM_ROOT_DIR}")
|
SET(_glm_ENV_ROOT_DIR "$ENV{GLM_ROOT_DIR}")
|
||||||
|
|
||||||
IF(NOT GLM_ROOT_DIR AND _glm_ENV_ROOT_DIR)
|
IF(NOT GLM_ROOT_DIR AND _glm_ENV_ROOT_DIR)
|
||||||
SET(GLM_ROOT_DIR "${_glm_ENV_ROOT_DIR}")
|
SET(GLM_ROOT_DIR "${_glm_ENV_ROOT_DIR}")
|
||||||
ENDIF(NOT GLM_ROOT_DIR AND _glm_ENV_ROOT_DIR)
|
ENDIF(NOT GLM_ROOT_DIR AND _glm_ENV_ROOT_DIR)
|
||||||
|
|
||||||
# put user specified location at beginning of search
|
# put user specified location at beginning of search
|
||||||
IF(GLM_ROOT_DIR)
|
IF(GLM_ROOT_DIR)
|
||||||
SET(_glm_HEADER_SEARCH_DIRS "${GLM_ROOT_DIR}"
|
SET(_glm_HEADER_SEARCH_DIRS "${GLM_ROOT_DIR}"
|
||||||
"${GLM_ROOT_DIR}/include"
|
"${GLM_ROOT_DIR}/include"
|
||||||
${_glm_HEADER_SEARCH_DIRS})
|
${_glm_HEADER_SEARCH_DIRS})
|
||||||
ENDIF(GLM_ROOT_DIR)
|
ENDIF(GLM_ROOT_DIR)
|
||||||
|
|
||||||
# locate header
|
# locate header
|
||||||
FIND_PATH(GLM_INCLUDE_DIR "glm/glm.hpp"
|
FIND_PATH(GLM_INCLUDE_DIR "glm/glm.hpp"
|
||||||
PATHS ${_glm_HEADER_SEARCH_DIRS})
|
PATHS ${_glm_HEADER_SEARCH_DIRS})
|
||||||
|
|
||||||
INCLUDE(FindPackageHandleStandardArgs)
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLM DEFAULT_MSG
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLM DEFAULT_MSG
|
||||||
GLM_INCLUDE_DIR)
|
GLM_INCLUDE_DIR)
|
||||||
|
|
||||||
IF(GLM_FOUND)
|
IF(GLM_FOUND)
|
||||||
SET(GLM_INCLUDE_DIRS "${GLM_INCLUDE_DIR}")
|
SET(GLM_INCLUDE_DIRS "${GLM_INCLUDE_DIR}")
|
||||||
|
|
||||||
MESSAGE(STATUS "GLM_INCLUDE_DIR = ${GLM_INCLUDE_DIR}")
|
if (NOT GLM_FIND_QUIETLY)
|
||||||
ENDIF(GLM_FOUND)
|
MESSAGE(STATUS "GLM_INCLUDE_DIR = ${GLM_INCLUDE_DIR}")
|
||||||
|
endif (NOT GLM_FIND_QUIETLY)
|
||||||
|
ENDIF(GLM_FOUND)
|
||||||
|
ENDIF(GLM_INCLUDE_DIR)
|
|
@ -57,6 +57,7 @@ endif (APPLE)
|
||||||
|
|
||||||
find_package(Qt4 REQUIRED QtCore QtGui QtOpenGL)
|
find_package(Qt4 REQUIRED QtCore QtGui QtOpenGL)
|
||||||
include(${QT_USE_FILE})
|
include(${QT_USE_FILE})
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${QT_QTGUI_INCLUDE_DIR}")
|
||||||
|
|
||||||
# run qt moc on qt-enabled headers
|
# run qt moc on qt-enabled headers
|
||||||
qt4_wrap_cpp(INTERFACE_SRCS src/Application.h)
|
qt4_wrap_cpp(INTERFACE_SRCS src/Application.h)
|
||||||
|
|
|
@ -233,11 +233,6 @@ void Application::initializeGL() {
|
||||||
glutInit(&argc, 0);
|
glutInit(&argc, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
glewInit();
|
|
||||||
printLog( "Glew Init complete.\n" );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Before we render anything, let's set up our viewFrustumOffsetCamera with a sufficiently large
|
// Before we render anything, let's set up our viewFrustumOffsetCamera with a sufficiently large
|
||||||
// field of view and near and far clip to make it interesting.
|
// field of view and near and far clip to make it interesting.
|
||||||
//viewFrustumOffsetCamera.setFieldOfView(90.0);
|
//viewFrustumOffsetCamera.setFieldOfView(90.0);
|
||||||
|
@ -1110,7 +1105,6 @@ void Application::setWantsResIn(bool wantsResIn) {
|
||||||
_myAvatar.setWantResIn(wantsResIn);
|
_myAvatar.setWantResIn(wantsResIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Application::setWantsDelta(bool wantsDelta) {
|
void Application::setWantsDelta(bool wantsDelta) {
|
||||||
_myAvatar.setWantDelta(wantsDelta);
|
_myAvatar.setWantDelta(wantsDelta);
|
||||||
}
|
}
|
||||||
|
@ -1266,7 +1260,7 @@ void Application::initMenu() {
|
||||||
QMenu* debugMenu = menuBar->addMenu("Debug");
|
QMenu* debugMenu = menuBar->addMenu("Debug");
|
||||||
debugMenu->addAction("Show Render Pipeline Warnings", this, SLOT(setRenderWarnings(bool)))->setCheckable(true);
|
debugMenu->addAction("Show Render Pipeline Warnings", this, SLOT(setRenderWarnings(bool)))->setCheckable(true);
|
||||||
debugMenu->addAction("Kill Local Voxels", this, SLOT(doKillLocalVoxels()));
|
debugMenu->addAction("Kill Local Voxels", this, SLOT(doKillLocalVoxels()));
|
||||||
debugMenu->addAction("Randomize Voxel TRUE Colors", this, SLOT(doRandomizeVoxelColors()));
|
debugMenu->addAction("Randomize Voxel TRUE Colors", this, SLOT(doRandomizeVoxelColors()), Qt::CTRL | Qt::Key_R);
|
||||||
debugMenu->addAction("FALSE Color Voxels Randomly", this, SLOT(doFalseRandomizeVoxelColors()));
|
debugMenu->addAction("FALSE Color Voxels Randomly", this, SLOT(doFalseRandomizeVoxelColors()));
|
||||||
debugMenu->addAction("FALSE Color Voxel Every Other Randomly", this, SLOT(doFalseRandomizeEveryOtherVoxelColors()));
|
debugMenu->addAction("FALSE Color Voxel Every Other Randomly", this, SLOT(doFalseRandomizeEveryOtherVoxelColors()));
|
||||||
debugMenu->addAction("FALSE Color Voxels by Distance", this, SLOT(doFalseColorizeByDistance()));
|
debugMenu->addAction("FALSE Color Voxels by Distance", this, SLOT(doFalseColorizeByDistance()));
|
||||||
|
@ -1704,9 +1698,9 @@ void Application::displaySide(Camera& whichCamera) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
agentList->unlock();
|
agentList->unlock();
|
||||||
|
|
||||||
// Render my own Avatar
|
// Render my own Avatar
|
||||||
_myAvatar.render(_lookingInMirror, _myCamera.getPosition());
|
_myAvatar.render(_lookingInMirror->isChecked(), _myCamera.getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the world box
|
// Render the world box
|
||||||
|
@ -2032,11 +2026,9 @@ void Application::maybeEditVoxelUnderCursor() {
|
||||||
|
|
||||||
void Application::deleteVoxelUnderCursor() {
|
void Application::deleteVoxelUnderCursor() {
|
||||||
if (_mouseVoxel.s != 0) {
|
if (_mouseVoxel.s != 0) {
|
||||||
|
// sending delete to the server is sufficient, server will send new version so we see updates soon enough
|
||||||
sendVoxelEditMessage(PACKET_HEADER_ERASE_VOXEL, _mouseVoxel);
|
sendVoxelEditMessage(PACKET_HEADER_ERASE_VOXEL, _mouseVoxel);
|
||||||
|
|
||||||
// delete the voxel locally so it disappears immediately
|
|
||||||
_voxels.deleteVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
|
||||||
|
|
||||||
// remember the position for drag detection
|
// remember the position for drag detection
|
||||||
_justEditedVoxel = true;
|
_justEditedVoxel = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ const float AVATAR_BRAKING_STRENGTH = 40.0f;
|
||||||
const float JOINT_TOUCH_RANGE = 0.0005f;
|
const float JOINT_TOUCH_RANGE = 0.0005f;
|
||||||
|
|
||||||
float skinColor [] = {1.0, 0.84, 0.66};
|
float skinColor [] = {1.0, 0.84, 0.66};
|
||||||
float darkSkinColor[] = {0.8, 0.74, 0.6 };
|
float darkSkinColor[] = {0.9, 0.78, 0.63};
|
||||||
float lightBlue [] = {0.7, 0.8, 1.0 };
|
float lightBlue [] = {0.7, 0.8, 1.0 };
|
||||||
|
|
||||||
bool usingBigSphereCollisionTest = true;
|
bool usingBigSphereCollisionTest = true;
|
||||||
|
@ -130,8 +130,8 @@ void Avatar::updateHeadFromGyros(float deltaTime, SerialInterface* serialInterfa
|
||||||
// Update avatar head position based on measured gyro rates
|
// Update avatar head position based on measured gyro rates
|
||||||
|
|
||||||
_head.addPitch(measuredPitchRate * deltaTime);
|
_head.addPitch(measuredPitchRate * deltaTime);
|
||||||
_head.addYaw(measuredYawRate * deltaTime);
|
_head.addYaw (measuredYawRate * deltaTime);
|
||||||
_head.addRoll(measuredRollRate * deltaTime);
|
_head.addRoll (measuredRollRate * deltaTime);
|
||||||
|
|
||||||
// Update head lean distance based on accelerometer data
|
// Update head lean distance based on accelerometer data
|
||||||
const float LEAN_SENSITIVITY = 0.15;
|
const float LEAN_SENSITIVITY = 0.15;
|
||||||
|
@ -213,9 +213,8 @@ void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int scree
|
||||||
void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
|
|
||||||
//figure out if the mouse cursor is over any body spheres...
|
//figure out if the mouse cursor is over any body spheres...
|
||||||
if (_isMine) {
|
checkForMouseRayTouching();
|
||||||
checkForMouseRayTouching();
|
|
||||||
}
|
|
||||||
// copy velocity so we can use it later for acceleration
|
// copy velocity so we can use it later for acceleration
|
||||||
glm::vec3 oldVelocity = getVelocity();
|
glm::vec3 oldVelocity = getVelocity();
|
||||||
|
|
||||||
|
@ -385,11 +384,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition += headLean * 0.0f;
|
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition += headLean * 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update head state
|
// set head lookat position
|
||||||
_head.setPositionAndScale(_joint[AVATAR_JOINT_HEAD_BASE].springyPosition, _joint[AVATAR_JOINT_HEAD_BASE].radius);
|
|
||||||
|
|
||||||
_head.setLookAtPosition(glm::vec3(0.0f, 0.0f, 0.0f)); //default lookat position is 0,0,0
|
|
||||||
|
|
||||||
if (_interactingOther) {
|
if (_interactingOther) {
|
||||||
_head.setLooking(true);
|
_head.setLooking(true);
|
||||||
|
|
||||||
|
@ -400,7 +395,9 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
_head.setLooking(false);
|
_head.setLooking(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
_head.setBodyYaw(_bodyYaw);
|
_head.setBodyRotation (glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
||||||
|
_head.setPosition(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition);
|
||||||
|
_head.setScale (_joint[ AVATAR_JOINT_HEAD_BASE ].radius);
|
||||||
_head.setAudioLoudness(_audioLoudness);
|
_head.setAudioLoudness(_audioLoudness);
|
||||||
_head.setSkinColor(glm::vec3(skinColor[0], skinColor[1], skinColor[2]));
|
_head.setSkinColor(glm::vec3(skinColor[0], skinColor[1], skinColor[2]));
|
||||||
_head.simulate(deltaTime, _isMine);
|
_head.simulate(deltaTime, _isMine);
|
||||||
|
@ -714,7 +711,7 @@ void Avatar::setGravity(glm::vec3 gravity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) {
|
void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) {
|
||||||
|
|
||||||
_cameraPosition = cameraPosition; // store this for use in various parts of the code
|
_cameraPosition = cameraPosition; // store this for use in various parts of the code
|
||||||
|
|
||||||
if (usingBigSphereCollisionTest) {
|
if (usingBigSphereCollisionTest) {
|
||||||
|
@ -1074,10 +1071,6 @@ const glm::vec3& Avatar::getHeadPosition() const {
|
||||||
return _joint[ AVATAR_JOINT_HEAD_BASE ].position;
|
return _joint[ AVATAR_JOINT_HEAD_BASE ].position;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 Avatar::getApproximateEyePosition() {
|
|
||||||
return _head.getApproximateEyePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Avatar::updateArmIKAndConstraints(float deltaTime) {
|
void Avatar::updateArmIKAndConstraints(float deltaTime) {
|
||||||
|
|
||||||
// determine the arm vector
|
// determine the arm vector
|
||||||
|
@ -1127,46 +1120,41 @@ void Avatar::renderBody(bool lookingInMirror) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//show direction vectors of the bone orientation
|
glColor3f(
|
||||||
//renderOrientationDirections(_joint[b].springyPosition, _joint[b].orientation, _joint[b].radius * 2.0);
|
skinColor[0] + _joint[b].touchForce * 0.3f,
|
||||||
|
skinColor[1] - _joint[b].touchForce * 0.2f,
|
||||||
|
skinColor[2] - _joint[b].touchForce * 0.1f
|
||||||
|
);
|
||||||
|
|
||||||
glColor3fv(skinColor);
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(_joint[b].springyPosition.x, _joint[b].springyPosition.y, _joint[b].springyPosition.z);
|
glTranslatef(_joint[b].springyPosition.x, _joint[b].springyPosition.y, _joint[b].springyPosition.z);
|
||||||
glutSolidSphere(_joint[b].radius, 20.0f, 20.0f);
|
glutSolidSphere(_joint[b].radius, 20.0f, 20.0f);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_joint[b].touchForce > 0.0f) {
|
|
||||||
|
|
||||||
float alpha = _joint[b].touchForce * 0.2;
|
|
||||||
float r = _joint[b].radius * 1.1f + 0.005f;
|
|
||||||
glColor4f(0.5f, 0.2f, 0.2f, alpha);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(_joint[b].springyPosition.x, _joint[b].springyPosition.y, _joint[b].springyPosition.z);
|
|
||||||
glScalef(r, r, r);
|
|
||||||
glutSolidSphere(1, 20, 20);
|
|
||||||
glPopMatrix();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int b = 1; b < NUM_AVATAR_JOINTS; b++) {
|
for (int j = 1; j < NUM_AVATAR_JOINTS; j++) {
|
||||||
if (_joint[b].parent != AVATAR_JOINT_NULL)
|
if (_joint[j].parent != AVATAR_JOINT_NULL)
|
||||||
if (b != AVATAR_JOINT_HEAD_TOP) {
|
if ((j != AVATAR_JOINT_HEAD_TOP )
|
||||||
|
&& (j != AVATAR_JOINT_HEAD_BASE )
|
||||||
/*
|
&& (j != AVATAR_JOINT_PELVIS )
|
||||||
|
&& (j != AVATAR_JOINT_TORSO )
|
||||||
|
&& (j != AVATAR_JOINT_CHEST )
|
||||||
|
&& (j != AVATAR_JOINT_LEFT_COLLAR )
|
||||||
|
&& (j != AVATAR_JOINT_LEFT_SHOULDER )
|
||||||
|
&& (j != AVATAR_JOINT_RIGHT_COLLAR )
|
||||||
|
&& (j != AVATAR_JOINT_RIGHT_SHOULDER)) {
|
||||||
// Render cone sections connecting the joint positions
|
// Render cone sections connecting the joint positions
|
||||||
glColor3fv(darkSkinColor);
|
glColor3fv(darkSkinColor);
|
||||||
renderJointConnectingCone
|
renderJointConnectingCone
|
||||||
(
|
(
|
||||||
_joint[_joint[b].parent ].springyPosition,
|
_joint[_joint[j].parent ].springyPosition,
|
||||||
_joint[b ].springyPosition,
|
_joint[j ].springyPosition,
|
||||||
_joint[_joint[b].parent ].radius,
|
_joint[_joint[j].parent ].radius * 0.8,
|
||||||
_joint[b ].radius
|
_joint[j ].radius * 0.8
|
||||||
);
|
);
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
// Render lines connecting the joint positions
|
// Render lines connecting the joint positions
|
||||||
glColor3f(0.4f, 0.5f, 0.6f);
|
glColor3f(0.4f, 0.5f, 0.6f);
|
||||||
glLineWidth(3.0);
|
glLineWidth(3.0);
|
||||||
|
@ -1174,6 +1162,7 @@ void Avatar::renderBody(bool lookingInMirror) {
|
||||||
glVertex3fv(&_joint[ _joint[ b ].parent ].springyPosition.x);
|
glVertex3fv(&_joint[ _joint[ b ].parent ].springyPosition.x);
|
||||||
glVertex3fv(&_joint[ b ].springyPosition.x);
|
glVertex3fv(&_joint[ b ].springyPosition.x);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1194,18 +1183,18 @@ void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity
|
||||||
|
|
||||||
if (deltaTime == 0.f) {
|
if (deltaTime == 0.f) {
|
||||||
// On first sample, set head to absolute position
|
// On first sample, set head to absolute position
|
||||||
_head.setYaw(eulerAngles->x);
|
_head.setYaw (eulerAngles->x);
|
||||||
_head.setPitch(eulerAngles->y);
|
_head.setPitch(eulerAngles->y);
|
||||||
_head.setRoll(eulerAngles->z);
|
_head.setRoll (eulerAngles->z);
|
||||||
} else {
|
} else {
|
||||||
glm::vec3 angles(_head.getYaw(), _head.getPitch(), _head.getRoll());
|
glm::vec3 angles(_head.getYaw(), _head.getPitch(), _head.getRoll());
|
||||||
// Increment by detected velocity
|
// Increment by detected velocity
|
||||||
angles += (*angularVelocity) * deltaTime;
|
angles += (*angularVelocity) * deltaTime;
|
||||||
// Smooth to slowly follow absolute values
|
// Smooth to slowly follow absolute values
|
||||||
angles = ((1.f - deltaTime / smoothingTime) * angles) + (deltaTime / smoothingTime) * (*eulerAngles);
|
angles = ((1.f - deltaTime / smoothingTime) * angles) + (deltaTime / smoothingTime) * (*eulerAngles);
|
||||||
_head.setYaw(angles.x);
|
_head.setYaw (angles.x);
|
||||||
_head.setPitch(angles.y);
|
_head.setPitch(angles.y);
|
||||||
_head.setRoll(angles.z);
|
_head.setRoll (angles.z);
|
||||||
//printLog("Y/P/R: %3.1f, %3.1f, %3.1f\n", angles.x, angles.y, angles.z);
|
//printLog("Y/P/R: %3.1f, %3.1f, %3.1f\n", angles.x, angles.y, angles.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1239,11 +1228,12 @@ void Avatar::readAvatarDataFromFile() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// render a makeshift cone section that serves as a body part connecting joint spheres
|
||||||
void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2) {
|
void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2) {
|
||||||
|
|
||||||
glBegin(GL_TRIANGLES);
|
glBegin(GL_TRIANGLES);
|
||||||
|
|
||||||
int num = 5;
|
int num = 10;
|
||||||
|
|
||||||
glm::vec3 axis = glm::normalize(position2 - position1);
|
glm::vec3 axis = glm::normalize(position2 - position1);
|
||||||
float length = glm::length(axis);
|
float length = glm::length(axis);
|
||||||
|
@ -1253,26 +1243,30 @@ void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2,
|
||||||
glm::vec3 perpSin = glm::vec3(axis.y, axis.z, axis.x);
|
glm::vec3 perpSin = glm::vec3(axis.y, axis.z, axis.x);
|
||||||
glm::vec3 perpCos = glm::vec3(axis.z, axis.x, axis.y);
|
glm::vec3 perpCos = glm::vec3(axis.z, axis.x, axis.y);
|
||||||
|
|
||||||
|
float angle1 = 0.0;
|
||||||
|
float angle2 = 0.0;
|
||||||
|
|
||||||
for (int i = 0; i < num; i ++) {
|
for (int i = 0; i < num; i ++) {
|
||||||
|
|
||||||
float angle1 = ((float)i / (float)num) * PI * 2.0;
|
angle1 = angle2;
|
||||||
float angle2 = ((float)(i+1) / (float)num) * PI * 2.0;
|
angle2 = ((float)(i+1) / (float)num) * PI * 2.0;
|
||||||
|
|
||||||
|
float s1 = sinf(angle1);
|
||||||
|
float s2 = sinf(angle2);
|
||||||
|
float c1 = cosf(angle1);
|
||||||
|
float c2 = cosf(angle2);
|
||||||
|
|
||||||
glm::vec3 p1a = position1 + perpSin * sin(angle1) * radius1;
|
glm::vec3 p1a = position1 + perpSin * s1 * radius1 + perpCos * c1 * radius1;
|
||||||
glm::vec3 p1b = position1 + perpCos * cos(angle2) * radius1;
|
glm::vec3 p1b = position1 + perpSin * s2 * radius1 + perpCos * c2 * radius1;
|
||||||
|
glm::vec3 p2a = position2 + perpSin * s1 * radius2 + perpCos * c1 * radius2;
|
||||||
|
glm::vec3 p2b = position2 + perpSin * s2 * radius2 + perpCos * c2 * radius2;
|
||||||
|
|
||||||
glm::vec3 p2a = position2 + perpSin * sin(angle1) * radius2;
|
|
||||||
glm::vec3 p2b = position2 + perpCos * cos(angle2) * radius2;
|
|
||||||
|
|
||||||
glVertex3f(p1a.x, p1a.y, p1a.z);
|
glVertex3f(p1a.x, p1a.y, p1a.z);
|
||||||
glVertex3f(p1b.x, p1b.y, p1b.z);
|
glVertex3f(p1b.x, p1b.y, p1b.z);
|
||||||
glVertex3f(p2a.x, p2a.y, p2a.z);
|
glVertex3f(p2a.x, p2a.y, p2a.z);
|
||||||
|
|
||||||
/*
|
|
||||||
glVertex3f(p1b.x, p1b.y, p1b.z);
|
glVertex3f(p1b.x, p1b.y, p1b.z);
|
||||||
glVertex3f(p2a.x, p2a.y, p2a.z);
|
glVertex3f(p2a.x, p2a.y, p2a.z);
|
||||||
glVertex3f(p2b.x, p2b.y, p2b.z);
|
glVertex3f(p2b.x, p2b.y, p2b.z);
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,73 +12,40 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
const float HEAD_MOTION_DECAY = 0.1;
|
const float EYE_RIGHT_OFFSET = 0.27f;
|
||||||
const float MINIMUM_EYE_ROTATION = 0.7f; // based on a dot product: 1.0 is straight ahead, 0.0 is 90 degrees off
|
const float EYE_UP_OFFSET = 0.38f;
|
||||||
|
const float EYE_FRONT_OFFSET = 0.8f;
|
||||||
|
const float EAR_RIGHT_OFFSET = 1.0;
|
||||||
|
const float MOUTH_FRONT_OFFSET = 1.0f;
|
||||||
|
const float MOUTH_UP_OFFSET = -0.3f;
|
||||||
|
const float HEAD_MOTION_DECAY = 0.1;
|
||||||
|
const float MINIMUM_EYE_ROTATION = 0.7f; // based on a dot product: 1.0 is straight ahead, 0.0 is 90 degrees off
|
||||||
|
const float EYEBALL_RADIUS = 0.02;
|
||||||
|
const float EYEBALL_COLOR[3] = { 0.9f, 0.9f, 0.8f };
|
||||||
|
const float IRIS_RADIUS = 0.007;
|
||||||
|
const float IRIS_PROTRUSION = 0.018f;
|
||||||
|
const char IRIS_TEXTURE_FILENAME[] = "resources/images/iris.png";
|
||||||
|
|
||||||
const float EYEBALL_RADIUS = 0.02;
|
unsigned int IRIS_TEXTURE_WIDTH = 768;
|
||||||
const float IRIS_RADIUS = 0.007;
|
|
||||||
const float IRIS_PROTRUSION = 0.018f;
|
|
||||||
|
|
||||||
float _browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
|
|
||||||
float _mouthColor[] = {1, 0, 0};
|
|
||||||
|
|
||||||
float _BrowRollAngle [5] = { 0.0f, 15.0f, 30.0f, -30.0f, -15.0f};
|
|
||||||
float _BrowPitchAngle[3] = {-70.0f, -60.0f, -50.0f};
|
|
||||||
float _eyeColor [3] = { 0.9f, 0.9f, 0.8f};
|
|
||||||
|
|
||||||
float _MouthWidthChoices[3] = {0.5, 0.77, 0.3};
|
|
||||||
|
|
||||||
float _browWidth = 0.8;
|
|
||||||
float _browThickness = 0.16;
|
|
||||||
|
|
||||||
const char IRIS_TEXTURE_FILENAME[] = "resources/images/iris.png";
|
|
||||||
unsigned int IRIS_TEXTURE_WIDTH = 768;
|
|
||||||
unsigned int IRIS_TEXTURE_HEIGHT = 498;
|
unsigned int IRIS_TEXTURE_HEIGHT = 498;
|
||||||
vector<unsigned char> irisTexture;
|
vector<unsigned char> irisTexture;
|
||||||
|
|
||||||
Head::Head() :
|
Head::Head() :
|
||||||
yawRate(0.0f),
|
yawRate(0.0f),
|
||||||
noise(0.0f),
|
|
||||||
_audioLoudness(0.0f),
|
_audioLoudness(0.0f),
|
||||||
_skinColor(0.0f, 0.0f, 0.0f),
|
_skinColor(0.0f, 0.0f, 0.0f),
|
||||||
_position(0.0f, 0.0f, 0.0f),
|
_position(0.0f, 0.0f, 0.0f),
|
||||||
_rotation(0.0f, 0.0f, 0.0f),
|
_rotation(0.0f, 0.0f, 0.0f),
|
||||||
_eyeballPitch(),
|
_mouthPosition(0.0f, 0.0f, 0.0f),
|
||||||
_eyeballYaw(),
|
|
||||||
_interBrowDistance(0.75f),
|
|
||||||
_mouthPitch(0),
|
|
||||||
_mouthYaw(0),
|
|
||||||
_mouthWidth(1.0f),
|
|
||||||
_mouthHeight(0.2f),
|
|
||||||
_pitchTarget(0.0f),
|
|
||||||
_yawTarget(0.0f),
|
|
||||||
_noiseEnvelope(1.0f),
|
|
||||||
_scale(1.0f),
|
_scale(1.0f),
|
||||||
_eyeContact(1),
|
|
||||||
_browAudioLift(0.0f),
|
_browAudioLift(0.0f),
|
||||||
_gravity(0.0f, -1.0f, 0.0f),
|
_gravity(0.0f, -1.0f, 0.0f),
|
||||||
_lastLoudness(0.0f),
|
_lastLoudness(0.0f),
|
||||||
_averageLoudness(0.0f),
|
_averageLoudness(0.0f),
|
||||||
_audioAttack(0.0f),
|
_audioAttack(0.0f),
|
||||||
_returnSpringScale(1.0f),
|
_returnSpringScale(1.0f),
|
||||||
_bodyYaw(0.0f),
|
_bodyRotation(0.0f, 0.0f, 0.0f),
|
||||||
_eyeContactTarget(LEFT_EYE)
|
_headRotation(0.0f, 0.0f, 0.0f) {
|
||||||
{
|
|
||||||
_eyebrowPitch[0] = -30;
|
|
||||||
_eyebrowPitch[1] = -30;
|
|
||||||
_eyebrowRoll [0] = 20;
|
|
||||||
_eyebrowRoll [1] = -20;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Head::setPositionAndScale(glm::vec3 position, float scale) {
|
|
||||||
_position = position;
|
|
||||||
_scale = scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Head::setNewTarget(float pitch, float yaw) {
|
|
||||||
_pitchTarget = pitch;
|
|
||||||
_yawTarget = yaw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Head::reset() {
|
void Head::reset() {
|
||||||
|
@ -86,17 +53,13 @@ void Head::reset() {
|
||||||
_leanForward = _leanSideways = 0.0f;
|
_leanForward = _leanSideways = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Head::simulate(float deltaTime, bool isMine) {
|
void Head::simulate(float deltaTime, bool isMine) {
|
||||||
|
|
||||||
//generate orientation directions based on Euler angles...
|
|
||||||
_orientation.setToPitchYawRoll( -_pitch, _bodyYaw + _yaw, _roll);
|
|
||||||
|
|
||||||
//calculate the eye positions (algorithm still being designed)
|
|
||||||
updateEyePositions();
|
|
||||||
|
|
||||||
// Decay head back to center if turned on
|
// Decay head back to center if turned on
|
||||||
if (isMine && _returnHeadToCenter) {
|
if (isMine && _returnHeadToCenter) {
|
||||||
// Decay back toward center
|
|
||||||
|
// Decay rotation back toward center
|
||||||
_pitch *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * 2 * deltaTime);
|
_pitch *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * 2 * deltaTime);
|
||||||
_yaw *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * 2 * deltaTime);
|
_yaw *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * 2 * deltaTime);
|
||||||
_roll *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * 2 * deltaTime);
|
_roll *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * 2 * deltaTime);
|
||||||
|
@ -107,117 +70,32 @@ void Head::simulate(float deltaTime, bool isMine) {
|
||||||
const float RETURN_RANGE = 15.0;
|
const float RETURN_RANGE = 15.0;
|
||||||
const float RETURN_STRENGTH = 2.0;
|
const float RETURN_STRENGTH = 2.0;
|
||||||
if (fabs(_pitch) < RETURN_RANGE) { _pitch *= (1.0f - RETURN_STRENGTH * deltaTime); }
|
if (fabs(_pitch) < RETURN_RANGE) { _pitch *= (1.0f - RETURN_STRENGTH * deltaTime); }
|
||||||
if (fabs(_yaw) < RETURN_RANGE) { _yaw *= (1.0f - RETURN_STRENGTH * deltaTime); }
|
if (fabs(_yaw ) < RETURN_RANGE) { _yaw *= (1.0f - RETURN_STRENGTH * deltaTime); }
|
||||||
if (fabs(_roll) < RETURN_RANGE) { _roll *= (1.0f - RETURN_STRENGTH * deltaTime); }
|
if (fabs(_roll ) < RETURN_RANGE) { _roll *= (1.0f - RETURN_STRENGTH * deltaTime); }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noise) {
|
// decay lean
|
||||||
// Move toward new target
|
|
||||||
_pitch += (_pitchTarget - _pitch) * 10 * deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ;
|
|
||||||
_yaw += (_yawTarget - _yaw ) * 10 * deltaTime; // (1.f - DECAY*deltaTime);
|
|
||||||
_roll *= 1.f - (HEAD_MOTION_DECAY * deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
_leanForward *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime);
|
_leanForward *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime);
|
||||||
_leanSideways *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime);
|
_leanSideways *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime);
|
||||||
|
|
||||||
// Update where the avatar's eyes are
|
|
||||||
//
|
|
||||||
// First, decide if we are making eye contact or not
|
|
||||||
if (randFloat() < 0.005) {
|
|
||||||
_eyeContact = !_eyeContact;
|
|
||||||
_eyeContact = 1;
|
|
||||||
if (!_eyeContact) {
|
|
||||||
// If we just stopped making eye contact,move the eyes markedly away
|
|
||||||
_eyeballPitch[0] = _eyeballPitch[1] = _eyeballPitch[0] + 5.0 + (randFloat() - 0.5) * 10;
|
|
||||||
_eyeballYaw [0] = _eyeballYaw [1] = _eyeballYaw [0] + 5.0 + (randFloat() - 0.5) * 5;
|
|
||||||
} else {
|
|
||||||
// If now making eye contact, turn head to look right at viewer
|
|
||||||
setNewTarget(0,0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const float DEGREES_BETWEEN_VIEWER_EYES = 3;
|
|
||||||
const float DEGREES_TO_VIEWER_MOUTH = 7;
|
|
||||||
|
|
||||||
if (_eyeContact) {
|
|
||||||
// Should we pick a new eye contact target?
|
|
||||||
if (randFloat() < 0.01) {
|
|
||||||
// Choose where to look next
|
|
||||||
if (randFloat() < 0.1) {
|
|
||||||
_eyeContactTarget = MOUTH;
|
|
||||||
} else {
|
|
||||||
if (randFloat() < 0.5) {
|
|
||||||
_eyeContactTarget = LEFT_EYE;
|
|
||||||
} else {
|
|
||||||
_eyeContactTarget = RIGHT_EYE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set eyeball pitch and yaw to make contact
|
|
||||||
float eye_target_yaw_adjust = 0.0f;
|
|
||||||
float eye_target_pitch_adjust = 0.0f;
|
|
||||||
|
|
||||||
if (_eyeContactTarget == LEFT_EYE ) { eye_target_yaw_adjust = DEGREES_BETWEEN_VIEWER_EYES; }
|
|
||||||
if (_eyeContactTarget == RIGHT_EYE) { eye_target_yaw_adjust = -DEGREES_BETWEEN_VIEWER_EYES; }
|
|
||||||
if (_eyeContactTarget == MOUTH ) { eye_target_pitch_adjust = DEGREES_TO_VIEWER_MOUTH; }
|
|
||||||
|
|
||||||
_eyeballPitch[0] = _eyeballPitch[1] = -_pitch + eye_target_pitch_adjust;
|
|
||||||
_eyeballYaw [0] = _eyeballYaw [1] = _yaw + eye_target_yaw_adjust;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noise)
|
|
||||||
{
|
|
||||||
_pitch += (randFloat() - 0.5) * 0.2 * _noiseEnvelope;
|
|
||||||
_yaw += (randFloat() - 0.5) * 0.3 *_noiseEnvelope;
|
|
||||||
//PupilSize += (randFloat() - 0.5) * 0.001*NoiseEnvelope;
|
|
||||||
|
|
||||||
if (randFloat() < 0.005) _mouthWidth = _MouthWidthChoices[rand()%3];
|
|
||||||
|
|
||||||
if (!_eyeContact) {
|
|
||||||
if (randFloat() < 0.01) _eyeballPitch[0] = _eyeballPitch[1] = (randFloat() - 0.5) * 20;
|
|
||||||
if (randFloat() < 0.01) _eyeballYaw[0] = _eyeballYaw[1] = (randFloat()- 0.5) * 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((randFloat() < 0.005) && (fabs(_pitchTarget - _pitch) < 1.0) && (fabs(_yawTarget - _yaw) < 1.0)) {
|
|
||||||
setNewTarget((randFloat()-0.5) * 20.0, (randFloat()-0.5) * 45.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0) {
|
|
||||||
|
|
||||||
// Pick new target
|
|
||||||
_pitchTarget = (randFloat() - 0.5) * 45;
|
|
||||||
_yawTarget = (randFloat() - 0.5) * 22;
|
|
||||||
}
|
|
||||||
if (randFloat() < 0.01)
|
|
||||||
{
|
|
||||||
_eyebrowPitch[0] = _eyebrowPitch[1] = _BrowPitchAngle[rand()%3];
|
|
||||||
_eyebrowRoll [0] = _eyebrowRoll[1] = _BrowRollAngle[rand()%5];
|
|
||||||
_eyebrowRoll [1] *=-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update audio trailing average for rendering facial animations
|
// Update audio trailing average for rendering facial animations
|
||||||
const float AUDIO_AVERAGING_SECS = 0.05;
|
const float AUDIO_AVERAGING_SECS = 0.05;
|
||||||
_averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _averageLoudness +
|
_averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _averageLoudness +
|
||||||
(deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness;
|
(deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness;
|
||||||
|
|
||||||
}
|
|
||||||
|
// Update audio attack data for facial animation (eyebrows and mouth)
|
||||||
void Head::updateEyePositions() {
|
_audioAttack = 0.9 * _audioAttack + 0.1 * fabs(_audioLoudness - _lastLoudness);
|
||||||
float rightShift = _scale * 0.27f;
|
_lastLoudness = _audioLoudness;
|
||||||
float upShift = _scale * 0.38f;
|
|
||||||
float frontShift = _scale * 0.8f;
|
|
||||||
|
|
||||||
_leftEyePosition = _position
|
const float BROW_LIFT_THRESHOLD = 100;
|
||||||
+ _orientation.getRight() * rightShift
|
if (_audioAttack > BROW_LIFT_THRESHOLD)
|
||||||
+ _orientation.getUp () * upShift
|
_browAudioLift += sqrt(_audioAttack) * 0.00005;
|
||||||
+ _orientation.getFront() * frontShift;
|
|
||||||
_rightEyePosition = _position
|
float clamp = 0.01;
|
||||||
- _orientation.getRight() * rightShift
|
if (_browAudioLift > clamp) { _browAudioLift = clamp; }
|
||||||
+ _orientation.getUp () * upShift
|
|
||||||
+ _orientation.getFront() * frontShift;
|
_browAudioLift *= 0.7f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,101 +112,61 @@ void Head::setLooking(bool looking) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 Head::getApproximateEyePosition() {
|
|
||||||
return _leftEyePosition + (_rightEyePosition - _leftEyePosition) * ONE_HALF;
|
|
||||||
|
|
||||||
|
void Head::calculateGeometry(bool lookingInMirror) {
|
||||||
|
//generate orientation directions based on Euler angles...
|
||||||
|
|
||||||
|
float pitch = _pitch;
|
||||||
|
float yaw = -_yaw;
|
||||||
|
float roll = -_roll;
|
||||||
|
|
||||||
|
if (lookingInMirror) {
|
||||||
|
yaw = _yaw;
|
||||||
|
roll = _roll;
|
||||||
|
}
|
||||||
|
|
||||||
|
_orientation.setToPitchYawRoll
|
||||||
|
(
|
||||||
|
_bodyRotation.x + pitch,
|
||||||
|
_bodyRotation.y + yaw,
|
||||||
|
_bodyRotation.z + roll
|
||||||
|
);
|
||||||
|
|
||||||
|
//calculate the eye positions
|
||||||
|
_leftEyePosition = _position
|
||||||
|
- _orientation.getRight() * _scale * EYE_RIGHT_OFFSET
|
||||||
|
+ _orientation.getUp () * _scale * EYE_UP_OFFSET
|
||||||
|
+ _orientation.getFront() * _scale * EYE_FRONT_OFFSET;
|
||||||
|
_rightEyePosition = _position
|
||||||
|
+ _orientation.getRight() * _scale * EYE_RIGHT_OFFSET
|
||||||
|
+ _orientation.getUp () * _scale * EYE_UP_OFFSET
|
||||||
|
+ _orientation.getFront() * _scale * EYE_FRONT_OFFSET;
|
||||||
|
|
||||||
|
//calculate the ear positions
|
||||||
|
_leftEarPosition = _position - _orientation.getRight() * _scale * EAR_RIGHT_OFFSET;
|
||||||
|
_rightEarPosition = _position + _orientation.getRight() * _scale * EAR_RIGHT_OFFSET;
|
||||||
|
|
||||||
|
//calculate the mouth position
|
||||||
|
_mouthPosition = _position + _orientation.getUp () * _scale * MOUTH_UP_OFFSET
|
||||||
|
+ _orientation.getFront() * _scale * MOUTH_FRONT_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Head::render(bool lookingInMirror) {
|
void Head::render(bool lookingInMirror) {
|
||||||
|
|
||||||
int side = 0;
|
calculateGeometry(lookingInMirror);
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_RESCALE_NORMAL);
|
glEnable(GL_RESCALE_NORMAL);
|
||||||
|
|
||||||
glPushMatrix();
|
|
||||||
|
|
||||||
glTranslatef(_position.x, _position.y, _position.z); //translate to head position
|
renderHeadSphere();
|
||||||
glScalef(_scale, _scale, _scale); //scale to head size
|
|
||||||
|
|
||||||
if (lookingInMirror) {
|
|
||||||
glRotatef(_bodyYaw - _yaw, 0, 1, 0);
|
|
||||||
glRotatef(_pitch, 1, 0, 0);
|
|
||||||
glRotatef(-_roll, 0, 0, 1);
|
|
||||||
} else {
|
|
||||||
glRotatef(_bodyYaw + _yaw, 0, 1, 0);
|
|
||||||
glRotatef(_pitch, 1, 0, 0);
|
|
||||||
glRotatef(_roll, 0, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//glScalef(2.0, 2.0, 2.0);
|
|
||||||
glColor3f(_skinColor.x, _skinColor.y, _skinColor.z);
|
|
||||||
|
|
||||||
glutSolidSphere(1, 30, 30);
|
|
||||||
|
|
||||||
// Ears
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(1.0, 0, 0);
|
|
||||||
for(side = 0; side < 2; side++) {
|
|
||||||
glPushMatrix();
|
|
||||||
glScalef(0.3, 0.65, .65);
|
|
||||||
glutSolidSphere(0.5, 30, 30);
|
|
||||||
glPopMatrix();
|
|
||||||
glTranslatef(-2.0, 0, 0);
|
|
||||||
}
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
// Update audio attack data for facial animation (eyebrows and mouth)
|
|
||||||
_audioAttack = 0.9 * _audioAttack + 0.1 * fabs(_audioLoudness - _lastLoudness);
|
|
||||||
_lastLoudness = _audioLoudness;
|
|
||||||
|
|
||||||
const float BROW_LIFT_THRESHOLD = 100;
|
|
||||||
if (_audioAttack > BROW_LIFT_THRESHOLD)
|
|
||||||
_browAudioLift += sqrt(_audioAttack) / 1000.0;
|
|
||||||
|
|
||||||
_browAudioLift *= .90;
|
|
||||||
|
|
||||||
// Render Eyebrows
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(-_interBrowDistance / 2.0,0.4,0.45);
|
|
||||||
for(side = 0; side < 2; side++) {
|
|
||||||
glColor3fv(_browColor);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(0, 0.35 + _browAudioLift, 0);
|
|
||||||
glRotatef(_eyebrowPitch[side]/2.0, 1, 0, 0);
|
|
||||||
glRotatef(_eyebrowRoll[side]/2.0, 0, 0, 1);
|
|
||||||
glScalef(_browWidth, _browThickness, 1);
|
|
||||||
glutSolidCube(0.5);
|
|
||||||
glPopMatrix();
|
|
||||||
glTranslatef(_interBrowDistance, 0, 0);
|
|
||||||
}
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
// Mouth
|
|
||||||
// const float MIN_LOUDNESS_SCALE_WIDTH = 0.7f;
|
|
||||||
// const float WIDTH_SENSITIVITY = 60.f;
|
|
||||||
// const float HEIGHT_SENSITIVITY = 30.f;
|
|
||||||
// const float MIN_LOUDNESS_SCALE_HEIGHT = 1.0f;
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(0,-0.35,0.75);
|
|
||||||
glColor3f(0,0,0);
|
|
||||||
|
|
||||||
glRotatef(_mouthPitch, 1, 0, 0);
|
|
||||||
glRotatef(_mouthYaw, 0, 0, 1);
|
|
||||||
|
|
||||||
if (_averageLoudness > 1.f) {
|
|
||||||
glScalef(_mouthWidth * (.7f + sqrt(_averageLoudness) /60.f),
|
|
||||||
_mouthHeight * (1.f + sqrt(_averageLoudness) /30.f), 1);
|
|
||||||
} else {
|
|
||||||
glScalef(_mouthWidth, _mouthHeight, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
glutSolidCube(0.5);
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
renderEyeBalls();
|
renderEyeBalls();
|
||||||
|
renderEars();
|
||||||
|
renderMouth();
|
||||||
|
renderEyeBrows();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (_lookingAtSomething) {
|
if (_lookingAtSomething) {
|
||||||
// Render lines originating from the eyes and converging on the lookatPosition
|
// Render lines originating from the eyes and converging on the lookatPosition
|
||||||
|
@ -337,6 +175,154 @@ void Head::render(bool lookingInMirror) {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Head::renderHeadSphere() {
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(_position.x, _position.y, _position.z); //translate to head position
|
||||||
|
glScalef(_scale, _scale, _scale); //scale to head size
|
||||||
|
glColor3f(_skinColor.x, _skinColor.y, _skinColor.z);
|
||||||
|
glutSolidSphere(1, 30, 30);
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Head::renderEars() {
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glColor3f(_skinColor.x, _skinColor.y, _skinColor.z);
|
||||||
|
glTranslatef(_leftEarPosition.x, _leftEarPosition.y, _leftEarPosition.z);
|
||||||
|
glutSolidSphere(0.02, 30, 30);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glColor3f(_skinColor.x, _skinColor.y, _skinColor.z);
|
||||||
|
glTranslatef(_rightEarPosition.x, _rightEarPosition.y, _rightEarPosition.z);
|
||||||
|
glutSolidSphere(0.02, 30, 30);
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Head::renderMouth() {
|
||||||
|
|
||||||
|
float s = sqrt(_averageLoudness);
|
||||||
|
float height = _scale * (0.05f + s * 0.0040f );
|
||||||
|
float width = _scale * (0.30f + s * 0.0014f );
|
||||||
|
|
||||||
|
glm::vec3 leftCorner = _mouthPosition;
|
||||||
|
glm::vec3 rightCorner = _mouthPosition;
|
||||||
|
glm::vec3 leftTop = _mouthPosition;
|
||||||
|
glm::vec3 rightTop = _mouthPosition;
|
||||||
|
glm::vec3 leftBottom = _mouthPosition;
|
||||||
|
glm::vec3 rightBottom = _mouthPosition;
|
||||||
|
|
||||||
|
leftCorner -= _orientation.getRight() * width;
|
||||||
|
rightCorner += _orientation.getRight() * width;
|
||||||
|
leftTop -= _orientation.getRight() * width * 0.4f;
|
||||||
|
rightTop += _orientation.getRight() * width * 0.4f;
|
||||||
|
leftBottom -= _orientation.getRight() * width * 0.4f;
|
||||||
|
rightBottom += _orientation.getRight() * width * 0.4f;
|
||||||
|
|
||||||
|
leftTop += _orientation.getUp() * height * 0.7f;
|
||||||
|
rightTop += _orientation.getUp() * height * 0.7f;
|
||||||
|
leftBottom -= _orientation.getUp() * height;
|
||||||
|
rightBottom -= _orientation.getUp() * height;
|
||||||
|
|
||||||
|
leftTop += _orientation.getFront() * _scale * 0.1f;
|
||||||
|
rightTop += _orientation.getFront() * _scale * 0.1f;
|
||||||
|
leftBottom += _orientation.getFront() * _scale * 0.1f;
|
||||||
|
rightBottom += _orientation.getFront() * _scale * 0.1f;
|
||||||
|
|
||||||
|
glColor3f(0.2f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
|
||||||
|
glVertex3f(leftCorner.x, leftCorner.y, leftCorner.z);
|
||||||
|
glVertex3f(leftBottom.x, leftBottom.y, leftBottom.z);
|
||||||
|
glVertex3f(leftTop.x, leftTop.y, leftTop.z );
|
||||||
|
|
||||||
|
glVertex3f(leftTop.x, leftTop.y, leftTop.z );
|
||||||
|
glVertex3f(rightTop.x, rightTop.y, rightTop.z );
|
||||||
|
glVertex3f(leftBottom.x, leftBottom.y, leftBottom.z);
|
||||||
|
|
||||||
|
glVertex3f(rightTop.x, rightTop.y, rightTop.z );
|
||||||
|
glVertex3f(leftBottom.x, leftBottom.y, leftBottom.z );
|
||||||
|
glVertex3f(rightBottom.x, rightBottom.y, rightBottom.z);
|
||||||
|
|
||||||
|
glVertex3f(rightTop.x, rightTop.y, rightTop.z );
|
||||||
|
glVertex3f(rightBottom.x, rightBottom.y, rightBottom.z);
|
||||||
|
glVertex3f(rightCorner.x, rightCorner.y, rightCorner.z);
|
||||||
|
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Head::renderEyeBrows() {
|
||||||
|
|
||||||
|
float height = _scale * 0.3f + _browAudioLift;
|
||||||
|
float length = _scale * 0.2f;
|
||||||
|
float width = _scale * 0.07f;
|
||||||
|
|
||||||
|
glColor3f(0.3f, 0.25f, 0.2f);
|
||||||
|
|
||||||
|
glm::vec3 leftCorner = _leftEyePosition;
|
||||||
|
glm::vec3 rightCorner = _leftEyePosition;
|
||||||
|
glm::vec3 leftTop = _leftEyePosition;
|
||||||
|
glm::vec3 rightTop = _leftEyePosition;
|
||||||
|
glm::vec3 leftBottom = _leftEyePosition;
|
||||||
|
glm::vec3 rightBottom = _leftEyePosition;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
|
||||||
|
if ( i == 1 ) {
|
||||||
|
leftCorner = rightCorner = leftTop = rightTop = leftBottom = rightBottom = _rightEyePosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
leftCorner -= _orientation.getRight() * length;
|
||||||
|
rightCorner += _orientation.getRight() * length;
|
||||||
|
leftTop -= _orientation.getRight() * length * 0.4f;
|
||||||
|
rightTop += _orientation.getRight() * length * 0.4f;
|
||||||
|
leftBottom -= _orientation.getRight() * length * 0.4f;
|
||||||
|
rightBottom += _orientation.getRight() * length * 0.4f;
|
||||||
|
|
||||||
|
leftCorner += _orientation.getUp() * height;
|
||||||
|
rightCorner += _orientation.getUp() * height;
|
||||||
|
leftTop += _orientation.getUp() * (height + width);
|
||||||
|
rightTop += _orientation.getUp() * (height + width);
|
||||||
|
leftBottom += _orientation.getUp() * height;
|
||||||
|
rightBottom += _orientation.getUp() * height;
|
||||||
|
|
||||||
|
leftCorner += _orientation.getFront() * _scale * -0.1f;
|
||||||
|
rightCorner += _orientation.getFront() * _scale * -0.1f;
|
||||||
|
leftTop += _orientation.getFront() * _scale * -0.1f;
|
||||||
|
rightTop += _orientation.getFront() * _scale * -0.1f;
|
||||||
|
leftBottom += _orientation.getFront() * _scale * -0.1f;
|
||||||
|
rightBottom += _orientation.getFront() * _scale * -0.1f;
|
||||||
|
|
||||||
|
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
|
||||||
|
glVertex3f(leftCorner.x, leftCorner.y, leftCorner.z);
|
||||||
|
glVertex3f(leftBottom.x, leftBottom.y, leftBottom.z);
|
||||||
|
glVertex3f(leftTop.x, leftTop.y, leftTop.z );
|
||||||
|
|
||||||
|
glVertex3f(leftTop.x, leftTop.y, leftTop.z );
|
||||||
|
glVertex3f(rightTop.x, rightTop.y, rightTop.z );
|
||||||
|
glVertex3f(leftBottom.x, leftBottom.y, leftBottom.z);
|
||||||
|
|
||||||
|
glVertex3f(rightTop.x, rightTop.y, rightTop.z );
|
||||||
|
glVertex3f(leftBottom.x, leftBottom.y, leftBottom.z );
|
||||||
|
glVertex3f(rightBottom.x, rightBottom.y, rightBottom.z);
|
||||||
|
|
||||||
|
glVertex3f(rightTop.x, rightTop.y, rightTop.z );
|
||||||
|
glVertex3f(rightBottom.x, rightBottom.y, rightBottom.z);
|
||||||
|
glVertex3f(rightCorner.x, rightCorner.y, rightCorner.z);
|
||||||
|
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Head::renderEyeBalls() {
|
void Head::renderEyeBalls() {
|
||||||
|
|
||||||
if (::irisTexture.size() == 0) {
|
if (::irisTexture.size() == 0) {
|
||||||
|
@ -358,7 +344,7 @@ void Head::renderEyeBalls() {
|
||||||
|
|
||||||
// render white ball of left eyeball
|
// render white ball of left eyeball
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glColor3fv(_eyeColor);
|
glColor3fv(EYEBALL_COLOR);
|
||||||
glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z);
|
glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z);
|
||||||
gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30);
|
gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
@ -369,7 +355,7 @@ void Head::renderEyeBalls() {
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
|
||||||
if (_lookingAtSomething) {
|
//if (_lookingAtSomething) {
|
||||||
|
|
||||||
//rotate the eyeball to aim towards the lookat position
|
//rotate the eyeball to aim towards the lookat position
|
||||||
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _leftEyePosition); // the lookat direction
|
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _leftEyePosition); // the lookat direction
|
||||||
|
@ -377,6 +363,7 @@ void Head::renderEyeBalls() {
|
||||||
float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP);
|
float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP);
|
||||||
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||||
glRotatef(180.0, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations
|
glRotatef(180.0, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations
|
||||||
|
/*
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//rotate the eyeball to aim straight ahead
|
//rotate the eyeball to aim straight ahead
|
||||||
|
@ -390,6 +377,7 @@ void Head::renderEyeBalls() {
|
||||||
if ( dot < 0.0f ) { rollRotation = -rollRotation; }
|
if ( dot < 0.0f ) { rollRotation = -rollRotation; }
|
||||||
glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector
|
glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!)
|
glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!)
|
||||||
glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris
|
glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris
|
||||||
|
@ -402,7 +390,7 @@ void Head::renderEyeBalls() {
|
||||||
|
|
||||||
//render white ball of right eyeball
|
//render white ball of right eyeball
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glColor3fv(_eyeColor);
|
glColor3fv(EYEBALL_COLOR);
|
||||||
glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z);
|
glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z);
|
||||||
gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30);
|
gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
@ -413,7 +401,7 @@ void Head::renderEyeBalls() {
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
|
||||||
if (_lookingAtSomething) {
|
//if (_lookingAtSomething) {
|
||||||
|
|
||||||
//rotate the eyeball to aim towards the lookat position
|
//rotate the eyeball to aim towards the lookat position
|
||||||
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _rightEyePosition);
|
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _rightEyePosition);
|
||||||
|
@ -421,6 +409,7 @@ void Head::renderEyeBalls() {
|
||||||
float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP);
|
float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP);
|
||||||
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||||
glRotatef(180.0f, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations
|
glRotatef(180.0f, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations
|
||||||
|
/*
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//rotate the eyeball to aim straight ahead
|
//rotate the eyeball to aim straight ahead
|
||||||
|
@ -434,6 +423,7 @@ void Head::renderEyeBalls() {
|
||||||
if ( dot < 0.0f ) { rollRotation = -rollRotation; }
|
if ( dot < 0.0f ) { rollRotation = -rollRotation; }
|
||||||
glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector
|
glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!)
|
glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!)
|
||||||
glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris
|
glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris
|
||||||
|
|
|
@ -32,22 +32,21 @@ public:
|
||||||
void render(bool lookingInMirror);
|
void render(bool lookingInMirror);
|
||||||
|
|
||||||
void setLooking(bool looking);
|
void setLooking(bool looking);
|
||||||
void setPositionAndScale(glm::vec3 position, float scale);
|
|
||||||
void setNewTarget(float, float);
|
|
||||||
|
|
||||||
|
void setScale (float scale ) { _scale = scale; }
|
||||||
|
void setPosition (glm::vec3 position ) { _position = position; }
|
||||||
|
void setBodyRotation (glm::vec3 bodyRotation ) { _bodyRotation = bodyRotation; }
|
||||||
|
void setRotationOffBody(glm::vec3 headRotation ) { _headRotation = headRotation; }
|
||||||
void setGravity (glm::vec3 gravity ) { _gravity = gravity; }
|
void setGravity (glm::vec3 gravity ) { _gravity = gravity; }
|
||||||
void setSkinColor (glm::vec3 skinColor ) { _skinColor = skinColor; }
|
void setSkinColor (glm::vec3 skinColor ) { _skinColor = skinColor; }
|
||||||
void setBodyYaw (float bodyYaw ) { _bodyYaw = bodyYaw; }
|
|
||||||
void setSpringScale (float returnSpringScale ) { _returnSpringScale = returnSpringScale; }
|
void setSpringScale (float returnSpringScale ) { _returnSpringScale = returnSpringScale; }
|
||||||
void setAverageLoudness(float averageLoudness ) { _averageLoudness = averageLoudness; }
|
void setAverageLoudness(float averageLoudness ) { _averageLoudness = averageLoudness; }
|
||||||
void setAudioLoudness (float audioLoudness ) { _audioLoudness = audioLoudness; }
|
void setAudioLoudness (float audioLoudness ) { _audioLoudness = audioLoudness; }
|
||||||
void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; }
|
void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; }
|
||||||
|
|
||||||
glm::vec3 getApproximateEyePosition();
|
|
||||||
const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected)
|
const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected)
|
||||||
float getAverageLoudness() {return _averageLoudness;};
|
float getAverageLoudness() {return _averageLoudness;};
|
||||||
|
|
||||||
//some public members (left-over from pulling Head out of Avatar - I may see about privatizing these later).
|
|
||||||
float yawRate;
|
float yawRate;
|
||||||
float noise;
|
float noise;
|
||||||
|
|
||||||
|
@ -60,20 +59,10 @@ private:
|
||||||
glm::vec3 _rotation;
|
glm::vec3 _rotation;
|
||||||
glm::vec3 _leftEyePosition;
|
glm::vec3 _leftEyePosition;
|
||||||
glm::vec3 _rightEyePosition;
|
glm::vec3 _rightEyePosition;
|
||||||
float _eyeballPitch[2];
|
glm::vec3 _leftEarPosition;
|
||||||
float _eyeballYaw [2];
|
glm::vec3 _rightEarPosition;
|
||||||
float _eyebrowPitch[2];
|
glm::vec3 _mouthPosition;
|
||||||
float _eyebrowRoll [2];
|
|
||||||
float _interBrowDistance;
|
|
||||||
float _mouthPitch;
|
|
||||||
float _mouthYaw;
|
|
||||||
float _mouthWidth;
|
|
||||||
float _mouthHeight;
|
|
||||||
float _pitchTarget;
|
|
||||||
float _yawTarget;
|
|
||||||
float _noiseEnvelope;
|
|
||||||
float _scale;
|
float _scale;
|
||||||
int _eyeContact;
|
|
||||||
float _browAudioLift;
|
float _browAudioLift;
|
||||||
bool _lookingAtSomething;
|
bool _lookingAtSomething;
|
||||||
glm::vec3 _gravity;
|
glm::vec3 _gravity;
|
||||||
|
@ -82,13 +71,18 @@ private:
|
||||||
float _audioAttack;
|
float _audioAttack;
|
||||||
float _returnSpringScale; //strength of return springs
|
float _returnSpringScale; //strength of return springs
|
||||||
Orientation _orientation;
|
Orientation _orientation;
|
||||||
float _bodyYaw;
|
glm::vec3 _bodyRotation;
|
||||||
eyeContactTargets _eyeContactTarget;
|
glm::vec3 _headRotation;
|
||||||
|
|
||||||
// private methods
|
// private methods
|
||||||
|
void renderHeadSphere();
|
||||||
void renderEyeBalls();
|
void renderEyeBalls();
|
||||||
|
void renderEyeBrows();
|
||||||
|
void renderEars();
|
||||||
|
void renderMouth();
|
||||||
void debugRenderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition);
|
void debugRenderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition);
|
||||||
void updateEyePositions();
|
void updateEyePositions();
|
||||||
|
void calculateGeometry( bool lookingInMirror);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
107
interface/src/Transmitter.cpp
Normal file
107
interface/src/Transmitter.cpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
//
|
||||||
|
// Transmitter.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Philip Rosedale on 5/20/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Transmitter.h"
|
||||||
|
#include "InterfaceConfig.h"
|
||||||
|
#include "Util.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
const float DELTA_TIME = 1.f / 60.f;
|
||||||
|
const float DECAY_RATE = 0.15f;
|
||||||
|
|
||||||
|
Transmitter::Transmitter() :
|
||||||
|
_isConnected(false),
|
||||||
|
_lastRotationRate(0,0,0),
|
||||||
|
_lastAcceleration(0,0,0),
|
||||||
|
_estimatedRotation(0,0,0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Transmitter::resetLevels() {
|
||||||
|
_lastRotationRate *= 0.f;
|
||||||
|
_estimatedRotation *= 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Transmitter::processIncomingData(unsigned char* packetData, int numBytes) {
|
||||||
|
if (numBytes == 3 + sizeof(_lastRotationRate) +
|
||||||
|
sizeof(_lastAcceleration)) {
|
||||||
|
memcpy(&_lastRotationRate, packetData + 2, sizeof(_lastRotationRate));
|
||||||
|
memcpy(&_lastAcceleration, packetData + 3 + sizeof(_lastAcceleration), sizeof(_lastAcceleration));
|
||||||
|
|
||||||
|
// Update estimated absolute position from rotation rates
|
||||||
|
_estimatedRotation += _lastRotationRate * DELTA_TIME;
|
||||||
|
|
||||||
|
// Decay estimated absolute position to slowly return to zero regardless
|
||||||
|
_estimatedRotation *= (1.f - DECAY_RATE * DELTA_TIME);
|
||||||
|
|
||||||
|
if (!_isConnected) {
|
||||||
|
printf("Transmitter V2 Connected.\n");
|
||||||
|
_isConnected = true;
|
||||||
|
_estimatedRotation *= 0.0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Transmitter V2 packet read error.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Transmitter::renderLevels(int width, int height) {
|
||||||
|
char val[50];
|
||||||
|
const int LEVEL_CORNER_X = 10;
|
||||||
|
const int LEVEL_CORNER_Y = 400;
|
||||||
|
|
||||||
|
// Draw the numeric degree/sec values from the gyros
|
||||||
|
sprintf(val, "Pitch Rate %4.1f", _lastRotationRate.x);
|
||||||
|
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y, 0.10, 0, 1.0, 1, val, 0, 1, 0);
|
||||||
|
sprintf(val, "Yaw Rate %4.1f", _lastRotationRate.y);
|
||||||
|
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 15, 0.10, 0, 1.0, 1, val, 0, 1, 0);
|
||||||
|
sprintf(val, "Roll Rate %4.1f", _lastRotationRate.z);
|
||||||
|
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 30, 0.10, 0, 1.0, 1, val, 0, 1, 0);
|
||||||
|
sprintf(val, "Pitch %4.3f", _estimatedRotation.x);
|
||||||
|
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 45, 0.10, 0, 1.0, 1, val, 0, 1, 0);
|
||||||
|
sprintf(val, "Yaw %4.3f", _estimatedRotation.y);
|
||||||
|
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 60, 0.10, 0, 1.0, 1, val, 0, 1, 0);
|
||||||
|
sprintf(val, "Roll %4.3f", _estimatedRotation.z);
|
||||||
|
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 75, 0.10, 0, 1.0, 1, val, 0, 1, 0);
|
||||||
|
|
||||||
|
// Draw the levels as horizontal lines
|
||||||
|
const int LEVEL_CENTER = 150;
|
||||||
|
const float ACCEL_VIEW_SCALING = 1.f;
|
||||||
|
glLineWidth(2.0);
|
||||||
|
glColor4f(1, 1, 1, 1);
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
// Gyro rates
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y - 3);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastRotationRate.x, LEVEL_CORNER_Y - 3);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 12);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastRotationRate.y, LEVEL_CORNER_Y + 12);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 27);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastRotationRate.z, LEVEL_CORNER_Y + 27);
|
||||||
|
// Acceleration
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 42);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + (int)(_estimatedRotation.x * ACCEL_VIEW_SCALING),
|
||||||
|
LEVEL_CORNER_Y + 42);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 57);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + (int)(_estimatedRotation.y * ACCEL_VIEW_SCALING),
|
||||||
|
LEVEL_CORNER_Y + 57);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 72);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + (int)(_estimatedRotation.z * ACCEL_VIEW_SCALING),
|
||||||
|
LEVEL_CORNER_Y + 72);
|
||||||
|
|
||||||
|
glEnd();
|
||||||
|
// Draw green vertical centerline
|
||||||
|
glColor4f(0, 1, 0, 0.5);
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y - 6);
|
||||||
|
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 30);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,21 +1,38 @@
|
||||||
//
|
//
|
||||||
// Transmitter.h
|
// Transmitter.h
|
||||||
// interface
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Philip Rosedale on 5/20/13.
|
||||||
//
|
//
|
||||||
// Created by Brad Hefta-Gaub on 5/21/2013
|
|
||||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef __interface__transmitter__
|
#ifndef __hifi__Transmitter__
|
||||||
#define __interface__transmitter__
|
#define __hifi__Transmitter__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
#include <cstring>
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
class Transmitter {
|
class Transmitter
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
void processIncomingData(unsigned char* buffer, int size) { };
|
Transmitter();
|
||||||
void renderLevels(int x, int y) { };
|
void render();
|
||||||
void resetLevels(int x = 0, int y = 0) { };
|
void resetLevels();
|
||||||
bool isConnected() const { return false; };
|
void renderLevels(int width, int height);
|
||||||
glm::vec3 getEstimatedRotation() const { return glm::vec3(0, 0, 0); };
|
bool isConnected() { return _isConnected; };
|
||||||
|
const glm::vec3 getLastRotationRate() const { return _lastRotationRate; };
|
||||||
|
const glm::vec3 getLastAcceleration() const { return _lastRotationRate; };
|
||||||
|
const glm::vec3 getEstimatedRotation() const { return _estimatedRotation; };
|
||||||
|
void processIncomingData(unsigned char* packetData, int numBytes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _isConnected;
|
||||||
|
glm::vec3 _lastRotationRate;
|
||||||
|
glm::vec3 _lastAcceleration;
|
||||||
|
glm::vec3 _estimatedRotation;
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__Transmitter__) */
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
|
@ -106,20 +106,16 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
{
|
{
|
||||||
PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
|
PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
|
||||||
// ask the VoxelTree to read the bitstream into the tree
|
// ask the VoxelTree to read the bitstream into the tree
|
||||||
_tree->readBitstreamToTree(voxelData, numBytes - 1);
|
_tree->readBitstreamToTree(voxelData, numBytes - 1, WANT_COLOR, WANT_EXISTS_BITS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PACKET_HEADER_VOXEL_DATA_MONOCHROME:
|
case PACKET_HEADER_VOXEL_DATA_MONOCHROME:
|
||||||
{
|
{
|
||||||
PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
|
PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
|
||||||
// ask the VoxelTree to read the MONOCHROME bitstream into the tree
|
// ask the VoxelTree to read the MONOCHROME bitstream into the tree
|
||||||
_tree->readBitstreamToTree(voxelData, numBytes - 1, false);
|
_tree->readBitstreamToTree(voxelData, numBytes - 1, NO_COLOR, WANT_EXISTS_BITS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PACKET_HEADER_ERASE_VOXEL:
|
|
||||||
// ask the tree to read the "remove" bitstream
|
|
||||||
_tree->processRemoveVoxelBitstream(sourceBuffer, numBytes);
|
|
||||||
break;
|
|
||||||
case PACKET_HEADER_Z_COMMAND:
|
case PACKET_HEADER_Z_COMMAND:
|
||||||
|
|
||||||
// the Z command is a special command that allows the sender to send high level semantic
|
// the Z command is a special command that allows the sender to send high level semantic
|
||||||
|
@ -186,7 +182,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||||
if (_tree->isDirty()) {
|
if (_tree->isDirty()) {
|
||||||
static char buffer[64] = { 0 };
|
static char buffer[64] = { 0 };
|
||||||
if (_renderWarningsOn) {
|
if (_renderWarningsOn) {
|
||||||
sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", (_writeRenderFullVBO ? "yes" : "no"));
|
sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", debug::valueOf(_writeRenderFullVBO));
|
||||||
};
|
};
|
||||||
PerformanceWarning warn(_renderWarningsOn, buffer);
|
PerformanceWarning warn(_renderWarningsOn, buffer);
|
||||||
_callsToTreesToArrays++;
|
_callsToTreesToArrays++;
|
||||||
|
@ -614,7 +610,7 @@ void VoxelSystem::updatePartialVBOs() {
|
||||||
void VoxelSystem::updateVBOs() {
|
void VoxelSystem::updateVBOs() {
|
||||||
static char buffer[40] = { 0 };
|
static char buffer[40] = { 0 };
|
||||||
if (_renderWarningsOn) {
|
if (_renderWarningsOn) {
|
||||||
sprintf(buffer, "updateVBOs() _readRenderFullVBO=%s", (_readRenderFullVBO ? "yes" : "no"));
|
sprintf(buffer, "updateVBOs() _readRenderFullVBO=%s", debug::valueOf(_readRenderFullVBO));
|
||||||
};
|
};
|
||||||
PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays
|
PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays
|
||||||
if (_voxelsDirty) {
|
if (_voxelsDirty) {
|
||||||
|
@ -1030,7 +1026,7 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* ex
|
||||||
if (args->hasIndexFound[nodeIndex]) {
|
if (args->hasIndexFound[nodeIndex]) {
|
||||||
args->duplicateVBOIndex++;
|
args->duplicateVBOIndex++;
|
||||||
printLog("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex,
|
printLog("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex,
|
||||||
node->isDirty() ? "yes" : "no" , node->getShouldRender() ? "yes" : "no" );
|
debug::valueOf(node->isDirty()), debug::valueOf(node->getShouldRender()));
|
||||||
} else {
|
} else {
|
||||||
args->hasIndexFound[nodeIndex] = true;
|
args->hasIndexFound[nodeIndex] = true;
|
||||||
}
|
}
|
||||||
|
@ -1059,7 +1055,7 @@ void VoxelSystem::collectStatsForTreesAndVBOs() {
|
||||||
args.expectedMax = _voxelsInWriteArrays;
|
args.expectedMax = _voxelsInWriteArrays;
|
||||||
_tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args);
|
_tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args);
|
||||||
|
|
||||||
printLog("_voxelsDirty=%s _voxelsInWriteArrays=%ld minDirty=%ld maxDirty=%ld \n", (_voxelsDirty ? "yes" : "no"),
|
printLog("_voxelsDirty=%s _voxelsInWriteArrays=%ld minDirty=%ld maxDirty=%ld \n", debug::valueOf(_voxelsDirty),
|
||||||
_voxelsInWriteArrays, minDirty, maxDirty);
|
_voxelsInWriteArrays, minDirty, maxDirty);
|
||||||
|
|
||||||
printLog("stats: total %ld, leaves %ld, dirty %ld, colored %ld, shouldRender %ld, inVBO %ld\n",
|
printLog("stats: total %ld, leaves %ld, dirty %ld, colored %ld, shouldRender %ld, inVBO %ld\n",
|
||||||
|
|
|
@ -82,7 +82,6 @@ public:
|
||||||
void createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive = false);
|
void createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive = false);
|
||||||
void createSphere(float r,float xc, float yc, float zc, float s, bool solid,
|
void createSphere(float r,float xc, float yc, float zc, float s, bool solid,
|
||||||
creationMode mode, bool destructive = false, bool debug = false);
|
creationMode mode, bool destructive = false, bool debug = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// disallow copying of VoxelSystem objects
|
// disallow copying of VoxelSystem objects
|
||||||
VoxelSystem(const VoxelSystem&);
|
VoxelSystem(const VoxelSystem&);
|
||||||
|
@ -156,7 +155,7 @@ private:
|
||||||
void copyWrittenDataToReadArrays(bool fullVBOs);
|
void copyWrittenDataToReadArrays(bool fullVBOs);
|
||||||
|
|
||||||
bool _voxelsDirty;
|
bool _voxelsDirty;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void updateVBOs();
|
void updateVBOs();
|
||||||
void updateFullVBOs(); // all voxels in the VBO
|
void updateFullVBOs(); // all voxels in the VBO
|
||||||
|
|
15955
interface/src/glew.cpp
15955
interface/src/glew.cpp
File diff suppressed because it is too large
Load diff
|
@ -1,158 +0,0 @@
|
||||||
//
|
|
||||||
// Menu.cpp
|
|
||||||
// hifi
|
|
||||||
//
|
|
||||||
// Created by Dominque Vincent on 4/10/13.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "InterfaceConfig.h"
|
|
||||||
#include "Util.h"
|
|
||||||
|
|
||||||
#include "MenuRow.h"
|
|
||||||
#include "MenuColumn.h"
|
|
||||||
#include "Menu.h"
|
|
||||||
|
|
||||||
|
|
||||||
const int LINE_HEIGHT = 30;
|
|
||||||
const int MENU_HEIGHT = 30;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
const int MENU_Y_OFFSET = 8; // under windows we have 8 vertical pixels offset.
|
|
||||||
// In 2D an object with y=8, the object is displayed at y=0
|
|
||||||
// change the value in the other platforms (if required).
|
|
||||||
#else
|
|
||||||
const int MENU_Y_OFFSET = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Menu::Menu() {
|
|
||||||
currentColumn = -1;
|
|
||||||
leftMouseOver = 0;
|
|
||||||
rightMouseOver = 0;
|
|
||||||
topMouseOver = 0;
|
|
||||||
bottomMouseOver = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Menu::~Menu() {
|
|
||||||
columns.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Menu::mouseClickColumn(int columnIndex) {
|
|
||||||
if (currentColumn == columnIndex) {
|
|
||||||
currentColumn = -1;
|
|
||||||
} else {
|
|
||||||
currentColumn = columnIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Menu::setMouseOver(int leftPosition, int rightPosition, int top, int bottom) {
|
|
||||||
leftMouseOver = leftPosition;
|
|
||||||
rightMouseOver = rightPosition;
|
|
||||||
topMouseOver = top;
|
|
||||||
bottomMouseOver = bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Menu::renderMouseOver() {
|
|
||||||
if (leftMouseOver != 0 || topMouseOver != 0 || rightMouseOver != 0 ||& bottomMouseOver != 0) {
|
|
||||||
glColor4f(0, 0, 0, 0.1);
|
|
||||||
glBegin(GL_QUADS); {
|
|
||||||
glVertex2f(leftMouseOver, MENU_Y_OFFSET + topMouseOver);
|
|
||||||
glVertex2f(rightMouseOver, MENU_Y_OFFSET + topMouseOver);
|
|
||||||
glVertex2f(rightMouseOver, MENU_Y_OFFSET + bottomMouseOver);
|
|
||||||
glVertex2f(leftMouseOver, MENU_Y_OFFSET + bottomMouseOver);
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Menu::mouseClick(int x, int y) {
|
|
||||||
int leftPosition = 0.5 * SPACE_BETWEEN_COLUMNS;
|
|
||||||
int rightPosition = 0;
|
|
||||||
int columnWidth = 0;
|
|
||||||
bool menuFound = false;
|
|
||||||
for (unsigned int i = 0; i < columns.size(); ++i) {
|
|
||||||
columnWidth = columns[i].getWidth();
|
|
||||||
rightPosition = leftPosition + columnWidth + 1.5 * SPACE_BETWEEN_COLUMNS;
|
|
||||||
if (x > leftPosition && x < rightPosition && y > 0 && y < MENU_HEIGHT) {
|
|
||||||
mouseClickColumn(i);
|
|
||||||
menuFound = true;
|
|
||||||
break;
|
|
||||||
} else if (currentColumn == i) {
|
|
||||||
menuFound = columns[i].mouseClick(x, y, leftPosition, MENU_HEIGHT, LINE_HEIGHT);
|
|
||||||
if (menuFound) {
|
|
||||||
currentColumn = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
leftPosition = rightPosition;
|
|
||||||
}
|
|
||||||
return menuFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Menu::mouseOver(int x, int y) {
|
|
||||||
int leftPosition = 0.5 * SPACE_BETWEEN_COLUMNS;
|
|
||||||
int rightPosition;
|
|
||||||
int columnWidth;
|
|
||||||
bool overMenu = false;
|
|
||||||
for (unsigned int i = 0; i < columns.size(); ++i) {
|
|
||||||
columnWidth = columns[i].getWidth();
|
|
||||||
rightPosition = leftPosition + columnWidth + SPACE_BETWEEN_COLUMNS;
|
|
||||||
if (x > leftPosition && x < rightPosition && y > 0 && y < MENU_HEIGHT) {
|
|
||||||
setMouseOver(leftPosition, rightPosition, 0, MENU_HEIGHT);
|
|
||||||
overMenu = true;
|
|
||||||
if (currentColumn >= 0) {
|
|
||||||
columns[currentColumn].setMouseOver(0, 0, 0, 0);
|
|
||||||
currentColumn = i;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else if (currentColumn == i) {
|
|
||||||
columns[i].mouseOver(x, y, leftPosition, MENU_HEIGHT, LINE_HEIGHT);
|
|
||||||
}
|
|
||||||
leftPosition = rightPosition;
|
|
||||||
}
|
|
||||||
if (!overMenu) {
|
|
||||||
setMouseOver(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
return overMenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float MENU_COLOR[3] = {0.75, 0.75, 0.75};
|
|
||||||
|
|
||||||
void Menu::render(int screenWidth, int screenHeight) {
|
|
||||||
float scale = 0.10;
|
|
||||||
int mono = 0;
|
|
||||||
glColor3fv(MENU_COLOR);
|
|
||||||
int width = screenWidth;
|
|
||||||
glEnable(GL_LINE_SMOOTH);
|
|
||||||
glBegin(GL_QUADS); {
|
|
||||||
glVertex2f(0, MENU_Y_OFFSET);
|
|
||||||
glVertex2f(width, MENU_Y_OFFSET);
|
|
||||||
glVertex2f(width, MENU_HEIGHT + MENU_Y_OFFSET);
|
|
||||||
glVertex2f(0 , MENU_HEIGHT + MENU_Y_OFFSET);
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
int xPosition = SPACE_BETWEEN_COLUMNS;
|
|
||||||
char* columnName;
|
|
||||||
int columnWidth;
|
|
||||||
for (unsigned int i = 0; i < columns.size(); ++i) {
|
|
||||||
columnName = columns[i].getName();
|
|
||||||
columnWidth = columns[i].getWidth(scale, mono, xPosition - 0.5 * SPACE_BETWEEN_COLUMNS);
|
|
||||||
drawtext(xPosition, 18 + MENU_Y_OFFSET, scale, 0, 1.0, mono, columnName, 0, 0, 0);
|
|
||||||
xPosition += columnWidth + SPACE_BETWEEN_COLUMNS;
|
|
||||||
if (currentColumn == i) {
|
|
||||||
columns[i].render(MENU_Y_OFFSET, MENU_HEIGHT, LINE_HEIGHT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
renderMouseOver();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MenuColumn* Menu::addColumn(const char *columnName) {
|
|
||||||
MenuColumn* pColumn;
|
|
||||||
pColumn = new MenuColumn(columnName);
|
|
||||||
columns.push_back(*pColumn);
|
|
||||||
delete pColumn;
|
|
||||||
return &columns[columns.size() - 1];
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
//
|
|
||||||
// Menu.h
|
|
||||||
// hifi
|
|
||||||
//
|
|
||||||
// Created by Dominque Vincent on 4/10/13.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __hifi__Menu__
|
|
||||||
#define __hifi__Menu__
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
|
|
||||||
class Menu {
|
|
||||||
public:
|
|
||||||
Menu();
|
|
||||||
~Menu();
|
|
||||||
void mouseClickColumn(int iColumnIndex);
|
|
||||||
void setMouseOver(int xLeft, int xRight, int yTop, int yBottom);
|
|
||||||
void renderMouseOver();
|
|
||||||
bool mouseClick(int x, int y);
|
|
||||||
bool mouseOver(int x, int y);
|
|
||||||
void render(int screenwidth, int screenheight);
|
|
||||||
void renderColumn(int i);
|
|
||||||
MenuColumn* addColumn(const char *columnName);
|
|
||||||
void hidePopupMenu() { currentColumn = -1; };
|
|
||||||
private:
|
|
||||||
std::vector<MenuColumn> columns;
|
|
||||||
int currentColumn;
|
|
||||||
int leftMouseOver;
|
|
||||||
int rightMouseOver;
|
|
||||||
int topMouseOver;
|
|
||||||
int bottomMouseOver;
|
|
||||||
};
|
|
||||||
#endif /* defined(__hifi__Menu__) */
|
|
|
@ -1,183 +0,0 @@
|
||||||
//
|
|
||||||
// MenuColumn.cpp
|
|
||||||
// hifi
|
|
||||||
//
|
|
||||||
// Created by Dominque Vincent on 4/10/13.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "InterfaceConfig.h"
|
|
||||||
#include "Util.h"
|
|
||||||
|
|
||||||
#include "MenuRow.h"
|
|
||||||
#include "MenuColumn.h"
|
|
||||||
#include "Menu.h"
|
|
||||||
|
|
||||||
#include "ui/TextRenderer.h"
|
|
||||||
|
|
||||||
MenuColumn::MenuColumn() {
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuColumn::MenuColumn(const char* columnName) {
|
|
||||||
int length = std::min(MAX_COLUMN_NAME - 1,(int) strlen(columnName));
|
|
||||||
strncpy(this->columnName, columnName, length);
|
|
||||||
this->columnName[length] = '\0';
|
|
||||||
columnWidth = 0;
|
|
||||||
leftPosition = 0;
|
|
||||||
leftMouseOver = 0;
|
|
||||||
rightMouseOver = 0;
|
|
||||||
topMouseOver = 0;
|
|
||||||
bottomMouseOver = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuColumn::~MenuColumn() {
|
|
||||||
rows.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuColumn::mouseClickRow(int numberOfRowsIndex) {
|
|
||||||
rows[numberOfRowsIndex].call();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MenuColumn::mouseClick(int x, int y, int leftPosition, int menuHeight, int lineHeight) {
|
|
||||||
int rightPosition = leftPosition + 200; // XXXBHG - this looks like a hack?
|
|
||||||
int topPosition = menuHeight;
|
|
||||||
int bottomPosition = menuHeight;
|
|
||||||
int columnWidth = 0;
|
|
||||||
bool menuFound = false;
|
|
||||||
for (unsigned int i = 0; i < rows.size(); ++i) {
|
|
||||||
columnWidth = rows[i].getWidth();
|
|
||||||
topPosition = bottomPosition + lineHeight;
|
|
||||||
if (x > leftPosition && x < rightPosition && y > bottomPosition && y < topPosition) {
|
|
||||||
mouseClickRow(i);
|
|
||||||
menuFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bottomPosition = topPosition;
|
|
||||||
}
|
|
||||||
return menuFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuColumn::setMouseOver(int leftPosition, int rightPosition, int topPosition, int bottomPosition) {
|
|
||||||
leftMouseOver = leftPosition;
|
|
||||||
rightMouseOver = rightPosition;
|
|
||||||
topMouseOver = topPosition;
|
|
||||||
bottomMouseOver = bottomPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MenuColumn::mouseOver(int x, int y, int leftPosition, int menuHeight, int lineHeight) {
|
|
||||||
|
|
||||||
int maxColumnWidth = this->getMaxRowWidth();
|
|
||||||
|
|
||||||
int rightPosition = leftPosition + maxColumnWidth;
|
|
||||||
int topPosition = menuHeight;
|
|
||||||
int bottomPosition = menuHeight;
|
|
||||||
bool overMenu = false;
|
|
||||||
for (unsigned int i = 0; i < rows.size(); ++i) {
|
|
||||||
topPosition = bottomPosition + lineHeight ;
|
|
||||||
if (x > leftPosition && x < rightPosition && y > bottomPosition && y < topPosition) {
|
|
||||||
setMouseOver(leftPosition, rightPosition, bottomPosition, topPosition);
|
|
||||||
overMenu = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bottomPosition = topPosition;
|
|
||||||
}
|
|
||||||
if (!overMenu) {
|
|
||||||
setMouseOver(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
return overMenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* MenuColumn::getName() {
|
|
||||||
return this->columnName;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MenuColumn::getWidth(float scale, int mono, int leftPosition) {
|
|
||||||
if (columnWidth == 0) {
|
|
||||||
columnWidth = widthText(scale, mono, this->columnName);
|
|
||||||
this->leftPosition = leftPosition;
|
|
||||||
}
|
|
||||||
return columnWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MenuColumn::getWidth() {
|
|
||||||
return columnWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MenuColumn::getLeftPosition() {
|
|
||||||
return leftPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MenuColumn::addRow(const char* rowName, MenuRowCallback callback) {
|
|
||||||
MenuRow* row;
|
|
||||||
row = new MenuRow(rowName, callback);
|
|
||||||
rows.push_back(*row);
|
|
||||||
delete row;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MenuColumn::addRow(const char* rowName, MenuRowCallback callback, MenuStateNameCallback stateNameCallback) {
|
|
||||||
MenuRow* row;
|
|
||||||
row = new MenuRow(rowName, callback, stateNameCallback);
|
|
||||||
rows.push_back(*row);
|
|
||||||
delete row;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MenuColumn::getMaxRowWidth() {
|
|
||||||
float scale = 0.09;
|
|
||||||
int mono = 0;
|
|
||||||
int maxColumnWidth = 100 - (SPACE_BEFORE_ROW_NAME*2); // the minimum size we want
|
|
||||||
for (unsigned int i = 0; i < rows.size(); ++i) {
|
|
||||||
maxColumnWidth = std::max(maxColumnWidth,rows[i].getWidth(scale, mono, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
maxColumnWidth += SPACE_BEFORE_ROW_NAME*2; // space before and after!!
|
|
||||||
return maxColumnWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
static TextRenderer* textRenderer() {
|
|
||||||
static TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 11);
|
|
||||||
return renderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuColumn::render(int yOffset, int menuHeight, int lineHeight) {
|
|
||||||
int numberOfRows = rows.size();
|
|
||||||
if (numberOfRows > 0) {
|
|
||||||
|
|
||||||
int maxColumnWidth = this->getMaxRowWidth();
|
|
||||||
|
|
||||||
glColor3f(0.9,0.9,0.9);
|
|
||||||
glBegin(GL_QUADS); {
|
|
||||||
glVertex2f(leftPosition, yOffset + menuHeight);
|
|
||||||
glVertex2f(leftPosition+maxColumnWidth, yOffset + menuHeight);
|
|
||||||
glVertex2f(leftPosition+maxColumnWidth, yOffset + menuHeight + numberOfRows*lineHeight);
|
|
||||||
glVertex2f(leftPosition , yOffset + menuHeight + numberOfRows* lineHeight);
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
int y = menuHeight + lineHeight / 2 ;
|
|
||||||
char* rowName;
|
|
||||||
for (unsigned int i = 0; i < rows.size(); ++i) {
|
|
||||||
rowName = rows[i].getName();
|
|
||||||
glColor3f(0, 0, 0);
|
|
||||||
textRenderer()->draw(leftPosition + SPACE_BEFORE_ROW_NAME, y + 5 + yOffset, rowName);
|
|
||||||
y += lineHeight;
|
|
||||||
}
|
|
||||||
renderMouseOver(yOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuColumn::renderMouseOver(int yOffset) {
|
|
||||||
if (leftMouseOver != 0 || topMouseOver != 0 || rightMouseOver != 0 ||& bottomMouseOver != 0) {
|
|
||||||
glColor4f(0,0,0,0.1);
|
|
||||||
glBegin(GL_QUADS); {
|
|
||||||
glVertex2f(leftMouseOver, yOffset + topMouseOver);
|
|
||||||
glVertex2f(rightMouseOver, yOffset + topMouseOver);
|
|
||||||
glVertex2f(rightMouseOver, yOffset + bottomMouseOver);
|
|
||||||
glVertex2f(leftMouseOver , yOffset + bottomMouseOver);
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
//
|
|
||||||
// MenuColumn.h
|
|
||||||
// hifi
|
|
||||||
//
|
|
||||||
// Created by Dominque Vincent on 4/10/13.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __hifi__MenuColumn__
|
|
||||||
#define __hifi__MenuColumn__
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class MenuColumn {
|
|
||||||
public:
|
|
||||||
MenuColumn();
|
|
||||||
MenuColumn(const char* columnName);
|
|
||||||
~MenuColumn();
|
|
||||||
void mouseClickRow(int iColumnIndex);
|
|
||||||
bool mouseClick(int x, int y, int xLeft, int menuHeight, int lineHeight);
|
|
||||||
void setMouseOver(int xLeft, int xRight, int yTop, int yBottom);
|
|
||||||
bool mouseOver(int x, int y, int xLeft, int menuHeight, int lineHeight);
|
|
||||||
char* getName();
|
|
||||||
int getWidth(float scale, int mono, int leftPosition);
|
|
||||||
int getWidth();
|
|
||||||
int getLeftPosition();
|
|
||||||
void render(int yOffset, int menuHeight, int lineHeight);
|
|
||||||
void renderMouseOver(int yOffset);
|
|
||||||
int addRow(const char* rowName, MenuRowCallback callback);
|
|
||||||
int addRow(const char* rowName, MenuRowCallback callback, MenuStateNameCallback stateNameCallback);
|
|
||||||
int getMaxRowWidth();
|
|
||||||
private:
|
|
||||||
char columnName[MAX_COLUMN_NAME];
|
|
||||||
int columnWidth;
|
|
||||||
int leftPosition;
|
|
||||||
std::vector<MenuRow> rows;
|
|
||||||
int leftMouseOver;
|
|
||||||
int rightMouseOver;
|
|
||||||
int topMouseOver;
|
|
||||||
int bottomMouseOver;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined(__hifi__MenuColumn__) */
|
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
//
|
|
||||||
// MenuRow.cpp
|
|
||||||
// hifi
|
|
||||||
//
|
|
||||||
// Created by Dominque Vincent on 4/10/13.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "InterfaceConfig.h"
|
|
||||||
#include "Util.h"
|
|
||||||
|
|
||||||
#include "MenuRow.h"
|
|
||||||
#include "MenuColumn.h"
|
|
||||||
#include "Menu.h"
|
|
||||||
|
|
||||||
MenuRow::MenuRow() :
|
|
||||||
callback(NULL),
|
|
||||||
stateNameCallback(NULL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuRow::MenuRow(const char * columnName, MenuRowCallback callback) :
|
|
||||||
callback(callback),
|
|
||||||
stateNameCallback(NULL) {
|
|
||||||
this->nameLength = strlen(columnName);
|
|
||||||
strncpy(this->rowName, columnName, MAX_COLUMN_NAME); // copy the base name
|
|
||||||
strncpy(this->rowName, this->getName(), MAX_COLUMN_NAME); // now add in state
|
|
||||||
rowWidth = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuRow::MenuRow(const char * columnName, MenuRowCallback callback, MenuStateNameCallback stateNameCallback) :
|
|
||||||
callback(callback),
|
|
||||||
stateNameCallback(stateNameCallback) {
|
|
||||||
this->nameLength = strlen(columnName);
|
|
||||||
strncpy(this->rowName, columnName, MAX_COLUMN_NAME);
|
|
||||||
strncpy(this->rowName, this->getName(), MAX_COLUMN_NAME); // now add in state
|
|
||||||
rowWidth = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuRow::~MenuRow() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRow::call() {
|
|
||||||
callback(MENU_ROW_PICKED);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* MenuRow::getStateName() {
|
|
||||||
int currentValue = callback(MENU_ROW_GET_VALUE);
|
|
||||||
const char* stateName;
|
|
||||||
// If the MenuRow has a custom stateNameCallback function, then call it to get a string
|
|
||||||
// to display in the menu. Otherwise, use the default implementation.
|
|
||||||
if (stateNameCallback != NULL) {
|
|
||||||
stateName = stateNameCallback(currentValue);
|
|
||||||
} else {
|
|
||||||
if (currentValue == 0) {
|
|
||||||
stateName = " OFF ";
|
|
||||||
} else if (currentValue == 1) {
|
|
||||||
stateName = " ON ";
|
|
||||||
} else {
|
|
||||||
stateName = " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return stateName;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* MenuRow::getName() {
|
|
||||||
strcpy(this->rowName + nameLength, getStateName());
|
|
||||||
return this->rowName;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MenuRow::getWidth(float scale, int mono, int leftPosition) {
|
|
||||||
if (rowWidth == 0) {
|
|
||||||
rowWidth = widthText( scale, mono, this->rowName);
|
|
||||||
}
|
|
||||||
return rowWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MenuRow::getWidth() {
|
|
||||||
return rowWidth;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
//
|
|
||||||
// MenuRow.h
|
|
||||||
// hifi
|
|
||||||
//
|
|
||||||
// Created by Dominque Vincent on 4/10/13.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __hifi__MenuRow__
|
|
||||||
#define __hifi__MenuRow__
|
|
||||||
|
|
||||||
const int MAX_COLUMN_NAME = 50;
|
|
||||||
const int SPACE_BETWEEN_COLUMNS = 20;
|
|
||||||
const int SPACE_BEFORE_ROW_NAME = 10;
|
|
||||||
const int MENU_ROW_PICKED = -2;
|
|
||||||
const int MENU_ROW_GET_VALUE = -1;
|
|
||||||
|
|
||||||
typedef int(*MenuRowCallback)(int);
|
|
||||||
typedef const char*(*MenuStateNameCallback)(int);
|
|
||||||
|
|
||||||
class MenuRow {
|
|
||||||
public:
|
|
||||||
MenuRow();
|
|
||||||
MenuRow(const char* rowName, MenuRowCallback callback);
|
|
||||||
MenuRow(const char* rowName, MenuRowCallback callback, MenuStateNameCallback stateNameCallback);
|
|
||||||
~MenuRow();
|
|
||||||
void call();
|
|
||||||
char * getName();
|
|
||||||
const char* getStateName();
|
|
||||||
int getWidth(float scale, int mono, int leftPosition);
|
|
||||||
int getWidth();
|
|
||||||
private:
|
|
||||||
int nameLength;
|
|
||||||
char rowName[MAX_COLUMN_NAME];
|
|
||||||
int rowWidth;
|
|
||||||
MenuRowCallback callback;
|
|
||||||
MenuStateNameCallback stateNameCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined(__hifi__MenuRow__) */
|
|
|
@ -54,7 +54,6 @@ AvatarData::AvatarData() :
|
||||||
_wantDelta(false),
|
_wantDelta(false),
|
||||||
_headData(NULL)
|
_headData(NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarData::~AvatarData() {
|
AvatarData::~AvatarData() {
|
||||||
|
@ -232,10 +231,9 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
// voxel sending features...
|
// voxel sending features...
|
||||||
unsigned char wantItems = 0;
|
unsigned char wantItems = 0;
|
||||||
wantItems = (unsigned char)*sourceBuffer++;
|
wantItems = (unsigned char)*sourceBuffer++;
|
||||||
|
|
||||||
_wantResIn = oneAtBit(wantItems,WANT_RESIN_AT_BIT);
|
_wantResIn = oneAtBit(wantItems,WANT_RESIN_AT_BIT);
|
||||||
_wantColor = oneAtBit(wantItems,WANT_COLOR_AT_BIT);
|
_wantColor = oneAtBit(wantItems,WANT_COLOR_AT_BIT);
|
||||||
_wantDelta = oneAtBit(wantItems,WANT_DELTA_AT_BIT);
|
_wantDelta = oneAtBit(wantItems,WANT_DELTA_AT_BIT);
|
||||||
|
|
||||||
return sourceBuffer - startPosition;
|
return sourceBuffer - startPosition;
|
||||||
}
|
}
|
|
@ -250,7 +250,9 @@ Agent* AgentList::addOrUpdateAgent(sockaddr* publicSocket, sockaddr* localSocket
|
||||||
return newAgent;
|
return newAgent;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (agent->getType() == AGENT_TYPE_AUDIO_MIXER || agent->getType() == AGENT_TYPE_VOXEL) {
|
if (agent->getType() == AGENT_TYPE_AUDIO_MIXER ||
|
||||||
|
agent->getType() == AGENT_TYPE_VOXEL ||
|
||||||
|
agent->getType() == AGENT_TYPE_ANIMATION_SERVER) {
|
||||||
// until the Audio class also uses our agentList, we need to update
|
// until the Audio class also uses our agentList, we need to update
|
||||||
// the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously
|
// the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously
|
||||||
agent->setLastHeardMicrostamp(usecTimestampNow());
|
agent->setLastHeardMicrostamp(usecTimestampNow());
|
||||||
|
|
|
@ -80,4 +80,9 @@ int insertIntoSortedArrays(void* value, float key, int originalIndex,
|
||||||
void** valueArray, float* keyArray, int* originalIndexArray,
|
void** valueArray, float* keyArray, int* originalIndexArray,
|
||||||
int currentCount, int maxCount);
|
int currentCount, int maxCount);
|
||||||
|
|
||||||
|
// Helper Class for debugging
|
||||||
|
class debug {
|
||||||
|
public:
|
||||||
|
static const char* valueOf(bool checkValue) { return checkValue ? "yes" : "no"; };
|
||||||
|
};
|
||||||
#endif /* defined(__hifi__SharedUtil__) */
|
#endif /* defined(__hifi__SharedUtil__) */
|
||||||
|
|
|
@ -243,7 +243,7 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo) const {
|
||||||
compareTo._eyeOffsetOrientation == _eyeOffsetOrientation;
|
compareTo._eyeOffsetOrientation == _eyeOffsetOrientation;
|
||||||
|
|
||||||
if (!result && debug) {
|
if (!result && debug) {
|
||||||
printLog("ViewFrustum::matches()... result=%s\n", (result ? "yes" : "no"));
|
printLog("ViewFrustum::matches()... result=%s\n", debug::valueOf(result));
|
||||||
printLog("%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f\n",
|
printLog("%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f\n",
|
||||||
(compareTo._position == _position ? "MATCHES " : "NO MATCH"),
|
(compareTo._position == _position ? "MATCHES " : "NO MATCH"),
|
||||||
compareTo._position.x, compareTo._position.y, compareTo._position.z,
|
compareTo._position.x, compareTo._position.y, compareTo._position.z,
|
||||||
|
|
|
@ -119,6 +119,33 @@ void VoxelNode::addChildAtIndex(int childIndex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handles staging or deletion of all deep children
|
||||||
|
void VoxelNode::safeDeepDeleteChildAtIndex(int childIndex, bool& stagedForDeletion) {
|
||||||
|
VoxelNode* childToDelete = getChildAtIndex(childIndex);
|
||||||
|
if (childToDelete) {
|
||||||
|
// If the child is not a leaf, then call ourselves recursively on all the children
|
||||||
|
if (!childToDelete->isLeaf()) {
|
||||||
|
// delete all it's children
|
||||||
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
|
childToDelete->safeDeepDeleteChildAtIndex(i, stagedForDeletion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if this node has a BufferIndex then we need to stage it for deletion
|
||||||
|
// instead of actually deleting it from the tree
|
||||||
|
if (childToDelete->isKnownBufferIndex()) {
|
||||||
|
stagedForDeletion = true;
|
||||||
|
}
|
||||||
|
if (stagedForDeletion) {
|
||||||
|
childToDelete->stageForDeletion();
|
||||||
|
_isDirty = true;
|
||||||
|
} else {
|
||||||
|
deleteChildAtIndex(childIndex);
|
||||||
|
_isDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// will average the child colors...
|
// will average the child colors...
|
||||||
void VoxelNode::setColorFromAverageOfChildren() {
|
void VoxelNode::setColorFromAverageOfChildren() {
|
||||||
int colorArray[4] = {0,0,0,0};
|
int colorArray[4] = {0,0,0,0};
|
||||||
|
@ -242,8 +269,20 @@ void VoxelNode::setRandomColor(int minimumBrightness) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelNode::printDebugDetails(const char* label) const {
|
void VoxelNode::printDebugDetails(const char* label) const {
|
||||||
printLog("%s - Voxel at corner=(%f,%f,%f) size=%f octcode=", label,
|
unsigned char childBits = 0;
|
||||||
_box.getCorner().x, _box.getCorner().y, _box.getCorner().z, _box.getSize().x);
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
|
if (_children[i]) {
|
||||||
|
setAtBit(childBits,i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printLog("%s - Voxel at corner=(%f,%f,%f) size=%f\n isLeaf=%s isColored=%s isDirty=%s shouldRender=%s\n children=", label,
|
||||||
|
_box.getCorner().x, _box.getCorner().y, _box.getCorner().z, _box.getSize().x,
|
||||||
|
debug::valueOf(isLeaf()), debug::valueOf(isColored()), debug::valueOf(isDirty()),
|
||||||
|
debug::valueOf(getShouldRender()));
|
||||||
|
|
||||||
|
outputBits(childBits, false);
|
||||||
|
printLog("\n octalCode=");
|
||||||
printOctalCode(_octalCode);
|
printOctalCode(_octalCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,12 @@ public:
|
||||||
~VoxelNode();
|
~VoxelNode();
|
||||||
|
|
||||||
unsigned char* getOctalCode() const { return _octalCode; };
|
unsigned char* getOctalCode() const { return _octalCode; };
|
||||||
VoxelNode* getChildAtIndex(int i) const { return _children[i]; };
|
VoxelNode* getChildAtIndex(int childIndex) const { return _children[childIndex]; };
|
||||||
void deleteChildAtIndex(int childIndex);
|
void deleteChildAtIndex(int childIndex);
|
||||||
VoxelNode* removeChildAtIndex(int childIndex);
|
VoxelNode* removeChildAtIndex(int childIndex);
|
||||||
void addChildAtIndex(int childIndex);
|
void addChildAtIndex(int childIndex);
|
||||||
|
void safeDeepDeleteChildAtIndex(int childIndex, bool& stagedForDeletion); // handles staging or deletion of all descendents
|
||||||
|
|
||||||
void setColorFromAverageOfChildren();
|
void setColorFromAverageOfChildren();
|
||||||
void setRandomColor(int minimumBrightness);
|
void setRandomColor(int minimumBrightness);
|
||||||
bool collapseIdenticalLeaves();
|
bool collapseIdenticalLeaves();
|
||||||
|
@ -69,6 +71,7 @@ public:
|
||||||
float distanceToPoint(const glm::vec3& point) const;
|
float distanceToPoint(const glm::vec3& point) const;
|
||||||
|
|
||||||
bool isLeaf() const { return _childCount == 0; }
|
bool isLeaf() const { return _childCount == 0; }
|
||||||
|
int getChildCount() const { return _childCount; }
|
||||||
void printDebugDetails(const char* label) const;
|
void printDebugDetails(const char* label) const;
|
||||||
bool isDirty() const { return _isDirty; };
|
bool isDirty() const { return _isDirty; };
|
||||||
void clearDirtyBit() { _isDirty = false; };
|
void clearDirtyBit() { _isDirty = false; };
|
||||||
|
@ -81,7 +84,7 @@ public:
|
||||||
bool getShouldRender() const { return _shouldRender; }
|
bool getShouldRender() const { return _shouldRender; }
|
||||||
|
|
||||||
// Used by VoxelSystem to mark a node as to be deleted on next render pass
|
// Used by VoxelSystem to mark a node as to be deleted on next render pass
|
||||||
void stageForDeletion() { _isStagedForDeletion = true; };
|
void stageForDeletion() { _isStagedForDeletion = true; _isDirty = true; };
|
||||||
bool isStagedForDeletion() const { return _isStagedForDeletion; }
|
bool isStagedForDeletion() const { return _isStagedForDeletion; }
|
||||||
|
|
||||||
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
|
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
|
||||||
|
|
|
@ -100,10 +100,9 @@ VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char *
|
||||||
|
|
||||||
// returns the node created!
|
// returns the node created!
|
||||||
VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char* codeToReach) {
|
VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char* codeToReach) {
|
||||||
|
|
||||||
int indexOfNewChild = branchIndexWithDescendant(lastParentNode->getOctalCode(), codeToReach);
|
int indexOfNewChild = branchIndexWithDescendant(lastParentNode->getOctalCode(), codeToReach);
|
||||||
|
// If this parent node is a leaf, then you know the child path doesn't exist, so deal with
|
||||||
// we could be coming down a branch that was already created, so don't stomp on it.
|
// breaking up the leaf first, which will also create a child path
|
||||||
if (lastParentNode->isLeaf() && lastParentNode->isColored()) {
|
if (lastParentNode->isLeaf() && lastParentNode->isColored()) {
|
||||||
// for colored leaves, we must add *all* the children
|
// for colored leaves, we must add *all* the children
|
||||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
|
@ -111,6 +110,7 @@ VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char
|
||||||
lastParentNode->getChildAtIndex(i)->setColor(lastParentNode->getColor());
|
lastParentNode->getChildAtIndex(i)->setColor(lastParentNode->getColor());
|
||||||
}
|
}
|
||||||
} else if (!lastParentNode->getChildAtIndex(indexOfNewChild)) {
|
} else if (!lastParentNode->getChildAtIndex(indexOfNewChild)) {
|
||||||
|
// we could be coming down a branch that was already created, so don't stomp on it.
|
||||||
lastParentNode->addChildAtIndex(indexOfNewChild);
|
lastParentNode->addChildAtIndex(indexOfNewChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,12 +122,17 @@ VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, int bytesLeftToRead, bool includeColor) {
|
int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, int bytesLeftToRead,
|
||||||
|
bool includeColor, bool includeExistsBits) {
|
||||||
|
// give this destination node the child mask from the packet
|
||||||
|
const unsigned char ALL_CHILDREN_ASSUMED_TO_EXIST = 0xFF;
|
||||||
|
unsigned char colorInPacketMask = *nodeData;
|
||||||
|
|
||||||
// instantiate variable for bytes already read
|
// instantiate variable for bytes already read
|
||||||
int bytesRead = 1;
|
int bytesRead = sizeof(colorInPacketMask);
|
||||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
// check the colors mask to see if we have a child to color in
|
// check the colors mask to see if we have a child to color in
|
||||||
if (oneAtBit(*nodeData, i)) {
|
if (oneAtBit(colorInPacketMask, i)) {
|
||||||
// create the child if it doesn't exist
|
// create the child if it doesn't exist
|
||||||
if (!destinationNode->getChildAtIndex(i)) {
|
if (!destinationNode->getChildAtIndex(i)) {
|
||||||
destinationNode->addChildAtIndex(i);
|
destinationNode->addChildAtIndex(i);
|
||||||
|
@ -160,10 +165,11 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData,
|
||||||
}
|
}
|
||||||
|
|
||||||
// give this destination node the child mask from the packet
|
// give this destination node the child mask from the packet
|
||||||
unsigned char childMask = *(nodeData + bytesRead);
|
unsigned char childrenInTreeMask = includeExistsBits ? *(nodeData + bytesRead) : ALL_CHILDREN_ASSUMED_TO_EXIST;
|
||||||
|
unsigned char childMask = *(nodeData + bytesRead + (includeExistsBits ? sizeof(childrenInTreeMask) : 0));
|
||||||
|
|
||||||
int childIndex = 0;
|
int childIndex = 0;
|
||||||
bytesRead++;
|
bytesRead += includeExistsBits ? sizeof(childrenInTreeMask) + sizeof(childMask) : sizeof(childMask);
|
||||||
|
|
||||||
while (bytesLeftToRead - bytesRead > 0 && childIndex < NUMBER_OF_CHILDREN) {
|
while (bytesLeftToRead - bytesRead > 0 && childIndex < NUMBER_OF_CHILDREN) {
|
||||||
// check the exists mask to see if we have a child to traverse into
|
// check the exists mask to see if we have a child to traverse into
|
||||||
|
@ -186,17 +192,28 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData,
|
||||||
|
|
||||||
// tell the child to read the subsequent data
|
// tell the child to read the subsequent data
|
||||||
bytesRead += readNodeData(destinationNode->getChildAtIndex(childIndex),
|
bytesRead += readNodeData(destinationNode->getChildAtIndex(childIndex),
|
||||||
nodeData + bytesRead,
|
nodeData + bytesRead, bytesLeftToRead - bytesRead, includeColor, includeExistsBits);
|
||||||
bytesLeftToRead - bytesRead, includeColor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
childIndex++;
|
childIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (includeExistsBits) {
|
||||||
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
|
// now also check the childrenInTreeMask, if the mask is missing the bit, then it means we need to delete this child
|
||||||
|
// subtree/node, because it shouldn't actually exist in the tree.
|
||||||
|
if (!oneAtBit(childrenInTreeMask, i) && destinationNode->getChildAtIndex(i)) {
|
||||||
|
bool stagedForDeletion = false; // assume staging is not needed
|
||||||
|
destinationNode->safeDeepDeleteChildAtIndex(i, stagedForDeletion);
|
||||||
|
_isDirty = true; // by definition!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, bool includeColor) {
|
void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes,
|
||||||
|
bool includeColor, bool includeExistsBits) {
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
unsigned char* bitstreamAt = bitstream;
|
unsigned char* bitstreamAt = bitstream;
|
||||||
|
|
||||||
|
@ -225,7 +242,7 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int
|
||||||
int theseBytesRead = 0;
|
int theseBytesRead = 0;
|
||||||
theseBytesRead += octalCodeBytes;
|
theseBytesRead += octalCodeBytes;
|
||||||
theseBytesRead += readNodeData(bitstreamRootNode, bitstreamAt + octalCodeBytes,
|
theseBytesRead += readNodeData(bitstreamRootNode, bitstreamAt + octalCodeBytes,
|
||||||
bufferSizeBytes - (bytesRead + octalCodeBytes), includeColor);
|
bufferSizeBytes - (bytesRead + octalCodeBytes), includeColor, includeExistsBits);
|
||||||
|
|
||||||
// skip bitstream to new startPoint
|
// skip bitstream to new startPoint
|
||||||
bitstreamAt += theseBytesRead;
|
bitstreamAt += theseBytesRead;
|
||||||
|
@ -245,23 +262,30 @@ void VoxelTree::deleteVoxelAt(float x, float y, float z, float s, bool stage) {
|
||||||
|
|
||||||
// Note: uses the codeColorBuffer format, but the color's are ignored, because
|
// Note: uses the codeColorBuffer format, but the color's are ignored, because
|
||||||
// this only finds and deletes the node from the tree.
|
// this only finds and deletes the node from the tree.
|
||||||
void VoxelTree::deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage) {
|
void VoxelTree::deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool stage) {
|
||||||
VoxelNode* parentNode = NULL;
|
VoxelNode* parentNode = NULL;
|
||||||
VoxelNode* nodeToDelete = nodeForOctalCode(rootNode, codeBuffer, &parentNode);
|
VoxelNode* nodeToDelete = nodeForOctalCode(rootNode, codeBuffer, &parentNode);
|
||||||
|
|
||||||
// If the node exists...
|
// If the node exists...
|
||||||
int lengthInBytes = bytesRequiredForCodeLength(*codeBuffer); // includes octet count, not color!
|
int lengthInBytes = bytesRequiredForCodeLength(*codeBuffer); // includes octet count, not color!
|
||||||
|
|
||||||
if (0 == memcmp(nodeToDelete->getOctalCode(),codeBuffer,lengthInBytes)) {
|
// if the code we got back matches our target, then we know we can actually delete it
|
||||||
|
if (memcmp(nodeToDelete->getOctalCode(), codeBuffer, lengthInBytes) == 0) {
|
||||||
if (parentNode) {
|
if (parentNode) {
|
||||||
int childIndex = branchIndexWithDescendant(parentNode->getOctalCode(), codeBuffer);
|
int childIndex = branchIndexWithDescendant(parentNode->getOctalCode(), codeBuffer);
|
||||||
|
|
||||||
if (stage) {
|
if (stage) {
|
||||||
nodeToDelete->stageForDeletion();
|
nodeToDelete->stageForDeletion();
|
||||||
} else {
|
} else {
|
||||||
parentNode->deleteChildAtIndex(childIndex);
|
parentNode->deleteChildAtIndex(childIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're not a colored leaf, and we have no children, then delete ourselves
|
||||||
|
// This will collapse the empty tree above us.
|
||||||
|
if (parentNode->getChildCount() == 0 && !parentNode->isColored()) {
|
||||||
|
// Can't delete the root this way.
|
||||||
|
if (parentNode != rootNode) {
|
||||||
|
deleteVoxelCodeFromTree(parentNode->getOctalCode(),stage);
|
||||||
|
}
|
||||||
|
}
|
||||||
reaverageVoxelColors(rootNode); // Fix our colors!! Need to call it on rootNode
|
reaverageVoxelColors(rootNode); // Fix our colors!! Need to call it on rootNode
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
}
|
}
|
||||||
|
@ -329,19 +353,13 @@ void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer, bool d
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelTree::processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes) {
|
void VoxelTree::processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes) {
|
||||||
// XXXBHG: validate buffer is at least 4 bytes long? other guards??
|
//unsigned short int itemNumber = (*((unsigned short int*)&bitstream[sizeof(PACKET_HEADER)]));
|
||||||
unsigned short int itemNumber = (*((unsigned short int*)&bitstream[1]));
|
int atByte = sizeof(short int) + sizeof(PACKET_HEADER);
|
||||||
printLog("processRemoveVoxelBitstream() receivedBytes=%d itemNumber=%d\n",bufferSizeBytes,itemNumber);
|
unsigned char* pVoxelData = (unsigned char*)&bitstream[atByte];
|
||||||
int atByte = 3;
|
|
||||||
unsigned char* pVoxelData = (unsigned char*)&bitstream[3];
|
|
||||||
while (atByte < bufferSizeBytes) {
|
while (atByte < bufferSizeBytes) {
|
||||||
unsigned char octets = (unsigned char)*pVoxelData;
|
unsigned char octets = (unsigned char)*pVoxelData;
|
||||||
int voxelDataSize = bytesRequiredForCodeLength(octets)+3; // 3 for color!
|
int voxelDataSize = bytesRequiredForCodeLength(octets)+3; // 3 for color!
|
||||||
|
|
||||||
float* vertices = firstVertexForCode(pVoxelData);
|
|
||||||
printLog("deleting voxel at: %f,%f,%f\n",vertices[0],vertices[1],vertices[2]);
|
|
||||||
delete []vertices;
|
|
||||||
|
|
||||||
deleteVoxelCodeFromTree(pVoxelData);
|
deleteVoxelCodeFromTree(pVoxelData);
|
||||||
|
|
||||||
pVoxelData+=voxelDataSize;
|
pVoxelData+=voxelDataSize;
|
||||||
|
@ -428,7 +446,6 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
||||||
bool bail = false;
|
bool bail = false;
|
||||||
while (!file.eof() && !bail) {
|
while (!file.eof() && !bail) {
|
||||||
file.get(octets);
|
file.get(octets);
|
||||||
//printLog("octets=%d...\n",octets);
|
|
||||||
totalBytesRead++;
|
totalBytesRead++;
|
||||||
lengthInBytes = bytesRequiredForCodeLength(octets) - 1;
|
lengthInBytes = bytesRequiredForCodeLength(octets) - 1;
|
||||||
unsigned char * voxelData = new unsigned char[lengthInBytes + 1 + 3];
|
unsigned char * voxelData = new unsigned char[lengthInBytes + 1 + 3];
|
||||||
|
@ -837,7 +854,7 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
|
int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
|
||||||
VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor,
|
VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor, bool includeExistsBits,
|
||||||
bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const {
|
bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const {
|
||||||
|
|
||||||
// How many bytes have we written so far at this level;
|
// How many bytes have we written so far at this level;
|
||||||
|
@ -857,8 +874,8 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned
|
||||||
availableBytes -= codeLength; // keep track or remaining space
|
availableBytes -= codeLength; // keep track or remaining space
|
||||||
|
|
||||||
int currentEncodeLevel = 0;
|
int currentEncodeLevel = 0;
|
||||||
int childBytesWritten = encodeTreeBitstreamRecursion(maxEncodeLevel, currentEncodeLevel,
|
int childBytesWritten = encodeTreeBitstreamRecursion(maxEncodeLevel, currentEncodeLevel, node, outputBuffer, availableBytes,
|
||||||
node, outputBuffer, availableBytes, bag, viewFrustum, includeColor,
|
bag, viewFrustum, includeColor, includeExistsBits,
|
||||||
deltaViewFrustum, lastViewFrustum);
|
deltaViewFrustum, lastViewFrustum);
|
||||||
|
|
||||||
// if childBytesWritten == 1 then something went wrong... that's not possible
|
// if childBytesWritten == 1 then something went wrong... that's not possible
|
||||||
|
@ -880,10 +897,11 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned
|
||||||
return bytesWritten;
|
return bytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, VoxelNode* node,
|
||||||
VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
|
unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag,
|
||||||
VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor,
|
const ViewFrustum* viewFrustum, bool includeColor, bool includeExistsBits,
|
||||||
bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const {
|
bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const {
|
||||||
|
|
||||||
// How many bytes have we written so far at this level;
|
// How many bytes have we written so far at this level;
|
||||||
int bytesAtThisLevel = 0;
|
int bytesAtThisLevel = 0;
|
||||||
|
|
||||||
|
@ -928,7 +946,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
||||||
unsigned char thisLevelBuffer[MAX_LEVEL_BYTES];
|
unsigned char thisLevelBuffer[MAX_LEVEL_BYTES];
|
||||||
unsigned char* writeToThisLevelBuffer = &thisLevelBuffer[0];
|
unsigned char* writeToThisLevelBuffer = &thisLevelBuffer[0];
|
||||||
|
|
||||||
unsigned char childrenExistBits = 0;
|
unsigned char childrenExistInTreeBits = 0;
|
||||||
|
unsigned char childrenExistInPacketBits = 0;
|
||||||
unsigned char childrenColoredBits = 0;
|
unsigned char childrenColoredBits = 0;
|
||||||
int inViewCount = 0;
|
int inViewCount = 0;
|
||||||
int inViewNotLeafCount = 0;
|
int inViewNotLeafCount = 0;
|
||||||
|
@ -938,6 +957,12 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
||||||
// add them to our distance ordered array of children
|
// add them to our distance ordered array of children
|
||||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
VoxelNode* childNode = node->getChildAtIndex(i);
|
VoxelNode* childNode = node->getChildAtIndex(i);
|
||||||
|
|
||||||
|
// if the caller wants to include childExistsBits, then include them even if not in view
|
||||||
|
if (includeExistsBits && childNode) {
|
||||||
|
childrenExistInTreeBits += (1 << (7 - i));
|
||||||
|
}
|
||||||
|
|
||||||
bool childIsInView = (childNode && (!viewFrustum || childNode->isInView(*viewFrustum)));
|
bool childIsInView = (childNode && (!viewFrustum || childNode->isInView(*viewFrustum)));
|
||||||
|
|
||||||
if (childIsInView) {
|
if (childIsInView) {
|
||||||
|
@ -952,7 +977,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
||||||
// we don't care about recursing deeper on them, and we don't consider their
|
// we don't care about recursing deeper on them, and we don't consider their
|
||||||
// subtree to exist
|
// subtree to exist
|
||||||
if (!(childNode && childNode->isLeaf())) {
|
if (!(childNode && childNode->isLeaf())) {
|
||||||
childrenExistBits += (1 << (7 - i));
|
childrenExistInPacketBits += (1 << (7 - i));
|
||||||
inViewNotLeafCount++;
|
inViewNotLeafCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -970,7 +995,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
||||||
*writeToThisLevelBuffer = childrenColoredBits;
|
*writeToThisLevelBuffer = childrenColoredBits;
|
||||||
writeToThisLevelBuffer += sizeof(childrenColoredBits); // move the pointer
|
writeToThisLevelBuffer += sizeof(childrenColoredBits); // move the pointer
|
||||||
bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count
|
bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count
|
||||||
|
|
||||||
// write the color data...
|
// write the color data...
|
||||||
if (includeColor) {
|
if (includeColor) {
|
||||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
|
@ -981,12 +1006,20 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// write the child exist bits
|
|
||||||
*writeToThisLevelBuffer = childrenExistBits;
|
|
||||||
|
|
||||||
writeToThisLevelBuffer += sizeof(childrenExistBits); // move the pointer
|
// if the caller wants to include childExistsBits, then include them even if not in view, put them before the
|
||||||
bytesAtThisLevel += sizeof(childrenExistBits); // keep track of byte count
|
// childrenExistInPacketBits, so that the lower code can properly repair the packet exists bits
|
||||||
|
if (includeExistsBits) {
|
||||||
|
*writeToThisLevelBuffer = childrenExistInTreeBits;
|
||||||
|
writeToThisLevelBuffer += sizeof(childrenExistInTreeBits); // move the pointer
|
||||||
|
bytesAtThisLevel += sizeof(childrenExistInTreeBits); // keep track of byte count
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the child exist bits
|
||||||
|
*writeToThisLevelBuffer = childrenExistInPacketBits;
|
||||||
|
writeToThisLevelBuffer += sizeof(childrenExistInPacketBits); // move the pointer
|
||||||
|
bytesAtThisLevel += sizeof(childrenExistInPacketBits); // keep track of byte count
|
||||||
|
|
||||||
// We only need to keep digging, if there is at least one child that is inView, and not a leaf.
|
// We only need to keep digging, if there is at least one child that is inView, and not a leaf.
|
||||||
keepDiggingDeeper = (inViewNotLeafCount > 0);
|
keepDiggingDeeper = (inViewNotLeafCount > 0);
|
||||||
|
|
||||||
|
@ -1006,23 +1039,23 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
||||||
// and we need to determine if there's a deeper tree below them that we care about.
|
// and we need to determine if there's a deeper tree below them that we care about.
|
||||||
//
|
//
|
||||||
// Since this recursive function assumes we're already writing, we know we've already written our
|
// Since this recursive function assumes we're already writing, we know we've already written our
|
||||||
// childrenExistBits. But... we don't really know how big the child tree will be. And we don't know if
|
// childrenExistInPacketBits. But... we don't really know how big the child tree will be. And we don't know if
|
||||||
// we'll have room in our buffer to actually write all these child trees. What we kinda would like to do is
|
// we'll have room in our buffer to actually write all these child trees. What we kinda would like to do is
|
||||||
// write our childExistsBits as a place holder. Then let each potential tree have a go at it. If they
|
// write our childExistsBits as a place holder. Then let each potential tree have a go at it. If they
|
||||||
// write something, we keep them in the bits, if they don't, we take them out.
|
// write something, we keep them in the bits, if they don't, we take them out.
|
||||||
//
|
//
|
||||||
// we know the last thing we wrote to the outputBuffer was our childrenExistBits. Let's remember where that was!
|
// we know the last thing we wrote to the outputBuffer was our childrenExistInPacketBits. Let's remember where that was!
|
||||||
unsigned char* childExistsPlaceHolder = outputBuffer-sizeof(childrenExistBits);
|
unsigned char* childExistsPlaceHolder = outputBuffer-sizeof(childrenExistInPacketBits);
|
||||||
|
|
||||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
|
|
||||||
if (oneAtBit(childrenExistBits, i)) {
|
if (oneAtBit(childrenExistInPacketBits, i)) {
|
||||||
VoxelNode* childNode = node->getChildAtIndex(i);
|
VoxelNode* childNode = node->getChildAtIndex(i);
|
||||||
|
|
||||||
int thisLevel = currentEncodeLevel;
|
int thisLevel = currentEncodeLevel;
|
||||||
int childTreeBytesOut = encodeTreeBitstreamRecursion(maxEncodeLevel, thisLevel, childNode,
|
int childTreeBytesOut = encodeTreeBitstreamRecursion(maxEncodeLevel, thisLevel, childNode,
|
||||||
outputBuffer, availableBytes, bag,
|
outputBuffer, availableBytes, bag,
|
||||||
viewFrustum, includeColor,
|
viewFrustum, includeColor, includeExistsBits,
|
||||||
deltaViewFrustum, lastViewFrustum);
|
deltaViewFrustum, lastViewFrustum);
|
||||||
|
|
||||||
// if the child wrote 0 bytes, it means that nothing below exists or was in view, or we ran out of space,
|
// if the child wrote 0 bytes, it means that nothing below exists or was in view, or we ran out of space,
|
||||||
|
@ -1053,14 +1086,15 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
||||||
// then we want to remove their bit from the childExistsPlaceHolder bitmask
|
// then we want to remove their bit from the childExistsPlaceHolder bitmask
|
||||||
if (childTreeBytesOut == 0) {
|
if (childTreeBytesOut == 0) {
|
||||||
// remove this child's bit...
|
// remove this child's bit...
|
||||||
childrenExistBits -= (1 << (7 - i));
|
childrenExistInPacketBits -= (1 << (7 - i));
|
||||||
// repair the child exists mask
|
// repair the child exists mask
|
||||||
*childExistsPlaceHolder = childrenExistBits;
|
*childExistsPlaceHolder = childrenExistInPacketBits;
|
||||||
// Note: no need to move the pointer, cause we already stored this
|
// Note: no need to move the pointer, cause we already stored this
|
||||||
} // end if (childTreeBytesOut == 0)
|
} // end if (childTreeBytesOut == 0)
|
||||||
} // end if (oneAtBit(childrenExistBits, i))
|
} // end if (oneAtBit(childrenExistInPacketBits, i))
|
||||||
} // end for
|
} // end for
|
||||||
} // end keepDiggingDeeper
|
} // end keepDiggingDeeper
|
||||||
|
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,7 +1110,7 @@ bool VoxelTree::readFromFileV2(const char* fileName) {
|
||||||
// read the entire file into a buffer, WHAT!? Why not.
|
// read the entire file into a buffer, WHAT!? Why not.
|
||||||
unsigned char* entireFile = new unsigned char[fileLength];
|
unsigned char* entireFile = new unsigned char[fileLength];
|
||||||
file.read((char*)entireFile, fileLength);
|
file.read((char*)entireFile, fileLength);
|
||||||
readBitstreamToTree(entireFile, fileLength, true);
|
readBitstreamToTree(entireFile, fileLength, WANT_COLOR, NO_EXISTS_BITS);
|
||||||
delete[] entireFile;
|
delete[] entireFile;
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
@ -1101,7 +1135,7 @@ void VoxelTree::writeToFileV2(const char* fileName) const {
|
||||||
while (!nodeBag.isEmpty()) {
|
while (!nodeBag.isEmpty()) {
|
||||||
VoxelNode* subTree = nodeBag.extract();
|
VoxelNode* subTree = nodeBag.extract();
|
||||||
bytesWritten = encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0],
|
bytesWritten = encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0],
|
||||||
MAX_VOXEL_PACKET_SIZE - 1, nodeBag, NULL, true);
|
MAX_VOXEL_PACKET_SIZE - 1, nodeBag, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS);
|
||||||
|
|
||||||
file.write((const char*)&outputBuffer[0], bytesWritten);
|
file.write((const char*)&outputBuffer[0], bytesWritten);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,12 @@
|
||||||
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData);
|
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData);
|
||||||
typedef enum {GRADIENT, RANDOM, NATURAL} creationMode;
|
typedef enum {GRADIENT, RANDOM, NATURAL} creationMode;
|
||||||
|
|
||||||
|
#define NO_EXISTS_BITS false
|
||||||
|
#define WANT_EXISTS_BITS true
|
||||||
|
#define NO_COLOR false
|
||||||
|
#define WANT_COLOR true
|
||||||
|
#define IGNORE_VIEW_FRUSTUM NULL
|
||||||
|
|
||||||
class VoxelTree {
|
class VoxelTree {
|
||||||
public:
|
public:
|
||||||
// when a voxel is created in the tree (object new'd)
|
// when a voxel is created in the tree (object new'd)
|
||||||
|
@ -40,7 +46,8 @@ public:
|
||||||
void eraseAllVoxels();
|
void eraseAllVoxels();
|
||||||
|
|
||||||
void processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes);
|
void processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes);
|
||||||
void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, bool includeColor = true);
|
void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes,
|
||||||
|
bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS);
|
||||||
void readCodeColorBufferToTree(unsigned char *codeColorBuffer, bool destructive = false);
|
void readCodeColorBufferToTree(unsigned char *codeColorBuffer, bool destructive = false);
|
||||||
void deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage = false);
|
void deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage = false);
|
||||||
void printTreeForDebugging(VoxelNode *startNode);
|
void printTreeForDebugging(VoxelNode *startNode);
|
||||||
|
@ -57,7 +64,8 @@ public:
|
||||||
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
|
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
|
||||||
|
|
||||||
int encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
|
int encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
|
||||||
VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor = true,
|
VoxelNodeBag& bag, const ViewFrustum* viewFrustum,
|
||||||
|
bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS,
|
||||||
bool deltaViewFrustum = false, const ViewFrustum* lastViewFrustum = NULL) const;
|
bool deltaViewFrustum = false, const ViewFrustum* lastViewFrustum = NULL) const;
|
||||||
|
|
||||||
int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag,
|
int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag,
|
||||||
|
@ -85,8 +93,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
||||||
VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
|
VoxelNode* node, unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag,
|
||||||
VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor,
|
const ViewFrustum* viewFrustum, bool includeColor, bool includeExistsBits,
|
||||||
bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const;
|
bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const;
|
||||||
|
|
||||||
int searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel,
|
int searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel,
|
||||||
|
@ -98,7 +106,8 @@ private:
|
||||||
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData);
|
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData);
|
||||||
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const;
|
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const;
|
||||||
VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate);
|
VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate);
|
||||||
int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes, bool includeColor = true);
|
int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes,
|
||||||
|
bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS);
|
||||||
|
|
||||||
bool _isDirty;
|
bool _isDirty;
|
||||||
unsigned long int _nodesChangedFromBitstream;
|
unsigned long int _nodesChangedFromBitstream;
|
||||||
|
|
BIN
tools/samples/cube1.hio
Executable file
BIN
tools/samples/cube1.hio
Executable file
Binary file not shown.
BIN
tools/samples/oneRedVoxel.hio
Executable file
BIN
tools/samples/oneRedVoxel.hio
Executable file
Binary file not shown.
BIN
tools/samples/simple1.hio
Normal file
BIN
tools/samples/simple1.hio
Normal file
Binary file not shown.
BIN
tools/samples/single.hio
Executable file
BIN
tools/samples/single.hio
Executable file
Binary file not shown.
BIN
tools/samples/small.hio
Normal file
BIN
tools/samples/small.hio
Normal file
Binary file not shown.
|
@ -30,8 +30,8 @@ function send_voxels($inputFileName,$server,$port,$command) {
|
||||||
echo "sending adding octets=$octets size=$size to packet packetSize=$packetSize\n";
|
echo "sending adding octets=$octets size=$size to packet packetSize=$packetSize\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "sending packet server=$serverIP port=$serverSendPort $voxNum size=$packetSize result=$result\n";
|
|
||||||
$result = socket_sendto($socketHandle, $netData, $packetSize, 0, $serverIP, $serverSendPort);
|
$result = socket_sendto($socketHandle, $netData, $packetSize, 0, $serverIP, $serverSendPort);
|
||||||
|
echo "sent packet server=$serverIP port=$serverSendPort $voxNum size=$packetSize result=$result\n";
|
||||||
usleep(20000); // 1,000,000 per second
|
usleep(20000); // 1,000,000 per second
|
||||||
$voxNum++;
|
$voxNum++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,8 +57,7 @@ bool wantLocalDomain = false;
|
||||||
bool wantColorRandomizer = false;
|
bool wantColorRandomizer = false;
|
||||||
bool debugVoxelSending = false;
|
bool debugVoxelSending = false;
|
||||||
bool shouldShowAnimationDebug = false;
|
bool shouldShowAnimationDebug = false;
|
||||||
|
bool wantSearchForColoredNodes = false;
|
||||||
|
|
||||||
|
|
||||||
EnvironmentData environmentData[3];
|
EnvironmentData environmentData[3];
|
||||||
|
|
||||||
|
@ -169,7 +168,7 @@ void resInVoxelDistributor(AgentList* agentList,
|
||||||
bytesWritten = randomTree.encodeTreeBitstream(agentData->getMaxSearchLevel(), subTree,
|
bytesWritten = randomTree.encodeTreeBitstream(agentData->getMaxSearchLevel(), subTree,
|
||||||
&tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
|
&tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
|
||||||
agentData->nodeBag, &viewFrustum,
|
agentData->nodeBag, &viewFrustum,
|
||||||
agentData->getWantColor());
|
agentData->getWantColor(), WANT_EXISTS_BITS);
|
||||||
|
|
||||||
if (agentData->getAvailable() >= bytesWritten) {
|
if (agentData->getAvailable() >= bytesWritten) {
|
||||||
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
||||||
|
@ -244,20 +243,32 @@ void deepestLevelVoxelDistributor(AgentList* agentList,
|
||||||
|
|
||||||
if (::debugVoxelSending) {
|
if (::debugVoxelSending) {
|
||||||
printf("deepestLevelVoxelDistributor() viewFrustumChanged=%s, nodeBag.isEmpty=%s, viewSent=%s\n",
|
printf("deepestLevelVoxelDistributor() viewFrustumChanged=%s, nodeBag.isEmpty=%s, viewSent=%s\n",
|
||||||
viewFrustumChanged ? "yes" : "no",
|
debug::valueOf(viewFrustumChanged), debug::valueOf(agentData->nodeBag.isEmpty()),
|
||||||
agentData->nodeBag.isEmpty() ? "yes" : "no",
|
debug::valueOf(agentData->getViewSent())
|
||||||
agentData->getViewSent() ? "yes" : "no"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the current view frustum has changed OR we have nothing to send, then search against
|
// If the current view frustum has changed OR we have nothing to send, then search against
|
||||||
// the current view frustum for things to send.
|
// the current view frustum for things to send.
|
||||||
if (viewFrustumChanged || agentData->nodeBag.isEmpty()) {
|
if (viewFrustumChanged || agentData->nodeBag.isEmpty()) {
|
||||||
// If the bag was empty, then send everything in view, not just the delta
|
|
||||||
maxLevelReached = randomTree.searchForColoredNodes(INT_MAX, randomTree.rootNode, agentData->getCurrentViewFrustum(),
|
|
||||||
agentData->nodeBag, wantDelta, lastViewFrustum);
|
|
||||||
|
|
||||||
agentData->setViewSent(false);
|
// For now, we're going to disable the "search for colored nodes" because that strategy doesn't work when we support
|
||||||
|
// deletion of nodes. Instead if we just start at the root we get the correct behavior we want. We are keeping this
|
||||||
|
// code for now because we want to be able to go back to it and find a solution to support both. The search method
|
||||||
|
// helps improve overall bitrate performance.
|
||||||
|
if (::wantSearchForColoredNodes) {
|
||||||
|
// If the bag was empty, then send everything in view, not just the delta
|
||||||
|
maxLevelReached = randomTree.searchForColoredNodes(INT_MAX, randomTree.rootNode, agentData->getCurrentViewFrustum(),
|
||||||
|
agentData->nodeBag, wantDelta, lastViewFrustum);
|
||||||
|
|
||||||
|
// if nothing was found in view, send the root node.
|
||||||
|
if (agentData->nodeBag.isEmpty()){
|
||||||
|
agentData->nodeBag.insert(randomTree.rootNode);
|
||||||
|
}
|
||||||
|
agentData->setViewSent(false);
|
||||||
|
} else {
|
||||||
|
agentData->nodeBag.insert(randomTree.rootNode);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
double end = usecTimestampNow();
|
double end = usecTimestampNow();
|
||||||
|
@ -292,7 +303,8 @@ void deepestLevelVoxelDistributor(AgentList* agentList,
|
||||||
bytesWritten = randomTree.encodeTreeBitstream(INT_MAX, subTree,
|
bytesWritten = randomTree.encodeTreeBitstream(INT_MAX, subTree,
|
||||||
&tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
|
&tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
|
||||||
agentData->nodeBag, &agentData->getCurrentViewFrustum(),
|
agentData->nodeBag, &agentData->getCurrentViewFrustum(),
|
||||||
agentData->getWantColor(), wantDelta, lastViewFrustum);
|
agentData->getWantColor(), WANT_EXISTS_BITS,
|
||||||
|
wantDelta, lastViewFrustum);
|
||||||
|
|
||||||
if (agentData->getAvailable() >= bytesWritten) {
|
if (agentData->getAvailable() >= bytesWritten) {
|
||||||
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
||||||
|
@ -398,7 +410,7 @@ void *distributeVoxelsToListeners(void *args) {
|
||||||
if (agentData) {
|
if (agentData) {
|
||||||
bool viewFrustumChanged = agentData->updateCurrentViewFrustum();
|
bool viewFrustumChanged = agentData->updateCurrentViewFrustum();
|
||||||
if (::debugVoxelSending) {
|
if (::debugVoxelSending) {
|
||||||
printf("agentData->updateCurrentViewFrustum() changed=%s\n", (viewFrustumChanged ? "yes" : "no"));
|
printf("agentData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (agentData->getWantResIn()) {
|
if (agentData->getWantResIn()) {
|
||||||
|
@ -450,22 +462,26 @@ int main(int argc, const char * argv[])
|
||||||
|
|
||||||
const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending";
|
const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending";
|
||||||
::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING);
|
::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING);
|
||||||
printf("debugVoxelSending=%s\n", (::debugVoxelSending ? "yes" : "no"));
|
printf("debugVoxelSending=%s\n", debug::valueOf(::debugVoxelSending));
|
||||||
|
|
||||||
const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug";
|
const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug";
|
||||||
::shouldShowAnimationDebug = cmdOptionExists(argc, argv, WANT_ANIMATION_DEBUG);
|
::shouldShowAnimationDebug = cmdOptionExists(argc, argv, WANT_ANIMATION_DEBUG);
|
||||||
printf("shouldShowAnimationDebug=%s\n", (::shouldShowAnimationDebug ? "yes" : "no"));
|
printf("shouldShowAnimationDebug=%s\n", debug::valueOf(::shouldShowAnimationDebug));
|
||||||
|
|
||||||
const char* WANT_COLOR_RANDOMIZER = "--wantColorRandomizer";
|
const char* WANT_COLOR_RANDOMIZER = "--wantColorRandomizer";
|
||||||
::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER);
|
::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER);
|
||||||
printf("wantColorRandomizer=%s\n", (::wantColorRandomizer ? "yes" : "no"));
|
printf("wantColorRandomizer=%s\n", debug::valueOf(::wantColorRandomizer));
|
||||||
|
|
||||||
|
const char* WANT_SEARCH_FOR_NODES = "--wantSearchForColoredNodes";
|
||||||
|
::wantSearchForColoredNodes = cmdOptionExists(argc, argv, WANT_SEARCH_FOR_NODES);
|
||||||
|
printf("wantSearchForColoredNodes=%s\n", debug::valueOf(::wantSearchForColoredNodes));
|
||||||
|
|
||||||
// By default we will voxel persist, if you want to disable this, then pass in this parameter
|
// By default we will voxel persist, if you want to disable this, then pass in this parameter
|
||||||
const char* NO_VOXEL_PERSIST = "--NoVoxelPersist";
|
const char* NO_VOXEL_PERSIST = "--NoVoxelPersist";
|
||||||
if (cmdOptionExists(argc, argv, NO_VOXEL_PERSIST)) {
|
if (cmdOptionExists(argc, argv, NO_VOXEL_PERSIST)) {
|
||||||
::wantVoxelPersist = false;
|
::wantVoxelPersist = false;
|
||||||
}
|
}
|
||||||
printf("wantVoxelPersist=%s\n", (::wantVoxelPersist ? "yes" : "no"));
|
printf("wantVoxelPersist=%s\n", debug::valueOf(::wantVoxelPersist));
|
||||||
|
|
||||||
// if we want Voxel Persistance, load the local file now...
|
// if we want Voxel Persistance, load the local file now...
|
||||||
bool persistantFileRead = false;
|
bool persistantFileRead = false;
|
||||||
|
@ -473,7 +489,7 @@ int main(int argc, const char * argv[])
|
||||||
printf("loading voxels from file...\n");
|
printf("loading voxels from file...\n");
|
||||||
persistantFileRead = ::randomTree.readFromFileV2(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE);
|
persistantFileRead = ::randomTree.readFromFileV2(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE);
|
||||||
::randomTree.clearDirtyBit(); // the tree is clean since we just loaded it
|
::randomTree.clearDirtyBit(); // the tree is clean since we just loaded it
|
||||||
printf("DONE loading voxels from file... fileRead=%s\n", persistantFileRead ? "yes" : "no" );
|
printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead));
|
||||||
unsigned long nodeCount = ::randomTree.getVoxelCount();
|
unsigned long nodeCount = ::randomTree.getVoxelCount();
|
||||||
printf("Nodes after loading scene %ld nodes\n", nodeCount);
|
printf("Nodes after loading scene %ld nodes\n", nodeCount);
|
||||||
}
|
}
|
||||||
|
@ -548,16 +564,12 @@ int main(int argc, const char * argv[])
|
||||||
persistVoxelsWhenDirty();
|
persistVoxelsWhenDirty();
|
||||||
|
|
||||||
if (agentList->getAgentSocket()->receive(&agentPublicAddress, packetData, &receivedBytes)) {
|
if (agentList->getAgentSocket()->receive(&agentPublicAddress, packetData, &receivedBytes)) {
|
||||||
// XXXBHG: Hacked in support for 'S' SET command
|
|
||||||
if (packetData[0] == PACKET_HEADER_SET_VOXEL || packetData[0] == PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) {
|
if (packetData[0] == PACKET_HEADER_SET_VOXEL || packetData[0] == PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) {
|
||||||
bool destructive = (packetData[0] == PACKET_HEADER_SET_VOXEL_DESTRUCTIVE);
|
bool destructive = (packetData[0] == PACKET_HEADER_SET_VOXEL_DESTRUCTIVE);
|
||||||
|
|
||||||
PerformanceWarning warn(::shouldShowAnimationDebug,
|
PerformanceWarning warn(::shouldShowAnimationDebug,
|
||||||
destructive ? "PACKET_HEADER_SET_VOXEL_DESTRUCTIVE" : "PACKET_HEADER_SET_VOXEL",
|
destructive ? "PACKET_HEADER_SET_VOXEL_DESTRUCTIVE" : "PACKET_HEADER_SET_VOXEL",
|
||||||
::shouldShowAnimationDebug);
|
::shouldShowAnimationDebug);
|
||||||
|
|
||||||
unsigned short int itemNumber = (*((unsigned short int*)&packetData[1]));
|
unsigned short int itemNumber = (*((unsigned short int*)&packetData[1]));
|
||||||
|
|
||||||
if (::shouldShowAnimationDebug) {
|
if (::shouldShowAnimationDebug) {
|
||||||
printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n",
|
printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n",
|
||||||
destructive ? "PACKET_HEADER_SET_VOXEL_DESTRUCTIVE" : "PACKET_HEADER_SET_VOXEL",
|
destructive ? "PACKET_HEADER_SET_VOXEL_DESTRUCTIVE" : "PACKET_HEADER_SET_VOXEL",
|
||||||
|
@ -608,13 +620,8 @@ int main(int argc, const char * argv[])
|
||||||
if (packetData[0] == PACKET_HEADER_ERASE_VOXEL) {
|
if (packetData[0] == PACKET_HEADER_ERASE_VOXEL) {
|
||||||
|
|
||||||
// Send these bits off to the VoxelTree class to process them
|
// Send these bits off to the VoxelTree class to process them
|
||||||
printf("got Erase Voxels message, have voxel tree do the work... randomTree.processRemoveVoxelBitstream()\n");
|
//printf("got Erase Voxels message, have voxel tree do the work... randomTree.processRemoveVoxelBitstream()\n");
|
||||||
randomTree.processRemoveVoxelBitstream((unsigned char*)packetData,receivedBytes);
|
randomTree.processRemoveVoxelBitstream((unsigned char*)packetData,receivedBytes);
|
||||||
|
|
||||||
// Now send this to the connected agents so they know to delete
|
|
||||||
printf("rebroadcasting delete voxel message to connected agents... agentList.broadcastToAgents()\n");
|
|
||||||
agentList->broadcastToAgents(packetData,receivedBytes, &AGENT_TYPE_AVATAR, 1);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if (packetData[0] == PACKET_HEADER_Z_COMMAND) {
|
if (packetData[0] == PACKET_HEADER_Z_COMMAND) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue