mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-08-08 06:27:11 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into view_frustum_work
This commit is contained in:
commit
ff996c9946
12 changed files with 381 additions and 703 deletions
|
@ -121,7 +121,7 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
// put her hand out so somebody can shake it
|
||||
eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2,
|
||||
0.25,
|
||||
0.32, // this is the same as the pelvis standing height (as of 4/26/13)
|
||||
eve.getPosition()[2] + 0.1));
|
||||
// read eve's audio data
|
||||
AudioInjector eveAudioInjector("eve.raw");
|
||||
|
|
|
@ -127,13 +127,9 @@ int audioCallback (const void *inputBuffer,
|
|||
|
||||
loudness /= BUFFER_LENGTH_SAMPLES;
|
||||
data->lastInputLoudness = loudness;
|
||||
|
||||
// If scope is turned on, copy input buffer to scope
|
||||
if (scope->getState()) {
|
||||
for (int i = 0; i < BUFFER_LENGTH_SAMPLES; i++) {
|
||||
scope->addData((float)inputLeft[i]/32767.0, 1, i);
|
||||
}
|
||||
}
|
||||
|
||||
// add data to the scope
|
||||
scope->addSamples(0, inputLeft, BUFFER_LENGTH_SAMPLES);
|
||||
|
||||
if (data->mixerAddress != 0) {
|
||||
sockaddr_in audioMixerSocket;
|
||||
|
@ -278,6 +274,10 @@ int audioCallback (const void *inputBuffer,
|
|||
outputRight[s] = rightSample;
|
||||
}
|
||||
|
||||
// add data to the scope
|
||||
scope->addSamples(1, outputLeft, PACKET_LENGTH_SAMPLES_PER_CHANNEL);
|
||||
scope->addSamples(2, outputRight, PACKET_LENGTH_SAMPLES_PER_CHANNEL);
|
||||
|
||||
ringBuffer->setNextOutput(ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES);
|
||||
|
||||
if (ringBuffer->getNextOutput() == ringBuffer->getBuffer() + RING_BUFFER_SAMPLES) {
|
||||
|
@ -330,8 +330,9 @@ void *receiveAudioViaUDP(void *args) {
|
|||
delete[] directory;
|
||||
delete[] filename;
|
||||
}
|
||||
|
||||
|
||||
while (!stopAudioReceiveThread) {
|
||||
|
||||
if (sharedAudioData->audioSocket->receive((void *)receivedData, &receivedBytes)) {
|
||||
|
||||
gettimeofday(¤tReceiveTime, NULL);
|
||||
|
|
|
@ -50,23 +50,22 @@ Avatar::Avatar(bool isMine) {
|
|||
|
||||
_orientation.setToIdentity();
|
||||
|
||||
_velocity = glm::vec3( 0.0, 0.0, 0.0 );
|
||||
_thrust = glm::vec3( 0.0, 0.0, 0.0 );
|
||||
_rotation = glm::quat( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
_bodyYaw = -90.0;
|
||||
_bodyPitch = 0.0;
|
||||
_bodyRoll = 0.0;
|
||||
_bodyYawDelta = 0.0;
|
||||
_mousePressed = false;
|
||||
_mode = AVATAR_MODE_STANDING;
|
||||
_isMine = isMine;
|
||||
_maxArmLength = 0.0;
|
||||
//_transmitterTimer = 0;
|
||||
_transmitterHz = 0.0;
|
||||
_transmitterPackets = 0;
|
||||
_speed = 0.0;
|
||||
_velocity = glm::vec3( 0.0, 0.0, 0.0 );
|
||||
_thrust = glm::vec3( 0.0, 0.0, 0.0 );
|
||||
_rotation = glm::quat( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
_bodyYaw = -90.0;
|
||||
_bodyPitch = 0.0;
|
||||
_bodyRoll = 0.0;
|
||||
_bodyYawDelta = 0.0;
|
||||
_mousePressed = false;
|
||||
_mode = AVATAR_MODE_STANDING;
|
||||
_isMine = isMine;
|
||||
_maxArmLength = 0.0;
|
||||
_transmitterHz = 0.0;
|
||||
_transmitterPackets = 0;
|
||||
_speed = 0.0;
|
||||
_pelvisStandingHeight = 0.0f;
|
||||
|
||||
_displayingHead = true;
|
||||
_TEST_bigSphereRadius = 0.3f;
|
||||
_TEST_bigSpherePosition = glm::vec3( 0.0f, _TEST_bigSphereRadius, 2.0f );
|
||||
|
||||
|
@ -329,11 +328,7 @@ void Avatar::simulate(float deltaTime) {
|
|||
Avatar *otherAvatar = (Avatar *)agent->getLinkedData();
|
||||
|
||||
// check for collisions with other avatars and respond
|
||||
updateAvatarCollisionDetectionAndResponse(otherAvatar->getPosition(),
|
||||
0.1,
|
||||
0.1,
|
||||
otherAvatar->getBodyUpDirection(),
|
||||
deltaTime);
|
||||
updateCollisionWithOtherAvatar(otherAvatar, deltaTime );
|
||||
|
||||
// test other avatar hand position for proximity
|
||||
glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position );
|
||||
|
@ -382,12 +377,8 @@ void Avatar::simulate(float deltaTime) {
|
|||
}
|
||||
|
||||
if (usingBigSphereCollisionTest) {
|
||||
// test for avatar collision response (using a big sphere :)
|
||||
updateAvatarCollisionDetectionAndResponse(_TEST_bigSpherePosition,
|
||||
_TEST_bigSphereRadius,
|
||||
_TEST_bigSphereRadius,
|
||||
glm::vec3( 0.0, 1.0, 0.0 ),
|
||||
deltaTime);
|
||||
// test for avatar collision response with the big sphere
|
||||
updateCollisionWithSphere( _TEST_bigSpherePosition, _TEST_bigSphereRadius, deltaTime );
|
||||
}
|
||||
|
||||
if ( AVATAR_GRAVITY ) {
|
||||
|
@ -541,31 +532,22 @@ void Avatar::simulate(float deltaTime) {
|
|||
}
|
||||
}
|
||||
|
||||
float Avatar::getGirth() {
|
||||
return COLLISION_BODY_RADIUS;
|
||||
}
|
||||
|
||||
float Avatar::getHeight() {
|
||||
return COLLISION_HEIGHT;
|
||||
return _height;
|
||||
}
|
||||
|
||||
// This is a workspace for testing avatar body collision detection and response
|
||||
void Avatar::updateAvatarCollisionDetectionAndResponse(glm::vec3 collisionPosition,
|
||||
float collisionGirth,
|
||||
float collisionHeight,
|
||||
glm::vec3 collisionUpVector,
|
||||
float deltaTime) {
|
||||
|
||||
|
||||
void Avatar::updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime ) {
|
||||
float myBodyApproximateBoundingRadius = 1.0f;
|
||||
glm::vec3 vectorFromMyBodyToBigSphere(_position - collisionPosition);
|
||||
glm::vec3 vectorFromMyBodyToBigSphere(_position - position);
|
||||
bool jointCollision = false;
|
||||
|
||||
float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere);
|
||||
if ( distanceToBigSphere < myBodyApproximateBoundingRadius + collisionGirth ) {
|
||||
if ( distanceToBigSphere < myBodyApproximateBoundingRadius + radius ) {
|
||||
for (int b = 0; b < NUM_AVATAR_BONES; b++) {
|
||||
glm::vec3 vectorFromJointToBigSphereCenter(_bone[b].springyPosition - collisionPosition);
|
||||
glm::vec3 vectorFromJointToBigSphereCenter(_bone[b].springyPosition - position);
|
||||
float distanceToBigSphereCenter = glm::length(vectorFromJointToBigSphereCenter);
|
||||
float combinedRadius = _bone[b].radius + collisionGirth;
|
||||
float combinedRadius = _bone[b].radius + radius;
|
||||
|
||||
if ( distanceToBigSphereCenter < combinedRadius ) {
|
||||
jointCollision = true;
|
||||
|
@ -577,7 +559,7 @@ void Avatar::updateAvatarCollisionDetectionAndResponse(glm::vec3 collisionPositi
|
|||
|
||||
_bone[b].springyVelocity += collisionForce * 30.0f * deltaTime;
|
||||
_velocity += collisionForce * 100.0f * deltaTime;
|
||||
_bone[b].springyPosition = collisionPosition + directionVector * combinedRadius;
|
||||
_bone[b].springyPosition = position + directionVector * combinedRadius;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -591,6 +573,50 @@ void Avatar::updateAvatarCollisionDetectionAndResponse(glm::vec3 collisionPositi
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//detect collisions with other avatars and respond
|
||||
void Avatar::updateCollisionWithOtherAvatar( Avatar * otherAvatar, float deltaTime ) {
|
||||
|
||||
// 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 ) {
|
||||
|
||||
// loop through the bones of each avatar to check for every possible collision
|
||||
for (int b=1; b<NUM_AVATAR_BONES; b++) {
|
||||
for (int o=b+1; o<NUM_AVATAR_BONES; o++) {
|
||||
|
||||
glm::vec3 vectorBetweenJoints(_bone[b].springyPosition - otherAvatar->_bone[o].springyPosition);
|
||||
float distanceBetweenJoints = glm::length(vectorBetweenJoints);
|
||||
|
||||
// to avoid divide by zero
|
||||
if ( distanceBetweenJoints > 0.0 ) {
|
||||
float combinedRadius = _bone[b].radius + otherAvatar->_bone[o].radius;
|
||||
|
||||
// check for collision
|
||||
if ( distanceBetweenJoints < combinedRadius * COLLISION_RADIUS_SCALAR) {
|
||||
glm::vec3 directionVector = vectorBetweenJoints / distanceBetweenJoints;
|
||||
|
||||
// push ball away from colliding other ball and puch avatar body (_velocity) as well
|
||||
_bone[b].springyVelocity += directionVector * COLLISION_BALL_FORCE * deltaTime;
|
||||
_velocity += directionVector * COLLISION_BODY_FORCE * deltaTime;
|
||||
|
||||
// apply fruction to _velocity
|
||||
float momentum = 1.0 - COLLISION_FRICTION * deltaTime;
|
||||
if ( momentum < 0.0 ) { momentum = 0.0;}
|
||||
_velocity *= momentum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Avatar::setDisplayingHead( bool displayingHead ) {
|
||||
_displayingHead = displayingHead;
|
||||
}
|
||||
|
||||
|
||||
void Avatar::render(bool lookingInMirror) {
|
||||
|
||||
/*
|
||||
|
@ -618,8 +644,10 @@ void Avatar::render(bool lookingInMirror) {
|
|||
renderBody();
|
||||
|
||||
// render head
|
||||
renderHead(lookingInMirror);
|
||||
|
||||
if (_displayingHead) {
|
||||
renderHead(lookingInMirror);
|
||||
}
|
||||
|
||||
// if this is my avatar, then render my interactions with the other avatar
|
||||
if ( _isMine )
|
||||
{
|
||||
|
@ -959,12 +987,22 @@ void Avatar::initializeSkeleton() {
|
|||
calculateBoneLengths();
|
||||
|
||||
_pelvisStandingHeight =
|
||||
_bone[ AVATAR_BONE_PELVIS_SPINE ].length +
|
||||
_bone[ AVATAR_BONE_LEFT_THIGH ].length +
|
||||
_bone[ AVATAR_BONE_LEFT_FOOT ].radius +
|
||||
_bone[ AVATAR_BONE_LEFT_SHIN ].length +
|
||||
_bone[ AVATAR_BONE_LEFT_FOOT ].length +
|
||||
_bone[ AVATAR_BONE_RIGHT_FOOT ].radius;
|
||||
|
||||
_bone[ AVATAR_BONE_LEFT_THIGH ].length +
|
||||
_bone[ AVATAR_BONE_PELVIS_SPINE ].length;
|
||||
//printf( "_pelvisStandingHeight = %f\n", _pelvisStandingHeight );
|
||||
|
||||
_height =
|
||||
(
|
||||
_pelvisStandingHeight +
|
||||
_bone[ AVATAR_BONE_MID_SPINE ].length +
|
||||
_bone[ AVATAR_BONE_CHEST_SPINE].length +
|
||||
_bone[ AVATAR_BONE_NECK ].length +
|
||||
_bone[ AVATAR_BONE_HEAD ].length +
|
||||
_bone[ AVATAR_BONE_HEAD ].radius
|
||||
);
|
||||
|
||||
// generate world positions
|
||||
updateSkeleton();
|
||||
}
|
||||
|
@ -1131,25 +1169,27 @@ void Avatar::renderBody() {
|
|||
|
||||
// Render bone positions as spheres
|
||||
for (int b = 0; b < NUM_AVATAR_BONES; b++) {
|
||||
//renderBoneAsBlock( (AvatarBoneID)b);
|
||||
|
||||
//render bone orientation
|
||||
//renderOrientationDirections( _bone[b].springyPosition, _bone[b].orientation, _bone[b].radius * 2.0 );
|
||||
|
||||
if ( _usingBodySprings ) {
|
||||
glColor3fv( skinColor );
|
||||
glPushMatrix();
|
||||
glTranslatef( _bone[b].springyPosition.x, _bone[b].springyPosition.y, _bone[b].springyPosition.z );
|
||||
glutSolidSphere( _bone[b].radius, 20.0f, 20.0f );
|
||||
glPopMatrix();
|
||||
}
|
||||
else {
|
||||
glColor3fv( skinColor );
|
||||
glPushMatrix();
|
||||
glTranslatef( _bone[b].position.x, _bone[b].position.y, _bone[b].position.z );
|
||||
glutSolidSphere( _bone[b].radius, 20.0f, 20.0f );
|
||||
glPopMatrix();
|
||||
}
|
||||
if ( b != AVATAR_BONE_HEAD ) { // the head is rendered as a special case in "renderHead"
|
||||
|
||||
//render bone orientation
|
||||
//renderOrientationDirections( _bone[b].springyPosition, _bone[b].orientation, _bone[b].radius * 2.0 );
|
||||
|
||||
if ( _usingBodySprings ) {
|
||||
glColor3fv( skinColor );
|
||||
glPushMatrix();
|
||||
glTranslatef( _bone[b].springyPosition.x, _bone[b].springyPosition.y, _bone[b].springyPosition.z );
|
||||
glutSolidSphere( _bone[b].radius, 20.0f, 20.0f );
|
||||
glPopMatrix();
|
||||
}
|
||||
else {
|
||||
glColor3fv( skinColor );
|
||||
glPushMatrix();
|
||||
glTranslatef( _bone[b].position.x, _bone[b].position.y, _bone[b].position.z );
|
||||
glutSolidSphere( _bone[b].radius, 20.0f, 20.0f );
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render lines connecting the bone positions
|
||||
|
@ -1194,18 +1234,6 @@ void Avatar::renderBody() {
|
|||
}
|
||||
}
|
||||
|
||||
void Avatar::renderBoneAsBlock( AvatarBoneID b ) {
|
||||
glColor3fv( skinColor );
|
||||
glPushMatrix();
|
||||
glTranslatef( _bone[b].springyPosition.x, _bone[b].springyPosition.y, _bone[b].springyPosition.z );
|
||||
glScalef( _bone[b].radius, _bone[b].length, _bone[b].radius );
|
||||
glRotatef(_bone[b].yaw, 0, 1, 0 );
|
||||
glRotatef(_bone[b].pitch, 1, 0, 0 );
|
||||
glRotatef(_bone[b].roll, 0, 0, 1 );
|
||||
glutSolidCube(1.0);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void Avatar::SetNewHeadTarget(float pitch, float yaw) {
|
||||
_head.pitchTarget = pitch;
|
||||
_head.yawTarget = yaw;
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <AvatarData.h>
|
||||
#include <Orientation.h>
|
||||
|
||||
#include "Field.h"
|
||||
#include "world.h"
|
||||
#include "AvatarTouch.h"
|
||||
|
||||
|
@ -32,11 +31,29 @@ const float YAW_MAG = 500.0; //JJV - changed from 300.0;
|
|||
const float TEST_YAW_DECAY = 5.0;
|
||||
const float LIN_VEL_DECAY = 5.0;
|
||||
|
||||
const float COLLISION_BODY_RADIUS = 0.1;
|
||||
const float COLLISION_HEIGHT = 1.5;
|
||||
const float COLLISION_FRICTION = 0.5;
|
||||
const float COLLISION_RADIUS_SCALAR = 1.8;
|
||||
const float COLLISION_BALL_FORCE = 0.1;
|
||||
const float COLLISION_BODY_FORCE = 3.0;
|
||||
|
||||
enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
|
||||
|
||||
|
||||
|
||||
enum DriveKeys
|
||||
{
|
||||
FWD = 0,
|
||||
BACK,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
UP,
|
||||
DOWN,
|
||||
ROT_LEFT,
|
||||
ROT_RIGHT,
|
||||
MAX_DRIVE_KEYS
|
||||
};
|
||||
|
||||
/*
|
||||
#define FWD 0
|
||||
#define BACK 1
|
||||
#define LEFT 2
|
||||
|
@ -46,8 +63,9 @@ enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
|
|||
#define ROT_LEFT 6
|
||||
#define ROT_RIGHT 7
|
||||
#define MAX_DRIVE_KEYS 8
|
||||
*/
|
||||
|
||||
#define MAX_OTHER_AVATARS 10 // temporary - for testing purposes!
|
||||
//#define MAX_OTHER_AVATARS 10 // temporary - for testing purposes!
|
||||
|
||||
|
||||
|
||||
|
@ -89,16 +107,8 @@ enum AvatarBoneID
|
|||
NUM_AVATAR_BONES
|
||||
};
|
||||
|
||||
struct AvatarCollisionElipsoid
|
||||
{
|
||||
bool colliding;
|
||||
glm::vec3 position;
|
||||
float girth;
|
||||
float height;
|
||||
glm::vec3 upVector;
|
||||
};
|
||||
|
||||
struct AvatarHandHolding
|
||||
struct AvatarHandHolding //think of this as one half of a distributed spring :)
|
||||
{
|
||||
glm::vec3 position;
|
||||
glm::vec3 velocity;
|
||||
|
@ -111,7 +121,7 @@ struct AvatarBone
|
|||
glm::vec3 position; // the position at the "end" of the bone
|
||||
glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose"
|
||||
glm::vec3 springyPosition; // used for special effects (a 'flexible' variant of position)
|
||||
glm::dvec3 springyVelocity; // used for special effects ( the velocity of the springy position)
|
||||
glm::vec3 springyVelocity; // used for special effects ( the velocity of the springy position)
|
||||
float springBodyTightness; // how tightly the springy position tries to stay on the position
|
||||
glm::quat rotation; // this will eventually replace yaw, pitch and roll (and maybe orientation)
|
||||
float yaw; // the yaw Euler angle of the bone rotation off the parent
|
||||
|
@ -181,6 +191,8 @@ public:
|
|||
float getBodyYaw() {return _bodyYaw;};
|
||||
void addBodyYaw(float y) {_bodyYaw += y;};
|
||||
|
||||
bool getIsNearInteractingOther() { return _interactingOtherIsNearby; }
|
||||
|
||||
float getAbsoluteHeadYaw() const;
|
||||
void setLeanForward(float dist);
|
||||
void setLeanSideways(float dist);
|
||||
|
@ -208,6 +220,7 @@ public:
|
|||
void setHandMovementValues( glm::vec3 movement );
|
||||
void updateHandMovement( float deltaTime );
|
||||
void updateArmIKAndConstraints( float deltaTime );
|
||||
void setDisplayingHead( bool displayingHead );
|
||||
|
||||
float getAverageLoudness() {return _head.averageLoudness;};
|
||||
void setAverageLoudness(float al) {_head.averageLoudness = al;};
|
||||
|
@ -260,25 +273,20 @@ private:
|
|||
Avatar* _interactingOther;
|
||||
bool _interactingOtherIsNearby;
|
||||
float _pelvisStandingHeight;
|
||||
float _height;
|
||||
Balls* _balls;
|
||||
AvatarTouch _avatarTouch;
|
||||
bool _displayingHead; // should be false if in first-person view
|
||||
|
||||
// private methods...
|
||||
void initializeSkeleton();
|
||||
void updateSkeleton();
|
||||
void initializeBodySprings();
|
||||
void updateBodySprings( float deltaTime );
|
||||
void calculateBoneLengths();
|
||||
void readSensors();
|
||||
void renderBoneAsBlock( AvatarBoneID b );
|
||||
void updateAvatarCollisionDetectionAndResponse
|
||||
(
|
||||
glm::vec3 collisionPosition,
|
||||
float collisionGirth,
|
||||
float collisionHeight,
|
||||
glm::vec3 collisionUpVector,
|
||||
float deltaTime
|
||||
);
|
||||
// private methods...
|
||||
void initializeSkeleton();
|
||||
void updateSkeleton();
|
||||
void initializeBodySprings();
|
||||
void updateBodySprings( float deltaTime );
|
||||
void calculateBoneLengths();
|
||||
void readSensors();
|
||||
void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
|
||||
void updateCollisionWithOtherAvatar( Avatar * other, float deltaTime );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,10 +15,10 @@ Balls::Balls(int numberOfBalls) {
|
|||
_numberOfBalls = numberOfBalls;
|
||||
_balls = new Ball[_numberOfBalls];
|
||||
for (unsigned int i = 0; i < _numberOfBalls; ++i) {
|
||||
_balls[i].position = glm::vec3(1.0 + randFloat()*0.5,
|
||||
0.5 + randFloat()*0.5,
|
||||
1.0 + randFloat()*0.5);
|
||||
_balls[i].radius = 0.02 + randFloat()*0.06;
|
||||
_balls[i].position = glm::vec3(1.0 + randFloat() * 0.5,
|
||||
0.5 + randFloat() * 0.5,
|
||||
1.0 + randFloat() * 0.5);
|
||||
_balls[i].radius = 0.02 + randFloat() * 0.06;
|
||||
for (unsigned int j = 0; j < NUMBER_SPRINGS; ++j) {
|
||||
_balls[i].links[j] = rand() % (numberOfBalls + 1);
|
||||
if (_balls[i].links[j]-1 == i) { _balls[i].links[j] = 0; }
|
||||
|
@ -42,7 +42,7 @@ void Balls::render() {
|
|||
|
||||
// Render springs
|
||||
if (RENDER_SPRINGS) {
|
||||
glColor3f(0.74,0.91,0.62);
|
||||
glColor3f(0.74, 0.91, 0.62);
|
||||
for (unsigned int i = 0; i < _numberOfBalls; ++i) {
|
||||
glBegin(GL_LINES);
|
||||
for (unsigned int j = 0; j < NUMBER_SPRINGS; ++j) {
|
||||
|
@ -73,7 +73,7 @@ void Balls::simulate(float deltaTime) {
|
|||
_balls[i].position += _balls[i].velocity * deltaTime;
|
||||
|
||||
// Drag: decay velocity
|
||||
_balls[i].velocity *= (1.f - CONSTANT_VELOCITY_DAMPING*deltaTime);
|
||||
_balls[i].velocity *= (1.f - CONSTANT_VELOCITY_DAMPING * deltaTime);
|
||||
|
||||
// Add noise
|
||||
_balls[i].velocity += glm::vec3((randFloat() - 0.5) * NOISE_SCALE,
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
//
|
||||
// Cloud.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Philip Rosedale on 11/17/12.
|
||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <InterfaceConfig.h>
|
||||
#include "Cloud.h"
|
||||
#include "Util.h"
|
||||
|
||||
#define COLOR_MIN 0.2f // minimum R/G/B value at 0,0,0 - also needs setting in field.cpp
|
||||
|
||||
Cloud::Cloud(int num,
|
||||
glm::vec3 box,
|
||||
int wrap) {
|
||||
// Create and initialize particles
|
||||
unsigned int i;
|
||||
bounds = box;
|
||||
count = num;
|
||||
wrapBounds = wrap != 0;
|
||||
particles = new Particle[count];
|
||||
field = new Field();
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
float x = randFloat()*box.x;
|
||||
float y = randFloat()*box.y;
|
||||
float z = randFloat()*box.z;
|
||||
particles[i].position.x = x;
|
||||
particles[i].position.y = y;
|
||||
particles[i].position.z = z;
|
||||
|
||||
particles[i].velocity.x = randFloat() - 0.5f;
|
||||
particles[i].velocity.y = randFloat() - 0.5f;
|
||||
particles[i].velocity.z = randFloat() - 0.5f;
|
||||
|
||||
float color_mult = 1 - COLOR_MIN;
|
||||
particles[i].color = glm::vec3(x*color_mult/WORLD_SIZE + COLOR_MIN,
|
||||
y*color_mult/WORLD_SIZE + COLOR_MIN,
|
||||
z*color_mult/WORLD_SIZE + COLOR_MIN);
|
||||
}
|
||||
}
|
||||
|
||||
void Cloud::render() {
|
||||
|
||||
float particleAttenuationQuadratic[] = { 0.0f, 0.0f, 2.0f };
|
||||
float particleAttenuationConstant[] = { 1.0f, 0.0f, 0.0f };
|
||||
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
||||
float maxSize = 0.0f;
|
||||
glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize );
|
||||
glPointSize( maxSize );
|
||||
|
||||
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, particleAttenuationQuadratic );
|
||||
glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize );
|
||||
glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 0.001f );
|
||||
|
||||
glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
|
||||
glEnable( GL_POINT_SPRITE_ARB );
|
||||
glBegin( GL_POINTS );
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
glColor3f(particles[i].color.x,
|
||||
particles[i].color.y,
|
||||
particles[i].color.z);
|
||||
glVertex3f(particles[i].position.x,
|
||||
particles[i].position.y,
|
||||
particles[i].position.z);
|
||||
}
|
||||
glEnd();
|
||||
glDisable( GL_POINT_SPRITE_ARB );
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
|
||||
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, particleAttenuationConstant );
|
||||
glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, 1.0f );
|
||||
glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 0.0f );
|
||||
}
|
||||
|
||||
void Cloud::simulate (float deltaTime) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < count; ++i) {
|
||||
|
||||
// Update position
|
||||
particles[i].position += particles[i].velocity*deltaTime;
|
||||
//particles[i].position += particles[i].velocity;
|
||||
|
||||
// Decay Velocity (Drag)
|
||||
const float CONSTANT_DAMPING = 0.5;
|
||||
particles[i].velocity *= (1.f - CONSTANT_DAMPING*deltaTime);
|
||||
|
||||
// Interact with Field
|
||||
const float FIELD_COUPLE = 0.005f; //0.0000001;
|
||||
field->interact(deltaTime, &particles[i].position, &particles[i].velocity, &particles[i].color, FIELD_COUPLE);
|
||||
|
||||
// Update color to velocity
|
||||
particles[i].color = (glm::normalize(particles[i].velocity)*0.5f);
|
||||
particles[i].color += 0.5f;
|
||||
|
||||
|
||||
// Bounce or Wrap
|
||||
if (wrapBounds) {
|
||||
// wrap around bounds
|
||||
if (particles[i].position.x > bounds.x)
|
||||
particles[i].position.x -= bounds.x;
|
||||
else if (particles[i].position.x < 0.0f)
|
||||
particles[i].position.x += bounds.x;
|
||||
|
||||
if (particles[i].position.y > bounds.y)
|
||||
particles[i].position.y -= bounds.y;
|
||||
else if (particles[i].position.y < 0.0f)
|
||||
particles[i].position.y += bounds.y;
|
||||
|
||||
if (particles[i].position.z > bounds.z)
|
||||
particles[i].position.z -= bounds.z;
|
||||
else if (particles[i].position.z < 0.0f)
|
||||
particles[i].position.z += bounds.z;
|
||||
} else {
|
||||
// Bounce at bounds
|
||||
if (particles[i].position.x > bounds.x
|
||||
|| particles[i].position.x < 0.f) {
|
||||
if (particles[i].position.x > bounds.x) particles[i].position.x = bounds.x;
|
||||
else particles[i].position.x = 0.f;
|
||||
particles[i].velocity.x *= -1;
|
||||
}
|
||||
if (particles[i].position.y > bounds.y
|
||||
|| particles[i].position.y < 0.f) {
|
||||
if (particles[i].position.y > bounds.y) particles[i].position.y = bounds.y;
|
||||
else particles[i].position.y = 0.f;
|
||||
particles[i].velocity.y *= -1;
|
||||
}
|
||||
if (particles[i].position.z > bounds.z
|
||||
|| particles[i].position.z < 0.f) {
|
||||
if (particles[i].position.z > bounds.z) particles[i].position.z = bounds.z;
|
||||
else particles[i].position.z = 0.f;
|
||||
particles[i].velocity.z *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
//
|
||||
// Cloud.h
|
||||
// interface
|
||||
//
|
||||
// Created by Philip Rosedale on 11/17/12.
|
||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__Cloud__
|
||||
#define __interface__Cloud__
|
||||
|
||||
#include "Field.h"
|
||||
|
||||
class Cloud {
|
||||
public:
|
||||
Cloud(int num,
|
||||
glm::vec3 box,
|
||||
int wrap);
|
||||
|
||||
void simulate(float deltaTime);
|
||||
void render();
|
||||
|
||||
private:
|
||||
struct Particle {
|
||||
glm::vec3 position, velocity, color;
|
||||
} *particles;
|
||||
|
||||
unsigned int count;
|
||||
glm::vec3 bounds;
|
||||
bool wrapBounds;
|
||||
Field *field;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,229 +0,0 @@
|
|||
//
|
||||
// Field.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Philip Rosedale on 8/23/12.
|
||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Field.h"
|
||||
|
||||
#define FIELD_SCALE 0.00050
|
||||
#define FIELD_SCALEf 0.00050f
|
||||
#define COLOR_DRIFT_RATE 0.001f // per-frame drift of particle color towards field element color
|
||||
#define COLOR_MIN 0.2f // minimum R/G/B value at 0,0,0 - also needs setting in cloud.cpp
|
||||
|
||||
#define USE_SCALAR 0
|
||||
|
||||
// A vector-valued field over an array of elements arranged as a 3D lattice
|
||||
|
||||
int Field::value(float *value, float *pos)
|
||||
// sets the vector value (3 floats) to field value at location pos in space.
|
||||
// returns zero if the location is outside world bounds
|
||||
{
|
||||
int index = (int)(pos[0]/WORLD_SIZE*10.0) +
|
||||
(int)(pos[1]/WORLD_SIZE*10.0)*10 +
|
||||
(int)(pos[2]/WORLD_SIZE*10.0)*100;
|
||||
if ((index >= 0) && (index < FIELD_ELEMENTS))
|
||||
{
|
||||
value[0] = field[index].val.x;
|
||||
value[1] = field[index].val.y;
|
||||
value[2] = field[index].val.z;
|
||||
return 1;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
Field::Field()
|
||||
// Initializes the field to some random values
|
||||
{
|
||||
int i;
|
||||
float fx, fy, fz;
|
||||
for (i = 0; i < FIELD_ELEMENTS; i++)
|
||||
{
|
||||
field[i].val.x = (randFloat() - 0.5f)*FIELD_SCALEf;
|
||||
field[i].val.y = (randFloat() - 0.5f)*FIELD_SCALEf;
|
||||
field[i].val.z = (randFloat() - 0.5f)*FIELD_SCALEf;
|
||||
field[i].scalar = 0;
|
||||
// Record center point for this field cell
|
||||
fx = static_cast<float>(i % 10);
|
||||
fy = static_cast<float>(i%100 / 10);
|
||||
fz = static_cast<float>(i / 100);
|
||||
field[i].center.x = fx + 0.5f;
|
||||
field[i].center.y = fy + 0.5f;
|
||||
field[i].center.z = fz + 0.5f;
|
||||
|
||||
// and set up the RGB values for each field element.
|
||||
float color_mult = 1 - COLOR_MIN;
|
||||
fieldcolors[i].rgb = glm::vec3(((i%10)*(color_mult/10.0f)) + COLOR_MIN,
|
||||
((i%100)*(color_mult/100.0f)) + COLOR_MIN,
|
||||
(i*(color_mult/1000.0f)) + COLOR_MIN);
|
||||
}
|
||||
}
|
||||
|
||||
void Field::add(float* add, float *pos)
|
||||
// At location loc, add vector add to the field values
|
||||
{
|
||||
int index = (int)(pos[0]/WORLD_SIZE*10.0) +
|
||||
(int)(pos[1]/WORLD_SIZE*10.0)*10 +
|
||||
(int)(pos[2]/WORLD_SIZE*10.0)*100;
|
||||
if ((index >= 0) && (index < FIELD_ELEMENTS))
|
||||
{
|
||||
field[index].val.x += add[0];
|
||||
field[index].val.y += add[1];
|
||||
field[index].val.z += add[2];
|
||||
}
|
||||
}
|
||||
|
||||
void Field::interact(float dt, glm::vec3 * pos, glm::vec3 * vel, glm::vec3 * color, float coupling) {
|
||||
|
||||
int index = (int)(pos->x/WORLD_SIZE*10.0) +
|
||||
(int)(pos->y/WORLD_SIZE*10.0)*10 +
|
||||
(int)(pos->z/WORLD_SIZE*10.0)*100;
|
||||
if ((index >= 0) && (index < FIELD_ELEMENTS)) {
|
||||
//
|
||||
// Vector Coupling with particle velocity
|
||||
//
|
||||
*vel += field[index].val*dt; // Particle influenced by field
|
||||
|
||||
glm::vec3 temp = *vel*dt; // Field influenced by particle
|
||||
temp *= coupling;
|
||||
field[index].val += temp;
|
||||
//
|
||||
// Scalar coupling: Damp particle as function of local density
|
||||
//
|
||||
|
||||
if (USE_SCALAR) {
|
||||
//*vel *= (1.f + field[index].scalar*0.01*dt);
|
||||
const float SCALAR_PARTICLE_ADD = 1.0;
|
||||
field[index].scalar += SCALAR_PARTICLE_ADD*dt;
|
||||
}
|
||||
|
||||
|
||||
// add a fraction of the field color to the particle color
|
||||
//*color = (*color * (1 - COLOR_DRIFT_RATE)) + (fieldcolors[index].rgb * COLOR_DRIFT_RATE);
|
||||
}
|
||||
}
|
||||
|
||||
void Field::avg_neighbors(int index, glm::vec3 * result) {
|
||||
// Given index to field element i, return neighbor field values
|
||||
glm::vec3 neighbors(0,0,0);
|
||||
|
||||
int x,y,z;
|
||||
x = (int)(index % 10);
|
||||
y = (int)(index%100 / 10);
|
||||
z = (int)(index / 100);
|
||||
|
||||
neighbors += field[(x+1)%10 + y*10 + z*100].val;
|
||||
neighbors += field[(x-1)%10 + y*10 + z*100].val;
|
||||
|
||||
neighbors += field[x + ((y+1)%10)*10 + z*100].val;
|
||||
neighbors += field[x + ((y-1)%10)*10 + z*100].val;
|
||||
|
||||
neighbors += field[x + y*10 + ((z+1)%10)*100].val;
|
||||
neighbors += field[x%10 + y*10 + ((z-1)%10)*100].val;
|
||||
|
||||
neighbors /= 6;
|
||||
result->x = neighbors.x;
|
||||
result->y = neighbors.y;
|
||||
result->z = neighbors.z;
|
||||
|
||||
}
|
||||
|
||||
void Field::simulate(float dt) {
|
||||
glm::vec3 neighbors, add, diff;
|
||||
float size, distance;
|
||||
int i, j;
|
||||
for (i = 0; i < FIELD_ELEMENTS; i++)
|
||||
{
|
||||
if (0) { //(randFloat() > 0.01) {
|
||||
avg_neighbors(i, &neighbors);
|
||||
size = powf(field[i].val.x*field[i].val.x +
|
||||
field[i].val.y*field[i].val.y +
|
||||
field[i].val.z*field[i].val.z, 0.5);
|
||||
|
||||
neighbors *= 0.0001;
|
||||
field[i].val = glm::normalize(field[i].val);
|
||||
field[i].val *= size * 0.99;
|
||||
add = glm::normalize(neighbors);
|
||||
add *= size * 0.01;
|
||||
field[i].val += add;
|
||||
}
|
||||
else {
|
||||
const float CONSTANT_DAMPING = 0.5;
|
||||
const float CONSTANT_SCALAR_DAMPING = 2.5;
|
||||
field[i].val *= (1.f - CONSTANT_DAMPING*dt);
|
||||
field[i].scalar *= (1.f - CONSTANT_SCALAR_DAMPING*dt);
|
||||
}
|
||||
|
||||
if (USE_SCALAR) {
|
||||
//
|
||||
// Compute a field value from sum of all other field values (electrostatics, etc)
|
||||
//
|
||||
field[i].fld.x = field[i].fld.y = field[i].fld.z = 0;
|
||||
for (j = 0; j < FIELD_ELEMENTS; j++)
|
||||
{
|
||||
if (i != j) {
|
||||
// Compute vector field from scalar densities
|
||||
diff = field[j].center - field[i].center;
|
||||
distance = glm::length(diff);
|
||||
diff = glm::normalize(diff);
|
||||
field[i].fld += diff*field[j].scalar*(1/distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Field::render()
|
||||
// Render the field lines
|
||||
{
|
||||
int i;
|
||||
float fx, fy, fz;
|
||||
float scale_view = 0.1f;
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glBegin(GL_LINES);
|
||||
for (i = 0; i < FIELD_ELEMENTS; i++)
|
||||
{
|
||||
fx = field[i].center.x;
|
||||
fy = field[i].center.y;
|
||||
fz = field[i].center.z;
|
||||
|
||||
glColor3f(0, 1, 0);
|
||||
glVertex3f(fx, fy, fz);
|
||||
glVertex3f(fx + field[i].val.x*scale_view,
|
||||
fy + field[i].val.y*scale_view,
|
||||
fz + field[i].val.z*scale_view);
|
||||
if (USE_SCALAR) {
|
||||
glColor3f(1, 0, 0);
|
||||
glVertex3f(fx, fy, fz);
|
||||
glVertex3f(fx, fy+field[i].scalar*0.01f, fz);
|
||||
glColor3f(1, 1, 0);
|
||||
glVertex3f(fx, fy, fz);
|
||||
glVertex3f(fx + field[i].fld.x*0.0001f,
|
||||
fy + field[i].fld.y*0.0001f,
|
||||
fz + field[i].fld.z*0.0001f);
|
||||
}
|
||||
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glColor3f(0, 1, 0);
|
||||
glPointSize(4.0);
|
||||
glEnable(GL_POINT_SMOOTH);
|
||||
glBegin(GL_POINTS);
|
||||
|
||||
for (i = 0; i < FIELD_ELEMENTS; i++)
|
||||
{
|
||||
fx = static_cast<float>(i % 10);
|
||||
fy = static_cast<float>(i%100 / 10);
|
||||
fz = static_cast<float>(i / 100);
|
||||
|
||||
glVertex3f(fx, fy, fz);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
//
|
||||
// Field.h
|
||||
// interface
|
||||
//
|
||||
// Created by Philip Rosedale on 8/23/12.
|
||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__Field__
|
||||
#define __interface__Field__
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include "InterfaceConfig.h"
|
||||
#include "world.h"
|
||||
#include "Util.h"
|
||||
|
||||
// Field is a lattice of vectors uniformly distributed FIELD_ELEMENTS^(1/3) on side
|
||||
const int FIELD_ELEMENTS = 1000;
|
||||
|
||||
class Field {
|
||||
public:
|
||||
struct FieldElement {
|
||||
glm::vec3 val;
|
||||
glm::vec3 center;
|
||||
glm::vec3 fld;
|
||||
float scalar;
|
||||
} field[FIELD_ELEMENTS];
|
||||
|
||||
// Pre-calculated RGB values for each field element
|
||||
struct FieldColor {
|
||||
glm::vec3 rgb;
|
||||
} fieldcolors[FIELD_ELEMENTS];
|
||||
|
||||
Field();
|
||||
int value(float *ret, float *pos);
|
||||
void render();
|
||||
void add(float* add, float *loc);
|
||||
void interact(float dt, glm::vec3 * pos, glm::vec3 * vel, glm::vec3 * color, float coupling);
|
||||
void simulate(float dt);
|
||||
glm::vec3 hsv2rgb(glm::vec3 in);
|
||||
private:
|
||||
void avg_neighbors(int index, glm::vec3 * result);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -8,38 +8,123 @@
|
|||
|
||||
#include "Oscilloscope.h"
|
||||
|
||||
Oscilloscope::Oscilloscope(int w,
|
||||
int h, bool isOn) {
|
||||
width = w;
|
||||
height = h;
|
||||
data1 = new float[width];
|
||||
data2 = new float[width];
|
||||
for (int i = 0; i < width; i++) {
|
||||
data1[i] = 0.0;
|
||||
data2[i] = 0.0;
|
||||
#include "InterfaceConfig.h"
|
||||
#include <limits>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
// Reimplemented 4/26/13 (tosh) - don't blame Philip for bugs
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace { // everything in here only exists while compiling this .cpp file
|
||||
|
||||
// one sample buffer per channel
|
||||
unsigned const N_SAMPLES_ALLOC = Oscilloscope::MAX_SAMPLES * Oscilloscope::MAX_CHANNELS;
|
||||
|
||||
// adding an x-coordinate yields twice the amount of vertices
|
||||
unsigned const MAX_COORDS = Oscilloscope::MAX_SAMPLES * 2;
|
||||
unsigned const N_COORDS_ALLOC = MAX_COORDS * Oscilloscope::MAX_CHANNELS;
|
||||
|
||||
unsigned const N_ALLOC_TOTAL = N_SAMPLES_ALLOC + N_COORDS_ALLOC;
|
||||
}
|
||||
|
||||
|
||||
Oscilloscope::Oscilloscope(int w, int h, bool isEnabled) :
|
||||
_valWidth(w), _valHeight(h),
|
||||
_arrSamples(0l), _arrVertices(0l),
|
||||
_valLowpass(0.4f), _valDownsample(3),
|
||||
enabled(isEnabled), inputPaused(false) {
|
||||
|
||||
// allocate enough space for the sample data and to turn it into
|
||||
// vertices and since they're all 'short', do so in one shot
|
||||
_arrSamples = new short[N_ALLOC_TOTAL];
|
||||
memset(_arrSamples, 0, N_ALLOC_TOTAL * sizeof(short));
|
||||
_arrVertices = _arrSamples + N_SAMPLES_ALLOC;
|
||||
|
||||
// initialize write positions
|
||||
for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) {
|
||||
_arrWritePos[ch] = MAX_SAMPLES * ch;
|
||||
}
|
||||
state = isOn;
|
||||
current_sample = 0;
|
||||
}
|
||||
|
||||
void Oscilloscope::addData(float d, int channel, int position) {
|
||||
if (channel == 1) data1[position] = d;
|
||||
else data2[position] = d;
|
||||
Oscilloscope::~Oscilloscope() {
|
||||
|
||||
delete[] _arrSamples;
|
||||
}
|
||||
|
||||
void Oscilloscope::addSamples(unsigned ch, short const* data, unsigned n) {
|
||||
|
||||
if (! enabled || inputPaused) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned baseOffs = MAX_SAMPLES * ch;
|
||||
unsigned endOffs = baseOffs + MAX_SAMPLES;
|
||||
|
||||
unsigned writePos = _arrWritePos[ch];
|
||||
unsigned newWritePos = writePos + n;
|
||||
|
||||
unsigned n2 = 0;
|
||||
if (newWritePos >= endOffs) {
|
||||
n2 = newWritePos - endOffs;
|
||||
newWritePos = baseOffs + n2;
|
||||
n -= n2;
|
||||
}
|
||||
|
||||
memcpy(_arrSamples + writePos, data, n * sizeof(short));
|
||||
if (n2 > 0) {
|
||||
memcpy(_arrSamples + baseOffs, data + n, n2 * sizeof(short));
|
||||
}
|
||||
|
||||
_arrWritePos[ch] = newWritePos;
|
||||
}
|
||||
|
||||
void Oscilloscope::render() {
|
||||
glColor3f(1,1,1);
|
||||
glBegin(GL_LINES);
|
||||
for (int i = 0; i < width; i++) {
|
||||
glVertex2f((float)i, height/2 + data1[i]*(float)height);
|
||||
|
||||
if (! enabled) {
|
||||
return;
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glColor3f(0,1,1);
|
||||
glBegin(GL_LINES);
|
||||
for (int i = 0; i < width; i++) {
|
||||
glVertex2f((float)i, height/2 + data2[i]*(float)height);
|
||||
}
|
||||
glEnd();
|
||||
// expand data to vertex data, now
|
||||
int lowpass = -int(std::numeric_limits<short>::min()) * _valLowpass;
|
||||
unsigned downsample = _valDownsample;
|
||||
// keep half of the buffer for writing and ensure an even vertex count
|
||||
unsigned usedWidth = min(_valWidth, MAX_SAMPLES / (downsample * 2)) & ~1u;
|
||||
unsigned usedSamples = usedWidth * downsample;
|
||||
|
||||
}
|
||||
for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) {
|
||||
|
||||
short const* basePtr = _arrSamples + MAX_SAMPLES * ch;
|
||||
short const* endPtr = basePtr + MAX_SAMPLES;
|
||||
short const* inPtr = _arrSamples + _arrWritePos[ch];
|
||||
short* outPtr = _arrVertices + MAX_COORDS * ch;
|
||||
int sample = 0, x = usedWidth;
|
||||
for (int i = int(usedSamples); --i >= 0 ;) {
|
||||
|
||||
if (inPtr == basePtr) {
|
||||
inPtr = endPtr;
|
||||
}
|
||||
sample += ((*--inPtr - sample) * lowpass) >> 15;
|
||||
if (i % downsample == 0) {
|
||||
*outPtr++ = short(--x);
|
||||
*outPtr++ = short(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(0.0f, _valHeight / 2.0f, 0.0f);
|
||||
glScaled(1.0f, _valHeight / 32767.0f, 1.0f);
|
||||
glVertexPointer(2, GL_SHORT, 0, _arrVertices);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
glDrawArrays(GL_LINES, MAX_SAMPLES * 0, usedWidth);
|
||||
glColor3f(0.0f, 1.0f ,1.0f);
|
||||
glDrawArrays(GL_LINES, MAX_SAMPLES * 1, usedWidth);
|
||||
glColor3f(1.0f, 1.0f ,0.0f);
|
||||
glDrawArrays(GL_LINES, MAX_SAMPLES * 2, usedWidth);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,24 +9,45 @@
|
|||
#ifndef __interface__Oscilloscope__
|
||||
#define __interface__Oscilloscope__
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include <cassert>
|
||||
|
||||
class Oscilloscope {
|
||||
public:
|
||||
Oscilloscope(int width,
|
||||
int height, bool isOn);
|
||||
void addData(float d, int channel, int position);
|
||||
void render();
|
||||
void setState(bool s) {state = s;};
|
||||
bool getState() {return state;};
|
||||
static unsigned const MAX_CHANNELS = 3;
|
||||
static unsigned const MAX_SAMPLES = 4096; // per channel
|
||||
private:
|
||||
int width;
|
||||
int height;
|
||||
float *data1, *data2;
|
||||
int current_sample;
|
||||
bool state;
|
||||
unsigned _valWidth;
|
||||
unsigned _valHeight;
|
||||
short* _arrSamples;
|
||||
short* _arrVertices;
|
||||
unsigned _arrWritePos[MAX_CHANNELS];
|
||||
|
||||
float _valLowpass;
|
||||
unsigned _valDownsample;
|
||||
|
||||
public:
|
||||
|
||||
Oscilloscope(int width, int height, bool isEnabled);
|
||||
~Oscilloscope();
|
||||
|
||||
volatile bool enabled;
|
||||
volatile bool inputPaused;
|
||||
|
||||
|
||||
void addSamples(unsigned ch, short const* data, unsigned n);
|
||||
|
||||
void render();
|
||||
|
||||
void setLowpass(float w) { assert(w > 0.0f && w <= 1.0f); _valLowpass = w; }
|
||||
void setDownsampling(unsigned f) { assert(f > 0); _valDownsample = f; }
|
||||
|
||||
private:
|
||||
// don't copy/assign
|
||||
Oscilloscope(Oscilloscope const&); // = delete;
|
||||
Oscilloscope& operator=(Oscilloscope const&); // = delete;
|
||||
|
||||
// implementation
|
||||
inline short* bufferBase(int i, int channel);
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__oscilloscope__) */
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "voxels_Log.h"
|
||||
#include "avatars_Log.h"
|
||||
|
||||
#include "Field.h"
|
||||
#include "world.h"
|
||||
#include "Util.h"
|
||||
#ifndef _WIN32
|
||||
|
@ -67,7 +66,6 @@
|
|||
#include "ChatEntry.h"
|
||||
#include "Avatar.h"
|
||||
#include "Texture.h"
|
||||
#include "Cloud.h"
|
||||
#include <AgentList.h>
|
||||
#include <AgentTypes.h>
|
||||
#include "VoxelSystem.h"
|
||||
|
@ -124,13 +122,7 @@ bool showingVoxels = true;
|
|||
|
||||
glm::vec3 box(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);
|
||||
|
||||
Cloud cloud(0, // Particles
|
||||
box, // Bounding Box
|
||||
false // Wrap
|
||||
);
|
||||
|
||||
VoxelSystem voxels;
|
||||
Field field;
|
||||
|
||||
#ifndef _WIN32
|
||||
Audio audio(&audioScope, &myAvatar);
|
||||
|
@ -139,10 +131,6 @@ Audio audio(&audioScope, &myAvatar);
|
|||
#define IDLE_SIMULATE_MSECS 8 // How often should call simulate and other stuff
|
||||
// in the idle loop?
|
||||
|
||||
float startYaw = 122.f;
|
||||
float renderYawRate = 0.f;
|
||||
float renderPitchRate = 0.f;
|
||||
|
||||
// Where one's own agent begins in the world (needs to become a dynamic thing passed to the program)
|
||||
glm::vec3 start_location(6.1f, 0, 1.4f);
|
||||
|
||||
|
@ -158,11 +146,10 @@ bool logOn = true; // Whether to show on-screen log
|
|||
int noiseOn = 0; // Whether to add random noise
|
||||
float noise = 1.0; // Overall magnitude scaling for random noise levels
|
||||
|
||||
bool gyroLook = false; // Whether to allow the gyro data from head to move your view
|
||||
bool gyroLook = true; // Whether to allow the gyro data from head to move your view
|
||||
|
||||
int displayLevels = 0;
|
||||
bool lookingInMirror = 0; // Are we currently rendering one's own head as if in mirror?
|
||||
int displayField = 0;
|
||||
|
||||
int displayHeadMouse = 1; // Display sample mouse pointer controlled by head movement
|
||||
int headMouseX, headMouseY;
|
||||
|
@ -312,7 +299,6 @@ void init(void)
|
|||
{
|
||||
voxels.init();
|
||||
voxels.setViewerAvatar(&myAvatar);
|
||||
myAvatar.setRenderYaw(startYaw);
|
||||
|
||||
handControl.setScreenDimensions(WIDTH, HEIGHT);
|
||||
|
||||
|
@ -320,10 +306,7 @@ void init(void)
|
|||
headMouseY = HEIGHT/2;
|
||||
|
||||
stars.readInput(starFile, starCacheFile, 0);
|
||||
|
||||
// Initialize Field values
|
||||
field = Field();
|
||||
|
||||
|
||||
if (noiseOn) {
|
||||
myAvatar.setNoise(noise);
|
||||
}
|
||||
|
@ -365,13 +348,7 @@ void terminate () {
|
|||
|
||||
void reset_sensors()
|
||||
{
|
||||
//
|
||||
// Reset serial I/O sensors
|
||||
//
|
||||
myAvatar.setRenderYaw(startYaw);
|
||||
|
||||
renderYawRate = 0;
|
||||
renderPitchRate = 0;
|
||||
myAvatar.setPosition(start_location);
|
||||
headMouseX = WIDTH/2;
|
||||
headMouseY = HEIGHT/2;
|
||||
|
@ -409,28 +386,30 @@ void updateAvatar(float frametime)
|
|||
headMouseY = max(headMouseY, 0);
|
||||
headMouseY = min(headMouseY, HEIGHT);
|
||||
|
||||
// Update render direction (pitch/yaw) based on measured gyro rates
|
||||
const float MIN_YAW_RATE = 5;
|
||||
const float YAW_SENSITIVITY = 1.0;
|
||||
|
||||
// If enabled, Update render pitch and yaw based on gyro data
|
||||
if (::gyroLook) {
|
||||
if (fabs(gyroYawRate) > MIN_YAW_RATE) {
|
||||
myAvatar.addBodyYaw(-gyroYawRate * YAW_SENSITIVITY * frametime);
|
||||
}
|
||||
}
|
||||
|
||||
float renderPitch = myAvatar.getRenderPitch();
|
||||
// Decay renderPitch toward zero because we never look constantly up/down
|
||||
renderPitch *= (1.f - 2.0*frametime);
|
||||
// Update head and body pitch and yaw based on measured gyro rates
|
||||
if (::gyroLook) {
|
||||
// Yaw
|
||||
const float MIN_YAW_RATE = 50;
|
||||
const float YAW_SENSITIVITY = 1.0;
|
||||
|
||||
// Decay angular rates toward zero
|
||||
renderPitchRate *= (1.f - 5.0*frametime);
|
||||
renderYawRate *= (1.f - 7.0*frametime);
|
||||
|
||||
// Update own avatar data
|
||||
myAvatar.setRenderYaw(myAvatar.getRenderYaw() + renderYawRate);
|
||||
myAvatar.setRenderPitch(renderPitch + renderPitchRate);
|
||||
if (fabs(gyroYawRate) > MIN_YAW_RATE) {
|
||||
float addToBodyYaw = (gyroYawRate > 0.f)
|
||||
? gyroYawRate - MIN_YAW_RATE : gyroYawRate + MIN_YAW_RATE;
|
||||
|
||||
myAvatar.addBodyYaw(-addToBodyYaw * YAW_SENSITIVITY * frametime);
|
||||
}
|
||||
// Pitch NOTE: PER - Need to make camera able to pitch first!
|
||||
/*
|
||||
const float MIN_PITCH_RATE = 50;
|
||||
const float PITCH_SENSITIVITY = 1.0;
|
||||
|
||||
if (fabs(gyroPitchRate) > MIN_PITCH_RATE) {
|
||||
float addToBodyPitch = (gyroPitchRate > 0.f)
|
||||
? gyroPitchRate - MIN_PITCH_RATE : gyroPitchRate + MIN_PITCH_RATE;
|
||||
|
||||
myAvatar.addBodyPitch(addToBodyPitch * PITCH_SENSITIVITY * frametime);
|
||||
*/
|
||||
}
|
||||
|
||||
// Get audio loudness data from audio input device
|
||||
#ifndef _WIN32
|
||||
|
@ -720,9 +699,9 @@ void display(void)
|
|||
|
||||
GLfloat light_position0[] = { 1.0, 1.0, 0.0, 0.0 };
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
|
||||
GLfloat ambient_color[] = { 0.7, 0.7, 0.8 }; //{ 0.125, 0.305, 0.5 };
|
||||
GLfloat ambient_color[] = { 0.7, 0.7, 0.8 };
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color);
|
||||
GLfloat diffuse_color[] = { 0.8, 0.7, 0.7 }; //{ 0.5, 0.42, 0.33 };
|
||||
GLfloat diffuse_color[] = { 0.8, 0.7, 0.7 };
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color);
|
||||
GLfloat specular_color[] = { 1.0, 1.0, 1.0, 1.0};
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color);
|
||||
|
@ -742,9 +721,14 @@ void display(void)
|
|||
myCamera.setTightness ( 100.0f );
|
||||
} else {
|
||||
|
||||
//float firstPersonPitch = 20.0f;
|
||||
//float firstPersonUpShift = 0.0f;
|
||||
//float firstPersonDistance = 0.0f;
|
||||
//float firstPersonTightness = 100.0f;
|
||||
|
||||
float firstPersonPitch = 20.0f;
|
||||
float firstPersonUpShift = 0.1f;
|
||||
float firstPersonDistance = 0.0f;
|
||||
float firstPersonDistance = 0.4f;
|
||||
float firstPersonTightness = 100.0f;
|
||||
|
||||
float thirdPersonPitch = 0.0f;
|
||||
|
@ -753,14 +737,44 @@ void display(void)
|
|||
float thirdPersonTightness = 8.0f;
|
||||
|
||||
if ( USING_FIRST_PERSON_EFFECT ) {
|
||||
float ff = 0.0;
|
||||
float min = 0.1;
|
||||
float max = 0.5;
|
||||
|
||||
if ( myAvatar.getIsNearInteractingOther()){
|
||||
if ( myAvatar.getSpeed() < max ) {
|
||||
|
||||
float s = (myAvatar.getSpeed()- min)/max ;
|
||||
ff = 1.0 - s;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if ( ff < 0.8 ) {
|
||||
myAvatar.setDisplayingHead( true );
|
||||
} else {
|
||||
myAvatar.setDisplayingHead( false );
|
||||
}
|
||||
*/
|
||||
|
||||
//printf( "ff = %f\n", ff );
|
||||
|
||||
myCamera.setPitch ( thirdPersonPitch + ff * ( firstPersonPitch - thirdPersonPitch ));
|
||||
myCamera.setUpShift ( thirdPersonUpShift + ff * ( firstPersonUpShift - thirdPersonUpShift ));
|
||||
myCamera.setDistance ( thirdPersonDistance + ff * ( firstPersonDistance - thirdPersonDistance ));
|
||||
myCamera.setTightness ( thirdPersonTightness + ff * ( firstPersonTightness - thirdPersonTightness ));
|
||||
|
||||
|
||||
|
||||
// this version uses a ramp-up/ramp-down timer in the camera to determine shift between first and thirs-person view
|
||||
/*
|
||||
if ( myAvatar.getSpeed() < 0.02 ) {
|
||||
|
||||
if (myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) {
|
||||
myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
||||
}
|
||||
|
||||
printf( "myCamera.getModeShift() = %f\n", myCamera.getModeShift());
|
||||
|
||||
//printf( "myCamera.getModeShift() = %f\n", myCamera.getModeShift());
|
||||
myCamera.setPitch ( thirdPersonPitch + myCamera.getModeShift() * ( firstPersonPitch - thirdPersonPitch ));
|
||||
myCamera.setUpShift ( thirdPersonUpShift + myCamera.getModeShift() * ( firstPersonUpShift - thirdPersonUpShift ));
|
||||
myCamera.setDistance ( thirdPersonDistance + myCamera.getModeShift() * ( firstPersonDistance - thirdPersonDistance ));
|
||||
|
@ -770,13 +784,14 @@ void display(void)
|
|||
myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
|
||||
}
|
||||
|
||||
printf( "myCamera.getModeShift() = %f\n", myCamera.getModeShift());
|
||||
|
||||
//printf( "myCamera.getModeShift() = %f\n", myCamera.getModeShift());
|
||||
myCamera.setPitch ( firstPersonPitch + myCamera.getModeShift() * ( thirdPersonPitch - firstPersonPitch ));
|
||||
myCamera.setUpShift ( firstPersonUpShift + myCamera.getModeShift() * ( thirdPersonUpShift - firstPersonUpShift ));
|
||||
myCamera.setDistance ( firstPersonDistance + myCamera.getModeShift() * ( thirdPersonDistance - firstPersonDistance ));
|
||||
myCamera.setTightness ( firstPersonTightness + myCamera.getModeShift() * ( thirdPersonTightness - firstPersonTightness ));
|
||||
}
|
||||
*/
|
||||
|
||||
} else {
|
||||
myCamera.setPitch (thirdPersonPitch );
|
||||
myCamera.setUpShift (thirdPersonUpShift );
|
||||
|
@ -834,19 +849,6 @@ void display(void)
|
|||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
/*
|
||||
// Test - Draw a blue sphere around a body part of mine!
|
||||
|
||||
glPushMatrix();
|
||||
glColor4f(0,0,1, 0.7);
|
||||
glTranslatef(myAvatar.getBonePosition(AVATAR_BONE_RIGHT_HAND).x,
|
||||
myAvatar.getBonePosition(AVATAR_BONE_RIGHT_HAND).y,
|
||||
myAvatar.getBonePosition(AVATAR_BONE_RIGHT_HAND).z);
|
||||
glutSolidSphere(0.03, 10, 10);
|
||||
glPopMatrix();
|
||||
*/
|
||||
|
||||
// draw a red sphere
|
||||
float sphereRadius = 0.25f;
|
||||
glColor3f(1,0,0);
|
||||
|
@ -854,21 +856,15 @@ void display(void)
|
|||
glutSolidSphere( sphereRadius, 15, 15 );
|
||||
glPopMatrix();
|
||||
|
||||
//draw a grid gound plane....
|
||||
//draw a grid ground plane....
|
||||
drawGroundPlaneGrid( 5.0f, 9 );
|
||||
|
||||
// Draw cloud of dots
|
||||
if (!::lookingInMirror) cloud.render();
|
||||
|
||||
// Draw voxels
|
||||
if ( showingVoxels )
|
||||
{
|
||||
voxels.render();
|
||||
}
|
||||
|
||||
// Draw field vectors
|
||||
if (displayField) field.render();
|
||||
|
||||
// Render avatars of other agents
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
|
@ -900,7 +896,7 @@ void display(void)
|
|||
|
||||
#ifndef _WIN32
|
||||
audio.render(WIDTH, HEIGHT);
|
||||
if (audioScope.getState()) audioScope.render();
|
||||
audioScope.render();
|
||||
#endif
|
||||
|
||||
if (displayHeadMouse && !::lookingInMirror && statsOn) {
|
||||
|
@ -1007,10 +1003,6 @@ int setHead(int state) {
|
|||
return setValue(state, &::lookingInMirror);
|
||||
}
|
||||
|
||||
int setField(int state) {
|
||||
return setValue(state, &displayField);
|
||||
}
|
||||
|
||||
int setNoise(int state) {
|
||||
int iRet = setValue(state, &noiseOn);
|
||||
if (noiseOn) {
|
||||
|
@ -1161,7 +1153,6 @@ void initMenu() {
|
|||
menuColumnRender = menu.addColumn("Render");
|
||||
menuColumnRender->addRow("Voxels (V)", setVoxels);
|
||||
menuColumnRender->addRow("Stars (*)", setStars);
|
||||
menuColumnRender->addRow("Field (f)", setField);
|
||||
|
||||
// Tools
|
||||
menuColumnTools = menu.addColumn("Tools");
|
||||
|
@ -1399,16 +1390,13 @@ void key(unsigned char k, int x, int y)
|
|||
|
||||
if (k == 'm' || k == 'M') setMenu(MENU_ROW_PICKED);
|
||||
|
||||
if (k == 'f') displayField = !displayField;
|
||||
if (k == 'l') displayLevels = !displayLevels;
|
||||
if (k == 'e') myAvatar.setDriveKeys(UP, 1);
|
||||
if (k == 'c') myAvatar.setDriveKeys(DOWN, 1);
|
||||
if (k == 'w') myAvatar.setDriveKeys(FWD, 1);
|
||||
if (k == 's') myAvatar.setDriveKeys(BACK, 1);
|
||||
if (k == ' ') reset_sensors();
|
||||
if (k == 't') renderPitchRate -= KEYBOARD_PITCH_RATE;
|
||||
if (k == 'g') renderPitchRate += KEYBOARD_PITCH_RATE;
|
||||
if (k == 'a') myAvatar.setDriveKeys(ROT_LEFT, 1);
|
||||
if (k == 'a') myAvatar.setDriveKeys(ROT_LEFT, 1);
|
||||
if (k == 'd') myAvatar.setDriveKeys(ROT_RIGHT, 1);
|
||||
|
||||
if (k == '\r') {
|
||||
|
@ -1505,9 +1493,7 @@ void idle(void) {
|
|||
}
|
||||
}
|
||||
|
||||
field.simulate (deltaTime);
|
||||
myAvatar.simulate(deltaTime);
|
||||
cloud.simulate (deltaTime);
|
||||
|
||||
glutPostRedisplay();
|
||||
lastTimeIdle = check;
|
||||
|
|
Loading…
Reference in a new issue