From 8f4e641adeb40b8a75a68928aea6982037c7a324 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 5 Dec 2013 17:11:58 -0800 Subject: [PATCH 01/15] remove NodeList threads that are deprecated --- animation-server/src/AnimationServer.cpp | 885 +++++++++++++++++++ animation-server/src/AnimationServer.h | 24 + animation-server/src/main.cpp | 882 +----------------- interface/src/Application.cpp | 19 +- libraries/octree-server/src/OctreeServer.cpp | 1 - libraries/shared/src/NodeList.cpp | 23 - libraries/shared/src/NodeList.h | 9 - 7 files changed, 923 insertions(+), 920 deletions(-) create mode 100644 animation-server/src/AnimationServer.cpp create mode 100644 animation-server/src/AnimationServer.h diff --git a/animation-server/src/AnimationServer.cpp b/animation-server/src/AnimationServer.cpp new file mode 100644 index 0000000000..ede205ce90 --- /dev/null +++ b/animation-server/src/AnimationServer.cpp @@ -0,0 +1,885 @@ +// +// AnimationServer.cpp +// hifi +// +// Created by Stephen Birarda on 12/5/2013. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AnimationServer.h" + +bool shouldShowPacketsPerSecond = false; // do we want to debug packets per second +bool includeBillboard = true; +bool includeBorderTracer = true; +bool includeMovingBug = true; +bool includeBlinkingVoxel = false; +bool includeDanceFloor = true; +bool buildStreet = false; +bool nonThreadedPacketSender = false; +int packetsPerSecond = PacketSender::DEFAULT_PACKETS_PER_SECOND; +bool waitForVoxelServer = true; + + +const int ANIMATION_LISTEN_PORT = 40107; +int ANIMATE_FPS = 60; +double ANIMATE_FPS_IN_MILLISECONDS = 1000.0/ANIMATE_FPS; // determines FPS from our desired FPS +int ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs + + +int PROCESSING_FPS = 60; +double PROCESSING_FPS_IN_MILLISECONDS = 1000.0/PROCESSING_FPS; // determines FPS from our desired FPS +int FUDGE_USECS = 650; // a little bit of fudge to actually do some processing +int PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000.0) - FUDGE_USECS; // converts from milliseconds to usecs + +bool wantLocalDomain = false; + +unsigned long packetsSent = 0; +unsigned long bytesSent = 0; + +JurisdictionListener* jurisdictionListener = NULL; +VoxelEditPacketSender* voxelEditPacketSender = NULL; +pthread_t animateVoxelThread; + +glm::vec3 rotatePoint(glm::vec3 point, float angle) { + // First, create the quaternion based on this angle of rotation + glm::quat q(glm::vec3(0, -angle, 0)); + + // Next, create a rotation matrix from that quaternion + glm::mat4 rotation = glm::mat4_cast(q); + + // Transform the original vectors by the rotation matrix to get the new vectors + glm::vec4 quatPoint(point.x, point.y, point.z, 0); + glm::vec4 newPoint = quatPoint * rotation; + + return glm::vec3(newPoint.x, newPoint.y, newPoint.z); +} + + +const float BUG_VOXEL_SIZE = 0.0625f / TREE_SCALE; +glm::vec3 bugPosition = glm::vec3(BUG_VOXEL_SIZE * 20.0, BUG_VOXEL_SIZE * 30.0, BUG_VOXEL_SIZE * 20.0); +glm::vec3 bugDirection = glm::vec3(0, 0, 1); +const int VOXELS_PER_BUG = 18; +glm::vec3 bugPathCenter = glm::vec3(0.25f,0.15f,0.25f); // glm::vec3(BUG_VOXEL_SIZE * 150.0, BUG_VOXEL_SIZE * 30.0, BUG_VOXEL_SIZE * 150.0); +float bugPathRadius = 0.2f; //BUG_VOXEL_SIZE * 140.0; +float bugPathTheta = 0.0 * PI_OVER_180; +float bugRotation = 0.0 * PI_OVER_180; +float bugAngleDelta = 0.2 * PI_OVER_180; +bool moveBugInLine = false; + +class BugPart { +public: + glm::vec3 partLocation; + unsigned char partColor[3]; + + BugPart(const glm::vec3& location, unsigned char red, unsigned char green, unsigned char blue ) { + partLocation = location; + partColor[0] = red; + partColor[1] = green; + partColor[2] = blue; + } +}; + +const BugPart bugParts[VOXELS_PER_BUG] = { + + // tail + BugPart(glm::vec3( 0, 0, -3), 51, 51, 153) , + BugPart(glm::vec3( 0, 0, -2), 51, 51, 153) , + BugPart(glm::vec3( 0, 0, -1), 51, 51, 153) , + + // body + BugPart(glm::vec3( 0, 0, 0), 255, 200, 0) , + BugPart(glm::vec3( 0, 0, 1), 255, 200, 0) , + + // head + BugPart(glm::vec3( 0, 0, 2), 200, 0, 0) , + + // eyes + BugPart(glm::vec3( 1, 0, 3), 64, 64, 64) , + BugPart(glm::vec3(-1, 0, 3), 64, 64, 64) , + + // wings + BugPart(glm::vec3( 3, 1, 1), 0, 153, 0) , + BugPart(glm::vec3( 2, 1, 1), 0, 153, 0) , + BugPart(glm::vec3( 1, 0, 1), 0, 153, 0) , + BugPart(glm::vec3(-1, 0, 1), 0, 153, 0) , + BugPart(glm::vec3(-2, 1, 1), 0, 153, 0) , + BugPart(glm::vec3(-3, 1, 1), 0, 153, 0) , + + + BugPart(glm::vec3( 2, -1, 0), 153, 200, 0) , + BugPart(glm::vec3( 1, -1, 0), 153, 200, 0) , + BugPart(glm::vec3(-1, -1, 0), 153, 200, 0) , + BugPart(glm::vec3(-2, -1, 0), 153, 200, 0) , +}; + +static void renderMovingBug() { + VoxelDetail details[VOXELS_PER_BUG]; + + // Generate voxels for where bug used to be + for (int i = 0; i < VOXELS_PER_BUG; i++) { + details[i].s = BUG_VOXEL_SIZE; + + glm::vec3 partAt = bugParts[i].partLocation * BUG_VOXEL_SIZE * (bugDirection.x < 0 ? -1.0f : 1.0f); + glm::vec3 rotatedPartAt = rotatePoint(partAt, bugRotation); + glm::vec3 offsetPartAt = rotatedPartAt + bugPosition; + + details[i].x = offsetPartAt.x; + details[i].y = offsetPartAt.y; + details[i].z = offsetPartAt.z; + + details[i].red = bugParts[i].partColor[0]; + details[i].green = bugParts[i].partColor[1]; + details[i].blue = bugParts[i].partColor[2]; + } + + // send the "erase message" first... + PACKET_TYPE message = PACKET_TYPE_VOXEL_ERASE; + ::voxelEditPacketSender->queueVoxelEditMessages(message, VOXELS_PER_BUG, (VoxelDetail*)&details); + + // Move the bug... + if (moveBugInLine) { + bugPosition.x += (bugDirection.x * BUG_VOXEL_SIZE); + bugPosition.y += (bugDirection.y * BUG_VOXEL_SIZE); + bugPosition.z += (bugDirection.z * BUG_VOXEL_SIZE); + + // Check boundaries + if (bugPosition.z > 1.0) { + bugDirection.z = -1; + } + if (bugPosition.z < BUG_VOXEL_SIZE) { + bugDirection.z = 1; + } + } else { + + //printf("bugPathCenter=(%f,%f,%f)\n", bugPathCenter.x, bugPathCenter.y, bugPathCenter.z); + + bugPathTheta += bugAngleDelta; // move slightly + bugRotation -= bugAngleDelta; // rotate slightly + + // If we loop past end of circle, just reset back into normal range + if (bugPathTheta > (360.0f * PI_OVER_180)) { + bugPathTheta = 0; + bugRotation = 0; + } + + float x = bugPathCenter.x + bugPathRadius * cos(bugPathTheta); + float z = bugPathCenter.z + bugPathRadius * sin(bugPathTheta); + float y = bugPathCenter.y; + + bugPosition = glm::vec3(x, y, z); + //printf("bugPathTheta=%f\n", bugPathTheta); + //printf("bugRotation=%f\n", bugRotation); + } + + //printf("bugPosition=(%f,%f,%f)\n", bugPosition.x, bugPosition.y, bugPosition.z); + //printf("bugDirection=(%f,%f,%f)\n", bugDirection.x, bugDirection.y, bugDirection.z); + // would be nice to add some randomness here... + + // Generate voxels for where bug is going to + for (int i = 0; i < VOXELS_PER_BUG; i++) { + details[i].s = BUG_VOXEL_SIZE; + + glm::vec3 partAt = bugParts[i].partLocation * BUG_VOXEL_SIZE * (bugDirection.x < 0 ? -1.0f : 1.0f); + glm::vec3 rotatedPartAt = rotatePoint(partAt, bugRotation); + glm::vec3 offsetPartAt = rotatedPartAt + bugPosition; + + details[i].x = offsetPartAt.x; + details[i].y = offsetPartAt.y; + details[i].z = offsetPartAt.z; + + details[i].red = bugParts[i].partColor[0]; + details[i].green = bugParts[i].partColor[1]; + details[i].blue = bugParts[i].partColor[2]; + } + + // send the "create message" ... + message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; + ::voxelEditPacketSender->queueVoxelEditMessages(message, VOXELS_PER_BUG, (VoxelDetail*)&details); +} + + +float intensity = 0.5f; +float intensityIncrement = 0.1f; +const float MAX_INTENSITY = 1.0f; +const float MIN_INTENSITY = 0.5f; +const float BEACON_SIZE = 0.25f / TREE_SCALE; // approximately 1/4th meter + +static void sendVoxelBlinkMessage() { + VoxelDetail detail; + detail.s = BEACON_SIZE; + + glm::vec3 position = glm::vec3(0, 0, detail.s); + + detail.x = detail.s * floor(position.x / detail.s); + detail.y = detail.s * floor(position.y / detail.s); + detail.z = detail.s * floor(position.z / detail.s); + + ::intensity += ::intensityIncrement; + if (::intensity >= MAX_INTENSITY) { + ::intensity = MAX_INTENSITY; + ::intensityIncrement = -::intensityIncrement; + } + if (::intensity <= MIN_INTENSITY) { + ::intensity = MIN_INTENSITY; + ::intensityIncrement = -::intensityIncrement; + } + + detail.red = 255 * ::intensity; + detail.green = 0 * ::intensity; + detail.blue = 0 * ::intensity; + + PACKET_TYPE message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; + + ::voxelEditPacketSender->sendVoxelEditMessage(message, detail); +} + +bool stringOfLightsInitialized = false; +int currentLight = 0; +int lightMovementDirection = 1; +const int SEGMENT_COUNT = 4; +const int LIGHTS_PER_SEGMENT = 80; +const int LIGHT_COUNT = LIGHTS_PER_SEGMENT * SEGMENT_COUNT; +glm::vec3 stringOfLights[LIGHT_COUNT]; +unsigned char offColor[3] = { 240, 240, 240 }; +unsigned char onColor[3] = { 0, 255, 255 }; +const float STRING_OF_LIGHTS_SIZE = 0.125f / TREE_SCALE; // approximately 1/8th meter + +static void sendBlinkingStringOfLights() { + PACKET_TYPE message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; // we're a bully! + float lightScale = STRING_OF_LIGHTS_SIZE; + static VoxelDetail details[LIGHTS_PER_SEGMENT]; + + // first initialized the string of lights if needed... + if (!stringOfLightsInitialized) { + for (int segment = 0; segment < SEGMENT_COUNT; segment++) { + for (int indexInSegment = 0; indexInSegment < LIGHTS_PER_SEGMENT; indexInSegment++) { + + int i = (segment * LIGHTS_PER_SEGMENT) + indexInSegment; + + // four different segments on sides of initial platform + switch (segment) { + case 0: + // along x axis + stringOfLights[i] = glm::vec3(indexInSegment * lightScale, 0, 0); + break; + case 1: + // parallel to Z axis at outer X edge + stringOfLights[i] = glm::vec3(LIGHTS_PER_SEGMENT * lightScale, 0, indexInSegment * lightScale); + break; + case 2: + // parallel to X axis at outer Z edge + stringOfLights[i] = glm::vec3((LIGHTS_PER_SEGMENT-indexInSegment) * lightScale, 0, + LIGHTS_PER_SEGMENT * lightScale); + break; + case 3: + // on Z axis + stringOfLights[i] = glm::vec3(0, 0, (LIGHTS_PER_SEGMENT-indexInSegment) * lightScale); + break; + } + + details[indexInSegment].s = STRING_OF_LIGHTS_SIZE; + details[indexInSegment].x = stringOfLights[i].x; + details[indexInSegment].y = stringOfLights[i].y; + details[indexInSegment].z = stringOfLights[i].z; + + details[indexInSegment].red = offColor[0]; + details[indexInSegment].green = offColor[1]; + details[indexInSegment].blue = offColor[2]; + } + + ::voxelEditPacketSender->queueVoxelEditMessages(message, LIGHTS_PER_SEGMENT, (VoxelDetail*)&details); + } + stringOfLightsInitialized = true; + } else { + // turn off current light + details[0].x = stringOfLights[currentLight].x; + details[0].y = stringOfLights[currentLight].y; + details[0].z = stringOfLights[currentLight].z; + details[0].red = offColor[0]; + details[0].green = offColor[1]; + details[0].blue = offColor[2]; + + // move current light... + // if we're at the end of our string, then change direction + if (currentLight == LIGHT_COUNT-1) { + lightMovementDirection = -1; + } + if (currentLight == 0) { + lightMovementDirection = 1; + } + currentLight += lightMovementDirection; + + // turn on new current light + details[1].x = stringOfLights[currentLight].x; + details[1].y = stringOfLights[currentLight].y; + details[1].z = stringOfLights[currentLight].z; + details[1].red = onColor[0]; + details[1].green = onColor[1]; + details[1].blue = onColor[2]; + + // send both changes in same message + ::voxelEditPacketSender->queueVoxelEditMessages(message, 2, (VoxelDetail*)&details); + } +} + +bool danceFloorInitialized = false; +const float DANCE_FLOOR_LIGHT_SIZE = 1.0f / TREE_SCALE; // approximately 1 meter +const int DANCE_FLOOR_LENGTH = 10; +const int DANCE_FLOOR_WIDTH = 10; +glm::vec3 danceFloorPosition(100.0f / TREE_SCALE, 30.0f / TREE_SCALE, 10.0f / TREE_SCALE); +glm::vec3 danceFloorLights[DANCE_FLOOR_LENGTH][DANCE_FLOOR_WIDTH]; +unsigned char danceFloorOffColor[3] = { 240, 240, 240 }; +const int DANCE_FLOOR_COLORS = 6; + +unsigned char danceFloorOnColorA[DANCE_FLOOR_COLORS][3] = { + { 255, 0, 0 }, { 0, 255, 0 }, { 0, 0, 255 }, + { 0, 191, 255 }, { 0, 250, 154 }, { 255, 69, 0 }, +}; +unsigned char danceFloorOnColorB[DANCE_FLOOR_COLORS][3] = { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } , + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } +}; +float danceFloorGradient = 0.5f; +const float BEATS_PER_MINUTE = 118.0f; +const float SECONDS_PER_MINUTE = 60.0f; +const float FRAMES_PER_BEAT = (SECONDS_PER_MINUTE * ANIMATE_FPS) / BEATS_PER_MINUTE; +float danceFloorGradientIncrement = 1.0f / FRAMES_PER_BEAT; +const float DANCE_FLOOR_MAX_GRADIENT = 1.0f; +const float DANCE_FLOOR_MIN_GRADIENT = 0.0f; +const int DANCE_FLOOR_VOXELS_PER_PACKET = 100; +const int PACKETS_PER_DANCE_FLOOR = DANCE_FLOOR_VOXELS_PER_PACKET / (DANCE_FLOOR_WIDTH * DANCE_FLOOR_LENGTH); +int danceFloorColors[DANCE_FLOOR_WIDTH][DANCE_FLOOR_LENGTH]; + +void sendDanceFloor() { + PACKET_TYPE message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; // we're a bully! + float lightScale = DANCE_FLOOR_LIGHT_SIZE; + static VoxelDetail details[DANCE_FLOOR_VOXELS_PER_PACKET]; + + // first initialized the billboard of lights if needed... + if (!::danceFloorInitialized) { + for (int i = 0; i < DANCE_FLOOR_WIDTH; i++) { + for (int j = 0; j < DANCE_FLOOR_LENGTH; j++) { + + int randomColorIndex = randIntInRange(-DANCE_FLOOR_COLORS, DANCE_FLOOR_COLORS); + ::danceFloorColors[i][j] = randomColorIndex; + ::danceFloorLights[i][j] = ::danceFloorPosition + + glm::vec3(i * DANCE_FLOOR_LIGHT_SIZE, 0, j * DANCE_FLOOR_LIGHT_SIZE); + } + } + ::danceFloorInitialized = true; + } + + ::danceFloorGradient += ::danceFloorGradientIncrement; + + if (::danceFloorGradient >= DANCE_FLOOR_MAX_GRADIENT) { + ::danceFloorGradient = DANCE_FLOOR_MAX_GRADIENT; + ::danceFloorGradientIncrement = -::danceFloorGradientIncrement; + } + if (::danceFloorGradient <= DANCE_FLOOR_MIN_GRADIENT) { + ::danceFloorGradient = DANCE_FLOOR_MIN_GRADIENT; + ::danceFloorGradientIncrement = -::danceFloorGradientIncrement; + } + + for (int i = 0; i < DANCE_FLOOR_LENGTH; i++) { + for (int j = 0; j < DANCE_FLOOR_WIDTH; j++) { + + int nthVoxel = ((i * DANCE_FLOOR_WIDTH) + j); + int item = nthVoxel % DANCE_FLOOR_VOXELS_PER_PACKET; + + ::danceFloorLights[i][j] = ::danceFloorPosition + + glm::vec3(i * DANCE_FLOOR_LIGHT_SIZE, 0, j * DANCE_FLOOR_LIGHT_SIZE); + + details[item].s = lightScale; + details[item].x = ::danceFloorLights[i][j].x; + details[item].y = ::danceFloorLights[i][j].y; + details[item].z = ::danceFloorLights[i][j].z; + + if (danceFloorColors[i][j] > 0) { + int color = danceFloorColors[i][j] - 1; + details[item].red = (::danceFloorOnColorA[color][0] + + ((::danceFloorOnColorB[color][0] - ::danceFloorOnColorA[color][0]) + * ::danceFloorGradient)); + details[item].green = (::danceFloorOnColorA[color][1] + + ((::danceFloorOnColorB[color][1] - ::danceFloorOnColorA[color][1]) + * ::danceFloorGradient)); + details[item].blue = (::danceFloorOnColorA[color][2] + + ((::danceFloorOnColorB[color][2] - ::danceFloorOnColorA[color][2]) + * ::danceFloorGradient)); + } else if (::danceFloorColors[i][j] < 0) { + int color = -(::danceFloorColors[i][j] + 1); + details[item].red = (::danceFloorOnColorB[color][0] + + ((::danceFloorOnColorA[color][0] - ::danceFloorOnColorB[color][0]) + * ::danceFloorGradient)); + details[item].green = (::danceFloorOnColorB[color][1] + + ((::danceFloorOnColorA[color][1] - ::danceFloorOnColorB[color][1]) + * ::danceFloorGradient)); + details[item].blue = (::danceFloorOnColorB[color][2] + + ((::danceFloorOnColorA[color][2] - ::danceFloorOnColorB[color][2]) + * ::danceFloorGradient)); + } else { + int color = 0; + details[item].red = (::danceFloorOnColorB[color][0] + + ((::danceFloorOnColorA[color][0] - ::danceFloorOnColorB[color][0]) + * ::danceFloorGradient)); + details[item].green = (::danceFloorOnColorB[color][1] + + ((::danceFloorOnColorA[color][1] - ::danceFloorOnColorB[color][1]) + * ::danceFloorGradient)); + details[item].blue = (::danceFloorOnColorB[color][2] + + ((::danceFloorOnColorA[color][2] - ::danceFloorOnColorB[color][2]) + * ::danceFloorGradient)); + } + + if (item == DANCE_FLOOR_VOXELS_PER_PACKET - 1) { + ::voxelEditPacketSender->queueVoxelEditMessages(message, DANCE_FLOOR_VOXELS_PER_PACKET, (VoxelDetail*)&details); + } + } + } +} + +bool billboardInitialized = false; +const int BILLBOARD_HEIGHT = 9; +const int BILLBOARD_WIDTH = 45; +glm::vec3 billboardPosition((0.125f / TREE_SCALE),(0.125f / TREE_SCALE),0); +glm::vec3 billboardLights[BILLBOARD_HEIGHT][BILLBOARD_WIDTH]; +unsigned char billboardOffColor[3] = { 240, 240, 240 }; +unsigned char billboardOnColorA[3] = { 0, 0, 255 }; +unsigned char billboardOnColorB[3] = { 0, 255, 0 }; +float billboardGradient = 0.5f; +float billboardGradientIncrement = 0.01f; +const float BILLBOARD_MAX_GRADIENT = 1.0f; +const float BILLBOARD_MIN_GRADIENT = 0.0f; +const float BILLBOARD_LIGHT_SIZE = 0.125f / TREE_SCALE; // approximately 1/8 meter per light +const int VOXELS_PER_PACKET = 81; +const int PACKETS_PER_BILLBOARD = VOXELS_PER_PACKET / (BILLBOARD_HEIGHT * BILLBOARD_WIDTH); + + +// top to bottom... +bool billboardMessage[BILLBOARD_HEIGHT][BILLBOARD_WIDTH] = { + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, + { 0,0,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,0,0 }, + { 0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0,0,0 }, + { 0,0,1,1,1,1,0,1,0,1,1,1,0,1,1,1,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,0,1,0 }, + { 0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,1,0,1,0 }, + { 0,0,1,0,0,1,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,1,1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,1,1,0 }, + { 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0 }, + { 0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0 }, + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } +}; + +static void sendBillboard() { + PACKET_TYPE message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; // we're a bully! + float lightScale = BILLBOARD_LIGHT_SIZE; + static VoxelDetail details[VOXELS_PER_PACKET]; + + // first initialized the billboard of lights if needed... + if (!billboardInitialized) { + for (int i = 0; i < BILLBOARD_HEIGHT; i++) { + for (int j = 0; j < BILLBOARD_WIDTH; j++) { + + billboardLights[i][j] = billboardPosition + glm::vec3(j * lightScale, (float)((BILLBOARD_HEIGHT - i) * lightScale), 0); + } + } + billboardInitialized = true; + } + + ::billboardGradient += ::billboardGradientIncrement; + + if (::billboardGradient >= BILLBOARD_MAX_GRADIENT) { + ::billboardGradient = BILLBOARD_MAX_GRADIENT; + ::billboardGradientIncrement = -::billboardGradientIncrement; + } + if (::billboardGradient <= BILLBOARD_MIN_GRADIENT) { + ::billboardGradient = BILLBOARD_MIN_GRADIENT; + ::billboardGradientIncrement = -::billboardGradientIncrement; + } + + for (int i = 0; i < BILLBOARD_HEIGHT; i++) { + for (int j = 0; j < BILLBOARD_WIDTH; j++) { + + int nthVoxel = ((i * BILLBOARD_WIDTH) + j); + int item = nthVoxel % VOXELS_PER_PACKET; + + billboardLights[i][j] = billboardPosition + glm::vec3(j * lightScale, (float)((BILLBOARD_HEIGHT - i) * lightScale), 0); + + details[item].s = lightScale; + details[item].x = billboardLights[i][j].x; + details[item].y = billboardLights[i][j].y; + details[item].z = billboardLights[i][j].z; + + if (billboardMessage[i][j]) { + details[item].red = (billboardOnColorA[0] + ((billboardOnColorB[0] - billboardOnColorA[0]) * ::billboardGradient)); + details[item].green = (billboardOnColorA[1] + ((billboardOnColorB[1] - billboardOnColorA[1]) * ::billboardGradient)); + details[item].blue = (billboardOnColorA[2] + ((billboardOnColorB[2] - billboardOnColorA[2]) * ::billboardGradient)); + } else { + details[item].red = billboardOffColor[0]; + details[item].green = billboardOffColor[1]; + details[item].blue = billboardOffColor[2]; + } + + if (item == VOXELS_PER_PACKET - 1) { + ::voxelEditPacketSender->queueVoxelEditMessages(message, VOXELS_PER_PACKET, (VoxelDetail*)&details); + } + } + } +} + +bool roadInitialized = false; +const int ROAD_WIDTH_METERS = 3.0f; +const int BRICKS_ACROSS_ROAD = 32; +const float ROAD_BRICK_SIZE = 0.125f/TREE_SCALE; //(ROAD_WIDTH_METERS / TREE_SCALE) / BRICKS_ACROSS_ROAD; // in voxel units +const int ROAD_LENGTH = 1.0f / ROAD_BRICK_SIZE; // in bricks +const int ROAD_WIDTH = BRICKS_ACROSS_ROAD; // in bricks +glm::vec3 roadPosition(0.5f - (ROAD_BRICK_SIZE * BRICKS_ACROSS_ROAD), 0.0f, 0.0f); +const int BRICKS_PER_PACKET = 32; // guessing +const int PACKETS_PER_ROAD = VOXELS_PER_PACKET / (ROAD_LENGTH * ROAD_WIDTH); + +void doBuildStreet() { + if (roadInitialized) { + return; + } + + PACKET_TYPE message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; // we're a bully! + static VoxelDetail details[BRICKS_PER_PACKET]; + + for (int z = 0; z < ROAD_LENGTH; z++) { + for (int x = 0; x < ROAD_WIDTH; x++) { + + int nthVoxel = ((z * ROAD_WIDTH) + x); + int item = nthVoxel % BRICKS_PER_PACKET; + + glm::vec3 brick = roadPosition + glm::vec3(x * ROAD_BRICK_SIZE, 0, z * ROAD_BRICK_SIZE); + + details[item].s = ROAD_BRICK_SIZE; + details[item].x = brick.x; + details[item].y = brick.y; + details[item].z = brick.z; + + unsigned char randomTone = randIntInRange(118,138); + details[item].red = randomTone; + details[item].green = randomTone; + details[item].blue = randomTone; + + if (item == BRICKS_PER_PACKET - 1) { + ::voxelEditPacketSender->queueVoxelEditMessages(message, BRICKS_PER_PACKET, (VoxelDetail*)&details); + } + } + } + roadInitialized = true; +} + + +double start = 0; + + +void* animateVoxels(void* args) { + + uint64_t lastAnimateTime = 0; + uint64_t lastProcessTime = 0; + int processesPerAnimate = 0; + + bool firstTime = true; + + qDebug() << "Setting PPS to " << ::packetsPerSecond << "\n"; + ::voxelEditPacketSender->setPacketsPerSecond(::packetsPerSecond); + + qDebug() << "PPS set to " << ::voxelEditPacketSender->getPacketsPerSecond() << "\n"; + + while (true) { + + // If we're asked to wait for voxel servers, and there isn't one available yet, then + // let the voxelEditPacketSender process and move on. + if (::waitForVoxelServer && !::voxelEditPacketSender->voxelServersExist()) { + if (::nonThreadedPacketSender) { + ::voxelEditPacketSender->process(); + } + } else { + if (firstTime) { + lastAnimateTime = usecTimestampNow(); + firstTime = false; + } + lastProcessTime = usecTimestampNow(); + + int packetsStarting = 0; + int packetsEnding = 0; + + // The while loop will be running at PROCESSING_FPS, but we only want to call these animation functions at + // ANIMATE_FPS. So we check out last animate time and only call these if we've elapsed that time. + uint64_t now = usecTimestampNow(); + uint64_t animationElapsed = now - lastAnimateTime; + int withinAnimationTarget = ANIMATE_VOXELS_INTERVAL_USECS - animationElapsed; + const int CLOSE_ENOUGH_TO_ANIMATE = 2000; // approximately 2 ms + + int animateLoopsPerAnimate = 0; + while (withinAnimationTarget < CLOSE_ENOUGH_TO_ANIMATE) { + processesPerAnimate = 0; + animateLoopsPerAnimate++; + + lastAnimateTime = now; + packetsStarting = ::voxelEditPacketSender->packetsToSendCount(); + + // some animations + //sendVoxelBlinkMessage(); + + if (::includeBillboard) { + sendBillboard(); + } + if (::includeBorderTracer) { + sendBlinkingStringOfLights(); + } + if (::includeMovingBug) { + renderMovingBug(); + } + if (::includeBlinkingVoxel) { + sendVoxelBlinkMessage(); + } + if (::includeDanceFloor) { + sendDanceFloor(); + } + + if (::buildStreet) { + doBuildStreet(); + } + + packetsEnding = ::voxelEditPacketSender->packetsToSendCount(); + + if (animationElapsed > ANIMATE_VOXELS_INTERVAL_USECS) { + animationElapsed -= ANIMATE_VOXELS_INTERVAL_USECS; // credit ourselves one animation frame + } else { + animationElapsed = 0; + } + withinAnimationTarget = ANIMATE_VOXELS_INTERVAL_USECS - animationElapsed; + + ::voxelEditPacketSender->releaseQueuedMessages(); + } + + if (::nonThreadedPacketSender) { + ::voxelEditPacketSender->process(); + } + processesPerAnimate++; + + if (::shouldShowPacketsPerSecond) { + float lifetimeSeconds = ::voxelEditPacketSender->getLifetimeInSeconds(); + int targetPPS = ::voxelEditPacketSender->getPacketsPerSecond(); + float lifetimePPS = ::voxelEditPacketSender->getLifetimePPS(); + float lifetimeBPS = ::voxelEditPacketSender->getLifetimeBPS(); + uint64_t totalPacketsSent = ::voxelEditPacketSender->getLifetimePacketsSent(); + uint64_t totalBytesSent = ::voxelEditPacketSender->getLifetimeBytesSent(); + + float lifetimePPSQueued = ::voxelEditPacketSender->getLifetimePPSQueued(); + float lifetimeBPSQueued = ::voxelEditPacketSender->getLifetimeBPSQueued(); + uint64_t totalPacketsQueued = ::voxelEditPacketSender->getLifetimePacketsQueued(); + uint64_t totalBytesQueued = ::voxelEditPacketSender->getLifetimeBytesQueued(); + + uint64_t packetsPending = ::voxelEditPacketSender->packetsToSendCount(); + + printf("lifetime=%f secs packetsSent=%lld, bytesSent=%lld targetPPS=%d pps=%f bps=%f\n", + lifetimeSeconds, totalPacketsSent, totalBytesSent, targetPPS, lifetimePPS, lifetimeBPS); + printf("packetsPending=%lld packetsQueued=%lld, bytesQueued=%lld ppsQueued=%f bpsQueued=%f\n", + packetsPending, totalPacketsQueued, totalBytesQueued, lifetimePPSQueued, lifetimeBPSQueued); + } + } + // dynamically sleep until we need to fire off the next set of voxels + uint64_t usecToSleep = PROCESSING_INTERVAL_USECS - (usecTimestampNow() - lastProcessTime); + if (usecToSleep > PROCESSING_INTERVAL_USECS) { + usecToSleep = PROCESSING_INTERVAL_USECS; + } + + if (usecToSleep > 0) { + usleep(usecToSleep); + } + } + + pthread_exit(0); +} + +AnimationServer::AnimationServer(int &argc, char **argv) : + QCoreApplication(argc, argv) +{ + ::start = usecTimestampNow(); + + NodeList* nodeList = NodeList::createInstance(NODE_TYPE_ANIMATION_SERVER, ANIMATION_LISTEN_PORT); + setvbuf(stdout, NULL, _IOLBF, 0); + + // Handle Local Domain testing with the --local command line + const char* NON_THREADED_PACKETSENDER = "--NonThreadedPacketSender"; + ::nonThreadedPacketSender = cmdOptionExists(argc, (const char**) argv, NON_THREADED_PACKETSENDER); + printf("nonThreadedPacketSender=%s\n", debug::valueOf(::nonThreadedPacketSender)); + + // Handle Local Domain testing with the --local command line + const char* NO_BILLBOARD = "--NoBillboard"; + ::includeBillboard = !cmdOptionExists(argc, (const char**) argv, NO_BILLBOARD); + printf("includeBillboard=%s\n", debug::valueOf(::includeBillboard)); + + const char* NO_BORDER_TRACER = "--NoBorderTracer"; + ::includeBorderTracer = !cmdOptionExists(argc, (const char**) argv, NO_BORDER_TRACER); + printf("includeBorderTracer=%s\n", debug::valueOf(::includeBorderTracer)); + + const char* NO_MOVING_BUG = "--NoMovingBug"; + ::includeMovingBug = !cmdOptionExists(argc, (const char**) argv, NO_MOVING_BUG); + printf("includeMovingBug=%s\n", debug::valueOf(::includeMovingBug)); + + const char* INCLUDE_BLINKING_VOXEL = "--includeBlinkingVoxel"; + ::includeBlinkingVoxel = cmdOptionExists(argc, (const char**) argv, INCLUDE_BLINKING_VOXEL); + printf("includeBlinkingVoxel=%s\n", debug::valueOf(::includeBlinkingVoxel)); + + const char* NO_DANCE_FLOOR = "--NoDanceFloor"; + ::includeDanceFloor = !cmdOptionExists(argc, (const char**) argv, NO_DANCE_FLOOR); + printf("includeDanceFloor=%s\n", debug::valueOf(::includeDanceFloor)); + + const char* BUILD_STREET = "--BuildStreet"; + ::buildStreet = cmdOptionExists(argc, (const char**) argv, BUILD_STREET); + printf("buildStreet=%s\n", debug::valueOf(::buildStreet)); + + // Handle Local Domain testing with the --local command line + const char* showPPS = "--showPPS"; + ::shouldShowPacketsPerSecond = cmdOptionExists(argc, (const char**) argv, showPPS); + + // Handle Local Domain testing with the --local command line + const char* local = "--local"; + ::wantLocalDomain = cmdOptionExists(argc, (const char**) argv,local); + if (::wantLocalDomain) { + printf("Local Domain MODE!\n"); + nodeList->setDomainIPToLocalhost(); + } + + const char* domainHostname = getCmdOption(argc, (const char**) argv, "--domain"); + if (domainHostname) { + NodeList::getInstance()->setDomainHostname(domainHostname); + } + + const char* packetsPerSecondCommand = getCmdOption(argc, (const char**) argv, "--pps"); + if (packetsPerSecondCommand) { + ::packetsPerSecond = atoi(packetsPerSecondCommand); + } + printf("packetsPerSecond=%d\n",packetsPerSecond); + + const char* animateFPSCommand = getCmdOption(argc, (const char**) argv, "--AnimateFPS"); + const char* animateIntervalCommand = getCmdOption(argc, (const char**) argv, "--AnimateInterval"); + if (animateFPSCommand || animateIntervalCommand) { + if (animateIntervalCommand) { + ::ANIMATE_FPS_IN_MILLISECONDS = atoi(animateIntervalCommand); + ::ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs + ::ANIMATE_FPS = PacketSender::USECS_PER_SECOND / ::ANIMATE_VOXELS_INTERVAL_USECS; + } else { + ::ANIMATE_FPS = atoi(animateFPSCommand); + ::ANIMATE_FPS_IN_MILLISECONDS = 1000.0/ANIMATE_FPS; // determines FPS from our desired FPS + ::ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs + } + } + printf("ANIMATE_FPS=%d\n",ANIMATE_FPS); + printf("ANIMATE_VOXELS_INTERVAL_USECS=%d\n",ANIMATE_VOXELS_INTERVAL_USECS); + + const char* processingFPSCommand = getCmdOption(argc, (const char**) argv, "--ProcessingFPS"); + const char* processingIntervalCommand = getCmdOption(argc, (const char**) argv, "--ProcessingInterval"); + if (processingFPSCommand || processingIntervalCommand) { + if (processingIntervalCommand) { + ::PROCESSING_FPS_IN_MILLISECONDS = atoi(processingIntervalCommand); + ::PROCESSING_INTERVAL_USECS = ::PROCESSING_FPS_IN_MILLISECONDS * 1000.0; + ::PROCESSING_FPS = PacketSender::USECS_PER_SECOND / ::PROCESSING_INTERVAL_USECS; + } else { + ::PROCESSING_FPS = atoi(processingFPSCommand); + ::PROCESSING_FPS_IN_MILLISECONDS = 1000.0/PROCESSING_FPS; // determines FPS from our desired FPS + ::PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000.0) - FUDGE_USECS; // converts from milliseconds to usecs + } + } + printf("PROCESSING_FPS=%d\n",PROCESSING_FPS); + printf("PROCESSING_INTERVAL_USECS=%d\n",PROCESSING_INTERVAL_USECS); + + if (cmdOptionExists(argc, (const char**) argv, "--quickExit")) { + qDebug() << "quick exit asked for\n"; + quit(); + } + + nodeList->linkedDataCreateCallback = NULL; // do we need a callback? + + // Create our JurisdictionListener so we'll know where to send edit packets + ::jurisdictionListener = new JurisdictionListener(); + if (::jurisdictionListener) { + ::jurisdictionListener->initialize(true); + } + + // Create out VoxelEditPacketSender + ::voxelEditPacketSender = new VoxelEditPacketSender; + ::voxelEditPacketSender->initialize(!::nonThreadedPacketSender); + + if (::jurisdictionListener) { + ::voxelEditPacketSender->setVoxelServerJurisdictions(::jurisdictionListener->getJurisdictions()); + } + if (::nonThreadedPacketSender) { + ::voxelEditPacketSender->setProcessCallIntervalHint(PROCESSING_INTERVAL_USECS); + } + + srand((unsigned)time(0)); + + + pthread_create(&::animateVoxelThread, NULL, animateVoxels, NULL); + + NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_VOXEL_SERVER, 1); + + QTimer* domainServerTimer = new QTimer(this); + connect(domainServerTimer, SIGNAL(timeout()), nodeList, SLOT(sendDomainServerCheckIn())); + domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_USECS / 1000); + + QTimer* silentNodeTimer = new QTimer(this); + connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); + silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); + + connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), SLOT(readPendingDatagrams())); +} + +void AnimationServer::readPendingDatagrams() { + NodeList* nodeList = NodeList::getInstance(); + + static int receivedBytes = 0; + static unsigned char packetData[MAX_PACKET_SIZE]; + static HifiSockAddr nodeSockAddr; + + // Nodes sending messages to us... + while (nodeList->getNodeSocket().hasPendingDatagrams() + && (receivedBytes = nodeList->getNodeSocket().readDatagram((char*) packetData, MAX_PACKET_SIZE, + nodeSockAddr.getAddressPointer(), + nodeSockAddr.getPortPointer())) && + packetVersionMatch(packetData)) { + + if (packetData[0] == PACKET_TYPE_JURISDICTION) { + if (::jurisdictionListener) { + ::jurisdictionListener->queueReceivedPacket(nodeSockAddr, packetData, receivedBytes); + } + } + NodeList::getInstance()->processNodeData(nodeSockAddr, packetData, receivedBytes); + } +} + +void AnimationServer::exit(int returnCode) { + qDebug() << "AS exit called!\n"; + pthread_join(animateVoxelThread, NULL); + + if (::jurisdictionListener) { + ::jurisdictionListener->terminate(); + delete ::jurisdictionListener; + } + + if (::voxelEditPacketSender) { + ::voxelEditPacketSender->terminate(); + delete ::voxelEditPacketSender; + } +} diff --git a/animation-server/src/AnimationServer.h b/animation-server/src/AnimationServer.h new file mode 100644 index 0000000000..59b247f9cf --- /dev/null +++ b/animation-server/src/AnimationServer.h @@ -0,0 +1,24 @@ +// +// AnimationServer.h +// hifi +// +// Created by Stephen Birarda on 12/5/2013. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__AnimationServer__ +#define __hifi__AnimationServer__ + +#include + +class AnimationServer : public QCoreApplication { + Q_OBJECT +public: + AnimationServer(int &argc, char **argv); + void exit(int retCode = 0); +private slots: + void readPendingDatagrams(); +}; + + +#endif /* defined(__hifi__AnimationServer__) */ diff --git a/animation-server/src/main.cpp b/animation-server/src/main.cpp index de64f8c38d..4e6da69d41 100644 --- a/animation-server/src/main.cpp +++ b/animation-server/src/main.cpp @@ -6,884 +6,10 @@ // Copyright (c) 2012 High Fidelity, Inc. All rights reserved. // -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include "Syssocket.h" -#include "Systime.h" -#else -#include -#include -#include -#endif - -bool shouldShowPacketsPerSecond = false; // do we want to debug packets per second -bool includeBillboard = true; -bool includeBorderTracer = true; -bool includeMovingBug = true; -bool includeBlinkingVoxel = false; -bool includeDanceFloor = true; -bool buildStreet = false; -bool nonThreadedPacketSender = false; -int packetsPerSecond = PacketSender::DEFAULT_PACKETS_PER_SECOND; -bool waitForVoxelServer = true; +#include "AnimationServer.h" -const int ANIMATION_LISTEN_PORT = 40107; -int ANIMATE_FPS = 60; -double ANIMATE_FPS_IN_MILLISECONDS = 1000.0/ANIMATE_FPS; // determines FPS from our desired FPS -int ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs - - -int PROCESSING_FPS = 60; -double PROCESSING_FPS_IN_MILLISECONDS = 1000.0/PROCESSING_FPS; // determines FPS from our desired FPS -int FUDGE_USECS = 650; // a little bit of fudge to actually do some processing -int PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000.0) - FUDGE_USECS; // converts from milliseconds to usecs - -bool wantLocalDomain = false; - -unsigned long packetsSent = 0; -unsigned long bytesSent = 0; - - -JurisdictionListener* jurisdictionListener = NULL; -VoxelEditPacketSender* voxelEditPacketSender = NULL; - - -glm::vec3 rotatePoint(glm::vec3 point, float angle) { - // First, create the quaternion based on this angle of rotation - glm::quat q(glm::vec3(0, -angle, 0)); - - // Next, create a rotation matrix from that quaternion - glm::mat4 rotation = glm::mat4_cast(q); - - // Transform the original vectors by the rotation matrix to get the new vectors - glm::vec4 quatPoint(point.x, point.y, point.z, 0); - glm::vec4 newPoint = quatPoint * rotation; - - return glm::vec3(newPoint.x, newPoint.y, newPoint.z); -} - - -const float BUG_VOXEL_SIZE = 0.0625f / TREE_SCALE; -glm::vec3 bugPosition = glm::vec3(BUG_VOXEL_SIZE * 20.0, BUG_VOXEL_SIZE * 30.0, BUG_VOXEL_SIZE * 20.0); -glm::vec3 bugDirection = glm::vec3(0, 0, 1); -const int VOXELS_PER_BUG = 18; -glm::vec3 bugPathCenter = glm::vec3(0.25f,0.15f,0.25f); // glm::vec3(BUG_VOXEL_SIZE * 150.0, BUG_VOXEL_SIZE * 30.0, BUG_VOXEL_SIZE * 150.0); -float bugPathRadius = 0.2f; //BUG_VOXEL_SIZE * 140.0; -float bugPathTheta = 0.0 * PI_OVER_180; -float bugRotation = 0.0 * PI_OVER_180; -float bugAngleDelta = 0.2 * PI_OVER_180; -bool moveBugInLine = false; - -class BugPart { -public: - glm::vec3 partLocation; - unsigned char partColor[3]; - - BugPart(const glm::vec3& location, unsigned char red, unsigned char green, unsigned char blue ) { - partLocation = location; - partColor[0] = red; - partColor[1] = green; - partColor[2] = blue; - } -}; - -const BugPart bugParts[VOXELS_PER_BUG] = { - - // tail - BugPart(glm::vec3( 0, 0, -3), 51, 51, 153) , - BugPart(glm::vec3( 0, 0, -2), 51, 51, 153) , - BugPart(glm::vec3( 0, 0, -1), 51, 51, 153) , - - // body - BugPart(glm::vec3( 0, 0, 0), 255, 200, 0) , - BugPart(glm::vec3( 0, 0, 1), 255, 200, 0) , - - // head - BugPart(glm::vec3( 0, 0, 2), 200, 0, 0) , - - // eyes - BugPart(glm::vec3( 1, 0, 3), 64, 64, 64) , - BugPart(glm::vec3(-1, 0, 3), 64, 64, 64) , - - // wings - BugPart(glm::vec3( 3, 1, 1), 0, 153, 0) , - BugPart(glm::vec3( 2, 1, 1), 0, 153, 0) , - BugPart(glm::vec3( 1, 0, 1), 0, 153, 0) , - BugPart(glm::vec3(-1, 0, 1), 0, 153, 0) , - BugPart(glm::vec3(-2, 1, 1), 0, 153, 0) , - BugPart(glm::vec3(-3, 1, 1), 0, 153, 0) , - - - BugPart(glm::vec3( 2, -1, 0), 153, 200, 0) , - BugPart(glm::vec3( 1, -1, 0), 153, 200, 0) , - BugPart(glm::vec3(-1, -1, 0), 153, 200, 0) , - BugPart(glm::vec3(-2, -1, 0), 153, 200, 0) , -}; - -static void renderMovingBug() { - VoxelDetail details[VOXELS_PER_BUG]; - - // Generate voxels for where bug used to be - for (int i = 0; i < VOXELS_PER_BUG; i++) { - details[i].s = BUG_VOXEL_SIZE; - - glm::vec3 partAt = bugParts[i].partLocation * BUG_VOXEL_SIZE * (bugDirection.x < 0 ? -1.0f : 1.0f); - glm::vec3 rotatedPartAt = rotatePoint(partAt, bugRotation); - glm::vec3 offsetPartAt = rotatedPartAt + bugPosition; - - details[i].x = offsetPartAt.x; - details[i].y = offsetPartAt.y; - details[i].z = offsetPartAt.z; - - details[i].red = bugParts[i].partColor[0]; - details[i].green = bugParts[i].partColor[1]; - details[i].blue = bugParts[i].partColor[2]; - } - - // send the "erase message" first... - PACKET_TYPE message = PACKET_TYPE_VOXEL_ERASE; - ::voxelEditPacketSender->queueVoxelEditMessages(message, VOXELS_PER_BUG, (VoxelDetail*)&details); - - // Move the bug... - if (moveBugInLine) { - bugPosition.x += (bugDirection.x * BUG_VOXEL_SIZE); - bugPosition.y += (bugDirection.y * BUG_VOXEL_SIZE); - bugPosition.z += (bugDirection.z * BUG_VOXEL_SIZE); - - // Check boundaries - if (bugPosition.z > 1.0) { - bugDirection.z = -1; - } - if (bugPosition.z < BUG_VOXEL_SIZE) { - bugDirection.z = 1; - } - } else { - - //printf("bugPathCenter=(%f,%f,%f)\n", bugPathCenter.x, bugPathCenter.y, bugPathCenter.z); - - bugPathTheta += bugAngleDelta; // move slightly - bugRotation -= bugAngleDelta; // rotate slightly - - // If we loop past end of circle, just reset back into normal range - if (bugPathTheta > (360.0f * PI_OVER_180)) { - bugPathTheta = 0; - bugRotation = 0; - } - - float x = bugPathCenter.x + bugPathRadius * cos(bugPathTheta); - float z = bugPathCenter.z + bugPathRadius * sin(bugPathTheta); - float y = bugPathCenter.y; - - bugPosition = glm::vec3(x, y, z); - //printf("bugPathTheta=%f\n", bugPathTheta); - //printf("bugRotation=%f\n", bugRotation); - } - - //printf("bugPosition=(%f,%f,%f)\n", bugPosition.x, bugPosition.y, bugPosition.z); - //printf("bugDirection=(%f,%f,%f)\n", bugDirection.x, bugDirection.y, bugDirection.z); - // would be nice to add some randomness here... - - // Generate voxels for where bug is going to - for (int i = 0; i < VOXELS_PER_BUG; i++) { - details[i].s = BUG_VOXEL_SIZE; - - glm::vec3 partAt = bugParts[i].partLocation * BUG_VOXEL_SIZE * (bugDirection.x < 0 ? -1.0f : 1.0f); - glm::vec3 rotatedPartAt = rotatePoint(partAt, bugRotation); - glm::vec3 offsetPartAt = rotatedPartAt + bugPosition; - - details[i].x = offsetPartAt.x; - details[i].y = offsetPartAt.y; - details[i].z = offsetPartAt.z; - - details[i].red = bugParts[i].partColor[0]; - details[i].green = bugParts[i].partColor[1]; - details[i].blue = bugParts[i].partColor[2]; - } - - // send the "create message" ... - message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; - ::voxelEditPacketSender->queueVoxelEditMessages(message, VOXELS_PER_BUG, (VoxelDetail*)&details); -} - - -float intensity = 0.5f; -float intensityIncrement = 0.1f; -const float MAX_INTENSITY = 1.0f; -const float MIN_INTENSITY = 0.5f; -const float BEACON_SIZE = 0.25f / TREE_SCALE; // approximately 1/4th meter - -static void sendVoxelBlinkMessage() { - VoxelDetail detail; - detail.s = BEACON_SIZE; - - glm::vec3 position = glm::vec3(0, 0, detail.s); - - detail.x = detail.s * floor(position.x / detail.s); - detail.y = detail.s * floor(position.y / detail.s); - detail.z = detail.s * floor(position.z / detail.s); - - ::intensity += ::intensityIncrement; - if (::intensity >= MAX_INTENSITY) { - ::intensity = MAX_INTENSITY; - ::intensityIncrement = -::intensityIncrement; - } - if (::intensity <= MIN_INTENSITY) { - ::intensity = MIN_INTENSITY; - ::intensityIncrement = -::intensityIncrement; - } - - detail.red = 255 * ::intensity; - detail.green = 0 * ::intensity; - detail.blue = 0 * ::intensity; - - PACKET_TYPE message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; - - ::voxelEditPacketSender->sendVoxelEditMessage(message, detail); -} - -bool stringOfLightsInitialized = false; -int currentLight = 0; -int lightMovementDirection = 1; -const int SEGMENT_COUNT = 4; -const int LIGHTS_PER_SEGMENT = 80; -const int LIGHT_COUNT = LIGHTS_PER_SEGMENT * SEGMENT_COUNT; -glm::vec3 stringOfLights[LIGHT_COUNT]; -unsigned char offColor[3] = { 240, 240, 240 }; -unsigned char onColor[3] = { 0, 255, 255 }; -const float STRING_OF_LIGHTS_SIZE = 0.125f / TREE_SCALE; // approximately 1/8th meter - -static void sendBlinkingStringOfLights() { - PACKET_TYPE message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; // we're a bully! - float lightScale = STRING_OF_LIGHTS_SIZE; - static VoxelDetail details[LIGHTS_PER_SEGMENT]; - - // first initialized the string of lights if needed... - if (!stringOfLightsInitialized) { - for (int segment = 0; segment < SEGMENT_COUNT; segment++) { - for (int indexInSegment = 0; indexInSegment < LIGHTS_PER_SEGMENT; indexInSegment++) { - - int i = (segment * LIGHTS_PER_SEGMENT) + indexInSegment; - - // four different segments on sides of initial platform - switch (segment) { - case 0: - // along x axis - stringOfLights[i] = glm::vec3(indexInSegment * lightScale, 0, 0); - break; - case 1: - // parallel to Z axis at outer X edge - stringOfLights[i] = glm::vec3(LIGHTS_PER_SEGMENT * lightScale, 0, indexInSegment * lightScale); - break; - case 2: - // parallel to X axis at outer Z edge - stringOfLights[i] = glm::vec3((LIGHTS_PER_SEGMENT-indexInSegment) * lightScale, 0, - LIGHTS_PER_SEGMENT * lightScale); - break; - case 3: - // on Z axis - stringOfLights[i] = glm::vec3(0, 0, (LIGHTS_PER_SEGMENT-indexInSegment) * lightScale); - break; - } - - details[indexInSegment].s = STRING_OF_LIGHTS_SIZE; - details[indexInSegment].x = stringOfLights[i].x; - details[indexInSegment].y = stringOfLights[i].y; - details[indexInSegment].z = stringOfLights[i].z; - - details[indexInSegment].red = offColor[0]; - details[indexInSegment].green = offColor[1]; - details[indexInSegment].blue = offColor[2]; - } - - ::voxelEditPacketSender->queueVoxelEditMessages(message, LIGHTS_PER_SEGMENT, (VoxelDetail*)&details); - } - stringOfLightsInitialized = true; - } else { - // turn off current light - details[0].x = stringOfLights[currentLight].x; - details[0].y = stringOfLights[currentLight].y; - details[0].z = stringOfLights[currentLight].z; - details[0].red = offColor[0]; - details[0].green = offColor[1]; - details[0].blue = offColor[2]; - - // move current light... - // if we're at the end of our string, then change direction - if (currentLight == LIGHT_COUNT-1) { - lightMovementDirection = -1; - } - if (currentLight == 0) { - lightMovementDirection = 1; - } - currentLight += lightMovementDirection; - - // turn on new current light - details[1].x = stringOfLights[currentLight].x; - details[1].y = stringOfLights[currentLight].y; - details[1].z = stringOfLights[currentLight].z; - details[1].red = onColor[0]; - details[1].green = onColor[1]; - details[1].blue = onColor[2]; - - // send both changes in same message - ::voxelEditPacketSender->queueVoxelEditMessages(message, 2, (VoxelDetail*)&details); - } -} - -bool danceFloorInitialized = false; -const float DANCE_FLOOR_LIGHT_SIZE = 1.0f / TREE_SCALE; // approximately 1 meter -const int DANCE_FLOOR_LENGTH = 10; -const int DANCE_FLOOR_WIDTH = 10; -glm::vec3 danceFloorPosition(100.0f / TREE_SCALE, 30.0f / TREE_SCALE, 10.0f / TREE_SCALE); -glm::vec3 danceFloorLights[DANCE_FLOOR_LENGTH][DANCE_FLOOR_WIDTH]; -unsigned char danceFloorOffColor[3] = { 240, 240, 240 }; -const int DANCE_FLOOR_COLORS = 6; - -unsigned char danceFloorOnColorA[DANCE_FLOOR_COLORS][3] = { - { 255, 0, 0 }, { 0, 255, 0 }, { 0, 0, 255 }, - { 0, 191, 255 }, { 0, 250, 154 }, { 255, 69, 0 }, -}; -unsigned char danceFloorOnColorB[DANCE_FLOOR_COLORS][3] = { - { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } , - { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } -}; -float danceFloorGradient = 0.5f; -const float BEATS_PER_MINUTE = 118.0f; -const float SECONDS_PER_MINUTE = 60.0f; -const float FRAMES_PER_BEAT = (SECONDS_PER_MINUTE * ANIMATE_FPS) / BEATS_PER_MINUTE; -float danceFloorGradientIncrement = 1.0f / FRAMES_PER_BEAT; -const float DANCE_FLOOR_MAX_GRADIENT = 1.0f; -const float DANCE_FLOOR_MIN_GRADIENT = 0.0f; -const int DANCE_FLOOR_VOXELS_PER_PACKET = 100; -const int PACKETS_PER_DANCE_FLOOR = DANCE_FLOOR_VOXELS_PER_PACKET / (DANCE_FLOOR_WIDTH * DANCE_FLOOR_LENGTH); -int danceFloorColors[DANCE_FLOOR_WIDTH][DANCE_FLOOR_LENGTH]; - -void sendDanceFloor() { - PACKET_TYPE message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; // we're a bully! - float lightScale = DANCE_FLOOR_LIGHT_SIZE; - static VoxelDetail details[DANCE_FLOOR_VOXELS_PER_PACKET]; - - // first initialized the billboard of lights if needed... - if (!::danceFloorInitialized) { - for (int i = 0; i < DANCE_FLOOR_WIDTH; i++) { - for (int j = 0; j < DANCE_FLOOR_LENGTH; j++) { - - int randomColorIndex = randIntInRange(-DANCE_FLOOR_COLORS, DANCE_FLOOR_COLORS); - ::danceFloorColors[i][j] = randomColorIndex; - ::danceFloorLights[i][j] = ::danceFloorPosition + - glm::vec3(i * DANCE_FLOOR_LIGHT_SIZE, 0, j * DANCE_FLOOR_LIGHT_SIZE); - } - } - ::danceFloorInitialized = true; - } - - ::danceFloorGradient += ::danceFloorGradientIncrement; - - if (::danceFloorGradient >= DANCE_FLOOR_MAX_GRADIENT) { - ::danceFloorGradient = DANCE_FLOOR_MAX_GRADIENT; - ::danceFloorGradientIncrement = -::danceFloorGradientIncrement; - } - if (::danceFloorGradient <= DANCE_FLOOR_MIN_GRADIENT) { - ::danceFloorGradient = DANCE_FLOOR_MIN_GRADIENT; - ::danceFloorGradientIncrement = -::danceFloorGradientIncrement; - } - - for (int i = 0; i < DANCE_FLOOR_LENGTH; i++) { - for (int j = 0; j < DANCE_FLOOR_WIDTH; j++) { - - int nthVoxel = ((i * DANCE_FLOOR_WIDTH) + j); - int item = nthVoxel % DANCE_FLOOR_VOXELS_PER_PACKET; - - ::danceFloorLights[i][j] = ::danceFloorPosition + - glm::vec3(i * DANCE_FLOOR_LIGHT_SIZE, 0, j * DANCE_FLOOR_LIGHT_SIZE); - - details[item].s = lightScale; - details[item].x = ::danceFloorLights[i][j].x; - details[item].y = ::danceFloorLights[i][j].y; - details[item].z = ::danceFloorLights[i][j].z; - - if (danceFloorColors[i][j] > 0) { - int color = danceFloorColors[i][j] - 1; - details[item].red = (::danceFloorOnColorA[color][0] + - ((::danceFloorOnColorB[color][0] - ::danceFloorOnColorA[color][0]) - * ::danceFloorGradient)); - details[item].green = (::danceFloorOnColorA[color][1] + - ((::danceFloorOnColorB[color][1] - ::danceFloorOnColorA[color][1]) - * ::danceFloorGradient)); - details[item].blue = (::danceFloorOnColorA[color][2] + - ((::danceFloorOnColorB[color][2] - ::danceFloorOnColorA[color][2]) - * ::danceFloorGradient)); - } else if (::danceFloorColors[i][j] < 0) { - int color = -(::danceFloorColors[i][j] + 1); - details[item].red = (::danceFloorOnColorB[color][0] + - ((::danceFloorOnColorA[color][0] - ::danceFloorOnColorB[color][0]) - * ::danceFloorGradient)); - details[item].green = (::danceFloorOnColorB[color][1] + - ((::danceFloorOnColorA[color][1] - ::danceFloorOnColorB[color][1]) - * ::danceFloorGradient)); - details[item].blue = (::danceFloorOnColorB[color][2] + - ((::danceFloorOnColorA[color][2] - ::danceFloorOnColorB[color][2]) - * ::danceFloorGradient)); - } else { - int color = 0; - details[item].red = (::danceFloorOnColorB[color][0] + - ((::danceFloorOnColorA[color][0] - ::danceFloorOnColorB[color][0]) - * ::danceFloorGradient)); - details[item].green = (::danceFloorOnColorB[color][1] + - ((::danceFloorOnColorA[color][1] - ::danceFloorOnColorB[color][1]) - * ::danceFloorGradient)); - details[item].blue = (::danceFloorOnColorB[color][2] + - ((::danceFloorOnColorA[color][2] - ::danceFloorOnColorB[color][2]) - * ::danceFloorGradient)); - } - - if (item == DANCE_FLOOR_VOXELS_PER_PACKET - 1) { - ::voxelEditPacketSender->queueVoxelEditMessages(message, DANCE_FLOOR_VOXELS_PER_PACKET, (VoxelDetail*)&details); - } - } - } -} - -bool billboardInitialized = false; -const int BILLBOARD_HEIGHT = 9; -const int BILLBOARD_WIDTH = 45; -glm::vec3 billboardPosition((0.125f / TREE_SCALE),(0.125f / TREE_SCALE),0); -glm::vec3 billboardLights[BILLBOARD_HEIGHT][BILLBOARD_WIDTH]; -unsigned char billboardOffColor[3] = { 240, 240, 240 }; -unsigned char billboardOnColorA[3] = { 0, 0, 255 }; -unsigned char billboardOnColorB[3] = { 0, 255, 0 }; -float billboardGradient = 0.5f; -float billboardGradientIncrement = 0.01f; -const float BILLBOARD_MAX_GRADIENT = 1.0f; -const float BILLBOARD_MIN_GRADIENT = 0.0f; -const float BILLBOARD_LIGHT_SIZE = 0.125f / TREE_SCALE; // approximately 1/8 meter per light -const int VOXELS_PER_PACKET = 81; -const int PACKETS_PER_BILLBOARD = VOXELS_PER_PACKET / (BILLBOARD_HEIGHT * BILLBOARD_WIDTH); - - -// top to bottom... -bool billboardMessage[BILLBOARD_HEIGHT][BILLBOARD_WIDTH] = { - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, - { 0,0,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,0,0 }, - { 0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0,0,0 }, - { 0,0,1,1,1,1,0,1,0,1,1,1,0,1,1,1,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,0,1,0 }, - { 0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,1,0,1,0 }, - { 0,0,1,0,0,1,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,1,1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,1,1,0 }, - { 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0 }, - { 0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0 }, - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } -}; - -static void sendBillboard() { - PACKET_TYPE message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; // we're a bully! - float lightScale = BILLBOARD_LIGHT_SIZE; - static VoxelDetail details[VOXELS_PER_PACKET]; - - // first initialized the billboard of lights if needed... - if (!billboardInitialized) { - for (int i = 0; i < BILLBOARD_HEIGHT; i++) { - for (int j = 0; j < BILLBOARD_WIDTH; j++) { - - billboardLights[i][j] = billboardPosition + glm::vec3(j * lightScale, (float)((BILLBOARD_HEIGHT - i) * lightScale), 0); - } - } - billboardInitialized = true; - } - - ::billboardGradient += ::billboardGradientIncrement; - - if (::billboardGradient >= BILLBOARD_MAX_GRADIENT) { - ::billboardGradient = BILLBOARD_MAX_GRADIENT; - ::billboardGradientIncrement = -::billboardGradientIncrement; - } - if (::billboardGradient <= BILLBOARD_MIN_GRADIENT) { - ::billboardGradient = BILLBOARD_MIN_GRADIENT; - ::billboardGradientIncrement = -::billboardGradientIncrement; - } - - for (int i = 0; i < BILLBOARD_HEIGHT; i++) { - for (int j = 0; j < BILLBOARD_WIDTH; j++) { - - int nthVoxel = ((i * BILLBOARD_WIDTH) + j); - int item = nthVoxel % VOXELS_PER_PACKET; - - billboardLights[i][j] = billboardPosition + glm::vec3(j * lightScale, (float)((BILLBOARD_HEIGHT - i) * lightScale), 0); - - details[item].s = lightScale; - details[item].x = billboardLights[i][j].x; - details[item].y = billboardLights[i][j].y; - details[item].z = billboardLights[i][j].z; - - if (billboardMessage[i][j]) { - details[item].red = (billboardOnColorA[0] + ((billboardOnColorB[0] - billboardOnColorA[0]) * ::billboardGradient)); - details[item].green = (billboardOnColorA[1] + ((billboardOnColorB[1] - billboardOnColorA[1]) * ::billboardGradient)); - details[item].blue = (billboardOnColorA[2] + ((billboardOnColorB[2] - billboardOnColorA[2]) * ::billboardGradient)); - } else { - details[item].red = billboardOffColor[0]; - details[item].green = billboardOffColor[1]; - details[item].blue = billboardOffColor[2]; - } - - if (item == VOXELS_PER_PACKET - 1) { - ::voxelEditPacketSender->queueVoxelEditMessages(message, VOXELS_PER_PACKET, (VoxelDetail*)&details); - } - } - } -} - -bool roadInitialized = false; -const int ROAD_WIDTH_METERS = 3.0f; -const int BRICKS_ACROSS_ROAD = 32; -const float ROAD_BRICK_SIZE = 0.125f/TREE_SCALE; //(ROAD_WIDTH_METERS / TREE_SCALE) / BRICKS_ACROSS_ROAD; // in voxel units -const int ROAD_LENGTH = 1.0f / ROAD_BRICK_SIZE; // in bricks -const int ROAD_WIDTH = BRICKS_ACROSS_ROAD; // in bricks -glm::vec3 roadPosition(0.5f - (ROAD_BRICK_SIZE * BRICKS_ACROSS_ROAD), 0.0f, 0.0f); -const int BRICKS_PER_PACKET = 32; // guessing -const int PACKETS_PER_ROAD = VOXELS_PER_PACKET / (ROAD_LENGTH * ROAD_WIDTH); - -void doBuildStreet() { - if (roadInitialized) { - return; - } - - PACKET_TYPE message = PACKET_TYPE_VOXEL_SET_DESTRUCTIVE; // we're a bully! - static VoxelDetail details[BRICKS_PER_PACKET]; - - for (int z = 0; z < ROAD_LENGTH; z++) { - for (int x = 0; x < ROAD_WIDTH; x++) { - - int nthVoxel = ((z * ROAD_WIDTH) + x); - int item = nthVoxel % BRICKS_PER_PACKET; - - glm::vec3 brick = roadPosition + glm::vec3(x * ROAD_BRICK_SIZE, 0, z * ROAD_BRICK_SIZE); - - details[item].s = ROAD_BRICK_SIZE; - details[item].x = brick.x; - details[item].y = brick.y; - details[item].z = brick.z; - - unsigned char randomTone = randIntInRange(118,138); - details[item].red = randomTone; - details[item].green = randomTone; - details[item].blue = randomTone; - - if (item == BRICKS_PER_PACKET - 1) { - ::voxelEditPacketSender->queueVoxelEditMessages(message, BRICKS_PER_PACKET, (VoxelDetail*)&details); - } - } - } - roadInitialized = true; -} - - -double start = 0; - - -void* animateVoxels(void* args) { - - uint64_t lastAnimateTime = 0; - uint64_t lastProcessTime = 0; - int processesPerAnimate = 0; - - bool firstTime = true; - - std::cout << "Setting PPS to " << ::packetsPerSecond << "\n"; - ::voxelEditPacketSender->setPacketsPerSecond(::packetsPerSecond); - - std::cout << "PPS set to " << ::voxelEditPacketSender->getPacketsPerSecond() << "\n"; - - while (true) { - - // If we're asked to wait for voxel servers, and there isn't one available yet, then - // let the voxelEditPacketSender process and move on. - if (::waitForVoxelServer && !::voxelEditPacketSender->voxelServersExist()) { - if (::nonThreadedPacketSender) { - ::voxelEditPacketSender->process(); - } - } else { - if (firstTime) { - lastAnimateTime = usecTimestampNow(); - firstTime = false; - } - lastProcessTime = usecTimestampNow(); - - int packetsStarting = 0; - int packetsEnding = 0; - - // The while loop will be running at PROCESSING_FPS, but we only want to call these animation functions at - // ANIMATE_FPS. So we check out last animate time and only call these if we've elapsed that time. - uint64_t now = usecTimestampNow(); - uint64_t animationElapsed = now - lastAnimateTime; - int withinAnimationTarget = ANIMATE_VOXELS_INTERVAL_USECS - animationElapsed; - const int CLOSE_ENOUGH_TO_ANIMATE = 2000; // approximately 2 ms - - int animateLoopsPerAnimate = 0; - while (withinAnimationTarget < CLOSE_ENOUGH_TO_ANIMATE) { - processesPerAnimate = 0; - animateLoopsPerAnimate++; - - lastAnimateTime = now; - packetsStarting = ::voxelEditPacketSender->packetsToSendCount(); - - // some animations - //sendVoxelBlinkMessage(); - - if (::includeBillboard) { - sendBillboard(); - } - if (::includeBorderTracer) { - sendBlinkingStringOfLights(); - } - if (::includeMovingBug) { - renderMovingBug(); - } - if (::includeBlinkingVoxel) { - sendVoxelBlinkMessage(); - } - if (::includeDanceFloor) { - sendDanceFloor(); - } - - if (::buildStreet) { - doBuildStreet(); - } - - packetsEnding = ::voxelEditPacketSender->packetsToSendCount(); - - if (animationElapsed > ANIMATE_VOXELS_INTERVAL_USECS) { - animationElapsed -= ANIMATE_VOXELS_INTERVAL_USECS; // credit ourselves one animation frame - } else { - animationElapsed = 0; - } - withinAnimationTarget = ANIMATE_VOXELS_INTERVAL_USECS - animationElapsed; - - ::voxelEditPacketSender->releaseQueuedMessages(); - } - - if (::nonThreadedPacketSender) { - ::voxelEditPacketSender->process(); - } - processesPerAnimate++; - - if (::shouldShowPacketsPerSecond) { - float lifetimeSeconds = ::voxelEditPacketSender->getLifetimeInSeconds(); - int targetPPS = ::voxelEditPacketSender->getPacketsPerSecond(); - float lifetimePPS = ::voxelEditPacketSender->getLifetimePPS(); - float lifetimeBPS = ::voxelEditPacketSender->getLifetimeBPS(); - uint64_t totalPacketsSent = ::voxelEditPacketSender->getLifetimePacketsSent(); - uint64_t totalBytesSent = ::voxelEditPacketSender->getLifetimeBytesSent(); - - float lifetimePPSQueued = ::voxelEditPacketSender->getLifetimePPSQueued(); - float lifetimeBPSQueued = ::voxelEditPacketSender->getLifetimeBPSQueued(); - uint64_t totalPacketsQueued = ::voxelEditPacketSender->getLifetimePacketsQueued(); - uint64_t totalBytesQueued = ::voxelEditPacketSender->getLifetimeBytesQueued(); - - uint64_t packetsPending = ::voxelEditPacketSender->packetsToSendCount(); - - printf("lifetime=%f secs packetsSent=%lld, bytesSent=%lld targetPPS=%d pps=%f bps=%f\n", - lifetimeSeconds, totalPacketsSent, totalBytesSent, targetPPS, lifetimePPS, lifetimeBPS); - printf("packetsPending=%lld packetsQueued=%lld, bytesQueued=%lld ppsQueued=%f bpsQueued=%f\n", - packetsPending, totalPacketsQueued, totalBytesQueued, lifetimePPSQueued, lifetimeBPSQueued); - } - } - // dynamically sleep until we need to fire off the next set of voxels - uint64_t usecToSleep = PROCESSING_INTERVAL_USECS - (usecTimestampNow() - lastProcessTime); - if (usecToSleep > PROCESSING_INTERVAL_USECS) { - usecToSleep = PROCESSING_INTERVAL_USECS; - } - - if (usecToSleep > 0) { - usleep(usecToSleep); - } - } - - pthread_exit(0); -} - - -int main(int argc, const char * argv[]) -{ - ::start = usecTimestampNow(); - - NodeList* nodeList = NodeList::createInstance(NODE_TYPE_ANIMATION_SERVER, ANIMATION_LISTEN_PORT); - setvbuf(stdout, NULL, _IOLBF, 0); - - // Handle Local Domain testing with the --local command line - const char* NON_THREADED_PACKETSENDER = "--NonThreadedPacketSender"; - ::nonThreadedPacketSender = cmdOptionExists(argc, argv, NON_THREADED_PACKETSENDER); - printf("nonThreadedPacketSender=%s\n", debug::valueOf(::nonThreadedPacketSender)); - - // Handle Local Domain testing with the --local command line - const char* NO_BILLBOARD = "--NoBillboard"; - ::includeBillboard = !cmdOptionExists(argc, argv, NO_BILLBOARD); - printf("includeBillboard=%s\n", debug::valueOf(::includeBillboard)); - - const char* NO_BORDER_TRACER = "--NoBorderTracer"; - ::includeBorderTracer = !cmdOptionExists(argc, argv, NO_BORDER_TRACER); - printf("includeBorderTracer=%s\n", debug::valueOf(::includeBorderTracer)); - - const char* NO_MOVING_BUG = "--NoMovingBug"; - ::includeMovingBug = !cmdOptionExists(argc, argv, NO_MOVING_BUG); - printf("includeMovingBug=%s\n", debug::valueOf(::includeMovingBug)); - - const char* INCLUDE_BLINKING_VOXEL = "--includeBlinkingVoxel"; - ::includeBlinkingVoxel = cmdOptionExists(argc, argv, INCLUDE_BLINKING_VOXEL); - printf("includeBlinkingVoxel=%s\n", debug::valueOf(::includeBlinkingVoxel)); - - const char* NO_DANCE_FLOOR = "--NoDanceFloor"; - ::includeDanceFloor = !cmdOptionExists(argc, argv, NO_DANCE_FLOOR); - printf("includeDanceFloor=%s\n", debug::valueOf(::includeDanceFloor)); - - const char* BUILD_STREET = "--BuildStreet"; - ::buildStreet = cmdOptionExists(argc, argv, BUILD_STREET); - printf("buildStreet=%s\n", debug::valueOf(::buildStreet)); - - // Handle Local Domain testing with the --local command line - const char* showPPS = "--showPPS"; - ::shouldShowPacketsPerSecond = cmdOptionExists(argc, argv, showPPS); - - // Handle Local Domain testing with the --local command line - const char* local = "--local"; - ::wantLocalDomain = cmdOptionExists(argc, argv,local); - if (::wantLocalDomain) { - printf("Local Domain MODE!\n"); - nodeList->setDomainIPToLocalhost(); - } - - const char* domainHostname = getCmdOption(argc, argv, "--domain"); - if (domainHostname) { - NodeList::getInstance()->setDomainHostname(domainHostname); - } - - const char* packetsPerSecondCommand = getCmdOption(argc, argv, "--pps"); - if (packetsPerSecondCommand) { - ::packetsPerSecond = atoi(packetsPerSecondCommand); - } - printf("packetsPerSecond=%d\n",packetsPerSecond); - - const char* animateFPSCommand = getCmdOption(argc, argv, "--AnimateFPS"); - const char* animateIntervalCommand = getCmdOption(argc, argv, "--AnimateInterval"); - if (animateFPSCommand || animateIntervalCommand) { - if (animateIntervalCommand) { - ::ANIMATE_FPS_IN_MILLISECONDS = atoi(animateIntervalCommand); - ::ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs - ::ANIMATE_FPS = PacketSender::USECS_PER_SECOND / ::ANIMATE_VOXELS_INTERVAL_USECS; - } else { - ::ANIMATE_FPS = atoi(animateFPSCommand); - ::ANIMATE_FPS_IN_MILLISECONDS = 1000.0/ANIMATE_FPS; // determines FPS from our desired FPS - ::ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs - } - } - printf("ANIMATE_FPS=%d\n",ANIMATE_FPS); - printf("ANIMATE_VOXELS_INTERVAL_USECS=%d\n",ANIMATE_VOXELS_INTERVAL_USECS); - - const char* processingFPSCommand = getCmdOption(argc, argv, "--ProcessingFPS"); - const char* processingIntervalCommand = getCmdOption(argc, argv, "--ProcessingInterval"); - if (processingFPSCommand || processingIntervalCommand) { - if (processingIntervalCommand) { - ::PROCESSING_FPS_IN_MILLISECONDS = atoi(processingIntervalCommand); - ::PROCESSING_INTERVAL_USECS = ::PROCESSING_FPS_IN_MILLISECONDS * 1000.0; - ::PROCESSING_FPS = PacketSender::USECS_PER_SECOND / ::PROCESSING_INTERVAL_USECS; - } else { - ::PROCESSING_FPS = atoi(processingFPSCommand); - ::PROCESSING_FPS_IN_MILLISECONDS = 1000.0/PROCESSING_FPS; // determines FPS from our desired FPS - ::PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000.0) - FUDGE_USECS; // converts from milliseconds to usecs - } - } - printf("PROCESSING_FPS=%d\n",PROCESSING_FPS); - printf("PROCESSING_INTERVAL_USECS=%d\n",PROCESSING_INTERVAL_USECS); - - if (cmdOptionExists(argc, argv, "--quickExit")) { - return 0; - } - - - nodeList->linkedDataCreateCallback = NULL; // do we need a callback? - nodeList->startSilentNodeRemovalThread(); - - // Create our JurisdictionListener so we'll know where to send edit packets - ::jurisdictionListener = new JurisdictionListener(); - if (::jurisdictionListener) { - ::jurisdictionListener->initialize(true); - } - - // Create out VoxelEditPacketSender - ::voxelEditPacketSender = new VoxelEditPacketSender; - ::voxelEditPacketSender->initialize(!::nonThreadedPacketSender); - - if (::jurisdictionListener) { - ::voxelEditPacketSender->setVoxelServerJurisdictions(::jurisdictionListener->getJurisdictions()); - } - if (::nonThreadedPacketSender) { - ::voxelEditPacketSender->setProcessCallIntervalHint(PROCESSING_INTERVAL_USECS); - } - - srand((unsigned)time(0)); - - pthread_t animateVoxelThread; - pthread_create(&animateVoxelThread, NULL, animateVoxels, NULL); - - HifiSockAddr nodeSockAddr; - - unsigned char* packetData = new unsigned char[MAX_PACKET_SIZE]; - ssize_t receivedBytes; - - timeval lastDomainServerCheckIn = {}; - NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_VOXEL_SERVER, 1); - - // loop to send to nodes requesting data - while (true) { - // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed - if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { - gettimeofday(&lastDomainServerCheckIn, NULL); - NodeList::getInstance()->sendDomainServerCheckIn(); - } - - // Nodes sending messages to us... - if (nodeList->getNodeSocket().hasPendingDatagrams() - && (receivedBytes = nodeList->getNodeSocket().readDatagram((char*) packetData, MAX_PACKET_SIZE, - nodeSockAddr.getAddressPointer(), - nodeSockAddr.getPortPointer())) && - packetVersionMatch(packetData)) { - - if (packetData[0] == PACKET_TYPE_JURISDICTION) { - if (::jurisdictionListener) { - ::jurisdictionListener->queueReceivedPacket(nodeSockAddr, packetData, receivedBytes); - } - } - NodeList::getInstance()->processNodeData(nodeSockAddr, packetData, receivedBytes); - } - } - - pthread_join(animateVoxelThread, NULL); - - if (::jurisdictionListener) { - ::jurisdictionListener->terminate(); - delete ::jurisdictionListener; - } - - if (::voxelEditPacketSender) { - ::voxelEditPacketSender->terminate(); - delete ::voxelEditPacketSender; - } - - return 0; +int main(int argc, char * argv[]) { + AnimationServer animationServer(argc, argv); + return animationServer.exec(); } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b48a622772..0521f12e4e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -150,7 +150,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : listenPort = atoi(portStr); } - NodeList::createInstance(NODE_TYPE_AGENT, listenPort); + NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AGENT, listenPort); // put the audio processing on a separate thread QThread* audioThread = new QThread(this); @@ -160,10 +160,10 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : audioThread->start(); - NodeList::getInstance()->addHook(&_voxels); - NodeList::getInstance()->addHook(this); - NodeList::getInstance()->addDomainListener(this); - NodeList::getInstance()->addDomainListener(&_voxels); + nodeList->addHook(&_voxels); + nodeList->addHook(this); + nodeList->addDomainListener(this); + nodeList->addDomainListener(&_voxels); // network receive thread and voxel parsing thread are both controlled by the --nonblocking command line _enableProcessVoxelsThread = _enableNetworkThread = !cmdOptionExists(argc, constArgv, "--nonblocking"); @@ -196,7 +196,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _voxelsFilename = getCmdOption(argc, constArgv, "-i"); // the callback for our instance of NodeList is attachNewHeadToNode - NodeList::getInstance()->linkedDataCreateCallback = &attachNewHeadToNode; + nodeList->linkedDataCreateCallback = &attachNewHeadToNode; #ifdef _WIN32 WSADATA WsaData; @@ -205,10 +205,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : // tell the NodeList instance who to tell the domain server we care about const char nodeTypesOfInterest[] = {NODE_TYPE_AUDIO_MIXER, NODE_TYPE_AVATAR_MIXER, NODE_TYPE_VOXEL_SERVER}; - NodeList::getInstance()->setNodeTypesOfInterest(nodeTypesOfInterest, sizeof(nodeTypesOfInterest)); + nodeList->setNodeTypesOfInterest(nodeTypesOfInterest, sizeof(nodeTypesOfInterest)); - // start the nodeList threads - NodeList::getInstance()->startSilentNodeRemovalThread(); + QTimer* silentNodeTimer = new QTimer(this); + connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); + silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); _networkAccessManager = new QNetworkAccessManager(this); QNetworkDiskCache* cache = new QNetworkDiskCache(_networkAccessManager); diff --git a/libraries/octree-server/src/OctreeServer.cpp b/libraries/octree-server/src/OctreeServer.cpp index 82d5fa4035..568f26a960 100644 --- a/libraries/octree-server/src/OctreeServer.cpp +++ b/libraries/octree-server/src/OctreeServer.cpp @@ -615,7 +615,6 @@ void OctreeServer::run() { nodeList->addHook(this); nodeList->linkedDataCreateCallback = &OctreeServer::attachQueryNodeToNode; - nodeList->startSilentNodeRemovalThread(); srand((unsigned)time(0)); const char* VERBOSE_DEBUG = "--verboseDebug"; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 7f0a26a364..45b38edbc2 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -83,9 +83,6 @@ NodeList::~NodeList() { delete _nodeTypesOfInterest; clear(); - - // stop the spawned threads, if they were started - stopSilentNodeRemovalThread(); } void NodeList::setDomainHostname(const QString& domainHostname) { @@ -832,26 +829,6 @@ void* removeSilentNodesAndSleep(void *args) { return NULL; } -void NodeList::startSilentNodeRemovalThread() { - if (!::silentNodeThreadStopFlag) { - pthread_create(&removeSilentNodesThread, NULL, removeSilentNodesAndSleep, (void*) this); - } else { - qDebug("Refusing to start silent node removal thread from previously failed join.\n"); - } - -} - -void NodeList::stopSilentNodeRemovalThread() { - ::silentNodeThreadStopFlag = true; - int joinResult = pthread_join(removeSilentNodesThread, NULL); - - if (joinResult == 0) { - ::silentNodeThreadStopFlag = false; - } else { - qDebug("Silent node removal thread join failed with %d. Will not restart.\n", joinResult); - } -} - const QString QSETTINGS_GROUP_NAME = "NodeList"; const QString DOMAIN_SERVER_SETTING_KEY = "domainServerHostname"; diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 250474ee75..9ee4c8519d 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -21,10 +21,6 @@ #include "Node.h" #include "NodeTypes.h" -#ifdef _WIN32 -#include "pthread.h" -#endif - const int MAX_NUM_NODES = 10000; const int NODES_PER_BUCKET = 100; @@ -126,9 +122,6 @@ public: Node* soloNodeOfType(char nodeType); - void startSilentNodeRemovalThread(); - void stopSilentNodeRemovalThread(); - void loadData(QSettings* settings); void saveData(QSettings* settings); @@ -170,8 +163,6 @@ private: char _ownerType; char* _nodeTypesOfInterest; QUuid _ownerUUID; - pthread_t removeSilentNodesThread; - pthread_t checkInWithDomainServerThread; int _numNoReplyDomainCheckIns; HifiSockAddr _assignmentServerSocket; HifiSockAddr _publicSockAddr; From e99b1261340d47538818ee8573bb6e55e79257e8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 5 Dec 2013 17:35:26 -0800 Subject: [PATCH 02/15] remove quickExit option from AS, fix cleanup in DS --- animation-server/src/AnimationServer.cpp | 8 +------- animation-server/src/AnimationServer.h | 2 +- domain-server/src/DomainServer.cpp | 16 ++++++++++------ domain-server/src/DomainServer.h | 3 +-- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/animation-server/src/AnimationServer.cpp b/animation-server/src/AnimationServer.cpp index ede205ce90..8ae54c4963 100644 --- a/animation-server/src/AnimationServer.cpp +++ b/animation-server/src/AnimationServer.cpp @@ -804,11 +804,6 @@ AnimationServer::AnimationServer(int &argc, char **argv) : printf("PROCESSING_FPS=%d\n",PROCESSING_FPS); printf("PROCESSING_INTERVAL_USECS=%d\n",PROCESSING_INTERVAL_USECS); - if (cmdOptionExists(argc, (const char**) argv, "--quickExit")) { - qDebug() << "quick exit asked for\n"; - quit(); - } - nodeList->linkedDataCreateCallback = NULL; // do we need a callback? // Create our JurisdictionListener so we'll know where to send edit packets @@ -869,8 +864,7 @@ void AnimationServer::readPendingDatagrams() { } } -void AnimationServer::exit(int returnCode) { - qDebug() << "AS exit called!\n"; +AnimationServer::~AnimationServer() { pthread_join(animateVoxelThread, NULL); if (::jurisdictionListener) { diff --git a/animation-server/src/AnimationServer.h b/animation-server/src/AnimationServer.h index 59b247f9cf..cda5f8fb24 100644 --- a/animation-server/src/AnimationServer.h +++ b/animation-server/src/AnimationServer.h @@ -15,7 +15,7 @@ class AnimationServer : public QCoreApplication { Q_OBJECT public: AnimationServer(int &argc, char **argv); - void exit(int retCode = 0); + ~AnimationServer(); private slots: void readPendingDatagrams(); }; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index bf5a7db16d..a4806ed8c7 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -22,6 +22,12 @@ const int RESTART_HOLD_TIME_MSECS = 5 * 1000; +void signalhandler(int sig){ + if (sig == SIGINT) { + qApp->quit(); + } +} + DomainServer* DomainServer::domainServerInstance = NULL; DomainServer::DomainServer(int argc, char* argv[]) : @@ -35,6 +41,8 @@ DomainServer::DomainServer(int argc, char* argv[]) : { DomainServer::setDomainServerInstance(this); + signal(SIGINT, signalhandler); + const char CUSTOM_PORT_OPTION[] = "-p"; const char* customPortString = getCmdOption(argc, (const char**) argv, CUSTOM_PORT_OPTION); unsigned short domainServerPort = customPortString ? atoi(customPortString) : DEFAULT_DOMAIN_SERVER_PORT; @@ -88,10 +96,8 @@ DomainServer::DomainServer(int argc, char* argv[]) : // fire a single shot timer to add static assignments back into the queue after a restart QTimer::singleShot(RESTART_HOLD_TIME_MSECS, this, SLOT(addStaticAssignmentsBackToQueueAfterRestart())); -} - -void DomainServer::exit(int retCode) { - cleanup(); + + connect(this, SIGNAL(aboutToQuit()), SLOT(cleanup())); } void DomainServer::readAvailableDatagrams() { @@ -774,8 +780,6 @@ void DomainServer::addStaticAssignmentsBackToQueueAfterRestart() { } void DomainServer::cleanup() { - qDebug() << "cleanup called!\n"; - _staticAssignmentFile.unmap(_staticAssignmentFileData); _staticAssignmentFile.close(); } \ No newline at end of file diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 1ca8fb6936..e6047fed9a 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -50,8 +50,6 @@ private: const QUuid& checkInUUI); void addReleasedAssignmentBackToQueue(Assignment* releasedAssignment); - void cleanup(); - unsigned char* addNodeToBroadcastPacket(unsigned char* currentPosition, Node* nodeToAdd); QMutex _assignmentQueueMutex; @@ -69,6 +67,7 @@ private: private slots: void readAvailableDatagrams(); void addStaticAssignmentsBackToQueueAfterRestart(); + void cleanup(); }; #endif /* defined(__hifi__DomainServer__) */ From c2e11e8d8c9c85d9687f2f59375aea14bfdcff0d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 5 Dec 2013 17:39:02 -0800 Subject: [PATCH 03/15] more NodeList cleanup --- libraries/shared/src/NodeList.cpp | 33 ------------------------------- 1 file changed, 33 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 45b38edbc2..ea1421661e 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -37,9 +37,6 @@ const char SOLO_NODE_TYPES[2] = { const QString DEFAULT_DOMAIN_HOSTNAME = "root.highfidelity.io"; const unsigned short DEFAULT_DOMAIN_SERVER_PORT = 40102; -bool silentNodeThreadStopFlag = false; -bool pingUnknownNodeThreadStopFlag = false; - NodeList* NodeList::_sharedInstance = NULL; NodeList* NodeList::createInstance(char ownerType, unsigned short int socketListenPort) { @@ -799,36 +796,6 @@ void NodeList::removeSilentNodes() { } } -void* removeSilentNodesAndSleep(void *args) { - NodeList* nodeList = (NodeList*) args; - uint64_t checkTimeUsecs = 0; - int sleepTime = 0; - - while (!::silentNodeThreadStopFlag) { - - checkTimeUsecs = usecTimestampNow(); - - nodeList->removeSilentNodes(); - - sleepTime = NODE_SILENCE_THRESHOLD_USECS - (usecTimestampNow() - checkTimeUsecs); - - #ifdef _WIN32 - - Sleep( static_cast(1000.0f*sleepTime) ); - - #else - - if (sleepTime > 0) { - usleep(sleepTime); - } - - #endif - } - - pthread_exit(0); - return NULL; -} - const QString QSETTINGS_GROUP_NAME = "NodeList"; const QString DOMAIN_SERVER_SETTING_KEY = "domainServerHostname"; From 04b13149b558e0dac98eeb498c81748a829caca0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 5 Dec 2013 17:39:37 -0800 Subject: [PATCH 04/15] remove unneeded include in NodeList --- libraries/shared/src/NodeList.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index ea1421661e..d8661d9350 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -23,12 +23,6 @@ #include "SharedUtil.h" #include "UUID.h" -#ifdef _WIN32 -#include "Syssocket.h" -#else -#include -#endif - const char SOLO_NODE_TYPES[2] = { NODE_TYPE_AVATAR_MIXER, NODE_TYPE_AUDIO_MIXER From 992a418b8154fb11f6fbc41d1cdb5d5c37e78e0b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 5 Dec 2013 17:42:32 -0800 Subject: [PATCH 05/15] fix casing of include in AnimationServer --- animation-server/src/AnimationServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/animation-server/src/AnimationServer.cpp b/animation-server/src/AnimationServer.cpp index 8ae54c4963..09043d1b10 100644 --- a/animation-server/src/AnimationServer.cpp +++ b/animation-server/src/AnimationServer.cpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include From 0fcc2d86346d55dd9b566d172900720a7f5836de Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 6 Dec 2013 15:11:01 -0800 Subject: [PATCH 06/15] Removed _avatarTouch class --- interface/src/Application.cpp | 1 + interface/src/Util.cpp | 27 --------- interface/src/Util.h | 2 - interface/src/avatar/Avatar.cpp | 8 --- interface/src/avatar/Avatar.h | 2 - interface/src/avatar/MyAvatar.cpp | 98 +------------------------------ interface/src/avatar/MyAvatar.h | 10 +++- 7 files changed, 11 insertions(+), 137 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9718e21e1c..d5fa23177a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -369,6 +369,7 @@ void Application::paintGL() { _myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation()); } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { + _myCamera.setTightness (0.0f); // Camera is directly connected to head without smoothing _myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition()); _myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation()); diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 476e77cd97..f691d54a75 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -519,33 +519,6 @@ void renderNudgeGuide(float voxelX, float voxelY, float voxelZ, float voxelS) { glEnd(); } -void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness) { - - glColor4f(0.0f, 0.0f, 0.0f, darkness); - - int num = 20; - float y = 0.001f; - float x2 = 0.0f; - float z2 = radius; - float x1; - float z1; - - glBegin(GL_TRIANGLES); - - for (int i=1; i -#include "AvatarTouch.h" #include "AvatarVoxelSystem.h" #include "Balls.h" #include "Hand.h" @@ -229,7 +228,6 @@ protected: float _scale; float _height; Balls* _balls; - AvatarTouch _avatarTouch; glm::vec3 _worldUpDirection; glm::vec3 _mouseRayOrigin; glm::vec3 _mouseRayDirection; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 51b8b37007..17fc1192f6 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -32,7 +32,6 @@ const float COLLISION_RADIUS_SCALAR = 1.2; // pertains to avatar-to-avatar colli const float COLLISION_BALL_FORCE = 200.0; // pertains to avatar-to-avatar collisions const float COLLISION_BODY_FORCE = 30.0; // pertains to avatar-to-avatar collisions const float COLLISION_RADIUS_SCALE = 0.125f; -const float PERIPERSONAL_RADIUS = 1.0f; const float MOUSE_RAY_TOUCH_RANGE = 0.01f; const bool USING_HEAD_LEAN = false; const float SKIN_COLOR[] = {1.0, 0.84, 0.66}; @@ -46,7 +45,6 @@ MyAvatar::MyAvatar(Node* owningNode) : _shouldJump(false), _gravity(0.0f, -1.0f, 0.0f), _distanceToNearestAvatar(std::numeric_limits::max()), - _interactingOther(NULL), _elapsedTimeMoving(0.0f), _elapsedTimeStopped(0.0f), _elapsedTimeSinceCollision(0.0f), @@ -166,7 +164,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { // update the movement of the hand and process handshaking with other avatars... updateHandMovementAndTouching(deltaTime, enableHandMovement); - _avatarTouch.simulate(deltaTime); // apply gravity // For gravity, always move the avatar by the amount driven by gravity, so that the collision @@ -498,16 +495,10 @@ static TextRenderer* textRenderer() { } void MyAvatar::render(bool forceRenderHead) { - - // render a simple round on the ground projected down from the avatar's position - renderDiskShadow(_position, glm::vec3(0.0f, 1.0f, 0.0f), _scale * 0.1f, 0.2f); - + // render body renderBody(forceRenderHead); - // if this is my avatar, then render my interactions with the other avatar - _avatarTouch.render(Application::getInstance()->getCamera()->getPosition()); - // Render the balls if (_balls) { glPushMatrix(); @@ -882,90 +873,6 @@ void MyAvatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMov pointing = true; } - _avatarTouch.setMyBodyPosition(_position); - _avatarTouch.setMyOrientation(orientation); - - float closestDistance = std::numeric_limits::max(); - - _interactingOther = NULL; - - //loop through all the other avatars for potential interactions... - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { - Avatar *otherAvatar = (Avatar *)node->getLinkedData(); - - // test whether shoulders are close enough to allow for reaching to touch hands - glm::vec3 v(_position - otherAvatar->_position); - float distance = glm::length(v); - if (distance < closestDistance) { - closestDistance = distance; - - if (distance < _scale * PERIPERSONAL_RADIUS) { - _interactingOther = otherAvatar; - } - } - } - } - - if (_interactingOther) { - - _avatarTouch.setHasInteractingOther(true); - _avatarTouch.setYourBodyPosition(_interactingOther->_position); - _avatarTouch.setYourHandPosition(_interactingOther->_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS ].position); - _avatarTouch.setYourOrientation (_interactingOther->getOrientation()); - _avatarTouch.setYourHandState(_interactingOther->_handState); - - //if hand-holding is initiated by either avatar, turn on hand-holding... - if (_avatarTouch.getHandsCloseEnoughToGrasp()) { - if ((_handState == HAND_STATE_GRASPING ) || (_interactingOther->_handState == HAND_STATE_GRASPING)) { - if (!_avatarTouch.getHoldingHands()) - { - _avatarTouch.setHoldingHands(true); - } - } - } - - glm::vec3 vectorFromMyHandToYourHand - ( - _interactingOther->_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position - - _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position - ); - - float distanceBetweenOurHands = glm::length(vectorFromMyHandToYourHand); - - // if neither of us are grasping, turn off hand-holding - if ((_handState != HAND_STATE_GRASPING ) && (_interactingOther->_handState != HAND_STATE_GRASPING)) { - _avatarTouch.setHoldingHands(false); - } - - //if holding hands, apply the appropriate forces - if (_avatarTouch.getHoldingHands()) { - _skeleton.joint[AVATAR_JOINT_RIGHT_FINGERTIPS ].position += - (_interactingOther->_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position - - _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position) * 0.5f; - - const float MAX_FORCE = 1.0f; - const float FORCE_RATIO = 10.0f; - - if (distanceBetweenOurHands > 0.3) { - float force = min(MAX_FORCE, FORCE_RATIO * deltaTime); - _velocity += vectorFromMyHandToYourHand * force; - } - } - } else { - _avatarTouch.setHasInteractingOther(false); - } - - enableHandMovement |= updateLeapHandPositions(); - - //constrain right arm length and re-adjust elbow position as it bends - // NOTE - the following must be called on all avatars - not just _isMine - if (enableHandMovement) { - updateArmIKAndConstraints(deltaTime, AVATAR_JOINT_RIGHT_FINGERTIPS); - updateArmIKAndConstraints(deltaTime, AVATAR_JOINT_LEFT_FINGERTIPS); - } - //Set right hand position and state to be transmitted, and also tell AvatarTouch about it setHandPosition(_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position); @@ -976,9 +883,6 @@ void MyAvatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMov } else { _handState = HAND_STATE_NULL; } - - _avatarTouch.setMyHandState(_handState); - _avatarTouch.setMyHandPosition(_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS ].position); } void MyAvatar::updateCollisionWithEnvironment(float deltaTime) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9f440a50bf..e67071581c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -13,6 +13,15 @@ #include "Avatar.h" +enum AvatarHandState +{ + HAND_STATE_NULL = 0, + HAND_STATE_OPEN, + HAND_STATE_GRASPING, + HAND_STATE_POINTING, + NUM_HAND_STATES +}; + class MyAvatar : public Avatar { public: MyAvatar(Node* owningNode = NULL); @@ -67,7 +76,6 @@ private: float _driveKeys[MAX_DRIVE_KEYS]; glm::vec3 _gravity; float _distanceToNearestAvatar; // How close is the nearest avatar? - Avatar* _interactingOther; float _elapsedTimeMoving; // Timers to drive camera transitions when moving float _elapsedTimeStopped; float _elapsedTimeSinceCollision; From 470773356344b0c066f08e33a5305981d0e58d81 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 6 Dec 2013 16:26:02 -0800 Subject: [PATCH 07/15] Removed avatar balls --- interface/src/Application.cpp | 28 +- interface/src/Menu.cpp | 20 +- interface/src/Menu.h | 1 - interface/src/avatar/Avatar.cpp | 394 +-------------------- interface/src/avatar/Avatar.h | 16 +- interface/src/avatar/AvatarTouch.cpp | 120 ------- interface/src/avatar/AvatarTouch.h | 72 ---- interface/src/avatar/AvatarVoxelSystem.cpp | 339 ------------------ interface/src/avatar/AvatarVoxelSystem.h | 84 ----- interface/src/avatar/Hand.h | 1 + interface/src/avatar/Head.cpp | 5 +- interface/src/avatar/MyAvatar.cpp | 253 +------------ interface/src/avatar/MyAvatar.h | 3 - 13 files changed, 30 insertions(+), 1306 deletions(-) delete mode 100644 interface/src/avatar/AvatarTouch.cpp delete mode 100644 interface/src/avatar/AvatarTouch.h delete mode 100644 interface/src/avatar/AvatarVoxelSystem.cpp delete mode 100644 interface/src/avatar/AvatarVoxelSystem.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d5fa23177a..6a39aded67 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1414,10 +1414,7 @@ void Application::processAvatarURLsMessage(unsigned char* packetData, size_t dat QDataStream in(QByteArray((char*)packetData, dataBytes)); QUrl voxelURL; in >> voxelURL; - - // invoke the set URL functions on the simulate/render thread - QMetaObject::invokeMethod(avatar->getVoxels(), "setVoxelURL", Q_ARG(QUrl, voxelURL)); - + // use this timing to as the data-server for an updated mesh for this avatar (if we have UUID) DataServerClient::getValuesForKeysAndUUID(QStringList() << DataServerKey::FaceMeshURL << DataServerKey::SkeletonURL, avatar->getUUID()); @@ -1792,9 +1789,6 @@ void Application::init() { _voxels.setDisableFastVoxelPipeline(false); _voxels.init(); - - Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL()); - _palette.init(_glWidget->width(), _glWidget->height()); _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelAddMode), 0, 0); _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelDeleteMode), 0, 1); @@ -2329,20 +2323,6 @@ void Application::updateTransmitter(float deltaTime) { if (_voxels.findRayIntersection(_transmitterPickStart, direction, detail, distance, face)) { minDistance = min(minDistance, distance); } - NodeList* nodeList = NodeList::getInstance(); - for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - node->lock(); - if (node->getLinkedData() != NULL) { - Avatar *avatar = (Avatar*)node->getLinkedData(); - if (!avatar->isInitialized()) { - avatar->init(); - } - if (avatar->findRayIntersection(_transmitterPickStart, direction, distance)) { - minDistance = min(minDistance, distance); - } - } - node->unlock(); - } _transmitterPickEnd = _transmitterPickStart + direction * minDistance; } else { @@ -2572,12 +2552,6 @@ void Application::updateAvatar(float deltaTime) { controlledBroadcastToNodes(broadcastString, endOfBroadcastStringWrite - broadcastString, nodeTypesOfInterest, sizeof(nodeTypesOfInterest)); - // once in a while, send my urls - const float AVATAR_URLS_SEND_INTERVAL = 1.0f; // seconds - if (shouldDo(AVATAR_URLS_SEND_INTERVAL, deltaTime)) { - Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL()); - } - // Update _viewFrustum with latest camera and view frustum data... // NOTE: we get this from the view frustum, to make it simpler, since the // loadViewFrumstum() method will get the correct details from the camera diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 50fb0beed8..13510067cd 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -317,15 +317,8 @@ Menu::Menu() : QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options"); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Avatars, 0, true); - addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::AvatarAsBalls); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::CollisionProxies); - addActionToQMenuAndActionHash(avatarOptionsMenu, - MenuOption::VoxelMode, - 0, - appInstance->getAvatar()->getVoxels(), - SLOT(cycleMode())); - addActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::FaceMode, 0, @@ -781,11 +774,7 @@ void Menu::editPreferences() { QFormLayout* form = new QFormLayout(); layout->addLayout(form, 1); - - QLineEdit* avatarURL = new QLineEdit(applicationInstance->getAvatar()->getVoxels()->getVoxelURL().toString()); - avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH); - form->addRow("Avatar URL:", avatarURL); - + QString faceURLString = applicationInstance->getProfile()->getFaceModelURL().toString(); QLineEdit* faceURLEdit = new QLineEdit(faceURLString); faceURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); @@ -868,12 +857,7 @@ void Menu::editPreferences() { DataServerClient::putValueForKey(DataServerKey::SkeletonURL, skeletonModelURL.toString().toLocal8Bit().constData()); } - - QUrl avatarVoxelURL(avatarURL->text()); - applicationInstance->getAvatar()->getVoxels()->setVoxelURL(avatarVoxelURL); - - Avatar::sendAvatarURLsMessage(avatarVoxelURL); - + applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum()); _maxVoxels = maxVoxels->value(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 84f48e2ffa..aa3b925517 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -147,7 +147,6 @@ namespace MenuOption { const QString AboutApp = "About Interface"; const QString AmbientOcclusion = "Ambient Occlusion"; const QString Avatars = "Avatars"; - const QString AvatarAsBalls = "Avatar as Balls"; const QString Atmosphere = "Atmosphere"; const QString AutomaticallyAuditTree = "Automatically Audit Tree Stats"; const QString Bandwidth = "Bandwidth Display"; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 3399c6a330..e388abad87 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -96,7 +96,6 @@ Avatar::Avatar(Node* owningNode) : _mouseRayDirection(0.0f, 0.0f, 0.0f), _isCollisionsOn(true), _leadingAvatar(NULL), - _voxels(this), _moving(false), _initialized(false), _handHoldingPosition(0.0f, 0.0f, 0.0f), @@ -112,13 +111,11 @@ Avatar::Avatar(Node* owningNode) : _skeleton.initialize(); - initializeBodyBalls(); - - _height = _skeleton.getHeight() + _bodyBall[BODY_BALL_LEFT_HEEL].radius + _bodyBall[BODY_BALL_HEAD_BASE].radius; + _height = _skeleton.getHeight(); _maxArmLength = _skeleton.getArmLength(); - _pelvisStandingHeight = _skeleton.getPelvisStandingHeight() + _bodyBall[BODY_BALL_LEFT_HEEL].radius; - _pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight() + _bodyBall[BODY_BALL_LEFT_HEEL].radius; + _pelvisStandingHeight = _skeleton.getPelvisStandingHeight(); + _pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight(); _pelvisToHeadLength = _skeleton.getPelvisToHeadLength(); if (BALLS_ON) { @@ -129,126 +126,6 @@ Avatar::Avatar(Node* owningNode) : } -void Avatar::initializeBodyBalls() { - - _ballSpringsInitialized = false; //this gets set to true on the first update pass... - - for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - _bodyBall[b].parentJoint = AVATAR_JOINT_NULL; - _bodyBall[b].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[b].position = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[b].velocity = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[b].radius = 0.0; - _bodyBall[b].touchForce = 0.0; - _bodyBall[b].isCollidable = true; - _bodyBall[b].jointTightness = BODY_SPRING_DEFAULT_TIGHTNESS; - } - - // specify the radius of each ball - _bodyBall[BODY_BALL_PELVIS].radius = BODY_BALL_RADIUS_PELVIS; - _bodyBall[BODY_BALL_TORSO].radius = BODY_BALL_RADIUS_TORSO; - _bodyBall[BODY_BALL_CHEST].radius = BODY_BALL_RADIUS_CHEST; - _bodyBall[BODY_BALL_NECK_BASE].radius = BODY_BALL_RADIUS_NECK_BASE; - _bodyBall[BODY_BALL_HEAD_BASE].radius = BODY_BALL_RADIUS_HEAD_BASE; - _bodyBall[BODY_BALL_LEFT_COLLAR].radius = BODY_BALL_RADIUS_LEFT_COLLAR; - _bodyBall[BODY_BALL_LEFT_SHOULDER].radius = BODY_BALL_RADIUS_LEFT_SHOULDER; - _bodyBall[BODY_BALL_LEFT_ELBOW].radius = BODY_BALL_RADIUS_LEFT_ELBOW; - _bodyBall[BODY_BALL_LEFT_WRIST].radius = BODY_BALL_RADIUS_LEFT_WRIST; - _bodyBall[BODY_BALL_LEFT_FINGERTIPS].radius = BODY_BALL_RADIUS_LEFT_FINGERTIPS; - _bodyBall[BODY_BALL_RIGHT_COLLAR].radius = BODY_BALL_RADIUS_RIGHT_COLLAR; - _bodyBall[BODY_BALL_RIGHT_SHOULDER].radius = BODY_BALL_RADIUS_RIGHT_SHOULDER; - _bodyBall[BODY_BALL_RIGHT_ELBOW].radius = BODY_BALL_RADIUS_RIGHT_ELBOW; - _bodyBall[BODY_BALL_RIGHT_WRIST].radius = BODY_BALL_RADIUS_RIGHT_WRIST; - _bodyBall[BODY_BALL_RIGHT_FINGERTIPS].radius = BODY_BALL_RADIUS_RIGHT_FINGERTIPS; - _bodyBall[BODY_BALL_LEFT_HIP].radius = BODY_BALL_RADIUS_LEFT_HIP; - _bodyBall[BODY_BALL_LEFT_KNEE].radius = BODY_BALL_RADIUS_LEFT_KNEE; - _bodyBall[BODY_BALL_LEFT_HEEL].radius = BODY_BALL_RADIUS_LEFT_HEEL; - _bodyBall[BODY_BALL_LEFT_TOES].radius = BODY_BALL_RADIUS_LEFT_TOES; - _bodyBall[BODY_BALL_RIGHT_HIP].radius = BODY_BALL_RADIUS_RIGHT_HIP; - _bodyBall[BODY_BALL_RIGHT_KNEE].radius = BODY_BALL_RADIUS_RIGHT_KNEE; - _bodyBall[BODY_BALL_RIGHT_HEEL].radius = BODY_BALL_RADIUS_RIGHT_HEEL; - _bodyBall[BODY_BALL_RIGHT_TOES].radius = BODY_BALL_RADIUS_RIGHT_TOES; - - - // specify the parent joint for each ball - _bodyBall[BODY_BALL_PELVIS].parentJoint = AVATAR_JOINT_PELVIS; - _bodyBall[BODY_BALL_TORSO].parentJoint = AVATAR_JOINT_TORSO; - _bodyBall[BODY_BALL_CHEST].parentJoint = AVATAR_JOINT_CHEST; - _bodyBall[BODY_BALL_NECK_BASE].parentJoint = AVATAR_JOINT_NECK_BASE; - _bodyBall[BODY_BALL_HEAD_BASE].parentJoint = AVATAR_JOINT_HEAD_BASE; - _bodyBall[BODY_BALL_HEAD_TOP].parentJoint = AVATAR_JOINT_HEAD_TOP; - _bodyBall[BODY_BALL_LEFT_COLLAR].parentJoint = AVATAR_JOINT_LEFT_COLLAR; - _bodyBall[BODY_BALL_LEFT_SHOULDER].parentJoint = AVATAR_JOINT_LEFT_SHOULDER; - _bodyBall[BODY_BALL_LEFT_ELBOW].parentJoint = AVATAR_JOINT_LEFT_ELBOW; - _bodyBall[BODY_BALL_LEFT_WRIST].parentJoint = AVATAR_JOINT_LEFT_WRIST; - _bodyBall[BODY_BALL_LEFT_FINGERTIPS].parentJoint = AVATAR_JOINT_LEFT_FINGERTIPS; - _bodyBall[BODY_BALL_RIGHT_COLLAR].parentJoint = AVATAR_JOINT_RIGHT_COLLAR; - _bodyBall[BODY_BALL_RIGHT_SHOULDER].parentJoint = AVATAR_JOINT_RIGHT_SHOULDER; - _bodyBall[BODY_BALL_RIGHT_ELBOW].parentJoint = AVATAR_JOINT_RIGHT_ELBOW; - _bodyBall[BODY_BALL_RIGHT_WRIST].parentJoint = AVATAR_JOINT_RIGHT_WRIST; - _bodyBall[BODY_BALL_RIGHT_FINGERTIPS].parentJoint = AVATAR_JOINT_RIGHT_FINGERTIPS; - _bodyBall[BODY_BALL_LEFT_HIP].parentJoint = AVATAR_JOINT_LEFT_HIP; - _bodyBall[BODY_BALL_LEFT_KNEE].parentJoint = AVATAR_JOINT_LEFT_KNEE; - _bodyBall[BODY_BALL_LEFT_HEEL].parentJoint = AVATAR_JOINT_LEFT_HEEL; - _bodyBall[BODY_BALL_LEFT_TOES].parentJoint = AVATAR_JOINT_LEFT_TOES; - _bodyBall[BODY_BALL_RIGHT_HIP].parentJoint = AVATAR_JOINT_RIGHT_HIP; - _bodyBall[BODY_BALL_RIGHT_KNEE].parentJoint = AVATAR_JOINT_RIGHT_KNEE; - _bodyBall[BODY_BALL_RIGHT_HEEL].parentJoint = AVATAR_JOINT_RIGHT_HEEL; - _bodyBall[BODY_BALL_RIGHT_TOES].parentJoint = AVATAR_JOINT_RIGHT_TOES; - - // specify the parent offset for each ball - _bodyBall[BODY_BALL_PELVIS].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_TORSO].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_CHEST].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_NECK_BASE].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_HEAD_BASE].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_HEAD_TOP].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_LEFT_COLLAR].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_LEFT_SHOULDER].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_LEFT_ELBOW].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_LEFT_WRIST].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_LEFT_FINGERTIPS].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_RIGHT_COLLAR].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_RIGHT_SHOULDER].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_RIGHT_ELBOW].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_RIGHT_WRIST].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_RIGHT_FINGERTIPS].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_LEFT_HIP].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_LEFT_KNEE].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_LEFT_HEEL].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_LEFT_TOES].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_RIGHT_HIP].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_RIGHT_KNEE].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_RIGHT_HEEL].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _bodyBall[BODY_BALL_RIGHT_TOES].parentOffset = glm::vec3(0.0, 0.0, 0.0); - - // specify the parent BALL for each ball - _bodyBall[BODY_BALL_PELVIS].parentBall = BODY_BALL_NULL; - _bodyBall[BODY_BALL_TORSO].parentBall = BODY_BALL_PELVIS; - _bodyBall[BODY_BALL_CHEST].parentBall = BODY_BALL_TORSO; - _bodyBall[BODY_BALL_NECK_BASE].parentBall = BODY_BALL_CHEST; - _bodyBall[BODY_BALL_HEAD_BASE].parentBall = BODY_BALL_NECK_BASE; - _bodyBall[BODY_BALL_HEAD_TOP].parentBall = BODY_BALL_HEAD_BASE; - _bodyBall[BODY_BALL_LEFT_COLLAR].parentBall = BODY_BALL_CHEST; - _bodyBall[BODY_BALL_LEFT_SHOULDER].parentBall = BODY_BALL_LEFT_COLLAR; - _bodyBall[BODY_BALL_LEFT_ELBOW].parentBall = BODY_BALL_LEFT_SHOULDER; - _bodyBall[BODY_BALL_LEFT_WRIST].parentBall = BODY_BALL_LEFT_ELBOW; - _bodyBall[BODY_BALL_LEFT_FINGERTIPS].parentBall = BODY_BALL_LEFT_WRIST; - _bodyBall[BODY_BALL_RIGHT_COLLAR].parentBall = BODY_BALL_CHEST; - _bodyBall[BODY_BALL_RIGHT_SHOULDER].parentBall = BODY_BALL_RIGHT_COLLAR; - _bodyBall[BODY_BALL_RIGHT_ELBOW].parentBall = BODY_BALL_RIGHT_SHOULDER; - _bodyBall[BODY_BALL_RIGHT_WRIST].parentBall = BODY_BALL_RIGHT_ELBOW; - _bodyBall[BODY_BALL_RIGHT_FINGERTIPS].parentBall = BODY_BALL_RIGHT_WRIST; - _bodyBall[BODY_BALL_LEFT_HIP].parentBall = BODY_BALL_PELVIS; - _bodyBall[BODY_BALL_LEFT_KNEE].parentBall = BODY_BALL_LEFT_HIP; - _bodyBall[BODY_BALL_LEFT_HEEL].parentBall = BODY_BALL_LEFT_KNEE; - _bodyBall[BODY_BALL_LEFT_TOES].parentBall = BODY_BALL_LEFT_HEEL; - _bodyBall[BODY_BALL_RIGHT_HIP].parentBall = BODY_BALL_PELVIS; - _bodyBall[BODY_BALL_RIGHT_KNEE].parentBall = BODY_BALL_RIGHT_HIP; - _bodyBall[BODY_BALL_RIGHT_HEEL].parentBall = BODY_BALL_RIGHT_KNEE; - _bodyBall[BODY_BALL_RIGHT_TOES].parentBall = BODY_BALL_RIGHT_HEEL; -} - Avatar::~Avatar() { _headData = NULL; _handData = NULL; @@ -264,7 +141,6 @@ void Avatar::init() { _head.init(); _hand.init(); _skeletonModel.init(); - _voxels.init(); _initialized = true; } @@ -293,10 +169,6 @@ void Avatar::follow(Avatar* leadingAvatar) { void Avatar::simulate(float deltaTime, Transmitter* transmitter) { - glm::quat orientation = getOrientation(); - glm::vec3 front = orientation * IDENTITY_FRONT; - glm::vec3 right = orientation * IDENTITY_RIGHT; - if (_leadingAvatar && !_leadingAvatar->getOwningNode()->isAlive()) { follow(NULL); } @@ -336,23 +208,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // update avatar skeleton _skeleton.update(deltaTime, getOrientation(), _position); - //determine the lengths of the body springs now that we have updated the skeleton at least once - if (!_ballSpringsInitialized) { - for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - - glm::vec3 targetPosition - = _skeleton.joint[_bodyBall[b].parentJoint].position - + _skeleton.joint[_bodyBall[b].parentJoint].rotation * _bodyBall[b].parentOffset; - - glm::vec3 parentTargetPosition - = _skeleton.joint[_bodyBall[b].parentJoint].position - + _skeleton.joint[_bodyBall[b].parentJoint].rotation * _bodyBall[b].parentOffset; - - _bodyBall[b].springLength = glm::length(targetPosition - parentTargetPosition); - } - - _ballSpringsInitialized = true; - } // if this is not my avatar, then hand position comes from transmitted data _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handPosition; @@ -360,42 +215,11 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { //update the movement of the hand and process handshaking with other avatars... updateHandMovementAndTouching(deltaTime, enableHandMovement); - // update body balls - updateBodyBalls(deltaTime); - - //apply the head lean values to the ball positions... - if (USING_HEAD_LEAN) { - if (fabs(_head.getLeanSideways() + _head.getLeanForward()) > 0.0f) { - glm::vec3 headLean = - right * _head.getLeanSideways() + - front * _head.getLeanForward(); - - _bodyBall[BODY_BALL_TORSO].position += headLean * 0.1f; - _bodyBall[BODY_BALL_CHEST].position += headLean * 0.4f; - _bodyBall[BODY_BALL_NECK_BASE].position += headLean * 0.7f; - _bodyBall[BODY_BALL_HEAD_BASE].position += headLean * 1.0f; - - _bodyBall[BODY_BALL_LEFT_COLLAR].position += headLean * 0.6f; - _bodyBall[BODY_BALL_LEFT_SHOULDER].position += headLean * 0.6f; - _bodyBall[BODY_BALL_LEFT_ELBOW].position += headLean * 0.2f; - _bodyBall[BODY_BALL_LEFT_WRIST].position += headLean * 0.1f; - _bodyBall[BODY_BALL_LEFT_FINGERTIPS].position += headLean * 0.0f; - - _bodyBall[BODY_BALL_RIGHT_COLLAR].position += headLean * 0.6f; - _bodyBall[BODY_BALL_RIGHT_SHOULDER].position += headLean * 0.6f; - _bodyBall[BODY_BALL_RIGHT_ELBOW].position += headLean * 0.2f; - _bodyBall[BODY_BALL_RIGHT_WRIST].position += headLean * 0.1f; - _bodyBall[BODY_BALL_RIGHT_FINGERTIPS].position += headLean * 0.0f; - } - } - _hand.simulate(deltaTime, false); _skeletonModel.simulate(deltaTime); _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); glm::vec3 headPosition; - if (Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls) || !_skeletonModel.getHeadPosition(headPosition)) { - headPosition = _bodyBall[BODY_BALL_HEAD_BASE].position; - } + _skeletonModel.getHeadPosition(headPosition); _head.setPosition(headPosition); _head.setScale(_scale); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); @@ -479,7 +303,7 @@ void Avatar::render(bool forceRenderHead) { } glPushMatrix(); - glm::vec3 chatPosition = _bodyBall[BODY_BALL_HEAD_BASE].position + getBodyUpDirection() * chatMessageHeight * _scale; + glm::vec3 chatPosition = getPosition() + getBodyUpDirection() * chatMessageHeight * _scale; glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z); glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation(); glm::vec3 chatAxis = glm::axis(chatRotation); @@ -514,90 +338,7 @@ void Avatar::render(bool forceRenderHead) { } } -void Avatar::resetBodyBalls() { - for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - - glm::vec3 targetPosition - = _skeleton.joint[_bodyBall[b].parentJoint].position - + _skeleton.joint[_bodyBall[b].parentJoint].rotation * _bodyBall[b].parentOffset; - - _bodyBall[b].position = targetPosition; // put ball on target position - _bodyBall[b].velocity = glm::vec3(0.0f, 0.0f, 0.0f); - } -} -void Avatar::updateBodyBalls(float deltaTime) { - // Check for a large repositioning, and re-initialize balls if this has happened - const float BEYOND_BODY_SPRING_RANGE = _scale * 2.f; - if (glm::length(_position - _bodyBall[BODY_BALL_PELVIS].position) > BEYOND_BODY_SPRING_RANGE) { - resetBodyBalls(); - } - glm::quat orientation = getOrientation(); - for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - - glm::vec3 springVector; - float length = 0.0f; - if (_ballSpringsInitialized) { - - // apply spring forces - springVector = _bodyBall[b].position; - - if (b == BODY_BALL_PELVIS) { - springVector -= _position; - } else { - springVector -= _bodyBall[_bodyBall[b].parentBall].position; - } - - length = glm::length(springVector); - - if (length > 0.0f) { // to avoid divide by zero - glm::vec3 springDirection = springVector / length; - - float force = (length - _skeleton.joint[b].length) * BODY_SPRING_FORCE * deltaTime; - _bodyBall[b].velocity -= springDirection * force; - - if (_bodyBall[b].parentBall != BODY_BALL_NULL) { - _bodyBall[_bodyBall[b].parentBall].velocity += springDirection * force; - } - } - } - - // apply tightness force - (causing ball position to be close to skeleton joint position) - glm::vec3 targetPosition - = _skeleton.joint[_bodyBall[b].parentJoint].position - + _skeleton.joint[_bodyBall[b].parentJoint].rotation * _bodyBall[b].parentOffset; - - _bodyBall[b].velocity += (targetPosition - _bodyBall[b].position) * _bodyBall[b].jointTightness * deltaTime; - - // apply decay - float decay = 1.0 - BODY_SPRING_DECAY * deltaTime; - if (decay > 0.0) { - _bodyBall[b].velocity *= decay; - } else { - _bodyBall[b].velocity = glm::vec3(0.0f, 0.0f, 0.0f); - } - - // update position by velocity... - _bodyBall[b].position += _bodyBall[b].velocity * deltaTime; - - // update rotation - const float SMALL_SPRING_LENGTH = 0.001f; // too-small springs can change direction rapidly - if (_skeleton.joint[b].parent == AVATAR_JOINT_NULL || length < SMALL_SPRING_LENGTH) { - _bodyBall[b].rotation = orientation * _skeleton.joint[_bodyBall[b].parentJoint].absoluteBindPoseRotation; - } else { - glm::vec3 parentDirection = _bodyBall[ _bodyBall[b].parentBall ].rotation * JOINT_DIRECTION; - _bodyBall[b].rotation = rotationBetween(parentDirection, springVector) * - _bodyBall[ _bodyBall[b].parentBall ].rotation; - } - } - - // copy the head's rotation - _bodyBall[BODY_BALL_HEAD_BASE].rotation = _bodyBall[BODY_BALL_HEAD_TOP].rotation = _head.getOrientation(); - _bodyBall[BODY_BALL_HEAD_BASE].position = _bodyBall[BODY_BALL_NECK_BASE].position + - _bodyBall[BODY_BALL_HEAD_BASE].rotation * _skeleton.joint[BODY_BALL_HEAD_BASE].bindPosePosition; - _bodyBall[BODY_BALL_HEAD_TOP].position = _bodyBall[BODY_BALL_HEAD_BASE].position + - _bodyBall[BODY_BALL_HEAD_TOP].rotation * _skeleton.joint[BODY_BALL_HEAD_TOP].bindPosePosition; -} // returns true if the Leap controls any of the avatar's hands. bool Avatar::updateLeapHandPositions() { @@ -658,7 +399,7 @@ void Avatar::updateArmIKAndConstraints(float deltaTime, AvatarJointID fingerTipJ float distance = glm::length(armVector); // don't let right hand get dragged beyond maximum arm length... - float armLength = (_skeletonModel.isActive() && !Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)) ? + float armLength = _skeletonModel.isActive() ? _skeletonModel.getRightArmLength() : _skeleton.getArmLength(); const float ARM_RETRACTION = 0.75f; float retractedArmLength = armLength * ARM_RETRACTION; @@ -702,79 +443,17 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { return glm::angleAxis(angle * proportion, axis); } -float Avatar::getBallRenderAlpha(int ball, bool forceRenderHead) const { - return 1.0f; -} + void Avatar::renderBody(bool forceRenderHead) { if (_head.getVideoFace().isFullFrame()) { // Render the full-frame video - float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, forceRenderHead); - if (alpha > 0.0f) { - _head.getVideoFace().render(1.0f); - } - } else if (Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)) { - // Render the body as balls and cones - glm::vec3 skinColor, darkSkinColor; - getSkinColors(skinColor, darkSkinColor); - for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - float alpha = getBallRenderAlpha(b, forceRenderHead); - - // When we have leap hands, hide part of the arms. - if (_hand.getNumPalms() > 0) { - if (b == BODY_BALL_LEFT_FINGERTIPS - || b == BODY_BALL_RIGHT_FINGERTIPS) { - continue; - } - } - // Always render other people, and render myself when beyond threshold distance - if (b == BODY_BALL_HEAD_BASE) { // the head is rendered as a special - if (alpha > 0.0f) { - _head.render(alpha, true); - } - } else if (alpha > 0.0f) { - // Render the body ball sphere - glColor3f(skinColor.r + _bodyBall[b].touchForce * 0.3f, - skinColor.g - _bodyBall[b].touchForce * 0.2f, - skinColor.b - _bodyBall[b].touchForce * 0.1f); - - if ((b != BODY_BALL_HEAD_TOP ) - && (b != BODY_BALL_HEAD_BASE )) { - glPushMatrix(); - glTranslatef(_bodyBall[b].position.x, _bodyBall[b].position.y, _bodyBall[b].position.z); - glutSolidSphere(_bodyBall[b].radius, 20.0f, 20.0f); - glPopMatrix(); - } - - // Render the cone connecting this ball to its parent - if (_bodyBall[b].parentBall != BODY_BALL_NULL) { - if ((b != BODY_BALL_HEAD_TOP) - && (b != BODY_BALL_HEAD_BASE) - && (b != BODY_BALL_PELVIS) - && (b != BODY_BALL_TORSO) - && (b != BODY_BALL_CHEST) - && (b != BODY_BALL_LEFT_COLLAR) - && (b != BODY_BALL_LEFT_SHOULDER) - && (b != BODY_BALL_RIGHT_COLLAR) - && (b != BODY_BALL_RIGHT_SHOULDER)) { - glColor3fv((const GLfloat*)&darkSkinColor); - - float r2 = _bodyBall[b].radius * 0.8; - renderJointConnectingCone(_bodyBall[_bodyBall[b].parentBall].position, _bodyBall[b].position, r2, r2); - } - } - } - } + _head.getVideoFace().render(1.0f); } else { // Render the body's voxels and head - float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, forceRenderHead); - if (alpha > 0.0f) { - if (!_skeletonModel.render(alpha)) { - _voxels.render(false); - } - _head.render(alpha, false); - } + _skeletonModel.render(1.0f); + _head.render(1.0f, false); } _hand.render(false); } @@ -782,33 +461,13 @@ void Avatar::renderBody(bool forceRenderHead) { void Avatar::getSkinColors(glm::vec3& lighter, glm::vec3& darker) { lighter = glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2]); darker = glm::vec3(DARK_SKIN_COLOR[0], DARK_SKIN_COLOR[1], DARK_SKIN_COLOR[2]); - if (!Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls) && _head.getFaceModel().isActive()) { + if (_head.getFaceModel().isActive()) { lighter = glm::vec3(_head.getFaceModel().computeAverageColor()); const float SKIN_DARKENING = 0.9f; darker = lighter * SKIN_DARKENING; } } -void Avatar::getBodyBallTransform(AvatarJointID jointID, glm::vec3& position, glm::quat& rotation) const { - position = _bodyBall[jointID].position; - rotation = _bodyBall[jointID].rotation; -} - -bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { - float minDistance = FLT_MAX; - for (int i = 0; i < NUM_AVATAR_BODY_BALLS; i++) { - float distance; - if (rayIntersectsSphere(origin, direction, _bodyBall[i].position, _bodyBall[i].radius, distance)) { - minDistance = min(minDistance, distance); - } - } - if (minDistance == FLT_MAX) { - return false; - } - distance = minDistance; - return true; -} - bool Avatar::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, int skeletonSkipIndex) { bool didPenetrate = false; @@ -922,36 +581,11 @@ void Avatar::setScale(const float scale) { _skeleton.setScale(_scale); - // specify the new radius of each ball - _bodyBall[BODY_BALL_PELVIS].radius = _scale * BODY_BALL_RADIUS_PELVIS; - _bodyBall[BODY_BALL_TORSO].radius = _scale * BODY_BALL_RADIUS_TORSO; - _bodyBall[BODY_BALL_CHEST].radius = _scale * BODY_BALL_RADIUS_CHEST; - _bodyBall[BODY_BALL_NECK_BASE].radius = _scale * BODY_BALL_RADIUS_NECK_BASE; - _bodyBall[BODY_BALL_HEAD_BASE].radius = _scale * BODY_BALL_RADIUS_HEAD_BASE; - _bodyBall[BODY_BALL_LEFT_COLLAR].radius = _scale * BODY_BALL_RADIUS_LEFT_COLLAR; - _bodyBall[BODY_BALL_LEFT_SHOULDER].radius = _scale * BODY_BALL_RADIUS_LEFT_SHOULDER; - _bodyBall[BODY_BALL_LEFT_ELBOW].radius = _scale * BODY_BALL_RADIUS_LEFT_ELBOW; - _bodyBall[BODY_BALL_LEFT_WRIST].radius = _scale * BODY_BALL_RADIUS_LEFT_WRIST; - _bodyBall[BODY_BALL_LEFT_FINGERTIPS].radius = _scale * BODY_BALL_RADIUS_LEFT_FINGERTIPS; - _bodyBall[BODY_BALL_RIGHT_COLLAR].radius = _scale * BODY_BALL_RADIUS_RIGHT_COLLAR; - _bodyBall[BODY_BALL_RIGHT_SHOULDER].radius = _scale * BODY_BALL_RADIUS_RIGHT_SHOULDER; - _bodyBall[BODY_BALL_RIGHT_ELBOW].radius = _scale * BODY_BALL_RADIUS_RIGHT_ELBOW; - _bodyBall[BODY_BALL_RIGHT_WRIST].radius = _scale * BODY_BALL_RADIUS_RIGHT_WRIST; - _bodyBall[BODY_BALL_RIGHT_FINGERTIPS].radius = _scale * BODY_BALL_RADIUS_RIGHT_FINGERTIPS; - _bodyBall[BODY_BALL_LEFT_HIP].radius = _scale * BODY_BALL_RADIUS_LEFT_HIP; - _bodyBall[BODY_BALL_LEFT_KNEE].radius = _scale * BODY_BALL_RADIUS_LEFT_KNEE; - _bodyBall[BODY_BALL_LEFT_HEEL].radius = _scale * BODY_BALL_RADIUS_LEFT_HEEL; - _bodyBall[BODY_BALL_LEFT_TOES].radius = _scale * BODY_BALL_RADIUS_LEFT_TOES; - _bodyBall[BODY_BALL_RIGHT_HIP].radius = _scale * BODY_BALL_RADIUS_RIGHT_HIP; - _bodyBall[BODY_BALL_RIGHT_KNEE].radius = _scale * BODY_BALL_RADIUS_RIGHT_KNEE; - _bodyBall[BODY_BALL_RIGHT_HEEL].radius = _scale * BODY_BALL_RADIUS_RIGHT_HEEL; - _bodyBall[BODY_BALL_RIGHT_TOES].radius = _scale * BODY_BALL_RADIUS_RIGHT_TOES; - - _height = _skeleton.getHeight() + _bodyBall[BODY_BALL_LEFT_HEEL].radius + _bodyBall[BODY_BALL_HEAD_BASE].radius; + _height = _skeleton.getHeight(); _maxArmLength = _skeleton.getArmLength(); - _pelvisStandingHeight = _skeleton.getPelvisStandingHeight() + _bodyBall[BODY_BALL_LEFT_HEEL].radius; - _pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight() + _bodyBall[BODY_BALL_LEFT_HEEL].radius; + _pelvisStandingHeight = _skeleton.getPelvisStandingHeight(); + _pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight(); _pelvisToHeadLength = _skeleton.getPelvisToHeadLength(); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index a050827b62..2e3f9d001b 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -15,7 +15,6 @@ #include -#include "AvatarVoxelSystem.h" #include "Balls.h" #include "Hand.h" #include "Head.h" @@ -159,20 +158,9 @@ public: Hand& getHand() { return _hand; } glm::quat getOrientation() const; glm::quat getWorldAlignedOrientation() const; - AvatarVoxelSystem* getVoxels() { return &_voxels; } void getSkinColors(glm::vec3& lighter, glm::vec3& darker); - // Get the position/rotation of a single body ball - void getBodyBallTransform(AvatarJointID jointID, glm::vec3& position, glm::quat& rotation) const; - - /// Checks for an intersection between the described ray and any of the avatar's body balls. - /// \param origin the origin of the ray - /// \param direction the unit direction vector - /// \param[out] distance the variable in which to store the distance to intersection - /// \return whether or not the ray intersected - bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; - /// Checks for penetration between the described sphere and the avatar. /// \param penetratorCenter the center of the penetration test sphere /// \param penetratorRadius the radius of the penetration test sphere @@ -217,7 +205,7 @@ protected: SkeletonModel _skeletonModel; bool _ballSpringsInitialized; float _bodyYawDelta; - AvatarBall _bodyBall[ NUM_AVATAR_BODY_BALLS ]; + //AvatarBall _bodyBall[ NUM_AVATAR_BODY_BALLS ]; AvatarMode _mode; glm::vec3 _velocity; glm::vec3 _thrust; @@ -234,7 +222,6 @@ protected: bool _isCollisionsOn; Avatar* _leadingAvatar; float _stringLength; - AvatarVoxelSystem _voxels; bool _moving; ///< set when position is changing @@ -243,7 +230,6 @@ protected: glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; } glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; } glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const; - void updateBodyBalls(float deltaTime); bool updateLeapHandPositions(); void updateArmIKAndConstraints(float deltaTime, AvatarJointID fingerTipJointID); void setScale(const float scale); diff --git a/interface/src/avatar/AvatarTouch.cpp b/interface/src/avatar/AvatarTouch.cpp deleted file mode 100644 index 78a63bd3aa..0000000000 --- a/interface/src/avatar/AvatarTouch.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// AvatarTouch.cpp -// interface -// -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. - -#include -#include -#include -#include "AvatarTouch.h" -#include "InterfaceConfig.h" -#include "Util.h" - -const float THREAD_RADIUS = 0.007; -const float HANDS_CLOSE_ENOUGH_TO_GRASP = 0.2; -const float AVATAR_FACING_THRESHOLD = -0.5f; // (-1 to 1) (larger value indicates narrower angle of influence - -AvatarTouch::AvatarTouch() { - - _myHandPosition = glm::vec3(0.0f, 0.0f, 0.0f); - _yourHandPosition = glm::vec3(0.0f, 0.0f, 0.0f); - _myBodyPosition = glm::vec3(0.0f, 0.0f, 0.0f); - _yourBodyPosition = glm::vec3(0.0f, 0.0f, 0.0f); - _vectorBetweenHands = glm::vec3(0.0f, 0.0f, 0.0f); - _myHandState = HAND_STATE_NULL; - _yourHandState = HAND_STATE_NULL; - _reachableRadius = 0.0f; - _weAreHoldingHands = false; - _canReachToOtherAvatar = false; - _handsCloseEnoughToGrasp = false; - _hasInteractingOther = false; - - for (int p=0; p AVATAR_FACING_THRESHOLD)) { // I'm facing you - facingEachOther = true; - } - */ - - if (distanceBetweenBodies < _reachableRadius) - { - _canReachToOtherAvatar = true; - - _vectorBetweenHands = _yourHandPosition - _myHandPosition; - - float distanceBetweenHands = glm::length(_vectorBetweenHands); - if (distanceBetweenHands < HANDS_CLOSE_ENOUGH_TO_GRASP) { - _handsCloseEnoughToGrasp = true; - } else { - _handsCloseEnoughToGrasp = false; - } - } - } -} - - -void AvatarTouch::render(glm::vec3 cameraPosition) { - - if (_canReachToOtherAvatar) { - - //show circle indicating that we can reach out to each other... - glColor4f(0.3, 0.4, 0.5, 0.5); - glm::vec3 p(_yourBodyPosition); - p.y = 0.0005f; - renderCircle(p, _reachableRadius, glm::vec3(0.0f, 1.0f, 0.0f), 30); - } -} - - -void AvatarTouch::renderBeamBetweenHands() { - - glm::vec3 v1(_myHandPosition); - glm::vec3 v2(_yourHandPosition); - - glLineWidth(3.0); - glColor4f(0.9f, 0.9f, 0.1f, 0.6); - glBegin(GL_LINE_STRIP); - glVertex3f(v1.x, v1.y, v1.z); - glVertex3f(v2.x, v2.y, v2.z); - glEnd(); - - glColor3f(0.5f, 0.3f, 0.0f); - for (int p=0; p -#include - -#include - -enum AvatarHandState -{ - HAND_STATE_NULL = 0, - HAND_STATE_OPEN, - HAND_STATE_GRASPING, - HAND_STATE_POINTING, - NUM_HAND_STATES -}; - -class AvatarTouch { -public: - - AvatarTouch(); - - void simulate(float deltaTime); - void render(glm::vec3 cameraPosition); - - void setHasInteractingOther(bool hasInteractingOther) { _hasInteractingOther = hasInteractingOther;} - void setMyHandPosition (glm::vec3 position ) { _myHandPosition = position;} - void setYourHandPosition (glm::vec3 position ) { _yourHandPosition = position;} - void setMyOrientation (glm::quat orientation ) { _myOrientation = orientation;} - void setYourOrientation (glm::quat orientation ) { _yourOrientation = orientation;} - void setMyBodyPosition (glm::vec3 position ) { _myBodyPosition = position;} - void setYourBodyPosition (glm::vec3 position ) { _yourBodyPosition = position;} - void setMyHandState (int state ) { _myHandState = state;} - void setYourHandState (int state ) { _yourHandState = state;} - void setReachableRadius (float radius ) { _reachableRadius = radius;} - void setHoldingHands (bool holding ) { _weAreHoldingHands = holding;} - - bool getAbleToReachOtherAvatar () const {return _canReachToOtherAvatar; } - bool getHandsCloseEnoughToGrasp() const {return _handsCloseEnoughToGrasp;} - bool getHoldingHands () const {return _weAreHoldingHands; } - -private: - - static const int NUM_PARTICLE_POINTS = 100; - - bool _hasInteractingOther; - bool _weAreHoldingHands; - glm::vec3 _point [NUM_PARTICLE_POINTS]; - glm::vec3 _myBodyPosition; - glm::vec3 _yourBodyPosition; - glm::vec3 _myHandPosition; - glm::vec3 _yourHandPosition; - glm::quat _myOrientation; - glm::quat _yourOrientation; - glm::vec3 _vectorBetweenHands; - int _myHandState; - int _yourHandState; - bool _canReachToOtherAvatar; - bool _handsCloseEnoughToGrasp; - float _reachableRadius; - - void renderBeamBetweenHands(); -}; - -#endif diff --git a/interface/src/avatar/AvatarVoxelSystem.cpp b/interface/src/avatar/AvatarVoxelSystem.cpp deleted file mode 100644 index 1685187c57..0000000000 --- a/interface/src/avatar/AvatarVoxelSystem.cpp +++ /dev/null @@ -1,339 +0,0 @@ -// -// AvatarVoxelSystem.cpp -// interface -// -// Created by Andrzej Kapolka on 5/31/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. - -#include - -#include - -#include - -#include "Application.h" -#include "Avatar.h" -#include "AvatarVoxelSystem.h" -#include "renderer/ProgramObject.h" - -const float AVATAR_TREE_SCALE = 1.0f; -const int MAX_VOXELS_PER_AVATAR = 10000; -const int BONE_ELEMENTS_PER_VOXEL = BONE_ELEMENTS_PER_VERTEX * VERTICES_PER_VOXEL; - -AvatarVoxelSystem::AvatarVoxelSystem(Avatar* avatar) : - VoxelSystem(AVATAR_TREE_SCALE, MAX_VOXELS_PER_AVATAR), - _initialized(false), - _mode(0), - _avatar(avatar), - _voxelReply(0) { - - // we may have been created in the network thread, but we live in the main thread - moveToThread(Application::getInstance()->thread()); -} - -AvatarVoxelSystem::~AvatarVoxelSystem() { - if (_initialized) { - delete[] _readBoneIndicesArray; - delete[] _readBoneWeightsArray; - delete[] _writeBoneIndicesArray; - delete[] _writeBoneWeightsArray; - - glDeleteBuffers(1, &_vboBoneIndicesID); - glDeleteBuffers(1, &_vboBoneWeightsID); - } -} - -ProgramObject AvatarVoxelSystem::_skinProgram; -int AvatarVoxelSystem::_boneMatricesLocation; -int AvatarVoxelSystem::_boneIndicesLocation; -int AvatarVoxelSystem::_boneWeightsLocation; - -void AvatarVoxelSystem::init() { - if (_initialized) { - qDebug("[ERROR] AvatarVoxelSystem is already initialized.\n"); - return; - } - - VoxelSystem::init(); - - // prep the data structures for incoming voxel data - _writeBoneIndicesArray = new GLubyte[BONE_ELEMENTS_PER_VOXEL * _maxVoxels]; - _readBoneIndicesArray = new GLubyte[BONE_ELEMENTS_PER_VOXEL * _maxVoxels]; - - _writeBoneWeightsArray = new GLfloat[BONE_ELEMENTS_PER_VOXEL * _maxVoxels]; - _readBoneWeightsArray = new GLfloat[BONE_ELEMENTS_PER_VOXEL * _maxVoxels]; - - // VBO for the boneIndicesArray - glGenBuffers(1, &_vboBoneIndicesID); - glBindBuffer(GL_ARRAY_BUFFER, _vboBoneIndicesID); - glBufferData(GL_ARRAY_BUFFER, BONE_ELEMENTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); - - // VBO for the boneWeightsArray - glGenBuffers(1, &_vboBoneWeightsID); - glBindBuffer(GL_ARRAY_BUFFER, _vboBoneWeightsID); - glBufferData(GL_ARRAY_BUFFER, BONE_ELEMENTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); - - // load our skin program if this is the first avatar system to initialize - if (!_skinProgram.isLinked()) { - _skinProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/skin_voxels.vert"); - _skinProgram.link(); - } - - _boneMatricesLocation = _skinProgram.uniformLocation("boneMatrices"); - _boneIndicesLocation = _skinProgram.attributeLocation("boneIndices"); - _boneWeightsLocation = _skinProgram.attributeLocation("boneWeights"); - - VoxelTreeElement::removeUpdateHook(this); // we don't want this - - _initialized = true; -} - -void AvatarVoxelSystem::removeOutOfView() { - // no-op for now -} - -class Mode { -public: - - bool bindVoxelsTogether; - int maxBonesPerBind; - bool includeBonesOutsideBindRadius; -}; - -const Mode MODES[] = { - { false, BONE_ELEMENTS_PER_VERTEX, false }, // original - { false, 1, true }, // one bone per vertex - { true, 1, true }, // one bone per voxel - { true, BONE_ELEMENTS_PER_VERTEX, false } }; // four bones per voxel - -void AvatarVoxelSystem::cycleMode() { - _mode = (_mode + 1) % (sizeof(MODES) / sizeof(MODES[0])); - qDebug("Voxeltar bind mode %d.\n", _mode); - - // rebind - QUrl url = _voxelURL; - setVoxelURL(QUrl()); - setVoxelURL(url); -} - -void AvatarVoxelSystem::setVoxelURL(const QUrl& url) { - // don't restart the download if it's the same URL - if (_voxelURL == url) { - return; - } - - // cancel any current download - if (_voxelReply != 0) { - delete _voxelReply; - _voxelReply = 0; - } - - killLocalVoxels(); - - // remember the URL - _voxelURL = url; - - // handle "file://" urls... - if (url.isLocalFile()) { - QString pathString = url.path(); - QByteArray pathAsAscii = pathString.toLocal8Bit(); - const char* path = pathAsAscii.data(); - readFromSVOFile(path); - return; - } - - // load the URL data asynchronously - if (!url.isValid()) { - return; - } - _voxelReply = Application::getInstance()->getNetworkAccessManager()->get(QNetworkRequest(url)); - connect(_voxelReply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleVoxelDownloadProgress(qint64,qint64))); - connect(_voxelReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleVoxelReplyError())); -} - -void AvatarVoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex, - float voxelScale, const nodeColor& color) { - VoxelSystem::updateArraysDetails(nodeIndex, startVertex, voxelScale, color); - - GLubyte* writeBoneIndicesAt = _writeBoneIndicesArray + (nodeIndex * BONE_ELEMENTS_PER_VOXEL); - GLfloat* writeBoneWeightsAt = _writeBoneWeightsArray + (nodeIndex * BONE_ELEMENTS_PER_VOXEL); - - if (MODES[_mode].bindVoxelsTogether) { - BoneIndices boneIndices; - glm::vec4 boneWeights; - computeBoneIndicesAndWeights(startVertex + glm::vec3(voxelScale, voxelScale, voxelScale) * 0.5f, - boneIndices, boneWeights); - for (int i = 0; i < VERTICES_PER_VOXEL; i++) { - for (int j = 0; j < BONE_ELEMENTS_PER_VERTEX; j++) { - *(writeBoneIndicesAt + i * BONE_ELEMENTS_PER_VERTEX + j) = boneIndices[j]; - *(writeBoneWeightsAt + i * BONE_ELEMENTS_PER_VERTEX + j) = boneWeights[j]; - } - } - } else { - for (int i = 0; i < VERTICES_PER_VOXEL; i++) { - BoneIndices boneIndices; - glm::vec4 boneWeights; - computeBoneIndicesAndWeights(computeVoxelVertex(startVertex, voxelScale, i), boneIndices, boneWeights); - for (int j = 0; j < BONE_ELEMENTS_PER_VERTEX; j++) { - *(writeBoneIndicesAt + i * BONE_ELEMENTS_PER_VERTEX + j) = boneIndices[j]; - *(writeBoneWeightsAt + i * BONE_ELEMENTS_PER_VERTEX + j) = boneWeights[j]; - } - } - } -} - -void AvatarVoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd) { - VoxelSystem::copyWrittenDataSegmentToReadArrays(segmentStart, segmentEnd); - - int segmentLength = (segmentEnd - segmentStart) + 1; - GLintptr segmentStartAt = segmentStart * BONE_ELEMENTS_PER_VOXEL * sizeof(GLubyte); - GLsizeiptr segmentSizeBytes = segmentLength * BONE_ELEMENTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readBoneIndicesAt = _readBoneIndicesArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL); - GLubyte* writeBoneIndicesAt = _writeBoneIndicesArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL); - memcpy(readBoneIndicesAt, writeBoneIndicesAt, segmentSizeBytes); - - segmentStartAt = segmentStart * BONE_ELEMENTS_PER_VOXEL * sizeof(GLfloat); - segmentSizeBytes = segmentLength * BONE_ELEMENTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readBoneWeightsAt = _readBoneWeightsArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL); - GLfloat* writeBoneWeightsAt = _writeBoneWeightsArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL); - memcpy(readBoneWeightsAt, writeBoneWeightsAt, segmentSizeBytes); -} - -void AvatarVoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) { - VoxelSystem::updateVBOSegment(segmentStart, segmentEnd); - - int segmentLength = (segmentEnd - segmentStart) + 1; - GLintptr segmentStartAt = segmentStart * BONE_ELEMENTS_PER_VOXEL * sizeof(GLubyte); - GLsizeiptr segmentSizeBytes = segmentLength * BONE_ELEMENTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readBoneIndicesFrom = _readBoneIndicesArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboBoneIndicesID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readBoneIndicesFrom); - - segmentStartAt = segmentStart * BONE_ELEMENTS_PER_VOXEL * sizeof(GLfloat); - segmentSizeBytes = segmentLength * BONE_ELEMENTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readBoneWeightsFrom = _readBoneWeightsArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboBoneWeightsID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readBoneWeightsFrom); -} - -void AvatarVoxelSystem::applyScaleAndBindProgram(bool texture) { - _skinProgram.bind(); - - // the base matrix includes centering and scale - QMatrix4x4 baseMatrix; - baseMatrix.scale(_treeScale); - baseMatrix.translate(-0.5f, -0.5f, -0.5f); - - // bone matrices include joint transforms - QMatrix4x4 boneMatrices[NUM_AVATAR_JOINTS]; - for (int i = 0; i < NUM_AVATAR_JOINTS; i++) { - glm::vec3 position; - glm::quat orientation; - _avatar->getBodyBallTransform((AvatarJointID)i, position, orientation); - boneMatrices[i].translate(position.x, position.y, position.z); - orientation = orientation * glm::inverse(_avatar->getSkeleton().joint[i].absoluteBindPoseRotation); - boneMatrices[i].rotate(QQuaternion(orientation.w, orientation.x, orientation.y, orientation.z)); - const glm::vec3& bindPosition = _avatar->getSkeleton().joint[i].absoluteBindPosePosition; - boneMatrices[i].translate(-bindPosition.x, -bindPosition.y, -bindPosition.z); - boneMatrices[i] *= baseMatrix; - } - _skinProgram.setUniformValueArray(_boneMatricesLocation, boneMatrices, NUM_AVATAR_JOINTS); - - glBindBuffer(GL_ARRAY_BUFFER, _vboBoneIndicesID); - glVertexAttribPointer(_boneIndicesLocation, BONE_ELEMENTS_PER_VERTEX, GL_UNSIGNED_BYTE, false, 0, 0); - _skinProgram.enableAttributeArray(_boneIndicesLocation); - - glBindBuffer(GL_ARRAY_BUFFER, _vboBoneWeightsID); - _skinProgram.setAttributeBuffer(_boneWeightsLocation, GL_FLOAT, 0, BONE_ELEMENTS_PER_VERTEX); - _skinProgram.enableAttributeArray(_boneWeightsLocation); -} - -void AvatarVoxelSystem::removeScaleAndReleaseProgram(bool texture) { - _skinProgram.release(); - _skinProgram.disableAttributeArray(_boneIndicesLocation); - _skinProgram.disableAttributeArray(_boneWeightsLocation); -} - -void AvatarVoxelSystem::handleVoxelDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { - // for now, just wait until we have the full business - if (bytesReceived < bytesTotal) { - return; - } - - QByteArray entirety = _voxelReply->readAll(); - _voxelReply->disconnect(this); - _voxelReply->deleteLater(); - _voxelReply = 0; - - ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS); - _tree->readBitstreamToTree((unsigned char*)entirety.data(), entirety.size(), args); - setupNewVoxelsForDrawing(); -} - -void AvatarVoxelSystem::handleVoxelReplyError() { - qDebug("%s\n", _voxelReply->errorString().toLocal8Bit().constData()); - - _voxelReply->disconnect(this); - _voxelReply->deleteLater(); - _voxelReply = 0; -} - -class IndexDistance { -public: - IndexDistance(GLubyte index = AVATAR_JOINT_PELVIS, float distance = FLT_MAX) : index(index), distance(distance) { } - - GLubyte index; - float distance; -}; - -void AvatarVoxelSystem::computeBoneIndicesAndWeights(const glm::vec3& vertex, BoneIndices& indices, glm::vec4& weights) const { - // transform into joint space - glm::vec3 jointVertex = (vertex - glm::vec3(0.5f, 0.5f, 0.5f)) * AVATAR_TREE_SCALE; - - // find the nearest four joints (TODO: use a better data structure for the pose positions to speed this up) - IndexDistance nearest[BONE_ELEMENTS_PER_VERTEX]; - const Skeleton& skeleton = _avatar->getSkeleton(); - for (int i = 0; i < NUM_AVATAR_JOINTS; i++) { - AvatarJointID parent = skeleton.joint[i].parent; - float distance = glm::length(computeVectorFromPointToSegment(jointVertex, - skeleton.joint[parent == AVATAR_JOINT_NULL ? i : parent].absoluteBindPosePosition, - skeleton.joint[i].absoluteBindPosePosition)); - if (!MODES[_mode].includeBonesOutsideBindRadius && distance > skeleton.joint[i].bindRadius) { - continue; - } - for (int j = 0; j < BONE_ELEMENTS_PER_VERTEX; j++) { - if (distance < nearest[j].distance) { - // move the rest of the indices down - for (int k = BONE_ELEMENTS_PER_VERTEX - 1; k > j; k--) { - nearest[k] = nearest[k - 1]; - } - nearest[j] = IndexDistance(i, distance); - break; - } - } - } - - // compute the weights based on inverse distance - float totalWeight = 0.0f; - for (int i = 0; i < MODES[_mode].maxBonesPerBind; i++) { - indices[i] = nearest[i].index; - if (nearest[i].distance != FLT_MAX) { - weights[i] = 1.0f / glm::max(nearest[i].distance, EPSILON); - totalWeight += weights[i]; - - } else { - weights[i] = 0.0f; - } - } - - // if it's not attached to anything, consider it attached to the hip - if (totalWeight == 0.0f) { - weights[0] = 1.0f; - return; - } - - // ortherwise, normalize the weights - for (int i = 0; i < BONE_ELEMENTS_PER_VERTEX; i++) { - weights[i] /= totalWeight; - } -} diff --git a/interface/src/avatar/AvatarVoxelSystem.h b/interface/src/avatar/AvatarVoxelSystem.h deleted file mode 100644 index 2560af11a5..0000000000 --- a/interface/src/avatar/AvatarVoxelSystem.h +++ /dev/null @@ -1,84 +0,0 @@ -// -// AvatarVoxelSystem.h -// interface -// -// Created by Andrzej Kapolka on 5/31/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#ifndef __interface__AvatarVoxelSystem__ -#define __interface__AvatarVoxelSystem__ - -#include -#include - -#include "VoxelSystem.h" - -const int BONE_ELEMENTS_PER_VERTEX = 4; -typedef GLubyte BoneIndices[BONE_ELEMENTS_PER_VERTEX]; - -class QNetworkReply; - -class Avatar; - -class AvatarVoxelSystem : public VoxelSystem { - Q_OBJECT - -public: - - AvatarVoxelSystem(Avatar* avatar); - virtual ~AvatarVoxelSystem(); - - virtual void init(); - - virtual void removeOutOfView(); - - Q_INVOKABLE void setVoxelURL(const QUrl& url); - const QUrl& getVoxelURL() const { return _voxelURL; } - -public slots: - - void cycleMode(); - -protected: - - virtual void updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex, - float voxelScale, const nodeColor& color); - virtual void copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd); - virtual void updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd); - virtual void applyScaleAndBindProgram(bool texture); - virtual void removeScaleAndReleaseProgram(bool texture); - -private slots: - - void handleVoxelDownloadProgress(qint64 bytesReceived, qint64 bytesTotal); - void handleVoxelReplyError(); - -private: - - void computeBoneIndicesAndWeights(const glm::vec3& vertex, BoneIndices& indices, glm::vec4& weights) const; - - bool _initialized; - int _mode; - - Avatar* _avatar; - - QUrl _voxelURL; - - GLubyte* _readBoneIndicesArray; - GLfloat* _readBoneWeightsArray; - GLubyte* _writeBoneIndicesArray; - GLfloat* _writeBoneWeightsArray; - - GLuint _vboBoneIndicesID; - GLuint _vboBoneWeightsID; - - QNetworkReply* _voxelReply; - - static ProgramObject _skinProgram; - static int _boneMatricesLocation; - static int _boneIndicesLocation; - static int _boneWeightsLocation; -}; - -#endif /* defined(__interface__AvatarVoxelSystem__) */ diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 46dca6d0cf..12d6d0d8da 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -24,6 +24,7 @@ #include "ParticleSystem.h" #include "world.h" #include "devices/SerialInterface.h" +#include "VoxelSystem.h" class Avatar; class ProgramObject; diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 5dd59ed159..b593602e3f 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -250,9 +250,8 @@ void Head::simulate(float deltaTime, bool isMine) { calculateGeometry(); // the blend face may have custom eye meshes - if (!Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)) { - _faceModel.getEyePositions(_leftEyePosition, _rightEyePosition); - } + _faceModel.getEyePositions(_leftEyePosition, _rightEyePosition); + } void Head::calculateGeometry() { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 17fc1192f6..732ca58939 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -75,8 +75,6 @@ void MyAvatar::setMoveTarget(const glm::vec3 moveTarget) { void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { glm::quat orientation = getOrientation(); - glm::vec3 front = orientation * IDENTITY_FRONT; - glm::vec3 right = orientation * IDENTITY_RIGHT; // Update movement timers _elapsedTimeSinceCollision += deltaTime; @@ -113,9 +111,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { // calculate speed _speed = glm::length(_velocity); - // figure out if the mouse cursor is over any body spheres... - checkForMouseRayTouching(); - // update balls if (_balls) { _balls->moveOrigin(_position); @@ -143,24 +138,7 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { // update avatar skeleton _skeleton.update(deltaTime, getOrientation(), _position); - - // determine the lengths of the body springs now that we have updated the skeleton at least once - if (!_ballSpringsInitialized) { - for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - - glm::vec3 targetPosition - = _skeleton.joint[_bodyBall[b].parentJoint].position - + _skeleton.joint[_bodyBall[b].parentJoint].rotation * _bodyBall[b].parentOffset; - - glm::vec3 parentTargetPosition - = _skeleton.joint[_bodyBall[b].parentJoint].position - + _skeleton.joint[_bodyBall[b].parentJoint].rotation * _bodyBall[b].parentOffset; - - _bodyBall[b].springLength = glm::length(targetPosition - parentTargetPosition); - } - - _ballSpringsInitialized = true; - } + // update the movement of the hand and process handshaking with other avatars... updateHandMovementAndTouching(deltaTime, enableHandMovement); @@ -190,9 +168,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { updateAvatarCollisions(deltaTime); } - // update body balls - updateBodyBalls(deltaTime); - // add thrust to velocity _velocity += _thrust * deltaTime; @@ -234,31 +209,7 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } else { applyDamping(deltaTime, _velocity, linearDamping, SQUARED_DAMPING_STRENGTH); } - - // pitch and roll the body as a function of forward speed and turning delta - const float HIGH_VELOCITY = 10.f; - if (glm::length(_velocity) < HIGH_VELOCITY) { - const float BODY_PITCH_WHILE_WALKING = -20.0; - const float BODY_ROLL_WHILE_TURNING = 0.2; - float forwardComponentOfVelocity = glm::dot(getBodyFrontDirection(), _velocity); - orientation = orientation * glm::quat(glm::radians(glm::vec3( - BODY_PITCH_WHILE_WALKING * deltaTime * forwardComponentOfVelocity, 0.0f, - BODY_ROLL_WHILE_TURNING * deltaTime * _speed * _bodyYawDelta))); - } - - // these forces keep the body upright... - const float BODY_UPRIGHT_FORCE = _scale * 10.0; - float tiltDecay = BODY_UPRIGHT_FORCE * deltaTime; - if (tiltDecay > 1.0f) { - tiltDecay = 1.0f; - } - - // update the euler angles - setOrientation(orientation); - - //the following will be used to make the avatar upright no matter what gravity is - setOrientation(computeRotationFromBodyToWorldUp(tiltDecay) * orientation); - + // Compute instantaneous acceleration float forwardAcceleration = glm::length(glm::dot(getBodyFrontDirection(), getVelocity() - oldVelocity)) / deltaTime; const float ACCELERATION_PITCH_DECAY = 0.4f; @@ -292,39 +243,11 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } } - //apply the head lean values to the ball positions... - if (USING_HEAD_LEAN) { - if (fabs(_head.getLeanSideways() + _head.getLeanForward()) > 0.0f) { - glm::vec3 headLean = - right * _head.getLeanSideways() + - front * _head.getLeanForward(); - - _bodyBall[BODY_BALL_TORSO].position += headLean * 0.1f; - _bodyBall[BODY_BALL_CHEST].position += headLean * 0.4f; - _bodyBall[BODY_BALL_NECK_BASE].position += headLean * 0.7f; - _bodyBall[BODY_BALL_HEAD_BASE].position += headLean * 1.0f; - - _bodyBall[BODY_BALL_LEFT_COLLAR].position += headLean * 0.6f; - _bodyBall[BODY_BALL_LEFT_SHOULDER].position += headLean * 0.6f; - _bodyBall[BODY_BALL_LEFT_ELBOW].position += headLean * 0.2f; - _bodyBall[BODY_BALL_LEFT_WRIST].position += headLean * 0.1f; - _bodyBall[BODY_BALL_LEFT_FINGERTIPS].position += headLean * 0.0f; - - _bodyBall[BODY_BALL_RIGHT_COLLAR].position += headLean * 0.6f; - _bodyBall[BODY_BALL_RIGHT_SHOULDER].position += headLean * 0.6f; - _bodyBall[BODY_BALL_RIGHT_ELBOW].position += headLean * 0.2f; - _bodyBall[BODY_BALL_RIGHT_WRIST].position += headLean * 0.1f; - _bodyBall[BODY_BALL_RIGHT_FINGERTIPS].position += headLean * 0.0f; - } - } - _hand.simulate(deltaTime, true); _skeletonModel.simulate(deltaTime); _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); glm::vec3 headPosition; - if (Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls) || !_skeletonModel.getHeadPosition(headPosition)) { - headPosition = _bodyBall[BODY_BALL_HEAD_BASE].position; - } + _skeletonModel.getHeadPosition(headPosition); _head.setPosition(headPosition); _head.setScale(_scale); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); @@ -514,7 +437,7 @@ void MyAvatar::render(bool forceRenderHead) { } glPushMatrix(); - glm::vec3 chatPosition = _bodyBall[BODY_BALL_HEAD_BASE].position + getBodyUpDirection() * chatMessageHeight * _scale; + glm::vec3 chatPosition = getPosition() + getBodyUpDirection() * chatMessageHeight * _scale; glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z); glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation(); glm::vec3 chatAxis = glm::axis(chatRotation); @@ -562,7 +485,6 @@ void MyAvatar::saveData(QSettings* settings) { settings->setValue("position_y", _position.y); settings->setValue("position_z", _position.z); - settings->setValue("voxelURL", _voxels.getVoxelURL()); settings->setValue("pupilDilation", _head.getPupilDilation()); settings->setValue("leanScale", _leanScale); @@ -585,7 +507,6 @@ void MyAvatar::loadData(QSettings* settings) { _position.y = loadSetting(settings, "position_y", 0.0f); _position.z = loadSetting(settings, "position_z", 0.0f); - _voxels.setVoxelURL(settings->value("voxelURL").toUrl()); _head.setPupilDilation(settings->value("pupilDilation", 0.0f).toFloat()); _leanScale = loadSetting(settings, "leanScale", 0.05f); @@ -612,93 +533,15 @@ glm::vec3 MyAvatar::getEyeLevelPosition() const { glm::vec3(0.0f, _pelvisToHeadLength + _scale * BODY_BALL_RADIUS_HEAD_BASE * EYE_UP_OFFSET, 0.0f); } -float MyAvatar::getBallRenderAlpha(int ball, bool forceRenderHead) const { - const float RENDER_OPAQUE_OUTSIDE = _scale * 0.25f; // render opaque if greater than this distance - const float DO_NOT_RENDER_INSIDE = _scale * 0.25f; // do not render if less than this distance - float distanceToCamera = glm::length(Application::getInstance()->getCamera()->getPosition() - _bodyBall[ball].position); - return (forceRenderHead) ? 1.0f : glm::clamp( - (distanceToCamera - DO_NOT_RENDER_INSIDE) / (RENDER_OPAQUE_OUTSIDE - DO_NOT_RENDER_INSIDE), 0.f, 1.f); -} - void MyAvatar::renderBody(bool forceRenderHead) { if (_head.getVideoFace().isFullFrame()) { // Render the full-frame video - float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, forceRenderHead); - if (alpha > 0.0f) { _head.getVideoFace().render(1.0f); - } - } else if (Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)) { - // Render the body as balls and cones - glm::vec3 skinColor, darkSkinColor; - getSkinColors(skinColor, darkSkinColor); - for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - float alpha = getBallRenderAlpha(b, forceRenderHead); - - // When we have leap hands, hide part of the arms. - if (_hand.getNumPalms() > 0) { - if (b == BODY_BALL_LEFT_FINGERTIPS - || b == BODY_BALL_RIGHT_FINGERTIPS) { - continue; - } - } - // Always render other people, and render myself when beyond threshold distance - if (b == BODY_BALL_HEAD_BASE) { // the head is rendered as a special - if (alpha > 0.0f) { - _head.render(alpha, true); - } - } else if (alpha > 0.0f) { - // Render the body ball sphere - if (b == BODY_BALL_RIGHT_ELBOW - || b == BODY_BALL_RIGHT_WRIST - || b == BODY_BALL_RIGHT_FINGERTIPS ) { - glColor3f(skinColor.r + _bodyBall[b].touchForce * 0.3f, - skinColor.g - _bodyBall[b].touchForce * 0.2f, - skinColor.b - _bodyBall[b].touchForce * 0.1f); - } else { - glColor4f(skinColor.r + _bodyBall[b].touchForce * 0.3f, - skinColor.g - _bodyBall[b].touchForce * 0.2f, - skinColor.b - _bodyBall[b].touchForce * 0.1f, - alpha); - } - - if ((b != BODY_BALL_HEAD_TOP ) - && (b != BODY_BALL_HEAD_BASE )) { - glPushMatrix(); - glTranslatef(_bodyBall[b].position.x, _bodyBall[b].position.y, _bodyBall[b].position.z); - glutSolidSphere(_bodyBall[b].radius, 20.0f, 20.0f); - glPopMatrix(); - } - - // Render the cone connecting this ball to its parent - if (_bodyBall[b].parentBall != BODY_BALL_NULL) { - if ((b != BODY_BALL_HEAD_TOP) - && (b != BODY_BALL_HEAD_BASE) - && (b != BODY_BALL_PELVIS) - && (b != BODY_BALL_TORSO) - && (b != BODY_BALL_CHEST) - && (b != BODY_BALL_LEFT_COLLAR) - && (b != BODY_BALL_LEFT_SHOULDER) - && (b != BODY_BALL_RIGHT_COLLAR) - && (b != BODY_BALL_RIGHT_SHOULDER)) { - glColor3fv((const GLfloat*)&darkSkinColor); - - float r2 = _bodyBall[b].radius * 0.8; - - renderJointConnectingCone(_bodyBall[_bodyBall[b].parentBall].position, _bodyBall[b].position, r2, r2); - } - } - } - } } else { // Render the body's voxels and head - if (!_skeletonModel.render(1.0f)) { - _voxels.render(false); - } - float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, forceRenderHead); - if (alpha > 0.0f) { - _head.render(alpha, false); - } + _skeletonModel.render(1.0f); + _head.render(1.0f, false); } _hand.render(true); } @@ -980,74 +823,13 @@ void MyAvatar::updateAvatarCollisions(float deltaTime) { NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { - Avatar *otherAvatar = (Avatar *)node->getLinkedData(); - - // check if the bounding spheres of the two avatars are colliding - glm::vec3 vectorBetweenBoundingSpheres(_position - otherAvatar->_position); - - if (glm::length(vectorBetweenBoundingSpheres) < _height * ONE_HALF + otherAvatar->_height * ONE_HALF) { - // apply forces from collision - applyCollisionWithOtherAvatar(otherAvatar, deltaTime); - } - // test other avatar hand position for proximity - glm::vec3 v(_skeleton.joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position); - v -= otherAvatar->getPosition(); - - float distance = glm::length(v); - if (distance < _distanceToNearestAvatar) { - _distanceToNearestAvatar = distance; - } + //Avatar *otherAvatar = (Avatar *)node->getLinkedData(); + // + // Placeholder: Add code here when we want to add Avatar<->Avatar collision stuff } } } -// detect collisions with other avatars and respond -void MyAvatar::applyCollisionWithOtherAvatar(Avatar * otherAvatar, float deltaTime) { - - // for now, don't collide if we have a new skeleton - if (_skeletonModel.isActive()) { - return; - } - - glm::vec3 bodyPushForce = glm::vec3(0.0f, 0.0f, 0.0f); - - // loop through the body balls of each avatar to check for every possible collision - for (int b = 1; b < NUM_AVATAR_BODY_BALLS; b++) { - if (_bodyBall[b].isCollidable) { - - for (int o = b+1; o < NUM_AVATAR_BODY_BALLS; o++) { - if (otherAvatar->_bodyBall[o].isCollidable) { - - glm::vec3 vectorBetweenBalls(_bodyBall[b].position - otherAvatar->_bodyBall[o].position); - float distanceBetweenBalls = glm::length(vectorBetweenBalls); - - if (distanceBetweenBalls > 0.0) { // to avoid divide by zero - float combinedRadius = _bodyBall[b].radius + otherAvatar->_bodyBall[o].radius; - - // check for collision - if (distanceBetweenBalls < combinedRadius * COLLISION_RADIUS_SCALAR) { - glm::vec3 directionVector = vectorBetweenBalls / distanceBetweenBalls; - - // push balls away from each other and apply friction - float penetration = 1.0f - (distanceBetweenBalls / (combinedRadius * COLLISION_RADIUS_SCALAR)); - - glm::vec3 ballPushForce = directionVector * COLLISION_BALL_FORCE * penetration * deltaTime; - bodyPushForce += directionVector * COLLISION_BODY_FORCE * penetration * deltaTime; - - _bodyBall[b].velocity += ballPushForce; - otherAvatar->_bodyBall[o].velocity -= ballPushForce; - - }// check for collision - } // to avoid divide by zero - } // o loop - } // collidable - } // b loop - } // collidable - - // apply force on the whole body - _velocity += bodyPushForce; -} - class SortedAvatar { public: Avatar* avatar; @@ -1166,23 +948,6 @@ void MyAvatar::setGravity(glm::vec3 gravity) { } } -void MyAvatar::checkForMouseRayTouching() { - - for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - - glm::vec3 directionToBodySphere = glm::normalize(_bodyBall[b].position - _mouseRayOrigin); - float dot = glm::dot(directionToBodySphere, _mouseRayDirection); - - float range = _bodyBall[b].radius * MOUSE_RAY_TOUCH_RANGE; - - if (dot > (1.0f - range)) { - _bodyBall[b].touchForce = (dot - (1.0f - range)) / range; - } else { - _bodyBall[b].touchForce = 0.0; - } - } -} - void MyAvatar::setOrientation(const glm::quat& orientation) { glm::vec3 eulerAngles = safeEulerAngles(orientation); _bodyPitch = eulerAngles.x; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index e67071581c..df8ab4aa92 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -88,7 +88,6 @@ private: int _moveTargetStepCounter; // private methods - float getBallRenderAlpha(int ball, bool forceRenderHead) const; void renderBody(bool forceRenderHead); void updateThrust(float deltaTime, Transmitter * transmitter); void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement); @@ -97,9 +96,7 @@ private: void updateCollisionWithVoxels(float deltaTime); void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping); void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); - void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime ); void updateChatCircle(float deltaTime); - void checkForMouseRayTouching(); }; #endif From 66c5a100200d1e6dbc0bf5e78059919ce4f021c6 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 6 Dec 2013 16:47:13 -0800 Subject: [PATCH 08/15] Fix chat message height --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e388abad87..a9bd4e2f39 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -60,7 +60,7 @@ const float SKIN_COLOR[] = {1.0, 0.84, 0.66}; const float DARK_SKIN_COLOR[] = {0.9, 0.78, 0.63}; const int NUM_BODY_CONE_SIDES = 9; const float chatMessageScale = 0.0015; -const float chatMessageHeight = 0.20; +const float chatMessageHeight = 0.4f; void Avatar::sendAvatarURLsMessage(const QUrl& voxelURL) { QByteArray message; From 9195d60b719423b203d53d998e790d916a5e2c1b Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 6 Dec 2013 17:45:28 -0800 Subject: [PATCH 09/15] Fix to jerky avatar movement, fix for rotation broken --- interface/src/avatar/Avatar.cpp | 32 +++++++++++++++---------------- interface/src/avatar/Avatar.h | 1 - interface/src/avatar/MyAvatar.cpp | 32 ++++++++++++++++--------------- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index a9bd4e2f39..cab6e9f1df 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -205,16 +205,25 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { enableHandMovement &= (it->jointID != AVATAR_JOINT_RIGHT_WRIST); } - // update avatar skeleton - _skeleton.update(deltaTime, getOrientation(), _position); - - - // if this is not my avatar, then hand position comes from transmitted data - _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handPosition; - //update the movement of the hand and process handshaking with other avatars... updateHandMovementAndTouching(deltaTime, enableHandMovement); + // use speed and angular velocity to determine walking vs. standing + if (_speed + fabs(_bodyYawDelta) > 0.2) { + _mode = AVATAR_MODE_WALKING; + } else { + _mode = AVATAR_MODE_INTERACTING; + } + + // update position by velocity, and subtract the change added earlier for gravity + _position += _velocity * deltaTime; + + // update avatar skeleton + _skeleton.update(deltaTime, getOrientation(), _position); + + // if this is not my avatar, then hand position comes from transmitted data + _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handPosition; + _hand.simulate(deltaTime, false); _skeletonModel.simulate(deltaTime); _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); @@ -225,15 +234,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); _head.simulate(deltaTime, false); - // use speed and angular velocity to determine walking vs. standing - if (_speed + fabs(_bodyYawDelta) > 0.2) { - _mode = AVATAR_MODE_WALKING; - } else { - _mode = AVATAR_MODE_INTERACTING; - } - - // update position by velocity, and subtract the change added earlier for gravity - _position += _velocity * deltaTime; // Zero thrust out now that we've added it to velocity in this frame _thrust = glm::vec3(0, 0, 0); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 2e3f9d001b..c435191a18 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -205,7 +205,6 @@ protected: SkeletonModel _skeletonModel; bool _ballSpringsInitialized; float _bodyYawDelta; - //AvatarBall _bodyBall[ NUM_AVATAR_BODY_BALLS ]; AvatarMode _mode; glm::vec3 _velocity; glm::vec3 _thrust; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 732ca58939..314a70c80f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -136,10 +136,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { enableHandMovement &= (it->jointID != AVATAR_JOINT_RIGHT_WRIST); } - // update avatar skeleton - _skeleton.update(deltaTime, getOrientation(), _position); - - // update the movement of the hand and process handshaking with other avatars... updateHandMovementAndTouching(deltaTime, enableHandMovement); @@ -172,6 +168,7 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { _velocity += _thrust * deltaTime; // update body yaw by body yaw delta + printf("bodyYawDelta %.3f\n", _bodyYawDelta); orientation = orientation * glm::quat(glm::radians( glm::vec3(_bodyPitchDelta, _bodyYawDelta, _bodyRollDelta) * deltaTime)); // decay body rotation momentum @@ -209,7 +206,10 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } else { applyDamping(deltaTime, _velocity, linearDamping, SQUARED_DAMPING_STRENGTH); } - + + // update the euler angles + setOrientation(orientation); + // Compute instantaneous acceleration float forwardAcceleration = glm::length(glm::dot(getBodyFrontDirection(), getVelocity() - oldVelocity)) / deltaTime; const float ACCELERATION_PITCH_DECAY = 0.4f; @@ -243,16 +243,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } } - _hand.simulate(deltaTime, true); - _skeletonModel.simulate(deltaTime); - _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); - glm::vec3 headPosition; - _skeletonModel.getHeadPosition(headPosition); - _head.setPosition(headPosition); - _head.setScale(_scale); - _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); - _head.simulate(deltaTime, true); - const float WALKING_SPEED_THRESHOLD = 0.2f; // use speed and angular velocity to determine walking vs. standing if (_speed + fabs(_bodyYawDelta) > WALKING_SPEED_THRESHOLD) { @@ -284,6 +274,18 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { _position += _velocity * deltaTime; + // update avatar skeleton and simulate hand and head + _skeleton.update(deltaTime, getOrientation(), _position); + _hand.simulate(deltaTime, true); + _skeletonModel.simulate(deltaTime); + _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); + glm::vec3 headPosition; + _skeletonModel.getHeadPosition(headPosition); + _head.setPosition(headPosition); + _head.setScale(_scale); + _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); + _head.simulate(deltaTime, true); + // Zero thrust out now that we've added it to velocity in this frame _thrust = glm::vec3(0, 0, 0); From 4edb7decdf3f09f4c3601faa47c9e44b8576ea1c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 6 Dec 2013 17:47:01 -0800 Subject: [PATCH 10/15] removed printf --- interface/src/avatar/MyAvatar.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 314a70c80f..c65c6d50a3 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -168,7 +168,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { _velocity += _thrust * deltaTime; // update body yaw by body yaw delta - printf("bodyYawDelta %.3f\n", _bodyYawDelta); orientation = orientation * glm::quat(glm::radians( glm::vec3(_bodyPitchDelta, _bodyYawDelta, _bodyRollDelta) * deltaTime)); // decay body rotation momentum From 3bd8c53115467a0c3632c14666453519b8eb2df6 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 7 Dec 2013 11:36:51 -0800 Subject: [PATCH 11/15] =?UTF-8?q?Fix=20to=20get=20other=20avatar=E2=80=99s?= =?UTF-8?q?=20model=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- interface/src/Application.cpp | 18 ++++++++-- interface/src/avatar/Avatar.cpp | 46 ++++++++++++++------------ interface/src/avatar/SkeletonModel.cpp | 1 + 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f88b20334b..5852656655 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1412,9 +1412,16 @@ void Application::processAvatarURLsMessage(unsigned char* packetData, size_t dat if (!avatar) { return; } - QDataStream in(QByteArray((char*)packetData, dataBytes)); - QUrl voxelURL; - in >> voxelURL; + // PER Note: message is no longer processed but used to trigger + // Dataserver lookup - redesign this to instantly ask the + // dataserver on first receipt of other avatar UUID, and also + // don't ask over and over again. Instead use this message to + // Tell the other avatars that your dataserver data has + // changed. + + //QDataStream in(QByteArray((char*)packetData, dataBytes)); + //QUrl voxelURL; + //in >> voxelURL; // use this timing to as the data-server for an updated mesh for this avatar (if we have UUID) DataServerClient::getValuesForKeysAndUUID(QStringList() << DataServerKey::FaceMeshURL << DataServerKey::SkeletonURL, @@ -2553,6 +2560,11 @@ void Application::updateAvatar(float deltaTime) { controlledBroadcastToNodes(broadcastString, endOfBroadcastStringWrite - broadcastString, nodeTypesOfInterest, sizeof(nodeTypesOfInterest)); + const float AVATAR_URLS_SEND_INTERVAL = 1.0f; + if (shouldDo(AVATAR_URLS_SEND_INTERVAL, deltaTime)) { + QUrl empty; + Avatar::sendAvatarURLsMessage(empty); + } // Update _viewFrustum with latest camera and view frustum data... // NOTE: we get this from the view frustum, to make it simpler, since the // loadViewFrumstum() method will get the correct details from the camera diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index cab6e9f1df..f4a09ad069 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -168,18 +168,18 @@ void Avatar::follow(Avatar* leadingAvatar) { } void Avatar::simulate(float deltaTime, Transmitter* transmitter) { - + if (_leadingAvatar && !_leadingAvatar->getOwningNode()->isAlive()) { follow(NULL); } - + if (_scale != _newScale) { setScale(_newScale); } // copy velocity so we can use it later for acceleration glm::vec3 oldVelocity = getVelocity(); - + // update balls if (_balls) { _balls->moveOrigin(_position); @@ -194,7 +194,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // update torso rotation based on head lean _skeleton.joint[AVATAR_JOINT_TORSO].rotation = glm::quat(glm::radians(glm::vec3( - _head.getLeanForward(), 0.0f, _head.getLeanSideways()))); + _head.getLeanForward(), 0.0f, _head.getLeanSideways()))); // apply joint data (if any) to skeleton bool enableHandMovement = true; @@ -205,25 +205,16 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { enableHandMovement &= (it->jointID != AVATAR_JOINT_RIGHT_WRIST); } + // update avatar skeleton + _skeleton.update(deltaTime, getOrientation(), _position); + + + // if this is not my avatar, then hand position comes from transmitted data + _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handPosition; + //update the movement of the hand and process handshaking with other avatars... updateHandMovementAndTouching(deltaTime, enableHandMovement); - // use speed and angular velocity to determine walking vs. standing - if (_speed + fabs(_bodyYawDelta) > 0.2) { - _mode = AVATAR_MODE_WALKING; - } else { - _mode = AVATAR_MODE_INTERACTING; - } - - // update position by velocity, and subtract the change added earlier for gravity - _position += _velocity * deltaTime; - - // update avatar skeleton - _skeleton.update(deltaTime, getOrientation(), _position); - - // if this is not my avatar, then hand position comes from transmitted data - _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handPosition; - _hand.simulate(deltaTime, false); _skeletonModel.simulate(deltaTime); _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); @@ -233,11 +224,20 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _head.setScale(_scale); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); _head.simulate(deltaTime, false); - + + // use speed and angular velocity to determine walking vs. standing + if (_speed + fabs(_bodyYawDelta) > 0.2) { + _mode = AVATAR_MODE_WALKING; + } else { + _mode = AVATAR_MODE_INTERACTING; + } + + // update position by velocity, and subtract the change added earlier for gravity + _position += _velocity * deltaTime; // Zero thrust out now that we've added it to velocity in this frame _thrust = glm::vec3(0, 0, 0); - + } void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction) { @@ -452,6 +452,8 @@ void Avatar::renderBody(bool forceRenderHead) { _head.getVideoFace().render(1.0f); } else { // Render the body's voxels and head + glm::vec3 pos = getPosition(); + //printf("Render other at %.3f, %.2f, %.2f\n", pos.x, pos.y, pos.z); _skeletonModel.render(1.0f); _head.render(1.0f, false); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 2605c8438f..b8c500d3bd 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -61,6 +61,7 @@ void SkeletonModel::simulate(float deltaTime) { } bool SkeletonModel::render(float alpha) { + if (_jointStates.isEmpty()) { return false; } From 85f7995700f659bc2c1afc2e7765ca8f7517bd35 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Dec 2013 11:00:35 -0800 Subject: [PATCH 12/15] Don't apply ambient occlusion to avatars (just voxels). --- interface/src/Application.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5852656655..7d10928d87 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2992,6 +2992,13 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { } } + // render the ambient occlusion effect if enabled + if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) { + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "Application::displaySide() ... AmbientOcclusion..."); + _ambientOcclusionEffect.render(); + } + // restore default, white specular glMaterialfv(GL_FRONT, GL_SPECULAR, WHITE_SPECULAR_COLOR); @@ -3075,13 +3082,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { renderWorldBox(); } - // render the ambient occlusion effect if enabled - if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... AmbientOcclusion..."); - _ambientOcclusionEffect.render(); - } - // brad's frustum for debugging if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum) && whichCamera.getMode() != CAMERA_MODE_MIRROR) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), From c36e04c435ef9c5c4a6e43dad1badd0533f424bf Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Dec 2013 11:21:32 -0800 Subject: [PATCH 13/15] This should fix the erroneous persistence on startup. --- interface/src/renderer/GlowEffect.cpp | 10 +++++++--- interface/src/renderer/GlowEffect.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index fe46e02688..51128bf1c3 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -19,6 +19,7 @@ GlowEffect::GlowEffect() : _initialized(false), _renderMode(DIFFUSE_ADD_MODE), _isOddFrame(false), + _isFirstFrame(true), _intensity(0.0f) { } @@ -167,7 +168,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { newDiffusedFBO->bind(); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, oldDiffusedFBO->texture()); + glBindTexture(GL_TEXTURE_2D, _isFirstFrame ? 0 : oldDiffusedFBO->texture()); _diffuseProgram->bind(); QSize size = Application::getInstance()->getGLWidget()->size(); @@ -221,7 +222,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { maybeRelease(destFBO); } else { // _renderMode == BLUR_PERSIST_ADD_MODE - // render the secondary to the tertiary with horizontal blur and persistence + // render the secondary to the tertiary with vertical blur and persistence QOpenGLFramebufferObject* tertiaryFBO = Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject(); tertiaryFBO->bind(); @@ -229,7 +230,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { glEnable(GL_BLEND); glBlendFunc(GL_ONE_MINUS_CONSTANT_ALPHA, GL_CONSTANT_ALPHA); const float PERSISTENCE_SMOOTHING = 0.9f; - glBlendColor(0.0f, 0.0f, 0.0f, PERSISTENCE_SMOOTHING); + glBlendColor(0.0f, 0.0f, 0.0f, _isFirstFrame ? 0.0f : PERSISTENCE_SMOOTHING); glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture()); @@ -270,6 +271,8 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { glDepthMask(GL_TRUE); glBindTexture(GL_TEXTURE_2D, 0); + _isFirstFrame = false; + return destFBO; } @@ -292,6 +295,7 @@ void GlowEffect::cycleRenderMode() { qDebug() << "Glow mode: Diffuse/add\n"; break; } + _isFirstFrame = true; } Glower::Glower(float amount) { diff --git a/interface/src/renderer/GlowEffect.h b/interface/src/renderer/GlowEffect.h index 8168ae4374..65d3d6c8ce 100644 --- a/interface/src/renderer/GlowEffect.h +++ b/interface/src/renderer/GlowEffect.h @@ -66,6 +66,7 @@ private: bool _isEmpty; ///< set when nothing in the scene is currently glowing bool _isOddFrame; ///< controls the alternation between texture targets in diffuse add mode + bool _isFirstFrame; ///< for persistent modes, notes whether this is the first frame rendered float _intensity; QStack _intensityStack; From 2381b2bbaf6a1b672b6c422117e7bd7c1360b784 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Dec 2013 12:30:14 -0800 Subject: [PATCH 14/15] Get rid of initial glow. --- interface/src/renderer/GlowEffect.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index 51128bf1c3..3bd71b2dd4 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -167,16 +167,21 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } newDiffusedFBO->bind(); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, _isFirstFrame ? 0 : oldDiffusedFBO->texture()); + if (_isFirstFrame) { + glClear(GL_COLOR_BUFFER_BIT); - _diffuseProgram->bind(); - QSize size = Application::getInstance()->getGLWidget()->size(); - _diffuseProgram->setUniformValue(_diffusionScaleLocation, 1.0f / size.width(), 1.0f / size.height()); + } else { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, oldDiffusedFBO->texture()); + + _diffuseProgram->bind(); + QSize size = Application::getInstance()->getGLWidget()->size(); + _diffuseProgram->setUniformValue(_diffusionScaleLocation, 1.0f / size.width(), 1.0f / size.height()); - renderFullscreenQuad(); + renderFullscreenQuad(); - _diffuseProgram->release(); + _diffuseProgram->release(); + } newDiffusedFBO->release(); From 9616268da7192ac0ffcd53123e458c492b70c28d Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 9 Dec 2013 13:02:18 -0800 Subject: [PATCH 15/15] Improved full screen mirror view to allow leaning --- interface/src/Application.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5852656655..69224b75f6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -79,8 +79,10 @@ const int MIRROR_VIEW_TOP_PADDING = 5; const int MIRROR_VIEW_LEFT_PADDING = 10; const int MIRROR_VIEW_WIDTH = 265; const int MIRROR_VIEW_HEIGHT = 215; -const float MAX_ZOOM_DISTANCE = 0.3f; -const float MIN_ZOOM_DISTANCE = 2.0f; +const float MIRROR_FULLSCREEN_DISTANCE = 0.2f; +const float MIRROR_REARVIEW_DISTANCE = 0.3f; +const float MIRROR_REARVIEW_BODY_DISTANCE = 1.f; + void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) { fprintf(stdout, "%s", message.toLocal8Bit().constData()); @@ -376,11 +378,12 @@ void Application::paintGL() { } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { _myCamera.setTightness(0.0f); - _myCamera.setDistance(MAX_ZOOM_DISTANCE); - _myCamera.setTargetPosition(_myAvatar.getHead().calculateAverageEyePosition()); + float headHeight = _myAvatar.getHead().calculateAverageEyePosition().y - _myAvatar.getPosition().y; + _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _myAvatar.getScale()); + _myCamera.setTargetPosition(_myAvatar.getPosition() + glm::vec3(0, headHeight, 0)); _myCamera.setTargetRotation(_myAvatar.getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f))); } - + // Update camera position _myCamera.update( 1.f/_fps ); @@ -432,10 +435,10 @@ void Application::paintGL() { bool eyeRelativeCamera = false; if (_rearMirrorTools->getZoomLevel() == BODY) { - _mirrorCamera.setDistance(MIN_ZOOM_DISTANCE); + _mirrorCamera.setDistance(MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar.getScale()); _mirrorCamera.setTargetPosition(_myAvatar.getChestJointPosition()); } else { // HEAD zoom level - _mirrorCamera.setDistance(MAX_ZOOM_DISTANCE); + _mirrorCamera.setDistance(MIRROR_REARVIEW_DISTANCE * _myAvatar.getScale()); if (_myAvatar.getSkeletonModel().isActive() && _myAvatar.getHead().getFaceModel().isActive()) { // as a hack until we have a better way of dealing with coordinate precision issues, reposition the // face/body so that the average eye position lies at the origin