Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jeffrey Ventrella 2013-04-29 10:41:58 -07:00
commit 9924be9188
7 changed files with 35 additions and 537 deletions

View file

@ -12,7 +12,6 @@
#include <AvatarData.h>
#include <Orientation.h>
#include "Field.h"
#include "world.h"
#include "AvatarTouch.h"

View file

@ -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,

View file

@ -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;
}
}
}
}

View file

@ -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

View file

@ -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();
}

View file

@ -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

View file

@ -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);
@ -870,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);
@ -890,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++) {
@ -1043,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) {
@ -1197,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");
@ -1435,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') {
@ -1540,9 +1492,7 @@ void idle(void) {
}
}
field.simulate (deltaTime);
myAvatar.simulate(deltaTime);
cloud.simulate (deltaTime);
glutPostRedisplay();
lastTimeIdle = check;