Merge branch 'master' of git://github.com/worklist/interface

Conflicts:
	main.cpp
This commit is contained in:
Yoz Grahame 2012-11-26 14:17:32 -08:00
commit 20ae9e0f11
13 changed files with 448 additions and 629 deletions

87
agent.cpp Normal file
View file

@ -0,0 +1,87 @@
//
// agent.cpp
// interface
//
// Created by Philip Rosedale on 11/20/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#include <iostream>
#include "agent.h"
// Structure to hold references to other agents that are nearby
const int MAX_AGENTS = 100;
struct AgentList {
in_addr sin_addr;
glm::vec3 position;
} agents[MAX_AGENTS];
int num_agents = 0;
//
// Process an incoming spaceserver packet telling you about other nearby agents
//
void update_agents(char * data, int length) {
std::string packet(data, length);
//std::string packet("127.0.0.1,");
//std::cout << " Update Agents, string: " << packet << "\n";
size_t spot;
size_t start_spot = 0;
spot = packet.find_first_of (",", 0);
while (spot != std::string::npos) {
std::string IPstring = packet.substr(start_spot, spot-start_spot);
//std::cout << "Found " << num_agents <<
//" with IP " << IPstring << " from " << start_spot << " to " << spot << "\n";
// Add the IP address to the agent table
add_agent(&IPstring);
start_spot = spot + 1;
if (start_spot < packet.length())
spot = packet.find_first_of (",", start_spot);
else spot = std::string::npos;
}
}
//
// Look for an agent by it's IP number, add if it does not exist in local list
//
int add_agent(std::string * IP) {
in_addr_t addr = inet_addr(IP->c_str());
//std::cout << "Checking for " << IP->c_str() << " ";
for (int i = 0; i < num_agents; i++) {
if (agents[i].sin_addr.s_addr == addr) {
//std::cout << "Found!\n";
return 0;
}
}
if (num_agents < MAX_AGENTS) {
agents[num_agents].sin_addr.s_addr = addr;
std::cout << "Added Agent # " << num_agents << " with IP " <<
inet_ntoa(agents[num_agents].sin_addr) << "\n";
num_agents++;
return 1;
} else {
std::cout << "Max agents reached fail!\n";
return 0;
}
}
//
// Broadcast data to all the other agents you are aware of, returns 1 for success
//
int broadcast(int handle, char * data, int length) {
sockaddr_in dest_address;
dest_address.sin_family = AF_INET;
dest_address.sin_port = htons( (unsigned short) UDP_PORT );
int sent_bytes;
for (int i = 0; i < num_agents; i++) {
dest_address.sin_addr.s_addr = agents[i].sin_addr.s_addr;
sent_bytes = sendto( handle, (const char*)data, length,
0, (sockaddr*)&dest_address, sizeof(sockaddr_in) );
if (sent_bytes != length) {
std::cout << "Broadcast packet fail!\n";
return 0;
}
}
return 1;
}

24
agent.h Normal file
View file

@ -0,0 +1,24 @@
//
// agent.h
// interface
//
// Created by Philip Rosedale on 11/20/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#ifndef interface_agent_h
#define interface_agent_h
#include "glm/glm.hpp"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <string.h>
#include "network.h"
void update_agents(char * data, int length);
int add_agent(std::string * IP);
int broadcast(int handle, char * data, int length);
#endif

119
head.cpp
View file

