mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 08:21:24 +02:00
Improved comments at start of main.cpp, dropped unused octal.h,.cpp files, deleted many unused system variables and functions.
This commit is contained in:
parent
5a98ebfff2
commit
ef785ba7aa
3 changed files with 138 additions and 294 deletions
|
@ -1,16 +1,25 @@
|
||||||
//
|
|
||||||
//
|
//
|
||||||
// Interface
|
// Interface
|
||||||
//
|
//
|
||||||
// Show a field of objects rendered in 3D, with yaw and pitch of scene driven
|
// Allows you to connect to and see/hear the shared 3D space.
|
||||||
// by accelerometer data
|
// Optionally uses serialUSB connection to get gyro data for head movement.
|
||||||
// serial port connected to Maple board/arduino.
|
// Optionally gets UDP stream from transmitter to animate controller/hand.
|
||||||
|
//
|
||||||
|
// Usage: The interface client first attempts to contact a domain server to
|
||||||
|
// discover the appropriate audio, voxel, and avatar servers to contact.
|
||||||
|
// Right now, the default domain server is "highfidelity.below92.com"
|
||||||
|
// You can change the domain server to use your own by editing the
|
||||||
|
// DOMAIN_HOSTNAME or DOMAIN_IP strings in the file AgentList.cpp
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Welcome Aboard!
|
||||||
|
//
|
||||||
//
|
//
|
||||||
// Keyboard Commands:
|
// Keyboard Commands:
|
||||||
//
|
//
|
||||||
// / = toggle stats display
|
// / = toggle stats display
|
||||||
// spacebar = reset gyros/head
|
// spacebar = reset gyros/head position
|
||||||
// h = render Head
|
// h = render Head facing yourself (mirror)
|
||||||
// l = show incoming gyro levels
|
// l = show incoming gyro levels
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -68,41 +77,31 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int audio_on = 1; // Whether to turn on the audio support
|
|
||||||
int simulate_on = 1;
|
|
||||||
|
|
||||||
AgentList agentList(AGENT_TYPE_INTERFACE);
|
AgentList agentList(AGENT_TYPE_INTERFACE);
|
||||||
pthread_t networkReceiveThread;
|
pthread_t networkReceiveThread;
|
||||||
bool stopNetworkReceiveThread = false;
|
bool stopNetworkReceiveThread = false;
|
||||||
|
|
||||||
// For testing, add milliseconds of delay for received UDP packets
|
int packetCount = 0;
|
||||||
int packetcount = 0;
|
int packetsPerSecond = 0;
|
||||||
int packets_per_second = 0;
|
int bytesPerSecond = 0;
|
||||||
int bytes_per_second = 0;
|
int bytesCount = 0;
|
||||||
int bytescount = 0;
|
|
||||||
|
|
||||||
// Getting a target location from other machine (or loopback) to display
|
int headMirror = 1; // Whether to mirror own head when viewing it
|
||||||
int target_x, target_y;
|
|
||||||
int target_display = 0;
|
|
||||||
|
|
||||||
int head_mirror = 1; // Whether to mirror own head when viewing it
|
int WIDTH = 1200; // Window size
|
||||||
int sendToSelf = 1;
|
int HEIGHT = 800;
|
||||||
|
|
||||||
int WIDTH = 1200;
|
|
||||||
int HEIGHT = 800;
|
|
||||||
int fullscreen = 0;
|
int fullscreen = 0;
|
||||||
|
|
||||||
bool wantColorRandomizer = true; // for addSphere and load file
|
bool wantColorRandomizer = true; // for addSphere and load file
|
||||||
|
|
||||||
Oscilloscope audioScope(256,200,true);
|
Oscilloscope audioScope(256,200,true);
|
||||||
|
|
||||||
#define HAND_RADIUS 0.25 // Radius of in-world 'hand' of you
|
|
||||||
Head myHead; // The rendered head of oneself
|
Head myHead; // The rendered head of oneself
|
||||||
Camera myCamera; // My view onto the world (sometimes on myself :)
|
Camera myCamera; // My view onto the world (sometimes on myself :)
|
||||||
|
|
||||||
|
// Starfield information
|
||||||
char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
|
char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
|
||||||
FieldOfView fov;
|
FieldOfView fov;
|
||||||
|
|
||||||
Stars stars;
|
Stars stars;
|
||||||
#ifdef STARFIELD_KEYS
|
#ifdef STARFIELD_KEYS
|
||||||
int starsTiles = 20;
|
int starsTiles = 20;
|
||||||
|
@ -110,15 +109,16 @@ double starsLod = 1.0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glm::vec3 box(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);
|
glm::vec3 box(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);
|
||||||
|
|
||||||
ParticleSystem balls(0,
|
ParticleSystem balls(0,
|
||||||
box,
|
box,
|
||||||
false, // Wrap?
|
false, // Wrap?
|
||||||
0.02f, // Noise
|
0.02f, // Noise
|
||||||
0.3f, // Size scale
|
0.3f, // Size scale
|
||||||
0.0 // Gravity
|
0.0 // Gravity
|
||||||
);
|
);
|
||||||
|
|
||||||
Cloud cloud(20000, // Particles
|
Cloud cloud(0, // Particles
|
||||||
box, // Bounding Box
|
box, // Bounding Box
|
||||||
false // Wrap
|
false // Wrap
|
||||||
);
|
);
|
||||||
|
@ -133,12 +133,12 @@ Field field;
|
||||||
Audio audio(&audioScope, &myHead);
|
Audio audio(&audioScope, &myHead);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RENDER_FRAME_MSECS 8
|
#define IDLE_SIMULATE_MSECS 8 // How often should call simulate and other stuff
|
||||||
int steps_per_frame = 0;
|
// in the idle loop?
|
||||||
|
|
||||||
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 pitch = 0.f;
|
||||||
float start_yaw = 122;
|
float startYaw = 122.f;
|
||||||
float renderPitch = 0.f;
|
float renderPitch = 0.f;
|
||||||
float renderYawRate = 0.f;
|
float renderYawRate = 0.f;
|
||||||
float renderPitchRate = 0.f;
|
float renderPitchRate = 0.f;
|
||||||
|
@ -146,31 +146,25 @@ float renderPitchRate = 0.f;
|
||||||
// Where one's own agent begins in the world (needs to become a dynamic thing passed to the program)
|
// 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);
|
glm::vec3 start_location(6.1f, 0, 1.4f);
|
||||||
|
|
||||||
int stats_on = 0; // Whether to show onscreen text overlay with stats
|
int statsOn = 0; // Whether to show onscreen text overlay with stats
|
||||||
bool starsOn = false; // Whether to display the stars
|
bool starsOn = false; // Whether to display the stars
|
||||||
bool paintOn = false; // Whether to paint voxels as you fly around
|
bool paintOn = false; // Whether to paint voxels as you fly around
|
||||||
VoxelDetail paintingVoxel; // The voxel we're painting if we're painting
|
VoxelDetail paintingVoxel; // The voxel we're painting if we're painting
|
||||||
unsigned char dominantColor = 0; // The dominant color of the voxel we're painting
|
unsigned char dominantColor = 0; // The dominant color of the voxel we're painting
|
||||||
bool perfStatsOn = false; // Do we want to display perfStats?
|
bool perfStatsOn = false; // Do we want to display perfStats?
|
||||||
int noise_on = 0; // Whether to add random noise
|
int noiseOn = 0; // Whether to add random noise
|
||||||
float noise = 1.0; // Overall magnitude scaling for random noise levels
|
float noise = 1.0; // Overall magnitude scaling for random noise levels
|
||||||
|
|
||||||
int step_on = 0;
|
int displayLevels = 0;
|
||||||
int display_levels = 0;
|
int displayHead = 0;
|
||||||
int display_head = 0;
|
int displayField = 0;
|
||||||
int display_field = 0;
|
|
||||||
|
|
||||||
int display_head_mouse = 1; // Display sample mouse pointer controlled by head movement
|
int displayHeadMouse = 1; // Display sample mouse pointer controlled by head movement
|
||||||
int head_mouse_x, head_mouse_y;
|
int headMouseX, headMouseY;
|
||||||
int head_lean_x, head_lean_y;
|
|
||||||
|
|
||||||
int mouse_x, mouse_y; // Where is the mouse
|
int mouseX, mouseY; // Where is the mouse
|
||||||
int mouse_start_x, mouse_start_y; // Mouse location at start of last down click
|
int mouseStartX, mouseStartY; // Mouse location at start of last down click
|
||||||
int mouse_pressed = 0; // true if mouse has been pressed (clear when finished)
|
int mousePressed = 0; // true if mouse has been pressed (clear when finished)
|
||||||
|
|
||||||
int nearbyAgents = 0; // How many other people near you is the domain server reporting?
|
|
||||||
|
|
||||||
int speed;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Serial USB Variables
|
// Serial USB Variables
|
||||||
|
@ -185,17 +179,14 @@ int first_measurement = 1;
|
||||||
|
|
||||||
// Frame rate Measurement
|
// Frame rate Measurement
|
||||||
|
|
||||||
int framecount = 0;
|
int frameCount = 0;
|
||||||
float FPS = 120.f;
|
float FPS = 120.f;
|
||||||
timeval timer_start, timer_end;
|
timeval timerStart, timerEnd;
|
||||||
timeval last_frame;
|
timeval lastTimeIdle;
|
||||||
double elapsedTime;
|
double elapsedTime;
|
||||||
|
|
||||||
// Particles
|
// Particles
|
||||||
|
|
||||||
char texture_filename[] = "images/int-texture256-v4.png";
|
|
||||||
unsigned int texture_width = 256;
|
|
||||||
unsigned int texture_height = 256;
|
|
||||||
|
|
||||||
float particle_attenuation_quadratic[] = { 0.0f, 0.0f, 2.0f }; // larger Z = smaller particles
|
float particle_attenuation_quadratic[] = { 0.0f, 0.0f, 2.0f }; // larger Z = smaller particles
|
||||||
float pointer_attenuation_quadratic[] = { 1.0f, 0.0f, 0.0f }; // for 2D view
|
float pointer_attenuation_quadratic[] = { 1.0f, 0.0f, 0.0f }; // for 2D view
|
||||||
|
@ -218,34 +209,19 @@ float pointer_attenuation_quadratic[] = { 1.0f, 0.0f, 0.0f }; // for 2D view
|
||||||
// Every second, check the frame rates and other stuff
|
// Every second, check the frame rates and other stuff
|
||||||
void Timer(int extra)
|
void Timer(int extra)
|
||||||
{
|
{
|
||||||
gettimeofday(&timer_end, NULL);
|
gettimeofday(&timerEnd, NULL);
|
||||||
FPS = (float)framecount / ((float)diffclock(&timer_start, &timer_end) / 1000.f);
|
FPS = (float)frameCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f);
|
||||||
packets_per_second = (float)packetcount / ((float)diffclock(&timer_start, &timer_end) / 1000.f);
|
packetsPerSecond = (float)packetCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f);
|
||||||
bytes_per_second = (float)bytescount / ((float)diffclock(&timer_start, &timer_end) / 1000.f);
|
bytesPerSecond = (float)bytesCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f);
|
||||||
framecount = 0;
|
frameCount = 0;
|
||||||
packetcount = 0;
|
packetCount = 0;
|
||||||
bytescount = 0;
|
bytesCount = 0;
|
||||||
|
|
||||||
glutTimerFunc(1000,Timer,0);
|
glutTimerFunc(1000,Timer,0);
|
||||||
gettimeofday(&timer_start, NULL);
|
gettimeofday(&timerStart, NULL);
|
||||||
|
|
||||||
// Ping the agents we can see
|
// Ping the agents we can see
|
||||||
agentList.pingAgents();
|
agentList.pingAgents();
|
||||||
|
|
||||||
if (0) {
|
|
||||||
// Massive send packet speed test
|
|
||||||
timeval starttest, endtest;
|
|
||||||
gettimeofday(&starttest, NULL);
|
|
||||||
char junk[1000];
|
|
||||||
junk[0] = 'J';
|
|
||||||
for (int i = 0; i < 10000; i++)
|
|
||||||
{
|
|
||||||
// agentSocket.send((char *)"192.168.1.38", AGENT_UDP_PORT, junk, 1000);
|
|
||||||
}
|
|
||||||
gettimeofday(&endtest, NULL);
|
|
||||||
float sendTime = static_cast<float>( diffclock(&starttest, &endtest) );
|
|
||||||
printf("packet test = %4.1f\n", sendTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we haven't detected gyros, check for them now
|
// if we haven't detected gyros, check for them now
|
||||||
if (!serialPort.active) {
|
if (!serialPort.active) {
|
||||||
|
@ -253,10 +229,7 @@ void Timer(int extra)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void displayStats(void)
|
||||||
|
|
||||||
|
|
||||||
void display_stats(void)
|
|
||||||
{
|
{
|
||||||
// bitmap chars are about 10 pels high
|
// bitmap chars are about 10 pels high
|
||||||
char legend[] = "/ - toggle this display, Q - exit, H - show head, M - show hand, T - test audio";
|
char legend[] = "/ - toggle this display, Q - exit, H - show head, M - show hand, T - test audio";
|
||||||
|
@ -269,7 +242,7 @@ void display_stats(void)
|
||||||
|
|
||||||
char stats[200];
|
char stats[200];
|
||||||
sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d Head(x,y,z)=( %f , %f , %f )",
|
sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d Head(x,y,z)=( %f , %f , %f )",
|
||||||
FPS, packets_per_second, bytes_per_second, headPos.x,headPos.y,headPos.z);
|
FPS, packetsPerSecond, bytesPerSecond, headPos.x,headPos.y,headPos.z);
|
||||||
drawtext(10, 49, 0.10f, 0, 1.0, 0, stats);
|
drawtext(10, 49, 0.10f, 0, 1.0, 0, stats);
|
||||||
if (serialPort.active) {
|
if (serialPort.active) {
|
||||||
sprintf(stats, "ADC samples = %d, LED = %d",
|
sprintf(stats, "ADC samples = %d, LED = %d",
|
||||||
|
@ -327,26 +300,10 @@ void display_stats(void)
|
||||||
}
|
}
|
||||||
delete []perfStatLinesArray; // we're responsible for cleanup
|
delete []perfStatLinesArray; // we're responsible for cleanup
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
std::stringstream angles;
|
|
||||||
angles << "render_yaw: " << myHead.getRenderYaw() << ", Yaw: " << myHead.getYaw();
|
|
||||||
drawtext(10,50,0.10, 0, 1.0, 0, (char *)angles.str().c_str());
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
char adc[200];
|
|
||||||
sprintf(adc, "location = %3.1f,%3.1f,%3.1f, angle_to(origin) = %3.1f, head yaw = %3.1f, render_yaw = %3.1f",
|
|
||||||
-location[0], -location[1], -location[2],
|
|
||||||
angle_to(myHead.getPos()*-1.f, glm::vec3(0,0,0), myHead.getRenderYaw(), myHead.getYaw()),
|
|
||||||
myHead.getYaw(), myHead.getRenderYaw());
|
|
||||||
drawtext(10, 50, 0.10, 0, 1.0, 0, adc);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initDisplay(void)
|
void initDisplay(void)
|
||||||
{
|
{
|
||||||
// Set up blending function so that we can NOT clear the display
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
@ -355,36 +312,27 @@ void initDisplay(void)
|
||||||
glEnable(GL_LIGHT0);
|
glEnable(GL_LIGHT0);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
// load_png_as_texture(texture_filename);
|
|
||||||
|
|
||||||
if (fullscreen) glutFullScreen();
|
if (fullscreen) glutFullScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void init(void)
|
void init(void)
|
||||||
{
|
{
|
||||||
voxels.init();
|
voxels.init();
|
||||||
voxels.setViewerHead(&myHead);
|
voxels.setViewerHead(&myHead);
|
||||||
myHead.setRenderYaw(start_yaw);
|
myHead.setRenderYaw(startYaw);
|
||||||
|
|
||||||
head_mouse_x = WIDTH/2;
|
headMouseX = WIDTH/2;
|
||||||
head_mouse_y = HEIGHT/2;
|
headMouseY = HEIGHT/2;
|
||||||
head_lean_x = WIDTH/2;
|
|
||||||
head_lean_y = HEIGHT/2;
|
|
||||||
|
|
||||||
stars.readInput(starFile, 0);
|
stars.readInput(starFile, 0);
|
||||||
|
|
||||||
// Initialize Field values
|
// Initialize Field values
|
||||||
field = Field();
|
field = Field();
|
||||||
printf( "Field Initialized.\n" );
|
|
||||||
|
if (noiseOn) {
|
||||||
if (noise_on) {
|
|
||||||
myHead.setNoise(noise);
|
myHead.setNoise(noise);
|
||||||
}
|
}
|
||||||
myHead.setPos(start_location );
|
myHead.setPos(start_location );
|
||||||
|
|
||||||
myCamera.setPosition( start_location );
|
myCamera.setPosition( start_location );
|
||||||
|
|
||||||
#ifdef MARKER_CAPTURE
|
#ifdef MARKER_CAPTURE
|
||||||
|
@ -399,8 +347,8 @@ void init(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gettimeofday(&timer_start, NULL);
|
gettimeofday(&timerStart, NULL);
|
||||||
gettimeofday(&last_frame, NULL);
|
gettimeofday(&lastTimeIdle, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminate () {
|
void terminate () {
|
||||||
|
@ -421,15 +369,13 @@ void reset_sensors()
|
||||||
//
|
//
|
||||||
// Reset serial I/O sensors
|
// Reset serial I/O sensors
|
||||||
//
|
//
|
||||||
myHead.setRenderYaw(start_yaw);
|
myHead.setRenderYaw(startYaw);
|
||||||
|
|
||||||
yaw = renderYawRate = 0;
|
yaw = renderYawRate = 0;
|
||||||
pitch = renderPitch = renderPitchRate = 0;
|
pitch = renderPitch = renderPitchRate = 0;
|
||||||
myHead.setPos(start_location);
|
myHead.setPos(start_location);
|
||||||
head_mouse_x = WIDTH/2;
|
headMouseX = WIDTH/2;
|
||||||
head_mouse_y = HEIGHT/2;
|
headMouseY = HEIGHT/2;
|
||||||
head_lean_x = WIDTH/2;
|
|
||||||
head_lean_y = HEIGHT/2;
|
|
||||||
|
|
||||||
myHead.reset();
|
myHead.reset();
|
||||||
|
|
||||||
|
@ -440,12 +386,12 @@ void reset_sensors()
|
||||||
|
|
||||||
void simulateHand(float deltaTime) {
|
void simulateHand(float deltaTime) {
|
||||||
// If mouse is being dragged, send current force to the hand controller
|
// If mouse is being dragged, send current force to the hand controller
|
||||||
if (mouse_pressed == 1)
|
if (mousePressed == 1)
|
||||||
{
|
{
|
||||||
// Add a velocity to the hand corresponding to the detected size of the drag vector
|
// Add a velocity to the hand corresponding to the detected size of the drag vector
|
||||||
const float MOUSE_HAND_FORCE = 1.5;
|
const float MOUSE_HAND_FORCE = 1.5;
|
||||||
float dx = mouse_x - mouse_start_x;
|
float dx = mouseX - mouseStartX;
|
||||||
float dy = mouse_y - mouse_start_y;
|
float dy = mouseY - mouseStartY;
|
||||||
glm::vec3 vel(dx*MOUSE_HAND_FORCE, -dy*MOUSE_HAND_FORCE*(WIDTH/HEIGHT), 0);
|
glm::vec3 vel(dx*MOUSE_HAND_FORCE, -dy*MOUSE_HAND_FORCE*(WIDTH/HEIGHT), 0);
|
||||||
myHead.hand->addVelocity(vel*deltaTime);
|
myHead.hand->addVelocity(vel*deltaTime);
|
||||||
}
|
}
|
||||||
|
@ -463,7 +409,7 @@ void simulateHead(float frametime)
|
||||||
//float measured_lateral_accel = serialPort.getRelativeValue(ACCEL_X);
|
//float measured_lateral_accel = serialPort.getRelativeValue(ACCEL_X);
|
||||||
//float measured_fwd_accel = serialPort.getRelativeValue(ACCEL_Z);
|
//float measured_fwd_accel = serialPort.getRelativeValue(ACCEL_Z);
|
||||||
|
|
||||||
myHead.UpdatePos(frametime, &serialPort, head_mirror, &gravity);
|
myHead.UpdatePos(frametime, &serialPort, headMirror, &gravity);
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// set the position of the avatar
|
// set the position of the avatar
|
||||||
|
@ -476,13 +422,13 @@ void simulateHead(float frametime)
|
||||||
if (powf(measured_yaw_rate*measured_yaw_rate +
|
if (powf(measured_yaw_rate*measured_yaw_rate +
|
||||||
measured_pitch_rate*measured_pitch_rate, 0.5) > MIN_MOUSE_RATE)
|
measured_pitch_rate*measured_pitch_rate, 0.5) > MIN_MOUSE_RATE)
|
||||||
{
|
{
|
||||||
head_mouse_x += measured_yaw_rate*MOUSE_SENSITIVITY;
|
headMouseX += measured_yaw_rate*MOUSE_SENSITIVITY;
|
||||||
head_mouse_y += measured_pitch_rate*MOUSE_SENSITIVITY*(float)HEIGHT/(float)WIDTH;
|
headMouseY += measured_pitch_rate*MOUSE_SENSITIVITY*(float)HEIGHT/(float)WIDTH;
|
||||||
}
|
}
|
||||||
head_mouse_x = max(head_mouse_x, 0);
|
headMouseX = max(headMouseX, 0);
|
||||||
head_mouse_x = min(head_mouse_x, WIDTH);
|
headMouseX = min(headMouseX, WIDTH);
|
||||||
head_mouse_y = max(head_mouse_y, 0);
|
headMouseY = max(headMouseY, 0);
|
||||||
head_mouse_y = min(head_mouse_y, HEIGHT);
|
headMouseY = min(headMouseY, HEIGHT);
|
||||||
|
|
||||||
// Update render direction (pitch/yaw) based on measured gyro rates
|
// Update render direction (pitch/yaw) based on measured gyro rates
|
||||||
const int MIN_YAW_RATE = 100;
|
const int MIN_YAW_RATE = 100;
|
||||||
|
@ -563,12 +509,6 @@ void simulateHead(float frametime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int render_test_spot = WIDTH/2;
|
|
||||||
int render_test_direction = 1;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void display(void)
|
void display(void)
|
||||||
{
|
{
|
||||||
PerfStat("display");
|
PerfStat("display");
|
||||||
|
@ -601,7 +541,7 @@ void display(void)
|
||||||
//--------------------------------------------------------
|
//--------------------------------------------------------
|
||||||
myCamera.setTargetPosition( myHead.getPos() );
|
myCamera.setTargetPosition( myHead.getPos() );
|
||||||
|
|
||||||
if ( display_head )
|
if ( displayHead )
|
||||||
{
|
{
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
// set the camera to looking at my own face
|
// set the camera to looking at my own face
|
||||||
|
@ -650,13 +590,13 @@ void display(void)
|
||||||
// Draw cloud of dots
|
// Draw cloud of dots
|
||||||
glDisable( GL_POINT_SPRITE_ARB );
|
glDisable( GL_POINT_SPRITE_ARB );
|
||||||
glDisable( GL_TEXTURE_2D );
|
glDisable( GL_TEXTURE_2D );
|
||||||
// if (!display_head) cloud.render();
|
if (!displayHead) cloud.render();
|
||||||
|
|
||||||
// Draw voxels
|
// Draw voxels
|
||||||
voxels.render();
|
voxels.render();
|
||||||
|
|
||||||
// Draw field vectors
|
// Draw field vectors
|
||||||
if (display_field) field.render();
|
if (displayField) field.render();
|
||||||
|
|
||||||
// Render heads of other agents
|
// Render heads of other agents
|
||||||
for(std::vector<Agent>::iterator agent = agentList.getAgents().begin(); agent != agentList.getAgents().end(); agent++)
|
for(std::vector<Agent>::iterator agent = agentList.getAgents().begin(); agent != agentList.getAgents().end(); agent++)
|
||||||
|
@ -672,10 +612,10 @@ void display(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !display_head ) balls.render();
|
if ( !displayHead ) balls.render();
|
||||||
|
|
||||||
// Render the world box
|
// Render the world box
|
||||||
if (!display_head && stats_on) render_world_box();
|
if (!displayHead && statsOn) render_world_box();
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
|
@ -687,7 +627,7 @@ void display(void)
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glTranslatef(0.f, 0.f, -7.f);
|
glTranslatef(0.f, 0.f, -7.f);
|
||||||
myHead.render(display_head, 1);
|
myHead.render(displayHead, 1);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -714,57 +654,31 @@ void display(void)
|
||||||
//drawvec3(100, 100, 0.15, 0, 1.0, 0, myHead.getPos(), 0, 1, 0);
|
//drawvec3(100, 100, 0.15, 0, 1.0, 0, myHead.getPos(), 0, 1, 0);
|
||||||
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, pointer_attenuation_quadratic );
|
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, pointer_attenuation_quadratic );
|
||||||
|
|
||||||
if (mouse_pressed == 1)
|
if (displayHeadMouse && !displayHead && statsOn)
|
||||||
{
|
|
||||||
glPointSize( 10.0f );
|
|
||||||
glColor3f(1,1,1);
|
|
||||||
//glEnable(GL_POINT_SMOOTH);
|
|
||||||
glBegin(GL_POINTS);
|
|
||||||
glVertex2f(target_x, target_y);
|
|
||||||
glEnd();
|
|
||||||
char val[20];
|
|
||||||
sprintf(val, "%d,%d", target_x, target_y);
|
|
||||||
drawtext(target_x, target_y-20, 0.08, 0, 1.0, 0, val, 0, 1, 0);
|
|
||||||
}
|
|
||||||
if (display_head_mouse && !display_head && stats_on)
|
|
||||||
{
|
{
|
||||||
// Display small target box at center or head mouse target that can also be used to measure LOD
|
// Display small target box at center or head mouse target that can also be used to measure LOD
|
||||||
glColor3f(1.0, 1.0, 1.0);
|
glColor3f(1.0, 1.0, 1.0);
|
||||||
glDisable(GL_LINE_SMOOTH);
|
glDisable(GL_LINE_SMOOTH);
|
||||||
const int PIXEL_BOX = 20;
|
const int PIXEL_BOX = 20;
|
||||||
glBegin(GL_LINE_STRIP);
|
glBegin(GL_LINE_STRIP);
|
||||||
glVertex2f(head_mouse_x - PIXEL_BOX/2, head_mouse_y - PIXEL_BOX/2);
|
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||||
glVertex2f(head_mouse_x + PIXEL_BOX/2, head_mouse_y - PIXEL_BOX/2);
|
glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||||
glVertex2f(head_mouse_x + PIXEL_BOX/2, head_mouse_y + PIXEL_BOX/2);
|
glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
|
||||||
glVertex2f(head_mouse_x - PIXEL_BOX/2, head_mouse_y + PIXEL_BOX/2);
|
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
|
||||||
glVertex2f(head_mouse_x - PIXEL_BOX/2, head_mouse_y - PIXEL_BOX/2);
|
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
glEnable(GL_LINE_SMOOTH);
|
glEnable(GL_LINE_SMOOTH);
|
||||||
}
|
}
|
||||||
// Spot bouncing back and forth on bottom of screen
|
|
||||||
if (0)
|
|
||||||
{
|
|
||||||
glPointSize(50.0f);
|
|
||||||
glColor4f(1.0, 1.0, 1.0, 1.0);
|
|
||||||
glEnable(GL_POINT_SMOOTH);
|
|
||||||
glBegin(GL_POINTS);
|
|
||||||
glVertex2f(render_test_spot, HEIGHT-100);
|
|
||||||
glEnd();
|
|
||||||
render_test_spot += render_test_direction*50;
|
|
||||||
if ((render_test_spot > WIDTH-100) || (render_test_spot < 100)) render_test_direction *= -1.0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Show detected levels from the serial I/O ADC channel sensors
|
// Show detected levels from the serial I/O ADC channel sensors
|
||||||
if (display_levels) serialPort.renderLevels(WIDTH,HEIGHT);
|
if (displayLevels) serialPort.renderLevels(WIDTH,HEIGHT);
|
||||||
|
|
||||||
// Display miscellaneous text stats onscreen
|
// Display miscellaneous text stats onscreen
|
||||||
if (stats_on) {
|
if (statsOn) {
|
||||||
glLineWidth(1.0f);
|
glLineWidth(1.0f);
|
||||||
glPointSize(1.0f);
|
glPointSize(1.0f);
|
||||||
display_stats();
|
displayStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw number of nearby people always
|
// Draw number of nearby people always
|
||||||
|
@ -785,13 +699,9 @@ void display(void)
|
||||||
|
|
||||||
|
|
||||||
glutSwapBuffers();
|
glutSwapBuffers();
|
||||||
framecount++;
|
frameCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void testPointToVoxel()
|
void testPointToVoxel()
|
||||||
{
|
{
|
||||||
float y=0;
|
float y=0;
|
||||||
|
@ -931,7 +841,7 @@ void key(unsigned char k, int x, int y)
|
||||||
|
|
||||||
// Process keypresses
|
// Process keypresses
|
||||||
if (k == 'q') ::terminate();
|
if (k == 'q') ::terminate();
|
||||||
if (k == '/') stats_on = !stats_on; // toggle stats
|
if (k == '/') statsOn = !statsOn; // toggle stats
|
||||||
if (k == '*') ::starsOn = !::starsOn; // toggle stars
|
if (k == '*') ::starsOn = !::starsOn; // toggle stars
|
||||||
if (k == '&') {
|
if (k == '&') {
|
||||||
::paintOn = !::paintOn; // toggle paint
|
::paintOn = !::paintOn; // toggle paint
|
||||||
|
@ -942,8 +852,8 @@ void key(unsigned char k, int x, int y)
|
||||||
if (k == '%') ::sendVoxelServerAddScene(); // sends add scene command to voxel server
|
if (k == '%') ::sendVoxelServerAddScene(); // sends add scene command to voxel server
|
||||||
if (k == 'n')
|
if (k == 'n')
|
||||||
{
|
{
|
||||||
noise_on = !noise_on; // Toggle noise
|
noiseOn = !noiseOn; // Toggle noise
|
||||||
if (noise_on)
|
if (noiseOn)
|
||||||
{
|
{
|
||||||
myHead.setNoise(noise);
|
myHead.setNoise(noise);
|
||||||
}
|
}
|
||||||
|
@ -955,16 +865,16 @@ void key(unsigned char k, int x, int y)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k == 'h') {
|
if (k == 'h') {
|
||||||
display_head = !display_head;
|
displayHead = !displayHead;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
audio.setMixerLoopbackFlag(display_head);
|
audio.setMixerLoopbackFlag(displayHead);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k == 'm') head_mirror = !head_mirror;
|
if (k == 'm') headMirror = !headMirror;
|
||||||
|
|
||||||
if (k == 'f') display_field = !display_field;
|
if (k == 'f') displayField = !displayField;
|
||||||
if (k == 'l') display_levels = !display_levels;
|
if (k == 'l') displayLevels = !displayLevels;
|
||||||
if (k == 'e') myHead.setDriveKeys(UP, 1);
|
if (k == 'e') myHead.setDriveKeys(UP, 1);
|
||||||
if (k == 'c') myHead.setDriveKeys(DOWN, 1);
|
if (k == 'c') myHead.setDriveKeys(DOWN, 1);
|
||||||
if (k == 'w') myHead.setDriveKeys(FWD, 1);
|
if (k == 'w') myHead.setDriveKeys(FWD, 1);
|
||||||
|
@ -981,18 +891,6 @@ void key(unsigned char k, int x, int y)
|
||||||
#endif
|
#endif
|
||||||
if (k == 'a') myHead.setDriveKeys(ROT_LEFT, 1);
|
if (k == 'a') myHead.setDriveKeys(ROT_LEFT, 1);
|
||||||
if (k == 'd') myHead.setDriveKeys(ROT_RIGHT, 1);
|
if (k == 'd') myHead.setDriveKeys(ROT_RIGHT, 1);
|
||||||
if (k == 'o') simulate_on = !simulate_on;
|
|
||||||
if (k == 'p')
|
|
||||||
{
|
|
||||||
// Add to field vector
|
|
||||||
float pos[] = {5,5,5};
|
|
||||||
float add[] = {0.001, 0.001, 0.001};
|
|
||||||
field.add(add, pos);
|
|
||||||
}
|
|
||||||
if (k == '1')
|
|
||||||
{
|
|
||||||
myHead.SetNewHeadTarget((randFloat()-0.5)*20.0, (randFloat()-0.5)*20.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// press the . key to get a new random sphere of voxels added
|
// press the . key to get a new random sphere of voxels added
|
||||||
if (k == '.') addRandomSphere(wantColorRandomizer);
|
if (k == '.') addRandomSphere(wantColorRandomizer);
|
||||||
|
@ -1009,8 +907,8 @@ void *networkReceive(void *args)
|
||||||
|
|
||||||
while (!stopNetworkReceiveThread) {
|
while (!stopNetworkReceiveThread) {
|
||||||
if (agentList.getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
if (agentList.getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
||||||
packetcount++;
|
packetCount++;
|
||||||
bytescount += bytesReceived;
|
bytesCount += bytesReceived;
|
||||||
|
|
||||||
if (incomingPacket[0] == PACKET_HEADER_TRANSMITTER_DATA) {
|
if (incomingPacket[0] == PACKET_HEADER_TRANSMITTER_DATA) {
|
||||||
// Pass everything but transmitter data to the agent list
|
// Pass everything but transmitter data to the agent list
|
||||||
|
@ -1034,18 +932,17 @@ void idle(void)
|
||||||
timeval check;
|
timeval check;
|
||||||
gettimeofday(&check, NULL);
|
gettimeofday(&check, NULL);
|
||||||
|
|
||||||
// Check and render display frame
|
// Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time
|
||||||
if (diffclock(&last_frame, &check) > RENDER_FRAME_MSECS)
|
|
||||||
|
if (diffclock(&lastTimeIdle, &check) > IDLE_SIMULATE_MSECS)
|
||||||
{
|
{
|
||||||
steps_per_frame++;
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// If mouse is being dragged, update hand movement in the avatar
|
// If mouse is being dragged, update hand movement in the avatar
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
if ( mouse_pressed == 1 )
|
if ( mousePressed == 1 )
|
||||||
{
|
{
|
||||||
float xOffset = ( mouse_x - mouse_start_x ) / (double)WIDTH;
|
float xOffset = ( mouseX - mouseStartX ) / (double)WIDTH;
|
||||||
float yOffset = ( mouse_y - mouse_start_y ) / (double)HEIGHT;
|
float yOffset = ( mouseY - mouseStartY ) / (double)HEIGHT;
|
||||||
|
|
||||||
float leftRight = xOffset;
|
float leftRight = xOffset;
|
||||||
float downUp = yOffset;
|
float downUp = yOffset;
|
||||||
|
@ -1074,17 +971,15 @@ void idle(void)
|
||||||
|
|
||||||
simulateHand(1.f/FPS);
|
simulateHand(1.f/FPS);
|
||||||
|
|
||||||
if (simulate_on) {
|
field.simulate(1.f/FPS);
|
||||||
field.simulate(1.f/FPS);
|
myHead.simulate(1.f/FPS);
|
||||||
myHead.simulate(1.f/FPS);
|
balls.simulate(1.f/FPS);
|
||||||
balls.simulate(1.f/FPS);
|
cloud.simulate(1.f/FPS);
|
||||||
cloud.simulate(1.f/FPS);
|
lattice.simulate(1.f/FPS);
|
||||||
lattice.simulate(1.f/FPS);
|
myFinger.simulate(1.f/FPS);
|
||||||
myFinger.simulate(1.f/FPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!step_on) glutPostRedisplay();
|
glutPostRedisplay();
|
||||||
last_frame = check;
|
lastTimeIdle = check;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1120,38 +1015,38 @@ void mouseFunc( int button, int state, int x, int y )
|
||||||
{
|
{
|
||||||
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
|
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
|
||||||
{
|
{
|
||||||
mouse_x = x;
|
mouseX = x;
|
||||||
mouse_y = y;
|
mouseY = y;
|
||||||
mouse_pressed = 1;
|
mousePressed = 1;
|
||||||
lattice.mouseClick((float)x/(float)WIDTH,(float)y/(float)HEIGHT);
|
lattice.mouseClick((float)x/(float)WIDTH,(float)y/(float)HEIGHT);
|
||||||
mouse_start_x = x;
|
mouseStartX = x;
|
||||||
mouse_start_y = y;
|
mouseStartY = y;
|
||||||
}
|
}
|
||||||
if( button == GLUT_LEFT_BUTTON && state == GLUT_UP )
|
if( button == GLUT_LEFT_BUTTON && state == GLUT_UP )
|
||||||
{
|
{
|
||||||
mouse_x = x;
|
mouseX = x;
|
||||||
mouse_y = y;
|
mouseY = y;
|
||||||
mouse_pressed = 0;
|
mousePressed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void motionFunc( int x, int y)
|
void motionFunc( int x, int y)
|
||||||
{
|
{
|
||||||
mouse_x = x;
|
mouseX = x;
|
||||||
mouse_y = y;
|
mouseY = y;
|
||||||
|
|
||||||
lattice.mouseClick((float)x/(float)WIDTH,(float)y/(float)HEIGHT);
|
lattice.mouseClick((float)x/(float)WIDTH,(float)y/(float)HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouseoverFunc( int x, int y)
|
void mouseoverFunc( int x, int y)
|
||||||
{
|
{
|
||||||
mouse_x = x;
|
mouseX = x;
|
||||||
mouse_y = y;
|
mouseY = y;
|
||||||
if (mouse_pressed == 0)
|
if (mousePressed == 0)
|
||||||
{
|
{
|
||||||
// lattice.mouseOver((float)x/(float)WIDTH,(float)y/(float)HEIGHT);
|
// lattice.mouseOver((float)x/(float)WIDTH,(float)y/(float)HEIGHT);
|
||||||
// myFinger.setTarget(mouse_x, mouse_y);
|
// myFinger.setTarget(mouseX, mouseY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1209,6 +1104,8 @@ int main(int argc, const char * argv[])
|
||||||
printf( "Created Display Window.\n" );
|
printf( "Created Display Window.\n" );
|
||||||
|
|
||||||
initDisplay();
|
initDisplay();
|
||||||
|
printf( "Initialized Display.\n" );
|
||||||
|
|
||||||
|
|
||||||
glutDisplayFunc(display);
|
glutDisplayFunc(display);
|
||||||
glutReshapeFunc(reshape);
|
glutReshapeFunc(reshape);
|
||||||
|
@ -1221,9 +1118,10 @@ int main(int argc, const char * argv[])
|
||||||
glutMouseFunc(mouseFunc);
|
glutMouseFunc(mouseFunc);
|
||||||
glutIdleFunc(idle);
|
glutIdleFunc(idle);
|
||||||
|
|
||||||
printf( "Initialized Display.\n" );
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
printf( "Init() complete.\n" );
|
||||||
|
|
||||||
|
|
||||||
// Check to see if the user passed in a command line option for randomizing colors
|
// Check to see if the user passed in a command line option for randomizing colors
|
||||||
if (cmdOptionExists(argc, argv, "--NoColorRandomizer")) {
|
if (cmdOptionExists(argc, argv, "--NoColorRandomizer")) {
|
||||||
|
@ -1235,16 +1133,17 @@ int main(int argc, const char * argv[])
|
||||||
const char* voxelsFilename = getCmdOption(argc, argv, "-i");
|
const char* voxelsFilename = getCmdOption(argc, argv, "-i");
|
||||||
if (voxelsFilename) {
|
if (voxelsFilename) {
|
||||||
voxels.loadVoxelsFile(voxelsFilename,wantColorRandomizer);
|
voxels.loadVoxelsFile(voxelsFilename,wantColorRandomizer);
|
||||||
|
printf("Local Voxel File loaded.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// create thread for receipt of data via UDP
|
// create thread for receipt of data via UDP
|
||||||
pthread_create(&networkReceiveThread, NULL, networkReceive, NULL);
|
pthread_create(&networkReceiveThread, NULL, networkReceive, NULL);
|
||||||
|
printf("Network receive thread created.\n");
|
||||||
printf( "Init() complete.\n" );
|
|
||||||
|
|
||||||
glutTimerFunc(1000, Timer, 0);
|
glutTimerFunc(1000, Timer, 0);
|
||||||
glutMainLoop();
|
glutMainLoop();
|
||||||
|
|
||||||
|
printf("Normal exit.\n");
|
||||||
::terminate();
|
::terminate();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
//
|
|
||||||
// octal.cpp
|
|
||||||
// interface
|
|
||||||
//
|
|
||||||
// Created by Philip on 2/4/13.
|
|
||||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// Various subroutines for converting between X,Y,Z coords and octree coordinates.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "Util.h"
|
|
||||||
#include "octal.h"
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
const int X = 0;
|
|
||||||
const int Y = 1;
|
|
||||||
const int Z = 2;
|
|
||||||
|
|
||||||
domainNode rootNode;
|
|
||||||
|
|
||||||
// Given a position vector between zero and one (but less than one), and a voxel scale 1/2^scale,
|
|
||||||
// returns the smallest voxel at that scale which encloses the given point.
|
|
||||||
void getVoxel(float * pos, int scale, float * vpos) {
|
|
||||||
float vscale = powf(2, scale);
|
|
||||||
vpos[X] = floor(pos[X]*vscale)/vscale;
|
|
||||||
vpos[Y] = floor(pos[Y]*vscale)/vscale;
|
|
||||||
vpos[Z] = floor(pos[Z]*vscale)/vscale;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
//
|
|
||||||
// octal.h
|
|
||||||
// interface
|
|
||||||
//
|
|
||||||
// Created by Philip on 2/4/13.
|
|
||||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __interface__octal__
|
|
||||||
#define __interface__octal__
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
struct domainNode {
|
|
||||||
domainNode * child[8];
|
|
||||||
char * hostname;
|
|
||||||
char * nickname;
|
|
||||||
int domain_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
domainNode* createNode(int lengthInBits, char * octalData,
|
|
||||||
char * hostname, char * nickname, int domain_id);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* defined(__interface__octal__) */
|
|
Loading…
Reference in a new issue