@ -62,6 +62,125 @@ void readSensors()
}
/*
void update_pos(float frametime)
// Using serial data, update avatar/render position and angles
{
float measured_pitch_rate = adc_channels[0] - avg_adc_channels[0];
float measured_yaw_rate = adc_channels[1] - avg_adc_channels[1];
float measured_lateral_accel = adc_channels[3] - avg_adc_channels[3];
float measured_fwd_accel = avg_adc_channels[2] - adc_channels[2];
// Update avatar head position based on measured gyro rates
const float HEAD_ROTATION_SCALE = 0.20;
const float HEAD_LEAN_SCALE = 0.02;
if (head_mirror) {
myHead.addYaw(measured_yaw_rate * HEAD_ROTATION_SCALE * frametime);
myHead.addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime);
myHead.addLean(measured_lateral_accel * frametime * HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE);
} else {
myHead.addYaw(measured_yaw_rate * -HEAD_ROTATION_SCALE * frametime);
myHead.addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime);
myHead.addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE);
}
// Decay avatar head back toward zero
//pitch *= (1.f - 5.0*frametime);
//yaw *= (1.f - 7.0*frametime);
// Update head_mouse model
const float MIN_MOUSE_RATE = 30.0;
const float MOUSE_SENSITIVITY = 0.1;
if (powf(measured_yaw_rate*measured_yaw_rate +
measured_pitch_rate*measured_pitch_rate, 0.5) > MIN_MOUSE_RATE)
{
head_mouse_x -= measured_yaw_rate*MOUSE_SENSITIVITY;
head_mouse_y += measured_pitch_rate*MOUSE_SENSITIVITY*(float)HEIGHT/(float)WIDTH;
}
head_mouse_x = max(head_mouse_x, 0);
head_mouse_x = min(head_mouse_x, WIDTH);
head_mouse_y = max(head_mouse_y, 0);
head_mouse_y = min(head_mouse_y, HEIGHT);
// Update render direction (pitch/yaw) based on measured gyro rates
const int MIN_YAW_RATE = 300;
const float YAW_SENSITIVITY = 0.03;
const int MIN_PITCH_RATE = 300;
const float PITCH_SENSITIVITY = 0.04;
if (fabs(measured_yaw_rate) > MIN_YAW_RATE)
{
if (measured_yaw_rate > 0)
render_yaw_rate -= (measured_yaw_rate - MIN_YAW_RATE) * YAW_SENSITIVITY * frametime;
else
render_yaw_rate -= (measured_yaw_rate + MIN_YAW_RATE) * YAW_SENSITIVITY * frametime;
}
if (fabs(measured_pitch_rate) > MIN_PITCH_RATE)
{
if (measured_pitch_rate > 0)
render_pitch_rate += (measured_pitch_rate - MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime;
else
render_pitch_rate += (measured_pitch_rate + MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime;
}
render_yaw += render_yaw_rate;
render_pitch += render_pitch_rate;
// Decay render_pitch toward zero because we never look constantly up/down
render_pitch *= (1.f - 2.0*frametime);
// Decay angular rates toward zero
render_pitch_rate *= (1.f - 5.0*frametime);
render_yaw_rate *= (1.f - 7.0*frametime);
// Update slide left/right based on accelerometer reading
const int MIN_LATERAL_ACCEL = 20;
const float LATERAL_SENSITIVITY = 0.001;
if (fabs(measured_lateral_accel) > MIN_LATERAL_ACCEL)
{
if (measured_lateral_accel > 0)
lateral_vel += (measured_lateral_accel - MIN_LATERAL_ACCEL) * LATERAL_SENSITIVITY * frametime;
else
lateral_vel += (measured_lateral_accel + MIN_LATERAL_ACCEL) * LATERAL_SENSITIVITY * frametime;
}
//slide += lateral_vel;
lateral_vel *= (1.f - 4.0*frametime);
// Update fwd/back based on accelerometer reading
const int MIN_FWD_ACCEL = 20;
const float FWD_SENSITIVITY = 0.001;
if (fabs(measured_fwd_accel) > MIN_FWD_ACCEL)
{
if (measured_fwd_accel > 0)
fwd_vel += (measured_fwd_accel - MIN_FWD_ACCEL) * FWD_SENSITIVITY * frametime;
else
fwd_vel += (measured_fwd_accel + MIN_FWD_ACCEL) * FWD_SENSITIVITY * frametime;
}
// Decrease forward velocity
fwd_vel *= (1.f - 4.0*frametime);
// Update forward vector based on pitch and yaw
fwd_vec[0] = -sinf(render_yaw*PI/180);
fwd_vec[1] = sinf(render_pitch*PI/180);
fwd_vec[2] = cosf(render_yaw*PI/180);
// Advance location forward
location[0] += fwd_vec[0]*fwd_vel;
location[1] += fwd_vec[1]*fwd_vel;
location[2] += fwd_vec[2]*fwd_vel;
// Slide location sideways
location[0] += fwd_vec[2]*-lateral_vel;
location[2] += fwd_vec[0]*lateral_vel;
// Update head and manipulator objects with object with current location
myHead.setPos(glm::vec3(location[0], location[1], location[2]));
balls.updateHand(myHead.getPos() + myHand.getPos(), glm::vec3(0,0,0), myHand.getRadius());
}
*/
void Head::addLean(float x, float z) {
// Add Body lean as impulse
leanSideways += x;

View file

@ -16,6 +16,7 @@
B6BDADE415F44AC7002A07DF /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BDADDC15F444D3002A07DF /* AudioUnit.framework */; };
B6BDAE4415F6BE53002A07DF /* particle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6BDAE4315F6BE53002A07DF /* particle.cpp */; };
D409B98A165849180099B0B3 /* cloud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D409B989165849180099B0B3 /* cloud.cpp */; };
D409B9A8165CA7BC0099B0B3 /* agent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D409B9A7165CA7BB0099B0B3 /* agent.cpp */; };
D40BDFD513404BA300B0BE1F /* GLUT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40BDFD413404BA300B0BE1F /* GLUT.framework */; };
D40BDFD713404BB300B0BE1F /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40BDFD613404BB300B0BE1F /* OpenGL.framework */; };
D40FD5FB164AF1C200878184 /* int-texture256-v2.png in CopyFiles */ = {isa = PBXBuildFile; fileRef = D40FD5FA164AF1A700878184 /* int-texture256-v2.png */; };
@ -69,6 +70,8 @@
C6859E8B029090EE04C91782 /* test_c_plus.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = test_c_plus.1; sourceTree = "<group>"; };
D409B988165849030099B0B3 /* cloud.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cloud.h; sourceTree = "<group>"; };
D409B989165849180099B0B3 /* cloud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cloud.cpp; sourceTree = "<group>"; };
D409B9A6165CA7A50099B0B3 /* agent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = agent.h; sourceTree = "<group>"; };
D409B9A7165CA7BB0099B0B3 /* agent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = agent.cpp; sourceTree = "<group>"; };
D40BDFD413404BA300B0BE1F /* GLUT.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLUT.framework; path = /System/Library/Frameworks/GLUT.framework; sourceTree = "<absolute>"; };
D40BDFD613404BB300B0BE1F /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = "<absolute>"; };
D40FD5FA164AF1A700878184 /* int-texture256-v2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "int-texture256-v2.png"; sourceTree = SOURCE_ROOT; };
@ -137,6 +140,8 @@
isa = PBXGroup;
children = (
08FB7796FE84155DC02AAC07 /* main.cpp */,
D409B9A6165CA7A50099B0B3 /* agent.h */,
D409B9A7165CA7BB0099B0B3 /* agent.cpp */,
D409B988165849030099B0B3 /* cloud.h */,
D409B989165849180099B0B3 /* cloud.cpp */,
D4EE3BC015E746E900EE4C89 /* world.h */,
@ -230,6 +235,7 @@
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0430;
ORGANIZATIONNAME = "Rosedale Lab";
};
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "interface" */;
compatibilityVersion = "Xcode 3.2";
@ -267,6 +273,7 @@
F68135561648617D003040E3 /* texture.cpp in Sources */,
F681358B1648896D003040E3 /* lodepng.cpp in Sources */,
D409B98A165849180099B0B3 /* cloud.cpp in Sources */,
D409B9A8165CA7BC0099B0B3 /* agent.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View file

@ -16,5 +16,18 @@
landmarkName = "field_avg_neighbors(int index, glm::vec3 * result)"
landmarkType = "7">
</FileBreakpoint>
<FileBreakpoint
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "util.cpp"
timestampString = "375575185.217506"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "28"
endingLineNumber = "28"
landmarkName = "makeCubes(float location[3], float scale, int * index, float * cubes_position, float * cubes_scale, float * cubes_color)"
landmarkType = "7">
</FileBreakpoint>
</FileBreakpoints>
</Bucket>

241
main.cpp
View file

@ -33,7 +33,6 @@
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include "tga.h" // Texture loader library
#include "glm/glm.hpp"
#include <portaudio.h>
@ -46,10 +45,10 @@
#include "head.h"
#include "hand.h"
#include "particle.h"
#include "texture.h"
#include "cloud.h"
#include "agent.h"
//TGAImg Img;
@ -60,7 +59,7 @@ int serial_on = 0; // Is serial connection on/off? System wil
int audio_on = 0; // Whether to turn on the audio support
int simulate_on = 1;
// Network Socket Stuff
// Network Socket Stuff
// For testing, add milliseconds of delay for received UDP packets
int UDP_socket;
int delay = 0;
@ -79,16 +78,9 @@ int target_display = 0;
int head_mirror = 0; // Whether to mirror the head when viewing it
unsigned char last_key = 0;
double ping = 0;
int WIDTH = 1200;
int HEIGHT = 800;
#define BOTTOM_MARGIN 0
#define RIGHT_MARGIN 0
#define HAND_RADIUS 0.25 // Radius of in-world 'hand' of you
Head myHead; // The rendered head of oneself or others
Hand myHand(HAND_RADIUS,
@ -103,33 +95,20 @@ ParticleSystem balls(0,
0.0 // Gravity
);
Cloud cloud(250000, // Particles
Cloud cloud(0, // Particles
box, // Bounding Box
false // Wrap
);
// FIELD INFORMATION
// If the simulation 'world' is a box with 10M boundaries, the offset to a field cell is given by:
// element = [x/10 + (y/10)*10 + (z*/10)*100]
//
// The vec(x,y,z) corner of a field cell at element i is:
//
// z = (int)( i / 100)
// y = (int)(i % 100 / 10)
// x = (int)(i % 10)
float cubes_position[MAX_CUBES*3];
float cubes_scale[MAX_CUBES];
float cubes_color[MAX_CUBES*3];
int cube_count = 0;
#define RENDER_FRAME_MSECS 10
#define SLEEP 0
#define NUM_TRIS 0
struct {
float vertices[NUM_TRIS * 3];
float vel [NUM_TRIS * 3];
}tris;
float yaw =0.f; // The yaw, pitch for the avatar head
float yaw =0.f; // The yaw, pitch for the avatar head
float pitch = 0.f; //
float start_yaw = 90.0;
float render_yaw = start_yaw;
@ -165,7 +144,6 @@ int head_lean_x, head_lean_y;
int mouse_x, mouse_y; // Where is the mouse
int mouse_pressed = 0; // true if mouse has been pressed (clear when finished)
int accel_x, accel_y;
int speed;
@ -224,6 +202,10 @@ void Timer(int extra)
glutTimerFunc(1000,Timer,0);
gettimeofday(&timer_start, NULL);
// Send a message to the spaceserver telling it we are ALIVE
notify_spaceserver(UDP_socket, location[0], location[1], location[2]);
}
void display_stats(void)
@ -265,10 +247,7 @@ void initDisplay(void)
void init(void)
{
int i, j;
load_png_as_texture(texture_filename);
printf("Texture loaded.\n");
int i;
if (audio_on) {
Audio::init();
@ -297,42 +276,20 @@ void init(void)
myHead.setNoise(noise);
}
// Init particles
float tri_scale, r;
const float VEL_SCALE = 0.00;
for (i = 0; i < NUM_TRIS; i++)
{
r = randFloat();
if (r > .999) tri_scale = 0.7;
else if (r > 0.90) tri_scale = 0.1;
else tri_scale = 0.05;
glm::vec3 pos (randFloat() * WORLD_SIZE,
randFloat() * WORLD_SIZE,
randFloat() * WORLD_SIZE);
glm::vec3 verts[3];
verts[j].x = pos.x + randFloat() * tri_scale - tri_scale/2.f;
verts[j].y = pos.y + randFloat() * tri_scale - tri_scale/2.f;
verts[j].z = pos.z + randFloat() * tri_scale - tri_scale/2.f;
tris.vertices[i*3] = verts[j].x;
tris.vertices[i*3 + 1] = verts[j].y;
tris.vertices[i*3 + 2] = verts[j].z;
// reuse pos for the normal
//glm::normalize((pos += glm::cross(verts[1] - verts[0], verts[2] - verts[0])));
//tris.normals[i*3] = pos.x;
//tris.normals[i*3+1] = pos.y;
//tris.normals[i*3+2] = pos.z;
// Moving - white
//tris.colors[i*3] = 1.0; tris.colors[i*3+1] = 1.0; tris.colors[i*3+2] = 1.0;
tris.vel[i*3] = (randFloat() - 0.5)*VEL_SCALE;
tris.vel[i*3+1] = (randFloat() - 0.5)*VEL_SCALE;
tris.vel[i*3+2] = (randFloat() - 0.5)*VEL_SCALE;
int index = 0;
float location[] = {0,0,0};
float scale = 10.0;
int j = 0;
while (index < (MAX_CUBES/2)) {
index = 0;
j++;
makeCubes(location, scale, &index, cubes_position, cubes_scale, cubes_color);
std::cout << "Run " << j << " Made " << index << " cubes\n";
cube_count = index;
}
//load_png_as_texture(texture_filename);
if (serial_on)
{
// Call readsensors for a while to get stable initial values on sensors
@ -364,57 +321,6 @@ void terminate () {
exit(EXIT_SUCCESS);
}
const float SCALE_SENSORS = 0.3f;
const float SCALE_X = 2.f;
const float SCALE_Y = 1.f;
void update_tris()
{
int i, j;
float field_val[3];
float field_contrib[3];
for (i = 0; i < NUM_TRIS; i++)
{
// Update position
tris.vertices[i*3+0] += tris.vel[i*3];
tris.vertices[i*3+1] += tris.vel[i*3+1];
tris.vertices[i*3+2] += tris.vel[i*3+2];
// Add a little gravity
//tris.vel[i*3+1] -= 0.0001;
const float DRAG = 0.99;
// Drag: Decay velocity
tris.vel[i*3] *= DRAG;
tris.vel[i*3+1] *= DRAG;
tris.vel[i*3+2] *= DRAG;
// Read and add velocity from field
field_value(field_val, &tris.vertices[i*3]);
tris.vel[i*3] += field_val[0];
tris.vel[i*3+1] += field_val[1];
tris.vel[i*3+2] += field_val[2];
// Add a tiny bit of energy back to the field
const float FIELD_COUPLE = 0.0000001;
field_contrib[0] = tris.vel[i*3]*FIELD_COUPLE;
field_contrib[1] = tris.vel[i*3+1]*FIELD_COUPLE;
field_contrib[2] = tris.vel[i*3+2]*FIELD_COUPLE;
field_add(field_contrib, &tris.vertices[i*3]);
// bounce at edge of world
for (j=0; j < 3; j++) {
if ((tris.vertices[i*3+j] > WORLD_SIZE) || (tris.vertices[i*3+j] < 0.0)) {
tris.vertices[i*3+j] = min(WORLD_SIZE, tris.vertices[i*3+j]);
tris.vertices[i*3+j] = max(0.f, tris.vertices[i*3+j]);
tris.vel[i*3 + j]*= -1.0;
}
}
}
}
void reset_sensors()
{
//
@ -447,7 +353,7 @@ void update_pos(float frametime)
float measured_fwd_accel = avg_adc_channels[2] - adc_channels[2];
// Update avatar head position based on measured gyro rates
const float HEAD_ROTATION_SCALE = 0.10;
const float HEAD_ROTATION_SCALE = 0.20;
const float HEAD_LEAN_SCALE = 0.02;
if (head_mirror) {
myHead.addYaw(measured_yaw_rate * HEAD_ROTATION_SCALE * frametime);
@ -566,13 +472,16 @@ void update_pos(float frametime)
// Update head and manipulator objects with object with current location
myHead.setPos(glm::vec3(location[0], location[1], location[2]));
balls.updateHand(myHead.getPos() + myHand.getPos(), glm::vec3(0,0,0), myHand.getRadius());
// Update all this stuff to any agents that are nearby and need to see it!
char test[] = "BXXX";
broadcast(UDP_socket, test, strlen(test));
}
void display(void)
{
int i;
glEnable (GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LINE_SMOOTH);
@ -599,30 +508,27 @@ void display(void)
glRotatef(render_pitch, 1, 0, 0);
glRotatef(render_yaw, 0, 1, 0);
glTranslatef(location[0], location[1], location[2]);
glPushMatrix();
glTranslatef(WORLD_SIZE/2, WORLD_SIZE/2, WORLD_SIZE/2);
int i = 0;
while (i < cube_count) {
glPushMatrix();
glTranslatef(cubes_position[i*3], cubes_position[i*3+1], cubes_position[i*3+2]);
glColor3fv(&cubes_color[i*3]);
glutSolidCube(cubes_scale[i]);
glPopMatrix();
i++;
}
glPopMatrix();
/* Draw Point Sprites */
//glActiveTexture(GL_TEXTURE0);
glEnable( GL_TEXTURE_2D );
//glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, particle_attenuation_quadratic );
float maxSize = 0.0f;
glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize );
glPointSize( maxSize );
glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize );
glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 0.001f );
load_png_as_texture(texture_filename);
glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
glEnable( GL_POINT_SPRITE_ARB );
if (!display_head) {
glDrawElements(GL_POINTS, NUM_TRIS, GL_FLOAT, tris.vertices);
}
glDisable( GL_POINT_SPRITE_ARB );
glDisable( GL_TEXTURE_2D );
if (!display_head) cloud.render();
// Show field vectors
if (display_field) field_render();
@ -636,9 +542,13 @@ void display(void)
// Render the world box
if (!display_head) render_world_box();
glm::vec3 test(0.5, 0.5, 0.5);
render_vector(&test);
glPopMatrix();
// Render 2D overlay: I/O level bar graphs and text
glMatrixMode(GL_PROJECTION);
glPushMatrix();
@ -708,14 +618,24 @@ void display(void)
glutSwapBuffers();
framecount++;
}
void specialkey(int k, int x, int y)
{
if (k == GLUT_KEY_UP) fwd_vel += 0.05;
if (k == GLUT_KEY_DOWN) fwd_vel -= 0.05;
if (k == GLUT_KEY_LEFT) {
if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) lateral_vel -= 0.02;
else render_yaw_rate -= 0.25;
}
if (k == GLUT_KEY_RIGHT) {
if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) lateral_vel += 0.02;
else render_yaw_rate += 0.25;
}
}
void key(unsigned char k, int x, int y)
{
// Process keypresses
last_key = k;
if (k == 'q') ::terminate();
if (k == 'q') ::terminate();
if (k == '/') stats_on = !stats_on; // toggle stats
if (k == 'n')
{
@ -761,6 +681,9 @@ void key(unsigned char k, int x, int y)
}
}
//
// Check for and process incoming network packets
//
void read_network()
{
// Receive packets
@ -771,15 +694,29 @@ void read_network()
bytescount += bytes_recvd;
// If packet is a Mouse data packet, copy it over
if (incoming_packet[0] == 'M') {
//
// mouse location packet
//
sscanf(incoming_packet, "M %d %d", &target_x, &target_y);
target_display = 1;
printf("X = %d Y = %d\n", target_x, target_y);
} else if (incoming_packet[0] == 'P') {
// Ping packet - check time and record
//
// Ping packet - check time and record
//
timeval check;
gettimeofday(&check, NULL);
ping_msecs = (float)diffclock(ping_start, check);
} else if (incoming_packet[0] == 'S') {
//
// Message from Spaceserver
//
update_agents(&incoming_packet[1], bytes_recvd - 1);
} else if (incoming_packet[0] == 'B') {
//
// Broadcast packet from another agent
//
//std::cout << "Got broadcast from agent\n";
}
}
}
@ -795,7 +732,6 @@ void idle(void)
// Simulation
update_pos(1.f/FPS);
if (simulate_on) {
update_tris();
field_simulate(1.f/FPS);
myHead.simulate(1.f/FPS);
myHand.simulate(1.f/FPS);
@ -836,8 +772,8 @@ void reshape(int width, int height)
glLoadIdentity();
gluPerspective(45, //view angle
1.0, //aspect ratio
1.0, //near clip
200.0);//far clip
0.1, //near clip
50.0);//far clip
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
@ -908,7 +844,7 @@ int main(int argc, char** argv)
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(RIGHT_MARGIN + WIDTH, BOTTOM_MARGIN + HEIGHT);
glutInitWindowSize(WIDTH, HEIGHT);
glutCreateWindow("Interface");
printf( "Created Display Window.\n" );
@ -918,6 +854,7 @@ int main(int argc, char** argv)
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(key);
glutSpecialFunc(specialkey);
glutMotionFunc(motionFunc);
glutMouseFunc(mouseFunc);
glutIdleFunc(idle);

View file

@ -11,9 +11,6 @@
#include "network.h"
const int UDP_PORT = 30000;
const char DESTINATION_IP[] = "127.0.0.1";
// Implementation of optional delay behavior using a ring buffer
const int MAX_DELAY_PACKETS = 300;
char delay_buffer[MAX_PACKET_SIZE*MAX_DELAY_PACKETS];
@ -22,7 +19,7 @@ int delay_size_received[MAX_DELAY_PACKETS];
int next_to_receive = 0;
int next_to_send = 0;
sockaddr_in address, dest_address, from;
sockaddr_in address, dest_address, spaceserver_address, from;
socklen_t fromLength = sizeof( from );
int network_init()
@ -67,7 +64,11 @@ int network_init()
dest_address.sin_family = AF_INET;
dest_address.sin_addr.s_addr = inet_addr(DESTINATION_IP);
dest_address.sin_port = htons( (unsigned short) UDP_PORT );
spaceserver_address.sin_family = AF_INET;
spaceserver_address.sin_addr.s_addr = inet_addr(SPACESERVER_IP);
spaceserver_address.sin_port = htons( (unsigned short) SPACESERVER_PORT );
from.sin_family = AF_INET;
//from.sin_addr.s_addr = htonl(ip_address);
from.sin_port = htons( (unsigned short) UDP_PORT );
@ -86,6 +87,22 @@ timeval network_send_ping(int handle) {
return check;
}
int notify_spaceserver(int handle, float x, float y, float z) {
char data[100];
sprintf(data, "%f,%f,%f", x, y, z);
//std::cout << "sending: " << data << "\n";
int packet_size = strlen(data);
int sent_bytes = sendto( handle, (const char*)data, packet_size,
0, (sockaddr*)&spaceserver_address, sizeof(sockaddr_in) );
if ( sent_bytes != packet_size )
{
printf( "failed to send to spaceserver: return value = %d\n", sent_bytes );
return false;
}
return sent_bytes;
}
int network_send(int handle, char * packet_data, int packet_size)
{
int sent_bytes = sendto( handle, (const char*)packet_data, packet_size,

View file

@ -16,11 +16,19 @@
#include <sys/time.h>
#include "util.h"
// Port to use for communicating UDP with other nearby agents
const int MAX_PACKET_SIZE = 1500;
const int UDP_PORT = 30001;
const char DESTINATION_IP[] = "127.0.0.1";
// Address and port of spaceserver process to advertise other agents
const char SPACESERVER_IP[] = "127.0.0.1";
const int SPACESERVER_PORT = 40000;
int network_init();
int network_send(int handle, char * packet_data, int packet_size);
int network_receive(int handle, char * packet_data, int delay /*msecs*/);
timeval network_send_ping(int handle);
int notify_spaceserver(int handle, float x, float y, float z);
#endif

470
tga.h
View file

@ -1,470 +0,0 @@
#include <iostream>
#include <fstream>
#include <memory.h>
#define IMG_OK 0x1
#define IMG_ERR_NO_FILE 0x2
#define IMG_ERR_MEM_FAIL 0x4
#define IMG_ERR_BAD_FORMAT 0x8
#define IMG_ERR_UNSUPPORTED 0x40
class TGAImg
{
public:
TGAImg();
~TGAImg();
int Load(char* szFilename);
int GetBPP();
int GetWidth();
int GetHeight();
unsigned char* GetImg(); // Return a pointer to image data
unsigned char* GetPalette(); // Return a pointer to VGA palette
private:
short int iWidth,iHeight,iBPP;
unsigned long lImageSize;
char bEnc;
unsigned char *pImage, *pPalette, *pData;
// Internal workers
int ReadHeader();
int LoadRawData();
int LoadTgaRLEData();
int LoadTgaPalette();
void BGRtoRGB();
void FlipImg();
};
TGAImg::TGAImg()
{
pImage=pPalette=pData=NULL;
iWidth=iHeight=iBPP=bEnc=0;
lImageSize=0;
}
TGAImg::~TGAImg()
{
if(pImage)
{
delete [] pImage;
pImage=NULL;
}
if(pPalette)
{
delete [] pPalette;
pPalette=NULL;
}
if(pData)
{
delete [] pData;
pData=NULL;
}
}
int TGAImg::Load(char* szFilename)
{
using namespace std;
ifstream fIn;
unsigned long ulSize;
int iRet;
// Clear out any existing image and palette
if(pImage)
{
delete [] pImage;
pImage=NULL;
}
if(pPalette)
{
delete [] pPalette;
pPalette=NULL;
}
// Open the specified file
fIn.open(szFilename,ios::binary);
if(fIn==NULL)
return IMG_ERR_NO_FILE;
// Get file size
fIn.seekg(0,ios_base::end);
ulSize=fIn.tellg();
fIn.seekg(0,ios_base::beg);
// Allocate some space
// Check and clear pDat, just in case
if(pData)
delete [] pData;
pData=new unsigned char[ulSize];
if(pData==NULL)
{
fIn.close();
return IMG_ERR_MEM_FAIL;
}
// Read the file into memory
fIn.read((char*)pData,ulSize);
fIn.close();
// Process the header
iRet=ReadHeader();
if(iRet!=IMG_OK)
return iRet;
switch(bEnc)
{
case 1: // Raw Indexed
{
// Check filesize against header values
if((lImageSize+18+pData[0]+768)>ulSize)
return IMG_ERR_BAD_FORMAT;
// Double check image type field
if(pData[1]!=1)
return IMG_ERR_BAD_FORMAT;
// Load image data
iRet=LoadRawData();
if(iRet!=IMG_OK)
return iRet;
// Load palette
iRet=LoadTgaPalette();
if(iRet!=IMG_OK)
return iRet;
break;
}
case 2: // Raw RGB
{
// Check filesize against header values
if((lImageSize+18+pData[0])>ulSize)
return IMG_ERR_BAD_FORMAT;
// Double check image type field
if(pData[1]!=0)
return IMG_ERR_BAD_FORMAT;
// Load image data
iRet=LoadRawData();
if(iRet!=IMG_OK)
return iRet;
BGRtoRGB(); // Convert to RGB
break;
}
case 9: // RLE Indexed
{
// Double check image type field
if(pData[1]!=1)
return IMG_ERR_BAD_FORMAT;
// Load image data
iRet=LoadTgaRLEData();
if(iRet!=IMG_OK)
return iRet;
// Load palette
iRet=LoadTgaPalette();
if(iRet!=IMG_OK)
return iRet;
break;
}
case 10: // RLE RGB
{
// Double check image type field
if(pData[1]!=0)
return IMG_ERR_BAD_FORMAT;
// Load image data
iRet=LoadTgaRLEData();
if(iRet!=IMG_OK)
return iRet;
BGRtoRGB(); // Convert to RGB
break;
}
default:
return IMG_ERR_UNSUPPORTED;
}
// Check flip bit
if((pData[17] & 0x20)==0)
FlipImg();
// Release file memory
delete [] pData;
pData=NULL;
return IMG_OK;
}
int TGAImg::ReadHeader() // Examine the header and populate our class attributes
{
short ColMapStart,ColMapLen;
short x1,y1,x2,y2;
if(pData==NULL)
return IMG_ERR_NO_FILE;
if(pData[1]>1) // 0 (RGB) and 1 (Indexed) are the only types we know about
return IMG_ERR_UNSUPPORTED;
bEnc=pData[2]; // Encoding flag 1 = Raw indexed image
// 2 = Raw RGB
// 3 = Raw greyscale
// 9 = RLE indexed
// 10 = RLE RGB
// 11 = RLE greyscale
// 32 & 33 Other compression, indexed
if(bEnc>11) // We don't want 32 or 33
return IMG_ERR_UNSUPPORTED;
// Get palette info
memcpy(&ColMapStart,&pData[3],2);
memcpy(&ColMapLen,&pData[5],2);
// Reject indexed images if not a VGA palette (256 entries with 24 bits per entry)
if(pData[1]==1) // Indexed
{
if(ColMapStart!=0 || ColMapLen!=256 || pData[7]!=24)
return IMG_ERR_UNSUPPORTED;
}
// Get image window and produce width & height values
memcpy(&x1,&pData[8],2);
memcpy(&y1,&pData[10],2);
memcpy(&x2,&pData[12],2);
memcpy(&y2,&pData[14],2);
iWidth=(x2-x1);
iHeight=(y2-y1);
if(iWidth<1 || iHeight<1)
return IMG_ERR_BAD_FORMAT;
// Bits per Pixel
iBPP=pData[16];
// Check flip / interleave byte
if(pData[17]>32) // Interleaved data
return IMG_ERR_UNSUPPORTED;
// Calculate image size
lImageSize=(iWidth * iHeight * (iBPP/8));
return IMG_OK;
}
int TGAImg::LoadRawData() // Load uncompressed image data
{
short iOffset;
if(pImage) // Clear old data if present
delete [] pImage;
pImage=new unsigned char[lImageSize];
if(pImage==NULL)
return IMG_ERR_MEM_FAIL;
iOffset=pData[0]+18; // Add header to ident field size
if(pData[1]==1) // Indexed images
iOffset+=768; // Add palette offset
memcpy(pImage,&pData[iOffset],lImageSize);
return IMG_OK;
}
int TGAImg::LoadTgaRLEData() // Load RLE compressed image data
{
short iOffset,iPixelSize;
unsigned char *pCur;
unsigned long Index=0;
unsigned char bLength,bLoop;
// Calculate offset to image data
iOffset=pData[0]+18;
// Add palette offset for indexed images
if(pData[1]==1)
iOffset+=768;
// Get pixel size in bytes
iPixelSize=iBPP/8;
// Set our pointer to the beginning of the image data
pCur=&pData[iOffset];
// Allocate space for the image data
if(pImage!=NULL)
delete [] pImage;
pImage=new unsigned char[lImageSize];
if(pImage==NULL)
return IMG_ERR_MEM_FAIL;
// Decode
while(Index<lImageSize)
{
if(*pCur & 0x80) // Run length chunk (High bit = 1)
{
bLength=*pCur-127; // Get run length
pCur++; // Move to pixel data
// Repeat the next pixel bLength times
for(bLoop=0;bLoop!=bLength;++bLoop,Index+=iPixelSize)
memcpy(&pImage[Index],pCur,iPixelSize);
pCur+=iPixelSize; // Move to the next descriptor chunk
}
else // Raw chunk
{
bLength=*pCur+1; // Get run length
pCur++; // Move to pixel data
// Write the next bLength pixels directly
for(bLoop=0;bLoop!=bLength;++bLoop,Index+=iPixelSize,pCur+=iPixelSize)
memcpy(&pImage[Index],pCur,iPixelSize);
}
}
return IMG_OK;
}
int TGAImg::LoadTgaPalette() // Load a 256 color palette
{
unsigned char bTemp;
short iIndex,iPalPtr;
// Delete old palette if present
if(pPalette)
{
delete [] pPalette;
pPalette=NULL;
}
// Create space for new palette
pPalette=new unsigned char[768];
if(pPalette==NULL)
return IMG_ERR_MEM_FAIL;
// VGA palette is the 768 bytes following the header
memcpy(pPalette,&pData[pData[0]+18],768);
// Palette entries are BGR ordered so we have to convert to RGB
for(iIndex=0,iPalPtr=0;iIndex!=256;++iIndex,iPalPtr+=3)
{
bTemp=pPalette[iPalPtr]; // Get Blue value
pPalette[iPalPtr]=pPalette[iPalPtr+2]; // Copy Red to Blue
pPalette[iPalPtr+2]=bTemp; // Replace Blue at the end
}
return IMG_OK;
}
void TGAImg::BGRtoRGB() // Convert BGR to RGB (or back again)
{
unsigned long Index,nPixels;
unsigned char *bCur;
unsigned char bTemp;
short iPixelSize;
// Set ptr to start of image
bCur=pImage;
// Calc number of pixels
nPixels=iWidth*iHeight;
// Get pixel size in bytes
iPixelSize=iBPP/8;
for(Index=0;Index!=nPixels;Index++) // For each pixel
{
bTemp=*bCur; // Get Blue value
*bCur=*(bCur+2); // Swap red value into first position
*(bCur+2)=bTemp; // Write back blue to last position
bCur+=iPixelSize; // Jump to next pixel
}
}
void TGAImg::FlipImg() // Flips the image vertically (Why store images upside down?)
{
unsigned char bTemp;
unsigned char *pLine1, *pLine2;
int iLineLen,iIndex;
iLineLen=iWidth*(iBPP/8);
pLine1=pImage;
pLine2=&pImage[iLineLen * (iHeight - 1)];
for( ;pLine1<pLine2;pLine2-=(iLineLen*2))
{
for(iIndex=0;iIndex!=iLineLen;pLine1++,pLine2++,iIndex++)
{
bTemp=*pLine1;
*pLine1=*pLine2;
*pLine2=bTemp;
}
}
}
int TGAImg::GetBPP()
{
return iBPP;
}
int TGAImg::GetWidth()
{
return iWidth;
}
int TGAImg::GetHeight()
{
return iHeight;
}
unsigned char* TGAImg::GetImg()
{
return pImage;
}
unsigned char* TGAImg::GetPalette()
{
return pPalette;
}

View file

@ -15,11 +15,75 @@
#include "world.h"
#include "glm/glm.hpp"
float randFloat () {
return (rand()%10000)/10000.f;
}
void makeCubes(float location[3], float scale, int * index,
float * cubes_position, float * cubes_scale, float * cubes_color) {
int i;
float spot[3];
//std::cout << "loc: " << location[0] << ","
//<< location[1] << "," << location[2] << "\n";
if ((*index >= MAX_CUBES) || (scale < SMALLEST_CUBE)) return;
if (randFloat() < 0.5) {
// Make a cube
for (i = 0; i < 3; i++) cubes_position[*index*3 + i] = location[i];
cubes_scale[*index] = scale;
cubes_color[*index*3] = randFloat();
cubes_color[*index*3 + 1] = randFloat();
cubes_color[*index*3 + 2] = randFloat();
*index += 1;
//std::cout << "Quad made at scale " << scale << "\n";
} else {
for (i = 0; i < 8; i++) {
spot[0] = location[0] + (i%2)*scale/2.0;
spot[1] = location[1] + ((i/2)%2)*scale/2.0;
spot[2] = location[2] + ((i/4)%2)*scale/2.0;
//std::cout << spot[0] << "," << spot[1] << "," << spot[2] << "\n";
makeCubes(spot, scale/2.0, index, cubes_position, cubes_scale, cubes_color);
}
}
}
void render_vector(glm::vec3 * vec)
{
// Show edge of world
glDisable(GL_LIGHTING);
glColor4f(1.0, 1.0, 1.0, 1.0);
glLineWidth(1.0);
glBegin(GL_LINES);
// Draw axes
glColor3f(1,0,0);
glVertex3f(-1,0,0);
glVertex3f(1,0,0);
glColor3f(0,1,0);
glVertex3f(0,-1,0);
glVertex3f(0, 1, 0);
glColor3f(0,0,1);
glVertex3f(0,0,-1);
glVertex3f(0, 0, 1);
// Draw vector
glColor3f(1,1,1);
glVertex3f(0,0,0);
glVertex3f(vec->x, vec->y, vec->z);
// Draw marker dots for magnitude
glEnd();
float particle_attenuation_quadratic[] = { 0.0f, 0.0f, 2.0f }; // larger Z = smaller particles
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, particle_attenuation_quadratic );
glEnable(GL_POINT_SMOOTH);
glPointSize(10.0);
glBegin(GL_POINTS);
glColor3f(1,0,0);
glVertex3f(vec->x,0,0);
glColor3f(0,1,0);
glVertex3f(0,vec->y,0);
glColor3f(0,0,1);
glVertex3f(0,0,vec->z);
glEnd();
}
void render_world_box()
{
// Show edge of world
@ -39,6 +103,11 @@ void render_world_box()
glEnd();
}
void outstring(char * string, int length) {
char out[length];
memcpy(out, string, length);
std::cout << out << "\n";
}
double diffclock(timeval clock1,timeval clock2)
{

6
util.h
View file

@ -8,14 +8,20 @@
#ifndef interface_util_h
#define interface_util_h
#include "glm/glm.hpp"
void outstring(char * string, int length);
float randFloat();
void render_world_box();
void render_vector(glm::vec3 * vec);
void drawtext(int x, int y, float scale, float rotate, float thick, int mono, char *string,
float r=1.0, float g=1.0, float b=1.0);
void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, glm::vec3 vec,
float r=1.0, float g=1.0, float b=1.0);
double diffclock(timeval clock1,timeval clock2);
void makeCubes(float location[3], float scale, int * index,
float * cubes_position, float * cubes_scale, float * cubes_color);
#endif

View file

@ -6,7 +6,7 @@
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
// Simulation happens in positive cube with edge of size WORLD_SIZE
// Simulation happens in positive cube with edge of size WORLD_SIZE
#ifndef interface_world_h
#define interface_world_h
@ -14,5 +14,7 @@
const float WORLD_SIZE = 10.0;
#define PI 3.14159265
#define MAX_CUBES 2000
#define SMALLEST_CUBE 0.01
#endif