History

Various fixes, removed the bulk of main.cpp.

Andrzej Kapolka committed 13 years ago

Commit 1e993891 parent 75eee4b5 files · +56 −2165Browse files

Showing the changes to interface/src/main.cpp (1 of 5 files). Show all

Unified · Split

interface/src/main.cpp+1−2153
@@ -15,2040 +15,8 @@ · 14 unmodified lines
1515 // Welcome Aboard!
1616 //
1717
18−#include <math.h>
19−#include <string.h>
20−#include <sstream>
21−#include <stdio.h>
22−#include <stdlib.h>
23−
24−#ifdef _WIN32
25−#include "Syssocket.h"
26−#include "Systime.h"
27−#else
28−#include <sys/time.h>
29−#include <arpa/inet.h>
30−#include <ifaddrs.h>
31−#endif
32−
33−#include <pthread.h>
34−
35−#include <glm/glm.hpp>
36−#include <glm/gtc/matrix_transform.hpp>
37−#include <glm/gtc/type_ptr.hpp>
38−
39−#include "InterfaceConfig.h"
40−
41−#include "Log.h"
42−#include "shared_Log.h"
43−#include "voxels_Log.h"
44−#include "avatars_Log.h"
45−
46−#include "world.h"
47−#include "Util.h"
48−#ifndef _WIN32
49−#include "Audio.h"
50−#endif
51−
52−#include "AngleUtil.h"
53−#include "Stars.h"
54−
55−#include "ui/ChatEntry.h"
56−#include "ui/MenuRow.h"
57−#include "ui/MenuColumn.h"
58−#include "ui/Menu.h"
59−#include "ui/TextRenderer.h"
60−#include "renderer/ProgramObject.h"
61−#include "renderer/ShaderObject.h"
62−
6318 #include "Application.h"
64−#include "Camera.h"
65−#include "Avatar.h"
66−#include <AgentList.h>
67−#include <AgentTypes.h>
68−#include "VoxelSystem.h"
69−#include "Environment.h"
70−#include "Oscilloscope.h"
71−#include "UDPSocket.h"
72−#include "SerialInterface.h"
73−#include <PacketHeaders.h>
74−#include <AvatarData.h>
75−#include <PerfStat.h>
76−#include <SimpleMovingAverage.h>
77−
78−#include "ViewFrustum.h"
79−#include "HandControl.h"
80−#include "AvatarRenderer.h"
81−#include "OculusManager.h"
82−
83−using namespace std;
84−
85−void reshape(int width, int height); // will be defined below
86−void loadViewFrustum(ViewFrustum& viewFrustum); // will be defined below
87−
88−glm::vec3 getGravity(glm::vec3 pos); //get the local gravity vector at this location in the universe
89−
90−bool enableNetworkThread = true;
91−pthread_t networkReceiveThread;
92−bool stopNetworkReceiveThread = false;
93−
94−unsigned char incomingPacket[MAX_PACKET_SIZE];
95−int packetCount = 0;
96−int packetsPerSecond = 0;
97−int bytesPerSecond = 0;
98−int bytesCount = 0;
99−
100−
101−int screenWidth = 1200; // Window size
102−int screenHeight = 800;
103−
104−int fullscreen = 0;
105−float aspectRatio = 1.0f;
106−
107−// PER: Jeffrey - please move these our of main.cpp - also these not constants!
108−float mouseViewShiftYaw = 0.0f;
109−float mouseViewShiftPitch = 0.0f;
110−bool USING_MOUSE_VIEW_SHIFT = false;
111−float MOUSE_VIEW_SHIFT_RATE = 40.0f;
112−float MOUSE_VIEW_SHIFT_YAW_MARGIN = (float)(::screenWidth * 0.2f);
113−float MOUSE_VIEW_SHIFT_PITCH_MARGIN = (float)(::screenHeight * 0.2f);
114−float MOUSE_VIEW_SHIFT_YAW_LIMIT = 45.0;
115−float MOUSE_VIEW_SHIFT_PITCH_LIMIT = 30.0;
116−
117−//CameraMode defaultCameraMode = CAMERA_MODE_FIRST_PERSON;
118−CameraMode defaultCameraMode = CAMERA_MODE_THIRD_PERSON;
119−
120−bool wantColorRandomizer = true; // for addSphere and load file
121−
122−Oscilloscope audioScope(256,200,true);
123−
124−ViewFrustum viewFrustum; // current state of view frustum, perspective, orientation, etc.
125−
126−Avatar myAvatar(true); // The rendered avatar of oneself
127−Camera myCamera; // My view onto the world
128−Camera viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
129−
130−AvatarRenderer avatarRenderer;
131−
132−// Starfield information
133−char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
134−char starCacheFile[] = "cachedStars.txt";
135−Stars stars;
136−
137−glm::vec3 box(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);
138−
139−VoxelSystem voxels;
140−
141−Environment environment;
142−
143−
144−#ifndef _WIN32
145−Audio audio(&audioScope, &myAvatar);
146−#endif
147−
148−#define IDLE_SIMULATE_MSECS 16 // How often should call simulate and other stuff
149− // in the idle loop? (60 FPS is default)
150−
151−
152−glm::vec3 start_location(6.1f, 0, 1.4f); // Where one's own agent begins in the world
153− // (will be overwritten if avatar data file is found)
154−
155−bool renderWarningsOn = false; // Whether to show render pipeline warnings
156−bool renderStatsOn = false; // Whether to show onscreen text overlay with stats
157−bool renderVoxels = true; // Whether to render voxels
158−bool renderStarsOn = true; // Whether to display the stars
159−bool renderAtmosphereOn = true; // Whether to display the atmosphere
160−bool renderAvatarsOn = true; // Whether to render avatars
161−bool renderFirstPersonOn = false; // Whether to render in first person
162−bool paintOn = false; // Whether to paint voxels as you fly around
163−VoxelDetail paintingVoxel; // The voxel we're painting if we're painting
164−unsigned char dominantColor = 0; // The dominant color of the voxel we're painting
165−bool perfStatsOn = false; // Do we want to display perfStats?
166−bool wantMonochrome = false; // ask server to send us in monochrome
167−bool wantResIn = false; // ask server to res in
168−
169−bool logOn = true; // Whether to show on-screen log
170−
171−bool wantToKillLocalVoxels = false;
172−
173−int noiseOn = 0; // Whether to add random noise
174−float noise = 1.0; // Overall magnitude scaling for random noise levels
175−
176−bool gyroLook = true; // Whether to allow the gyro data from head to move your view
177−
178−int displayLevels = 0;
179−bool lookingInMirror = 0; // Are we currently rendering one's own head as if in mirror?
180−
181−int displayHeadMouse = 1; // Display sample mouse pointer controlled by head movement
182−int headMouseX, headMouseY;
183−
184−HandControl handControl;
185−
186−int mouseX = 0;
187−int mouseY = 0;
188−
189−// Mouse location at start of last down click
190−int mousePressed = 0; // true if mouse has been pressed (clear when finished)
191−
192−// The current mode for mouse interaction
193−enum MouseMode { NO_EDIT_MODE, ADD_VOXEL_MODE, DELETE_VOXEL_MODE, COLOR_VOXEL_MODE };
194−MouseMode mouseMode = NO_EDIT_MODE;
195−VoxelDetail mouseVoxel; // details of the voxel under the mouse cursor
196−float mouseVoxelScale = 1.0f / 1024.0f; // the scale for adding/removing voxels
197−
198−Menu menu; // main menu
199−int menuOn = 1; // Whether to show onscreen menu
200−
201−ChatEntry chatEntry; // chat entry field
202−bool chatEntryOn = false; // Whether to show the chat entry
203−
204−bool oculusOn = false; // Whether to configure the display for the Oculus Rift
205−GLuint oculusTextureID = 0; // The texture to which we render for Oculus distortion
206−ProgramObject* oculusProgram = 0; // The GLSL program containing the distortion shader
207−float oculusDistortionScale = 1.25; // Controls the Oculus field of viewa
208−
209−SerialInterface serialPort;
210−
211−glm::vec3 gravity;
212−
213−// Frame Rate Measurement
214−
215−int frameCount = 0;
216−float FPS = 120.f;
217−timeval timerStart, timerEnd;
218−timeval lastTimeIdle;
219−double elapsedTime;
220−timeval applicationStartupTime;
221−bool justStarted = true;
222−
223−// Every second, check the frame rates and other stuff
224−void Timer(int extra) {
225− gettimeofday(&timerEnd, NULL);
226− FPS = (float)frameCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f);
227− packetsPerSecond = (float)packetCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f);
228− bytesPerSecond = (float)bytesCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f);
229− frameCount = 0;
230− packetCount = 0;
231− bytesCount = 0;
232−
233− glutTimerFunc(1000,Timer,0);
234− gettimeofday(&timerStart, NULL);
235−
236− // if we haven't detected gyros, check for them now
237− if (!serialPort.active) {
238− serialPort.pair();
239− }
240−}
241−
242−void displayStats(void) {
243− int statsVerticalOffset = 50;
244− if (::menuOn == 0) {
245− statsVerticalOffset = 8;
246− }
247−
248− char stats[200];
249− sprintf(stats, "%3.0f FPS, %d Pkts/sec, %3.2f Mbps",
250− FPS, packetsPerSecond, (float)bytesPerSecond * 8.f / 1000000.f);
251− drawtext(10, statsVerticalOffset + 15, 0.10f, 0, 1.0, 0, stats);
252−
253− std::stringstream voxelStats;
254− voxelStats.precision(4);
255− voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered() / 1000.f << "K Updated: " << voxels.getVoxelsUpdated()/1000.f << "K";
256− drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
257−
258− voxelStats.str("");
259− voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() / 1000.f << "K (" << voxels.getVoxelsCreatedPerSecondAverage() / 1000.f
260− << "Kps) ";
261− drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
262−
263− voxelStats.str("");
264− voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() / 1000.f << "K (" << voxels.getVoxelsColoredPerSecondAverage() / 1000.f
265− << "Kps) ";
266− drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
267−
268− voxelStats.str("");
269− voxelStats << "Voxel Bits Read: " << voxels.getVoxelsBytesRead() * 8.f / 1000000.f
270− << "M (" << voxels.getVoxelsBytesReadPerSecondAverage() * 8.f / 1000000.f << " Mbps)";
271− drawtext(10, statsVerticalOffset + 290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
272−
273− voxelStats.str("");
274− float voxelsBytesPerColored = voxels.getVoxelsColored()
275− ? ((float) voxels.getVoxelsBytesRead() / voxels.getVoxelsColored())
276− : 0;
277−
278− voxelStats << "Voxels Bits per Colored: " << voxelsBytesPerColored * 8;
279− drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
280−
281− Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
282− char avatarMixerStats[200];
283−
284− if (avatarMixer) {
285− sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
286− roundf(avatarMixer->getAverageKilobitsPerSecond()),
287− roundf(avatarMixer->getAveragePacketsPerSecond()));
288− } else {
289− sprintf(avatarMixerStats, "No Avatar Mixer");
290− }
291−
292− drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, avatarMixerStats);
293−
294− if (::perfStatsOn) {
295− // Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups
296− char** perfStatLinesArray = new char*[PerfStat::getGroupCount()+1];
297− int lines = PerfStat::DumpStats(perfStatLinesArray);
298− int atZ = 150; // arbitrary place on screen that looks good
299− for (int line=0; line < lines; line++) {
300− drawtext(10, statsVerticalOffset + atZ, 0.10f, 0, 1.0, 0, perfStatLinesArray[line]);
301− delete perfStatLinesArray[line]; // we're responsible for cleanup
302− perfStatLinesArray[line]=NULL;
303− atZ+=20; // height of a line
304− }
305− delete []perfStatLinesArray; // we're responsible for cleanup
306− }
307−}
308−
309−void initDisplay(void) {
310− glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
311− glEnable(GL_BLEND);
312− glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
313− glShadeModel (GL_SMOOTH);
314− glEnable(GL_LIGHTING);
315− glEnable(GL_LIGHT0);
316− glEnable(GL_DEPTH_TEST);
317−
318− if (fullscreen) glutFullScreen();
319−}
320−
321−void init(void) {
322− voxels.init();
323− voxels.setViewerAvatar(&myAvatar);
324− voxels.setCamera(&myCamera);
325−
326− environment.init();
327−
328− handControl.setScreenDimensions(::screenWidth, ::screenHeight);
329−
330− headMouseX = ::screenWidth /2;
331− headMouseY = ::screenHeight/2;
332−
333− stars.readInput(starFile, starCacheFile, 0);
334−
335− if (noiseOn) {
336− myAvatar.setNoise(noise);
337− }
338−
339− myAvatar.setPosition(start_location);
340− myCamera.setMode(defaultCameraMode);
341−
342− OculusManager::connect();
343−
344− gettimeofday(&timerStart, NULL);
345− gettimeofday(&lastTimeIdle, NULL);
346−}
347−
348−void terminate () {
349− // Close serial port
350− // close(serial_fd);
351−
352− myAvatar.writeAvatarDataToFile();
353−
354− #ifndef _WIN32
355− audio.terminate();
356− #endif
357−
358− if (enableNetworkThread) {
359− stopNetworkReceiveThread = true;
360− pthread_join(networkReceiveThread, NULL);
361− }
362−
363− exit(EXIT_SUCCESS);
364−}
365−
366−void reset_sensors() {
367−
368− myAvatar.setPosition(start_location);
369− headMouseX = ::screenWidth / 2;
370− headMouseY = ::screenHeight / 2;
371−
372− myAvatar.reset();
373−}
374−
375−void sendVoxelEditMessage(PACKET_HEADER header, VoxelDetail& detail) {
376− unsigned char* bufferOut;
377− int sizeOut;
378−
379− if (createVoxelEditMessage(header, 0, 1, &detail, bufferOut, sizeOut)){
380− AgentList::getInstance()->broadcastToAgents(bufferOut, sizeOut, &AGENT_TYPE_VOXEL, 1);
381− delete bufferOut;
382− }
383−}
384−
385−// Using gyro data, update both view frustum and avatar head position
386−void updateAvatar(float deltaTime) {
387−
388− // Update my avatar's head position from gyros
389− myAvatar.updateHeadFromGyros(deltaTime, &serialPort, &gravity);
390−
391− // Grab latest readings from the gyros
392− float measuredPitchRate = serialPort.getLastPitchRate();
393− float measuredYawRate = serialPort.getLastYawRate();
394−
395− // Update gyro-based mouse (X,Y on screen)
396− const float MIN_MOUSE_RATE = 1.0;
397− const float HORIZONTAL_PIXELS_PER_DEGREE = 2880.f / 45.f;
398− const float VERTICAL_PIXELS_PER_DEGREE = 1800.f / 30.f;
399− if (powf(measuredYawRate * measuredYawRate +
400− measuredPitchRate * measuredPitchRate, 0.5) > MIN_MOUSE_RATE)
401− {
402− headMouseX += measuredYawRate * HORIZONTAL_PIXELS_PER_DEGREE * deltaTime;
403− headMouseY -= measuredPitchRate * VERTICAL_PIXELS_PER_DEGREE * deltaTime;
404− }
405− headMouseX = max(headMouseX, 0);
406− headMouseX = min(headMouseX, ::screenWidth);
407− headMouseY = max(headMouseY, 0);
408− headMouseY = min(headMouseY, ::screenHeight);
409−
410− // Update head and body pitch and yaw based on measured gyro rates
411− if (::gyroLook) {
412− // Render Yaw
413− float renderYawSpring = fabs(headMouseX - ::screenWidth / 2.f) / (::screenWidth / 2.f);
414− const float RENDER_YAW_MULTIPLY = 4.f;
415− myAvatar.setRenderYaw((1.f - renderYawSpring * deltaTime) * myAvatar.getRenderYaw() +
416− renderYawSpring * deltaTime * -myAvatar.getHeadYaw() * RENDER_YAW_MULTIPLY);
417− // Render Pitch
418− float renderPitchSpring = fabs(headMouseY - ::screenHeight / 2.f) / (::screenHeight / 2.f);
419− const float RENDER_PITCH_MULTIPLY = 4.f;
420− myAvatar.setRenderPitch((1.f - renderPitchSpring * deltaTime) * myAvatar.getRenderPitch() +
421− renderPitchSpring * deltaTime * -myAvatar.getHeadPitch() * RENDER_PITCH_MULTIPLY);
422− }
423−
424−
425− if (USING_MOUSE_VIEW_SHIFT)
426− {
427− //make it so that when your mouse hits the edge of the screen, the camera shifts
428− float rightBoundary = (float)::screenWidth - MOUSE_VIEW_SHIFT_YAW_MARGIN;
429− float bottomBoundary = (float)::screenHeight - MOUSE_VIEW_SHIFT_PITCH_MARGIN;
430−
431− if (mouseX > rightBoundary) {
432− float f = (mouseX - rightBoundary) / ( (float)::screenWidth - rightBoundary);
433− mouseViewShiftYaw += MOUSE_VIEW_SHIFT_RATE * f * deltaTime;
434− if (mouseViewShiftYaw > MOUSE_VIEW_SHIFT_YAW_LIMIT) { mouseViewShiftYaw = MOUSE_VIEW_SHIFT_YAW_LIMIT; }
435− } else if (mouseX < MOUSE_VIEW_SHIFT_YAW_MARGIN) {
436− float f = 1.0 - (mouseX / MOUSE_VIEW_SHIFT_YAW_MARGIN);
437− mouseViewShiftYaw -= MOUSE_VIEW_SHIFT_RATE * f * deltaTime;
438− if (mouseViewShiftYaw < -MOUSE_VIEW_SHIFT_YAW_LIMIT) { mouseViewShiftYaw = -MOUSE_VIEW_SHIFT_YAW_LIMIT; }
439− }
440− if (mouseY < MOUSE_VIEW_SHIFT_PITCH_MARGIN) {
441− float f = 1.0 - (mouseY / MOUSE_VIEW_SHIFT_PITCH_MARGIN);
442− mouseViewShiftPitch += MOUSE_VIEW_SHIFT_RATE * f * deltaTime;
443− if ( mouseViewShiftPitch > MOUSE_VIEW_SHIFT_PITCH_LIMIT ) { mouseViewShiftPitch = MOUSE_VIEW_SHIFT_PITCH_LIMIT; }
444− }
445− else if (mouseY > bottomBoundary) {
446− float f = (mouseY - bottomBoundary) / ((float)::screenHeight - bottomBoundary);
447− mouseViewShiftPitch -= MOUSE_VIEW_SHIFT_RATE * f * deltaTime;
448− if (mouseViewShiftPitch < -MOUSE_VIEW_SHIFT_PITCH_LIMIT) { mouseViewShiftPitch = -MOUSE_VIEW_SHIFT_PITCH_LIMIT; }
449− }
450− }
451−
452− if (OculusManager::isConnected()) {
453− float yaw, pitch, roll;
454− OculusManager::getEulerAngles(yaw, pitch, roll);
455−
456− myAvatar.setHeadYaw(-yaw);
457− myAvatar.setHeadPitch(pitch);
458− myAvatar.setHeadRoll(roll);
459− }
460−
461− // Get audio loudness data from audio input device
462− #ifndef _WIN32
463− myAvatar.setLoudness(audio.getInputLoudness());
464− #endif
465−
466− // Update Avatar with latest camera and view frustum data...
467− // NOTE: we get this from the view frustum, to make it simpler, since the
468− // loadViewFrumstum() method will get the correct details from the camera
469− // We could optimize this to not actually load the viewFrustum, since we don't
470− // actually need to calculate the view frustum planes to send these details
471− // to the server.
472− loadViewFrustum(::viewFrustum);
473− myAvatar.setCameraPosition(::viewFrustum.getPosition());
474− myAvatar.setCameraDirection(::viewFrustum.getDirection());
475− myAvatar.setCameraUp(::viewFrustum.getUp());
476− myAvatar.setCameraRight(::viewFrustum.getRight());
477− myAvatar.setCameraFov(::viewFrustum.getFieldOfView());
478− myAvatar.setCameraAspectRatio(::viewFrustum.getAspectRatio());
479− myAvatar.setCameraNearClip(::viewFrustum.getNearClip());
480− myAvatar.setCameraFarClip(::viewFrustum.getFarClip());
481−
482− AgentList* agentList = AgentList::getInstance();
483− if (agentList->getOwnerID() != UNKNOWN_AGENT_ID) {
484− // if I know my ID, send head/hand data to the avatar mixer and voxel server
485− unsigned char broadcastString[200];
486− unsigned char* endOfBroadcastStringWrite = broadcastString;
487−
488− *(endOfBroadcastStringWrite++) = PACKET_HEADER_HEAD_DATA;
489− endOfBroadcastStringWrite += packAgentId(endOfBroadcastStringWrite, agentList->getOwnerID());
490−
491− endOfBroadcastStringWrite += myAvatar.getBroadcastData(endOfBroadcastStringWrite);
492−
493− const char broadcastReceivers[2] = {AGENT_TYPE_VOXEL, AGENT_TYPE_AVATAR_MIXER};
494− AgentList::getInstance()->broadcastToAgents(broadcastString, endOfBroadcastStringWrite - broadcastString, broadcastReceivers, sizeof(broadcastReceivers));
495− }
496−
497− // If I'm in paint mode, send a voxel out to VOXEL server agents.
498− if (::paintOn) {
499−
500− glm::vec3 avatarPos = myAvatar.getPosition();
501−
502− // For some reason, we don't want to flip X and Z here.
503− ::paintingVoxel.x = avatarPos.x / 10.0;
504− ::paintingVoxel.y = avatarPos.y / 10.0;
505− ::paintingVoxel.z = avatarPos.z / 10.0;
506−
507− if (::paintingVoxel.x >= 0.0 && ::paintingVoxel.x <= 1.0 &&
508− ::paintingVoxel.y >= 0.0 && ::paintingVoxel.y <= 1.0 &&
509− ::paintingVoxel.z >= 0.0 && ::paintingVoxel.z <= 1.0) {
510−
511− sendVoxelEditMessage(PACKET_HEADER_SET_VOXEL, ::paintingVoxel);
512− }
513− }
514−}
515−
516−/////////////////////////////////////////////////////////////////////////////////////
517−// loadViewFrustum()
518−//
519−// Description: this will load the view frustum bounds for EITHER the head
520−// or the "myCamera".
521−//
522−
523−// These global scoped variables are used by our loadViewFrustum() and renderViewFrustum functions below, but are also
524−// available as globals so that the keyboard and menu can manipulate them.
525−
526−bool frustumOn = false; // Whether or not to display the debug view frustum
527−bool cameraFrustum = true; // which frustum to look at
528−
529−bool viewFrustumFromOffset =false; // Wether or not to offset the view of the frustum
530−float viewFrustumOffsetYaw = -135.0; // the following variables control yaw, pitch, roll and distance form regular
531−float viewFrustumOffsetPitch = 0.0; // camera to the offset camera
532−float viewFrustumOffsetRoll = 0.0;
533−float viewFrustumOffsetDistance = 25.0;
534−float viewFrustumOffsetUp = 0.0;
535−
536−void loadViewFrustum(ViewFrustum& viewFrustum) {
537− // We will use these below, from either the camera or head vectors calculated above
538− glm::vec3 position;
539− glm::vec3 direction;
540− glm::vec3 up;
541− glm::vec3 right;
542− float fov, nearClip, farClip;
543−
544− // Camera or Head?
545− if (::cameraFrustum) {
546− position = ::myCamera.getPosition();
547− } else {
548− position = ::myAvatar.getHeadPosition();
549− }
550−
551− fov = ::myCamera.getFieldOfView();
552− nearClip = ::myCamera.getNearClip();
553− farClip = ::myCamera.getFarClip();
554−
555− Orientation o = ::myCamera.getOrientation();
556−
557− direction = o.getFront();
558− up = o.getUp();
559− right = o.getRight();
560−
561− /*
562− printf("position.x=%f, position.y=%f, position.z=%f\n", position.x, position.y, position.z);
563− printf("yaw=%f, pitch=%f, roll=%f\n", yaw,pitch,roll);
564− printf("direction.x=%f, direction.y=%f, direction.z=%f\n", direction.x, direction.y, direction.z);
565− printf("up.x=%f, up.y=%f, up.z=%f\n", up.x, up.y, up.z);
566− printf("right.x=%f, right.y=%f, right.z=%f\n", right.x, right.y, right.z);
567− printf("fov=%f\n", fov);
568− printf("nearClip=%f\n", nearClip);
569− printf("farClip=%f\n", farClip);
570− */
571−
572− // Set the viewFrustum up with the correct position and orientation of the camera
573− viewFrustum.setPosition(position);
574− viewFrustum.setOrientation(direction,up,right);
575−
576− // Also make sure it's got the correct lens details from the camera
577− viewFrustum.setFieldOfView(fov);
578− viewFrustum.setNearClip(nearClip);
579− viewFrustum.setFarClip(farClip);
580−
581− // Ask the ViewFrustum class to calculate our corners
582− viewFrustum.calculate();
583−}
584−
585−/////////////////////////////////////////////////////////////////////////////////////
586−// renderViewFrustum()
587−//
588−// Description: this will render the view frustum bounds for EITHER the head
589−// or the "myCamera".
590−//
591−// Frustum rendering mode. For debug purposes, we allow drawing the frustum in a couple of different ways.
592−// We can draw it with each of these parts:
593−// * Origin Direction/Up/Right vectors - these will be drawn at the point of the camera
594−// * Near plane - this plane is drawn very close to the origin point.
595−// * Right/Left planes - these two planes are drawn between the near and far planes.
596−// * Far plane - the plane is drawn in the distance.
597−// Modes - the following modes, will draw the following parts.
598−// * All - draws all the parts listed above
599−// * Planes - draws the planes but not the origin vectors
600−// * Origin Vectors - draws the origin vectors ONLY
601−// * Near Plane - draws only the near plane
602−// * Far Plane - draws only the far plane
603−#define FRUSTUM_DRAW_MODE_ALL 0
604−#define FRUSTUM_DRAW_MODE_VECTORS 1
605−#define FRUSTUM_DRAW_MODE_PLANES 2
606−#define FRUSTUM_DRAW_MODE_NEAR_PLANE 3
607−#define FRUSTUM_DRAW_MODE_FAR_PLANE 4
608−#define FRUSTUM_DRAW_MODE_COUNT 5
609−
610−int frustumDrawingMode = FRUSTUM_DRAW_MODE_ALL; // the mode we're drawing the frustum in, see notes above
611−
612−void renderViewFrustum(ViewFrustum& viewFrustum) {
613−
614− // Load it with the latest details!
615− loadViewFrustum(viewFrustum);
616−
617− glm::vec3 position = viewFrustum.getPosition();
618− glm::vec3 direction = viewFrustum.getDirection();
619− glm::vec3 up = viewFrustum.getUp();
620− glm::vec3 right = viewFrustum.getRight();
621−
622− // Get ready to draw some lines
623− glDisable(GL_LIGHTING);
624− glColor4f(1.0, 1.0, 1.0, 1.0);
625− glLineWidth(1.0);
626− glBegin(GL_LINES);
627−
628− if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_VECTORS) {
629− // Calculate the origin direction vectors
630− glm::vec3 lookingAt = position + (direction * 0.2f);
631− glm::vec3 lookingAtUp = position + (up * 0.2f);
632− glm::vec3 lookingAtRight = position + (right * 0.2f);
633−
634− // Looking At = white
635− glColor3f(1,1,1);
636− glVertex3f(position.x, position.y, position.z);
637− glVertex3f(lookingAt.x, lookingAt.y, lookingAt.z);
638−
639− // Looking At Up = purple
640− glColor3f(1,0,1);
641− glVertex3f(position.x, position.y, position.z);
642− glVertex3f(lookingAtUp.x, lookingAtUp.y, lookingAtUp.z);
643−
644− // Looking At Right = cyan
645− glColor3f(0,1,1);
646− glVertex3f(position.x, position.y, position.z);
647− glVertex3f(lookingAtRight.x, lookingAtRight.y, lookingAtRight.z);
648− }
649−
650− if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES
651− || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_NEAR_PLANE) {
652− // Drawing the bounds of the frustum
653− // viewFrustum.getNear plane - bottom edge
654− glColor3f(1,0,0);
655− glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z);
656− glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z);
657−
658− // viewFrustum.getNear plane - top edge
659− glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z);
660− glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z);
661−
662− // viewFrustum.getNear plane - right edge
663− glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z);
664− glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z);
665−
666− // viewFrustum.getNear plane - left edge
667− glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z);
668− glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z);
669− }
670−
671− if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES
672− || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_FAR_PLANE) {
673− // viewFrustum.getFar plane - bottom edge
674− glColor3f(0,1,0); // GREEN!!!
675− glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z);
676− glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z);
677−
678− // viewFrustum.getFar plane - top edge
679− glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z);
680− glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z);
681−
682− // viewFrustum.getFar plane - right edge
683− glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z);
684− glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z);
685−
686− // viewFrustum.getFar plane - left edge
687− glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z);
688− glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z);
689− }
690−
691− if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES) {
692− // RIGHT PLANE IS CYAN
693− // right plane - bottom edge - viewFrustum.getNear to distant
694− glColor3f(0,1,1);
695− glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z);
696− glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z);
697−
698− // right plane - top edge - viewFrustum.getNear to distant
699− glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z);
700− glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z);
701−
702− // LEFT PLANE IS BLUE
703− // left plane - bottom edge - viewFrustum.getNear to distant
704− glColor3f(0,0,1);
705− glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z);
706− glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z);
707−
708− // left plane - top edge - viewFrustum.getNear to distant
709− glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z);
710− glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z);
711− }
712−
713− glEnd();
714− glEnable(GL_LIGHTING);
715−}
716−
717−// displays a single side (left, right, or combined for non-Oculus)
718−void displaySide(Camera& whichCamera) {
719− glPushMatrix();
720−
721− if (::renderStarsOn) {
722− // should be the first rendering pass - w/o depth buffer / lighting
723−
724− // compute starfield alpha based on distance from atmosphere
725− float alpha = 1.0f;
726− if (::renderAtmosphereOn) {
727− float height = glm::distance(whichCamera.getPosition(), environment.getAtmosphereCenter());
728− if (height < environment.getAtmosphereInnerRadius()) {
729− alpha = 0.0f;
730−
731− } else if (height < environment.getAtmosphereOuterRadius()) {
732− alpha = (height - environment.getAtmosphereInnerRadius()) /
733− (environment.getAtmosphereOuterRadius() - environment.getAtmosphereInnerRadius());
734− }
735− }
736−
737− // finally render the starfield
738− stars.render(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(), whichCamera.getNearClip(), alpha);
739− }
740−
741− // draw the sky dome
742− if (::renderAtmosphereOn) {
743− environment.renderAtmosphere(whichCamera);
744− }
745−
746− glEnable(GL_LIGHTING);
747− glEnable(GL_DEPTH_TEST);
748−
749− // draw a red sphere
750− float sphereRadius = 0.25f;
751− glColor3f(1,0,0);
752− glPushMatrix();
753− glutSolidSphere(sphereRadius, 15, 15);
754− glPopMatrix();
755−
756− //draw a grid ground plane....
757− drawGroundPlaneGrid(10.f);
758−
759− // Draw voxels
760− if (renderVoxels) {
761− voxels.render();
762− }
763−
764− // indicate what we'll be adding/removing in mouse mode, if anything
765− if (::mouseVoxel.s != 0) {
766− glPushMatrix();
767− if (::mouseMode == ADD_VOXEL_MODE) {
768− // use a contrasting color so that we can see what we're doing
769− glColor3ub(::mouseVoxel.red + 128, ::mouseVoxel.green + 128, ::mouseVoxel.blue + 128);
770− } else {
771− glColor3ub(::mouseVoxel.red, ::mouseVoxel.green, ::mouseVoxel.blue);
772− }
773− glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE);
774− glTranslatef(::mouseVoxel.x + ::mouseVoxel.s*0.5f,
775− ::mouseVoxel.y + ::mouseVoxel.s*0.5f,
776− ::mouseVoxel.z + ::mouseVoxel.s*0.5f);
777− glLineWidth(4.0f);
778− glutWireCube(::mouseVoxel.s);
779− glLineWidth(1.0f);
780− glPopMatrix();
781− }
782−
783− if (::renderAvatarsOn) {
784− // Render avatars of other agents
785− AgentList* agentList = AgentList::getInstance();
786− agentList->lock();
787− for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
788− if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
789− Avatar *avatar = (Avatar *)agent->getLinkedData();
790− avatar->render(0, ::myCamera.getPosition());
791− }
792− }
793− agentList->unlock();
794−
795− // Render my own Avatar
796− myAvatar.render(::lookingInMirror, ::myCamera.getPosition());
797− }
798−
799− // Render the world box
800− if (!::lookingInMirror && ::renderStatsOn) { render_world_box(); }
801−
802− // brad's frustum for debugging
803− if (::frustumOn) renderViewFrustum(::viewFrustum);
804−
805− glPopMatrix();
806−}
807−
808−// this shader is an adaptation (HLSL -> GLSL, removed conditional) of the one in the Oculus sample
809−// code (Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp), which is under the Apache license
810−// (http://www.apache.org/licenses/LICENSE-2.0)
811−const char* DISTORTION_FRAGMENT_SHADER =
812− "#version 120\n"
813− "uniform sampler2D texture;"
814− "uniform vec2 lensCenter;"
815− "uniform vec2 screenCenter;"
816− "uniform vec2 scale;"
817− "uniform vec2 scaleIn;"
818− "uniform vec4 hmdWarpParam;"
819− "vec2 hmdWarp(vec2 in01) {"
820− " vec2 theta = (in01 - lensCenter) * scaleIn;"
821− " float rSq = theta.x * theta.x + theta.y * theta.y;"
822− " vec2 theta1 = theta * (hmdWarpParam.x + hmdWarpParam.y * rSq + "
823− " hmdWarpParam.z * rSq * rSq + hmdWarpParam.w * rSq * rSq * rSq);"
824− " return lensCenter + scale * theta1;"
825− "}"
826− "void main(void) {"
827− " vec2 tc = hmdWarp(gl_TexCoord[0].st);"
828− " vec2 below = step(screenCenter.st + vec2(-0.25, -0.5), tc.st);"
829− " vec2 above = vec2(1.0, 1.0) - step(screenCenter.st + vec2(0.25, 0.5), tc.st);"
830− " gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), texture2D(texture, tc), "
831− " above.s * above.t * below.s * below.t);"
832− "}";
833−
834−// the locations of the uniform variables
835−int textureLocation;
836−int lensCenterLocation;
837−int screenCenterLocation;
838−int scaleLocation;
839−int scaleInLocation;
840−int hmdWarpParamLocation;
841−
842−// renders both sides into a texture, then renders the texture to the display with distortion
843−void displayOculus(Camera& whichCamera) {
844− // magic numbers ahoy! in order to avoid pulling in the Oculus utility library that calculates
845− // the rendering parameters from the hardware stats, i just folded their calculations into
846− // constants using the stats for the current-model hardware as contained in the SDK file
847− // LibOVR/Src/Util/Util_Render_Stereo.cpp
848−
849− // eye
850−
851− // render the left eye view to the left side of the screen
852− glMatrixMode(GL_PROJECTION);
853− glPushMatrix();
854− glLoadIdentity();
855− glTranslatef(0.151976, 0, 0); // +h, see Oculus SDK docs p. 26
856− gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
857− whichCamera.getNearClip(), whichCamera.getFarClip());
858− glTranslatef(0.032, 0, 0); // dip/2, see p. 27
859−
860− glMatrixMode(GL_MODELVIEW);
861− glViewport(0, 0, ::screenWidth / 2, ::screenHeight);
862− displaySide(whichCamera);
863−
864− // and the right eye to the right side
865− glMatrixMode(GL_PROJECTION);
866− glLoadIdentity();
867− glTranslatef(-0.151976, 0, 0); // -h
868− gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
869− whichCamera.getNearClip(), whichCamera.getFarClip());
870− glTranslatef(-0.032, 0, 0);
871−
872− glMatrixMode(GL_MODELVIEW);
873− glViewport(::screenWidth / 2, 0, ::screenWidth / 2, ::screenHeight);
874− displaySide(whichCamera);
875−
876− glPopMatrix();
877−
878− // restore our normal viewport
879− glViewport(0, 0, ::screenWidth, ::screenHeight);
880−
881− if (::oculusTextureID == 0) {
882− glGenTextures(1, &::oculusTextureID);
883− glBindTexture(GL_TEXTURE_2D, ::oculusTextureID);
884− glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ::screenWidth, ::screenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
885− glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
886−
887− ::oculusProgram = new ProgramObject();
888− ::oculusProgram->attachFromSourceCode(GL_FRAGMENT_SHADER_ARB, DISTORTION_FRAGMENT_SHADER);
889− ::oculusProgram->link();
890−
891− textureLocation = ::oculusProgram->getUniformLocation("texture");
892− lensCenterLocation = ::oculusProgram->getUniformLocation("lensCenter");
893− screenCenterLocation = ::oculusProgram->getUniformLocation("screenCenter");
894− scaleLocation = ::oculusProgram->getUniformLocation("scale");
895− scaleInLocation = ::oculusProgram->getUniformLocation("scaleIn");
896− hmdWarpParamLocation = ::oculusProgram->getUniformLocation("hmdWarpParam");
897−
898− } else {
899− glBindTexture(GL_TEXTURE_2D, ::oculusTextureID);
900− }
901− glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, ::screenWidth, ::screenHeight);
902−
903− glMatrixMode(GL_PROJECTION);
904− glLoadIdentity();
905− gluOrtho2D(0, ::screenWidth, 0, ::screenHeight);
906− glDisable(GL_DEPTH_TEST);
907− glDisable(GL_LIGHTING);
908−
909− // for reference on setting these values, see SDK file Samples/OculusRoomTiny/RenderTiny_Device.cpp
910−
911− float scaleFactor = 1.0 / ::oculusDistortionScale;
912− float aspectRatio = (::screenWidth * 0.5) / ::screenHeight;
913−
914− glDisable(GL_BLEND);
915− glEnable(GL_TEXTURE_2D);
916− ::oculusProgram->bind();
917− ::oculusProgram->setUniform(textureLocation, 0);
918− ::oculusProgram->setUniform(lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
919− ::oculusProgram->setUniform(screenCenterLocation, 0.25, 0.5);
920− ::oculusProgram->setUniform(scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio);
921− ::oculusProgram->setUniform(scaleInLocation, 4, 2 / aspectRatio);
922− ::oculusProgram->setUniform(hmdWarpParamLocation, 1.0, 0.22, 0.24, 0);
923−
924− glColor3f(1, 0, 1);
925− glBegin(GL_QUADS);
926− glTexCoord2f(0, 0);
927− glVertex2f(0, 0);
928− glTexCoord2f(0.5, 0);
929− glVertex2f(::screenWidth/2, 0);
930− glTexCoord2f(0.5, 1);
931− glVertex2f(::screenWidth / 2, ::screenHeight);
932− glTexCoord2f(0, 1);
933− glVertex2f(0, ::screenHeight);
934− glEnd();
935−
936− ::oculusProgram->setUniform(lensCenterLocation, 0.787994, 0.5);
937− ::oculusProgram->setUniform(screenCenterLocation, 0.75, 0.5);
938−
939− glBegin(GL_QUADS);
940− glTexCoord2f(0.5, 0);
941− glVertex2f(::screenWidth / 2, 0);
942− glTexCoord2f(1, 0);
943− glVertex2f(::screenWidth, 0);
944− glTexCoord2f(1, 1);
945− glVertex2f(::screenWidth, ::screenHeight);
946− glTexCoord2f(0.5, 1);
947− glVertex2f(::screenWidth / 2, ::screenHeight);
948− glEnd();
949−
950− glEnable(GL_BLEND);
951− glDisable(GL_TEXTURE_2D);
952− glBindTexture(GL_TEXTURE_2D, 0);
953− ::oculusProgram->release();
954−
955− glPopMatrix();
956−}
957−
958−void displayOverlay() {
959− // Render 2D overlay: I/O level bar graphs and text
960− glMatrixMode(GL_PROJECTION);
961− glPushMatrix();
962− glLoadIdentity();
963− gluOrtho2D(0, ::screenWidth, ::screenHeight, 0);
964− glDisable(GL_DEPTH_TEST);
965− glDisable(GL_LIGHTING);
966−
967− #ifndef _WIN32
968− audio.render(::screenWidth, ::screenHeight);
969− audioScope.render(20, ::screenHeight - 200);
970− #endif
971−
972− //noiseTest(::screenWidth, ::screenHeight);
973−
974− if (displayHeadMouse && !::lookingInMirror && USING_INVENSENSE_MPU9150) {
975− // Display small target box at center or head mouse target that can also be used to measure LOD
976− glColor3f(1.0, 1.0, 1.0);
977− glDisable(GL_LINE_SMOOTH);
978− const int PIXEL_BOX = 20;
979− glBegin(GL_LINE_STRIP);
980− glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
981− glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
982− glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
983− glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
984− glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
985− glEnd();
986− glEnable(GL_LINE_SMOOTH);
987− }
988−
989− // Show detected levels from the serial I/O ADC channel sensors
990− if (displayLevels) serialPort.renderLevels(::screenWidth,::screenHeight);
991−
992− // Display stats and log text onscreen
993− glLineWidth(1.0f);
994− glPointSize(1.0f);
995−
996− if (::renderStatsOn) { displayStats(); }
997− if (::logOn) { logger.render(::screenWidth, ::screenHeight); }
998−
999− // Show menu
1000− if (::menuOn) {
1001− glLineWidth(1.0f);
1002− glPointSize(1.0f);
1003− menu.render(::screenWidth,::screenHeight);
1004− }
1005−
1006− // Show chat entry field
1007− if (::chatEntryOn) {
1008− chatEntry.render(::screenWidth, ::screenHeight);
1009− }
1010−
1011− // Stats at upper right of screen about who domain server is telling us about
1012− glPointSize(1.0f);
1013− char agents[100];
1014−
1015− AgentList* agentList = AgentList::getInstance();
1016− int totalAvatars = 0, totalServers = 0;
1017−
1018− for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
1019− agent->getType() == AGENT_TYPE_AVATAR ? totalAvatars++ : totalServers++;
1020− }
1021−
1022− sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars);
1023− drawtext(::screenWidth - 150, 20, 0.10, 0, 1.0, 0, agents, 1, 0, 0);
1024−
1025− if (::paintOn) {
1026−
1027− char paintMessage[100];
1028− sprintf(paintMessage,"Painting (%.3f,%.3f,%.3f/%.3f/%d,%d,%d)",
1029− ::paintingVoxel.x,::paintingVoxel.y,::paintingVoxel.z,::paintingVoxel.s,
1030− (unsigned int)::paintingVoxel.red,(unsigned int)::paintingVoxel.green,(unsigned int)::paintingVoxel.blue);
1031− drawtext(::screenWidth - 350, 50, 0.10, 0, 1.0, 0, paintMessage, 1, 1, 0);
1032− }
1033−
1034− glPopMatrix();
1035−}
1036−
1037−void display(void)
1038−{
1039− PerfStat("display");
1040−
1041− glEnable(GL_LINE_SMOOTH);
1042− glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1043− glMatrixMode(GL_MODELVIEW);
1044−
1045− glPushMatrix(); {
1046− glLoadIdentity();
1047−
1048− // camera settings
1049− if (myCamera.getMode() == CAMERA_MODE_MIRROR) {
1050− myAvatar.setDisplayingHead(true);
1051− myCamera.setUpShift (0.0);
1052− myCamera.setDistance (0.2);
1053− myCamera.setTightness (100.0f);
1054− myCamera.setTargetPosition(myAvatar.getHeadPosition());
1055− myCamera.setTargetRotation(myAvatar.getBodyYaw() - 180.0f, 0.0f, 0.0f);
1056−
1057− } else if (myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || OculusManager::isConnected()) {
1058− myAvatar.setDisplayingHead(false);
1059− myCamera.setUpShift (0.0f);
1060− myCamera.setDistance (0.0f);
1061− myCamera.setTightness (100.0f);
1062− myCamera.setTargetPosition(myAvatar.getHeadPosition());
1063−
1064− if (OculusManager::isConnected()) {
1065− myCamera.setTargetRotation(myAvatar.getBodyYaw() + myAvatar.getHeadYaw(),
1066− -myAvatar.getHeadPitch(),
1067− myAvatar.getHeadRoll());
1068− } else {
1069− myCamera.setTargetRotation(myAvatar.getAbsoluteHeadYaw()- mouseViewShiftYaw, myAvatar.getAbsoluteHeadPitch() + myAvatar.getRenderPitch() + mouseViewShiftPitch, 0.0f);
1070− }
1071− } else if (myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
1072− myAvatar.setDisplayingHead(true);
1073− myCamera.setUpShift (-0.2f);
1074− myCamera.setDistance (1.5f);
1075− myCamera.setTightness (8.0f);
1076− myCamera.setTargetPosition(myAvatar.getHeadPosition());
1077− myCamera.setTargetRotation(myAvatar.getBodyYaw() - mouseViewShiftYaw, mouseViewShiftPitch, 0.0f);
1078− }
1079−
1080− // important...
1081− myCamera.update( 1.f/FPS );
1082−
1083− // Render anything (like HUD items) that we want to be in 3D but not in worldspace
1084− /*
1085− const float HUD_Z_OFFSET = -5.f;
1086− glPushMatrix();
1087− glm::vec3 test(0.5, 0.5, 0.5);
1088− glTranslatef(1, 1, HUD_Z_OFFSET);
1089− drawVector(&test);
1090− glPopMatrix();
1091− */
1092−
1093−
1094− // Note: whichCamera is used to pick between the normal camera myCamera for our
1095− // main camera, vs, an alternate camera. The alternate camera we support right now
1096− // is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
1097− // to add other cameras.
1098− //
1099− // Why have two cameras? Well, one reason is that because in the case of the renderViewFrustum()
1100− // code, we want to keep the state of "myCamera" intact, so we can render what the view frustum of
1101− // myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera
1102− Camera whichCamera = myCamera;
1103− Camera viewFrustumOffsetCamera = myCamera;
1104−
1105− if (::viewFrustumFromOffset && ::frustumOn) {
1106−
1107− // set the camera to third-person view but offset so we can see the frustum
1108− viewFrustumOffsetCamera.setTargetYaw(::viewFrustumOffsetYaw + myAvatar.getBodyYaw());
1109− viewFrustumOffsetCamera.setPitch (::viewFrustumOffsetPitch );
1110− viewFrustumOffsetCamera.setRoll (::viewFrustumOffsetRoll );
1111− viewFrustumOffsetCamera.setUpShift (::viewFrustumOffsetUp );
1112− viewFrustumOffsetCamera.setDistance (::viewFrustumOffsetDistance);
1113− viewFrustumOffsetCamera.update(1.f/FPS);
1114− whichCamera = viewFrustumOffsetCamera;
1115− }
1116−
1117− // transform view according to whichCamera
1118− // could be myCamera (if in normal mode)
1119− // or could be viewFrustumOffsetCamera if in offset mode
1120− // I changed the ordering here - roll is FIRST (JJV)
1121−
1122− glRotatef ( whichCamera.getRoll(), IDENTITY_FRONT.x, IDENTITY_FRONT.y, IDENTITY_FRONT.z);
1123− glRotatef ( whichCamera.getPitch(), IDENTITY_RIGHT.x, IDENTITY_RIGHT.y, IDENTITY_RIGHT.z);
1124− glRotatef (180.0 - whichCamera.getYaw(), IDENTITY_UP.x, IDENTITY_UP.y, IDENTITY_UP.z );
1125−
1126− glTranslatef(-whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z);
1127−
1128− // Setup 3D lights (after the camera transform, so that they are positioned in world space)
1129− glEnable(GL_COLOR_MATERIAL);
1130− glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1131−
1132− GLfloat light_position0[] = { 1.0, 1.0, 0.0, 0.0 };
1133− glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
1134− GLfloat ambient_color[] = { 0.7, 0.7, 0.8 };
1135− glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color);
1136− GLfloat diffuse_color[] = { 0.8, 0.7, 0.7 };
1137− glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color);
1138− GLfloat specular_color[] = { 1.0, 1.0, 1.0, 1.0};
1139− glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color);
1140−
1141− glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color);
1142− glMateriali(GL_FRONT, GL_SHININESS, 96);
1143−
1144− if (::oculusOn) {
1145− displayOculus(whichCamera);
1146−
1147− } else {
1148− displaySide(whichCamera);
1149− glPopMatrix();
1150−
1151− displayOverlay();
1152− }
1153− }
1154−
1155− glutSwapBuffers();
1156− frameCount++;
1157−
1158− // If application has just started, report time from startup to now (first frame display)
1159− if (justStarted) {
1160− float startupTime = (usecTimestampNow() - usecTimestamp(&applicationStartupTime))/1000000.0;
1161− justStarted = false;
1162− char title[30];
1163− snprintf(title, 30, "Interface: %4.2f seconds", startupTime);
1164− glutSetWindowTitle(title);
1165− }
1166−}
1167−
1168−// int version of setValue()
1169−int setValue(int state, int *value) {
1170− if (state == MENU_ROW_PICKED) {
1171− *value = !(*value);
1172− } else if (state == MENU_ROW_GET_VALUE) {
1173− return *value;
1174− } else {
1175− *value = state;
1176− }
1177− return *value;
1178−}
1179−
1180−// bool version of setValue()
1181−int setValue(int state, bool *value) {
1182− if (state == MENU_ROW_PICKED) {
1183− *value = !(*value);
1184− } else if (state == MENU_ROW_GET_VALUE) {
1185− return *value;
1186− } else {
1187− *value = state;
1188− }
1189− return *value;
1190−}
1191−
1192−int setHead(int state) {
1193− return setValue(state, &::lookingInMirror);
1194−}
1195−
1196−int setNoise(int state) {
1197− int iRet = setValue(state, &noiseOn);
1198− if (noiseOn) {
1199− myAvatar.setNoise(noise);
1200− } else {
1201− myAvatar.setNoise(0);
1202− }
1203− return iRet;
1204−}
1205−
1206−int setLog(int state) {
1207− int iRet = setValue(state, &::logOn);
1208− return iRet;
1209−}
1210−
1211−int setGyroLook(int state) {
1212− int iRet = setValue(state, &::gyroLook);
1213− return iRet;
1214−}
1215−
1216−int setFullscreen(int state) {
1217− bool wasFullscreen = ::fullscreen;
1218− int value = setValue(state, &::fullscreen);
1219− if (::fullscreen != wasFullscreen) {
1220− if (::fullscreen) {
1221− glutFullScreen();
1222−
1223− } else {
1224− glutReshapeWindow(::screenWidth, ::screenHeight);
1225− }
1226− }
1227− return value;
1228−}
1229−
1230−int setVoxels(int state) {
1231− return setValue(state, &::renderVoxels);
1232−}
1233−
1234−int setStars(int state) {
1235− return setValue(state, &::renderStarsOn);
1236−}
1237−
1238−int setAtmosphere(int state) {
1239− return setValue(state, &::renderAtmosphereOn);
1240−}
1241−
1242−int setRenderAvatars(int state) {
1243− return setValue(state, &::renderAvatarsOn);
1244−}
1245−
1246−int setRenderFirstPerson(int state) {
1247− bool value = setValue(state, &::renderFirstPersonOn);
1248− if (state == MENU_ROW_PICKED) {
1249− if (::renderFirstPersonOn) {
1250− myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
1251− } else {
1252− myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
1253− }
1254− }
1255− return value;
1256−}
1257−
1258−int setOculus(int state) {
1259− bool wasOn = ::oculusOn;
1260− int value = setValue(state, &::oculusOn);
1261− if (::oculusOn != wasOn) {
1262− reshape(::screenWidth, ::screenHeight);
1263− }
1264− return value;
1265−}
1266−
1267−int setStats(int state) {
1268− return setValue(state, &::renderStatsOn);
1269−}
1270−
1271−int setMenu(int state) {
1272− return setValue(state, &::menuOn);
1273−}
1274−
1275−int setRenderWarnings(int state) {
1276− int value = setValue(state, &::renderWarningsOn);
1277− if (state == MENU_ROW_PICKED) {
1278− ::voxels.setRenderPipelineWarnings(::renderWarningsOn);
1279− }
1280− return value;
1281−}
1282−
1283−int setWantResIn(int state) {
1284− int value = setValue(state, &::wantResIn);
1285− if (state == MENU_ROW_PICKED) {
1286− ::myAvatar.setWantResIn(::wantResIn);
1287− }
1288− return value;
1289−}
1290−
1291−int setWantMonochrome(int state) {
1292− int value = setValue(state, &::wantMonochrome);
1293− if (state == MENU_ROW_PICKED) {
1294− ::myAvatar.setWantColor(!::wantMonochrome);
1295− }
1296− return value;
1297−}
1298−
1299−int setDisplayFrustum(int state) {
1300− return setValue(state, &::frustumOn);
1301−}
1302−
1303−int setFrustumOffset(int state) {
1304− int value = setValue(state, &::viewFrustumFromOffset);
1305−
1306− // reshape so that OpenGL will get the right lens details for the camera of choice
1307− if (state == MENU_ROW_PICKED) {
1308− reshape(::screenWidth, ::screenHeight);
1309− }
1310−
1311− return value;
1312−}
1313−
1314−int setFrustumOrigin(int state) {
1315− return setValue(state, &::cameraFrustum);
1316−}
1317−
1318−int quitApp(int state) {
1319− if (state == MENU_ROW_PICKED) {
1320− ::terminate();
1321− }
1322− return 2; // non state so menu class doesn't add "state"
1323−}
1324−
1325−int setFrustumRenderMode(int state) {
1326− if (state == MENU_ROW_PICKED) {
1327− ::frustumDrawingMode = (::frustumDrawingMode+1)%FRUSTUM_DRAW_MODE_COUNT;
1328− }
1329− return ::frustumDrawingMode;
1330−}
1331−
1332−int doKillLocalVoxels(int state) {
1333− if (state == MENU_ROW_PICKED) {
1334− ::wantToKillLocalVoxels = true;
1335− }
1336− return state;
1337−}
1338−
1339−int doRandomizeVoxelColors(int state) {
1340− if (state == MENU_ROW_PICKED) {
1341− ::voxels.randomizeVoxelColors();
1342− }
1343− return state;
1344−}
1345−
1346−int doFalseRandomizeEveryOtherVoxelColors(int state) {
1347− if (state == MENU_ROW_PICKED) {
1348− ::voxels.falseColorizeRandomEveryOther();
1349− }
1350− return state;
1351−}
1352−
1353−int doTreeStats(int state) {
1354− if (state == MENU_ROW_PICKED) {
1355− ::voxels.collectStatsForTreesAndVBOs();
1356− }
1357− return state;
1358−}
1359−
1360−int doFalseRandomizeVoxelColors(int state) {
1361− if (state == MENU_ROW_PICKED) {
1362− ::voxels.falseColorizeRandom();
1363− }
1364− return state;
1365−}
1366−
1367−int doTrueVoxelColors(int state) {
1368− if (state == MENU_ROW_PICKED) {
1369− ::voxels.trueColorize();
1370− }
1371− return state;
1372−}
1373−
1374−int doFalseColorizeByDistance(int state) {
1375− if (state == MENU_ROW_PICKED) {
1376− loadViewFrustum(::viewFrustum);
1377− voxels.falseColorizeDistanceFromView(&::viewFrustum);
1378− }
1379− return state;
1380−}
1381−
1382−int doFalseColorizeInView(int state) {
1383− if (state == MENU_ROW_PICKED) {
1384− loadViewFrustum(::viewFrustum);
1385− // we probably want to make sure the viewFrustum is initialized first
1386− voxels.falseColorizeInView(&::viewFrustum);
1387− }
1388− return state;
1389−}
1390−
1391−
1392−
1393−const char* modeAll = " - All ";
1394−const char* modeVectors = " - Vectors ";
1395−const char* modePlanes = " - Planes ";
1396−const char* modeNear = " - Near ";
1397−const char* modeFar = " - Far ";
1398−
1399−const char* getFrustumRenderModeName(int state) {
1400− const char * mode;
1401− switch (state) {
1402− case FRUSTUM_DRAW_MODE_ALL:
1403− mode = modeAll;
1404− break;
1405− case FRUSTUM_DRAW_MODE_VECTORS:
1406− mode = modeVectors;
1407− break;
1408− case FRUSTUM_DRAW_MODE_PLANES:
1409− mode = modePlanes;
1410− break;
1411− case FRUSTUM_DRAW_MODE_NEAR_PLANE:
1412− mode = modeNear;
1413− break;
1414− case FRUSTUM_DRAW_MODE_FAR_PLANE:
1415− mode = modeFar;
1416− break;
1417− }
1418− return mode;
1419−}
1420−
1421−void initMenu() {
1422− MenuColumn *menuColumnOptions, *menuColumnRender, *menuColumnTools, *menuColumnDebug, *menuColumnFrustum;
1423− // Options
1424− menuColumnOptions = menu.addColumn("Options");
1425− menuColumnOptions->addRow("Mirror (h)", setHead);
1426− menuColumnOptions->addRow("Noise (n)", setNoise);
1427− menuColumnOptions->addRow("Gyro Look", setGyroLook);
1428− menuColumnOptions->addRow("Fullscreen (f)", setFullscreen);
1429− menuColumnOptions->addRow("Quit (q)", quitApp);
1430−
1431− // Render
1432− menuColumnRender = menu.addColumn("Render");
1433− menuColumnRender->addRow("Voxels (V)", setVoxels);
1434− menuColumnRender->addRow("Stars (*)", setStars);
1435− menuColumnRender->addRow("Atmosphere (A)", setAtmosphere);
1436− menuColumnRender->addRow("Avatars", setRenderAvatars);
1437− menuColumnRender->addRow("First Person (p)", setRenderFirstPerson);
1438− menuColumnRender->addRow("Oculus (o)", setOculus);
1439−
1440− // Tools
1441− menuColumnTools = menu.addColumn("Tools");
1442− menuColumnTools->addRow("Stats (/)", setStats);
1443− menuColumnTools->addRow("Log ", setLog);
1444− menuColumnTools->addRow("(M)enu", setMenu);
1445−
1446− // Frustum Options
1447− menuColumnFrustum = menu.addColumn("Frustum");
1448− menuColumnFrustum->addRow("Display (F)rustum", setDisplayFrustum);
1449− menuColumnFrustum->addRow("Use (O)ffset Camera", setFrustumOffset);
1450− menuColumnFrustum->addRow("Switch (C)amera", setFrustumOrigin);
1451− menuColumnFrustum->addRow("(R)ender Mode", setFrustumRenderMode, getFrustumRenderModeName);
1452−
1453− // Debug
1454− menuColumnDebug = menu.addColumn("Debug");
1455− menuColumnDebug->addRow("Show Render Pipeline Warnings", setRenderWarnings);
1456− menuColumnDebug->addRow("Kill Local Voxels", doKillLocalVoxels);
1457− menuColumnDebug->addRow("Randomize Voxel TRUE Colors", doRandomizeVoxelColors);
1458− menuColumnDebug->addRow("FALSE Color Voxels Randomly", doFalseRandomizeVoxelColors);
1459− menuColumnDebug->addRow("FALSE Color Voxel Every Other Randomly", doFalseRandomizeEveryOtherVoxelColors);
1460− menuColumnDebug->addRow("FALSE Color Voxels by Distance", doFalseColorizeByDistance);
1461− menuColumnDebug->addRow("FALSE Color Voxel Out of View", doFalseColorizeInView);
1462− menuColumnDebug->addRow("Show TRUE Colors", doTrueVoxelColors);
1463− menuColumnDebug->addRow("Calculate Tree Stats", doTreeStats);
1464− menuColumnDebug->addRow("Wants Res-In", setWantResIn);
1465− menuColumnDebug->addRow("Wants Monochrome", setWantMonochrome);
1466−}
1467−
1468−void testPointToVoxel() {
1469− float y=0;
1470− float z=0;
1471− float s=0.1;
1472− for (float x=0; x<=1; x+= 0.05) {
1473− printLog(" x=%f");
1474−
1475− unsigned char red = 200; //randomColorValue(65);
1476− unsigned char green = 200; //randomColorValue(65);
1477− unsigned char blue = 200; //randomColorValue(65);
1478−
1479− unsigned char* voxelCode = pointToVoxel(x, y, z, s,red,green,blue);
1480− printVoxelCode(voxelCode);
1481− delete voxelCode;
1482− printLog("\n");
1483− }
1484−}
1485−
1486−void sendVoxelServerEraseAll() {
1487− char message[100];
1488− sprintf(message,"%c%s",'Z',"erase all");
1489− int messageSize = strlen(message) + 1;
1490− AgentList::getInstance()->broadcastToAgents((unsigned char*) message, messageSize, &AGENT_TYPE_VOXEL, 1);
1491−}
1492−
1493−void sendVoxelServerAddScene() {
1494− char message[100];
1495− sprintf(message,"%c%s",'Z',"add scene");
1496− int messageSize = strlen(message) + 1;
1497− AgentList::getInstance()->broadcastToAgents((unsigned char*)message, messageSize, &AGENT_TYPE_VOXEL, 1);
1498−}
1499−
1500−void shiftPaintingColor()
1501−{
1502− // About the color of the paintbrush... first determine the dominant color
1503− ::dominantColor = (::dominantColor+1)%3; // 0=red,1=green,2=blue
1504− ::paintingVoxel.red = (::dominantColor==0)?randIntInRange(200,255):randIntInRange(40,100);
1505− ::paintingVoxel.green = (::dominantColor==1)?randIntInRange(200,255):randIntInRange(40,100);
1506− ::paintingVoxel.blue = (::dominantColor==2)?randIntInRange(200,255):randIntInRange(40,100);
1507−}
1508−
1509−void setupPaintingVoxel() {
1510− glm::vec3 avatarPos = myAvatar.getPosition();
1511−
1512− ::paintingVoxel.x = avatarPos.z/-10.0; // voxel space x is negative z head space
1513− ::paintingVoxel.y = avatarPos.y/-10.0; // voxel space y is negative y head space
1514− ::paintingVoxel.z = avatarPos.x/-10.0; // voxel space z is negative x head space
1515− ::paintingVoxel.s = 1.0/256;
1516−
1517− shiftPaintingColor();
1518−}
1519−
1520−void addVoxelInFrontOfAvatar() {
1521− VoxelDetail detail;
1522−
1523− glm::vec3 position = (myAvatar.getPosition() + myAvatar.getCameraDirection()) * (1.0f / TREE_SCALE);
1524− detail.s = ::mouseVoxelScale;
1525−
1526− detail.x = detail.s * floor(position.x / detail.s);
1527− detail.y = detail.s * floor(position.y / detail.s);
1528− detail.z = detail.s * floor(position.z / detail.s);
1529− detail.red = 128;
1530− detail.green = 128;
1531− detail.blue = 128;
1532−
1533− sendVoxelEditMessage(PACKET_HEADER_SET_VOXEL, detail);
1534−
1535− // create the voxel locally so it appears immediately
1536− voxels.createVoxel(detail.x, detail.y, detail.z, detail.s, detail.red, detail.green, detail.blue);
1537−}
1538−
1539−void addVoxelUnderCursor() {
1540− if (::mouseVoxel.s != 0) {
1541− sendVoxelEditMessage(PACKET_HEADER_SET_VOXEL, ::mouseVoxel);
1542−
1543− // create the voxel locally so it appears immediately
1544− voxels.createVoxel(::mouseVoxel.x, ::mouseVoxel.y, ::mouseVoxel.z, ::mouseVoxel.s,
1545− ::mouseVoxel.red, ::mouseVoxel.green, ::mouseVoxel.blue);
1546− }
1547−}
1548−
1549−void deleteVoxelUnderCursor() {
1550− if (::mouseVoxel.s != 0) {
1551− sendVoxelEditMessage(PACKET_HEADER_ERASE_VOXEL, ::mouseVoxel);
1552−
1553− // delete the voxel locally so it disappears immediately
1554− voxels.deleteVoxelAt(::mouseVoxel.x, ::mouseVoxel.y, ::mouseVoxel.z, ::mouseVoxel.s);
1555− }
1556−}
1557−
1558−const float KEYBOARD_YAW_RATE = 0.8;
1559−const float KEYBOARD_PITCH_RATE = 0.6;
1560−const float KEYBOARD_STRAFE_RATE = 0.03;
1561−const float KEYBOARD_FLY_RATE = 0.08;
1562−
1563−void specialkeyUp(int k, int x, int y) {
1564− if (k == GLUT_KEY_UP) {
1565− myAvatar.setDriveKeys(FWD, 0);
1566− myAvatar.setDriveKeys(UP, 0);
1567− }
1568− if (k == GLUT_KEY_DOWN) {
1569− myAvatar.setDriveKeys(BACK, 0);
1570− myAvatar.setDriveKeys(DOWN, 0);
1571− }
1572− if (k == GLUT_KEY_LEFT) {
1573− myAvatar.setDriveKeys(LEFT, 0);
1574− myAvatar.setDriveKeys(ROT_LEFT, 0);
1575− }
1576− if (k == GLUT_KEY_RIGHT) {
1577− myAvatar.setDriveKeys(RIGHT, 0);
1578− myAvatar.setDriveKeys(ROT_RIGHT, 0);
1579− }
1580−}
1581−
1582−void specialkey(int k, int x, int y) {
1583− if (::chatEntryOn) {
1584−
1585− return;
1586− }
1587−
1588− if (k == GLUT_KEY_UP || k == GLUT_KEY_DOWN || k == GLUT_KEY_LEFT || k == GLUT_KEY_RIGHT) {
1589− if (k == GLUT_KEY_UP) {
1590− if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) myAvatar.setDriveKeys(UP, 1);
1591− else myAvatar.setDriveKeys(FWD, 1);
1592− }
1593− if (k == GLUT_KEY_DOWN) {
1594− if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) myAvatar.setDriveKeys(DOWN, 1);
1595− else myAvatar.setDriveKeys(BACK, 1);
1596− }
1597− if (k == GLUT_KEY_LEFT) {
1598− if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) myAvatar.setDriveKeys(LEFT, 1);
1599− else myAvatar.setDriveKeys(ROT_LEFT, 1);
1600− }
1601− if (k == GLUT_KEY_RIGHT) {
1602− if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) myAvatar.setDriveKeys(RIGHT, 1);
1603− else myAvatar.setDriveKeys(ROT_RIGHT, 1);
1604− }
1605− }
1606−}
1607−
1608−void keyUp(unsigned char k, int x, int y) {
1609− if (::chatEntryOn) {
1610− myAvatar.setKeyState(NO_KEY_DOWN);
1611− return;
1612− }
1613−
1614− if (k == 'e') myAvatar.setDriveKeys(UP, 0);
1615− if (k == 'c') myAvatar.setDriveKeys(DOWN, 0);
1616− if (k == 'w') myAvatar.setDriveKeys(FWD, 0);
1617− if (k == 's') myAvatar.setDriveKeys(BACK, 0);
1618− if (k == 'a') myAvatar.setDriveKeys(ROT_LEFT, 0);
1619− if (k == 'd') myAvatar.setDriveKeys(ROT_RIGHT, 0);
1620−}
1621−
1622−void toggleMouseMode(MouseMode mode) {
1623− ::mouseMode = (::mouseMode == mode) ? NO_EDIT_MODE : mode;
1624−}
1625−
1626−void key(unsigned char k, int x, int y) {
1627− if (::chatEntryOn) {
1628−
1629− return;
1630− }
1631−
1632− // Process keypresses
1633−
1634− if (k == 'S') {
1635− ::voxels.collectStatsForTreesAndVBOs();
1636− }
1637−
1638− if (k == 'q' || k == 'Q') ::terminate();
1639− if (k == '/') ::renderStatsOn = !::renderStatsOn; // toggle stats
1640− if (k == '*') ::renderStarsOn = !::renderStarsOn; // toggle stars
1641− if (k == 'V' || k == 'v') ::renderVoxels = !::renderVoxels; // toggle voxels
1642− if (k == 'A') ::renderAtmosphereOn = !::renderAtmosphereOn;
1643− if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging
1644− if (k == 'C') ::cameraFrustum = !::cameraFrustum; // toggle which frustum to look at
1645− if (k == 'O' || k == 'G') setFrustumOffset(MENU_ROW_PICKED); // toggle view frustum offset debugging
1646− if (k == 'f') setFullscreen(!::fullscreen);
1647− if (k == 'o') setOculus(!::oculusOn);
1648− if (k == 'p') setRenderFirstPerson(MENU_ROW_PICKED);
1649− if (k == '[') ::viewFrustumOffsetYaw -= 0.5;
1650− if (k == ']') ::viewFrustumOffsetYaw += 0.5;
1651− if (k == '{') ::viewFrustumOffsetPitch -= 0.5;
1652− if (k == '}') ::viewFrustumOffsetPitch += 0.5;
1653− if (k == '(') ::viewFrustumOffsetRoll -= 0.5;
1654− if (k == ')') ::viewFrustumOffsetRoll += 0.5;
1655− if (k == '<') ::viewFrustumOffsetDistance -= 0.5;
1656− if (k == '>') ::viewFrustumOffsetDistance += 0.5;
1657− if (k == ',') ::viewFrustumOffsetUp -= 0.05;
1658− if (k == '.') ::viewFrustumOffsetUp += 0.05;
1659−
1660−// if (k == '|') ViewFrustum::fovAngleAdust -= 0.05;
1661−// if (k == '\\') ViewFrustum::fovAngleAdust += 0.05;
1662−
1663− if (k == 'R') setFrustumRenderMode(MENU_ROW_PICKED);
1664−
1665− if (k == '&') {
1666− ::paintOn = !::paintOn; // toggle paint
1667− ::setupPaintingVoxel(); // also randomizes colors
1668− }
1669− if (k == '^') ::shiftPaintingColor(); // shifts randomize color between R,G,B dominant
1670− if (k == '-') ::sendVoxelServerEraseAll(); // sends erase all command to voxel server
1671− if (k == '%') ::sendVoxelServerAddScene(); // sends add scene command to voxel server
1672− if (k == '1') ::mouseMode = (::mouseMode == ADD_VOXEL_MODE) ? NO_EDIT_MODE : ADD_VOXEL_MODE;
1673− if (k == '2') ::mouseMode = (::mouseMode == DELETE_VOXEL_MODE) ? NO_EDIT_MODE : DELETE_VOXEL_MODE;
1674− if (k == '3') ::mouseMode = (::mouseMode == COLOR_VOXEL_MODE) ? NO_EDIT_MODE : COLOR_VOXEL_MODE;
1675− if (k == '4') addVoxelInFrontOfAvatar();
1676− if (k == '5') ::mouseVoxelScale /= 2;
1677− if (k == '6') ::mouseVoxelScale *= 2;
1678− if (k == 'n' || k == 'N')
1679− {
1680− noiseOn = !noiseOn; // Toggle noise
1681− if (noiseOn)
1682− {
1683− myAvatar.setNoise(noise);
1684− }
1685− else
1686− {
1687− myAvatar.setNoise(0);
1688− }
1689− }
1690−
1691− if (k == 'h') {
1692− ::lookingInMirror = !::lookingInMirror;
1693− #ifndef _WIN32
1694− audio.setMixerLoopbackFlag(::lookingInMirror);
1695−
1696− if (::lookingInMirror) {
1697− myCamera.setMode(CAMERA_MODE_MIRROR);
1698− } else {
1699− myCamera.setMode(defaultCameraMode);
1700− }
1701− #endif
1702− }
1703−
1704− if (k == 'm' || k == 'M') setMenu(MENU_ROW_PICKED);
1705−
1706− if (k == 'l') displayLevels = !displayLevels;
1707− if (k == 'e') myAvatar.setDriveKeys(UP, 1);
1708− if (k == 'c') myAvatar.setDriveKeys(DOWN, 1);
1709− if (k == 'w') myAvatar.setDriveKeys(FWD, 1);
1710− if (k == 's') myAvatar.setDriveKeys(BACK, 1);
1711− if (k == ' ') reset_sensors();
1712− if (k == 'a') myAvatar.setDriveKeys(ROT_LEFT, 1);
1713− if (k == 'd') myAvatar.setDriveKeys(ROT_RIGHT, 1);
1714−
1715− if (k == '\r') {
1716− ::chatEntryOn = true;
1717− myAvatar.setKeyState(NO_KEY_DOWN);
1718− myAvatar.setChatMessage(string());
1719− }
1720−}
1721−
1722−// Receive packets from other agents/servers and decide what to do with them!
1723−void* networkReceive(void* args) {
1724− sockaddr senderAddress;
1725− ssize_t bytesReceived;
1726−
1727− while (!stopNetworkReceiveThread) {
1728− // check to see if the UI thread asked us to kill the voxel tree. since we're the only thread allowed to do that
1729− if (::wantToKillLocalVoxels) {
1730− ::voxels.killLocalVoxels();
1731− ::wantToKillLocalVoxels = false;
1732− }
1733−
1734− if (AgentList::getInstance()->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
1735− packetCount++;
1736− bytesCount += bytesReceived;
1737−
1738− switch (incomingPacket[0]) {
1739− case PACKET_HEADER_TRANSMITTER_DATA:
1740− // Process UDP packets that are sent to the client from local sensor devices
1741− myAvatar.processTransmitterData(incomingPacket, bytesReceived);
1742− break;
1743− case PACKET_HEADER_VOXEL_DATA:
1744− case PACKET_HEADER_VOXEL_DATA_MONOCHROME:
1745− case PACKET_HEADER_Z_COMMAND:
1746− case PACKET_HEADER_ERASE_VOXEL:
1747− voxels.parseData(incomingPacket, bytesReceived);
1748− break;
1749− case PACKET_HEADER_ENVIRONMENT_DATA:
1750− environment.parseData(incomingPacket, bytesReceived);
1751− break;
1752− case PACKET_HEADER_BULK_AVATAR_DATA:
1753− AgentList::getInstance()->processBulkAgentData(&senderAddress,
1754− incomingPacket,
1755− bytesReceived);
1756− break;
1757− default:
1758− AgentList::getInstance()->processAgentData(&senderAddress, incomingPacket, bytesReceived);
1759− break;
1760− }
1761− } else if (!enableNetworkThread) {
1762− break;
1763− }
1764− }
1765−
1766− if (enableNetworkThread) {
1767− pthread_exit(0);
1768− }
1769− return NULL;
1770−}
1771−
1772−glm::vec3 getFaceVector(BoxFace face) {
1773− switch (face) {
1774− case MIN_X_FACE:
1775− return glm::vec3(-1, 0, 0);
1776−
1777− case MAX_X_FACE:
1778− return glm::vec3(1, 0, 0);
1779−
1780− case MIN_Y_FACE:
1781− return glm::vec3(0, -1, 0);
1782−
1783− case MAX_Y_FACE:
1784− return glm::vec3(0, 1, 0);
1785−
1786− case MIN_Z_FACE:
1787− return glm::vec3(0, 0, -1);
1788−
1789− case MAX_Z_FACE:
1790− return glm::vec3(0, 0, 1);
1791− }
1792−}
1793−
1794−Application* app;
1795−
1796−void idle(void) {
1797− timeval check;
1798− gettimeofday(&check, NULL);
1799−
1800− app->processEvents();
1801−
1802− // Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time
1803−
1804− if (diffclock(&lastTimeIdle, &check) > IDLE_SIMULATE_MSECS) {
1805−
1806− float deltaTime = 1.f/FPS;
1807−
1808− // update behaviors for avatar hand movement: handControl takes mouse values as input,
1809− // and gives back 3D values modulated for smooth transitioning between interaction modes.
1810− handControl.update(mouseX, mouseY);
1811− myAvatar.setHandMovementValues(handControl.getValues());
1812−
1813− // tell my avatar if the mouse is being pressed...
1814− myAvatar.setMousePressed(mousePressed);
1815−
1816− // check what's under the mouse and update the mouse voxel
1817− glm::vec3 origin, direction;
1818− viewFrustum.computePickRay(mouseX / (float)::screenWidth, mouseY / (float)::screenHeight, origin, direction);
1819−
1820− float distance;
1821− BoxFace face;
1822− ::mouseVoxel.s = 0.0f;
1823− if (::mouseMode != NO_EDIT_MODE && voxels.findRayIntersection(origin, direction, ::mouseVoxel, distance, face)) {
1824− // find the nearest voxel with the desired scale
1825− if (::mouseVoxelScale > ::mouseVoxel.s) {
1826− // choose the larger voxel that encompasses the one selected
1827− ::mouseVoxel.x = ::mouseVoxelScale * floorf(::mouseVoxel.x / ::mouseVoxelScale);
1828− ::mouseVoxel.y = ::mouseVoxelScale * floorf(::mouseVoxel.y / ::mouseVoxelScale);
1829− ::mouseVoxel.z = ::mouseVoxelScale * floorf(::mouseVoxel.z / ::mouseVoxelScale);
1830− ::mouseVoxel.s = ::mouseVoxelScale;
1831−
1832− } else {
1833− glm::vec3 faceVector = getFaceVector(face);
1834− if (::mouseVoxelScale < ::mouseVoxel.s) {
1835− // find the closest contained voxel
1836− glm::vec3 pt = (origin + direction * distance) / (float)TREE_SCALE -
1837− faceVector * (::mouseVoxelScale * 0.5f);
1838− ::mouseVoxel.x = ::mouseVoxelScale * floorf(pt.x / ::mouseVoxelScale);
1839− ::mouseVoxel.y = ::mouseVoxelScale * floorf(pt.y / ::mouseVoxelScale);
1840− ::mouseVoxel.z = ::mouseVoxelScale * floorf(pt.z / ::mouseVoxelScale);
1841− ::mouseVoxel.s = ::mouseVoxelScale;
1842− }
1843− if (::mouseMode == ADD_VOXEL_MODE) {
1844− // use the face to determine the side on which to create a neighbor
1845− ::mouseVoxel.x += faceVector.x * ::mouseVoxel.s;
1846− ::mouseVoxel.y += faceVector.y * ::mouseVoxel.s;
1847− ::mouseVoxel.z += faceVector.z * ::mouseVoxel.s;
1848− }
1849− }
1850−
1851− if (::mouseMode == COLOR_VOXEL_MODE) {
1852− ::mouseVoxel.red = 0;
1853− ::mouseVoxel.green = 255;
1854− ::mouseVoxel.blue = 0;
1855−
1856− } else if (::mouseMode == DELETE_VOXEL_MODE) {
1857− // red indicates deletion
1858− ::mouseVoxel.red = 255;
1859− ::mouseVoxel.green = ::mouseVoxel.blue = 0;
1860− }
1861− }
1862−
1863− // walking triggers the handControl to stop
1864− if (myAvatar.getMode() == AVATAR_MODE_WALKING) {
1865− handControl.stop();
1866− mouseViewShiftYaw *= 0.9;
1867− mouseViewShiftPitch *= 0.9;
1868− }
1869−
1870− // Read serial port interface devices
1871− if (serialPort.active) {
1872− serialPort.readData();
1873− }
1874−
1875− // Sample hardware, update view frustum if needed, and send avatar data to mixer/agents
1876− updateAvatar(deltaTime);
1877−
1878− // read incoming packets from network
1879− if (!enableNetworkThread) {
1880− networkReceive(0);
1881− }
1882−
1883− //loop through all the remote avatars and simulate them...
1884− AgentList* agentList = AgentList::getInstance();
1885− agentList->lock();
1886− for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
1887− if (agent->getLinkedData() != NULL) {
1888− Avatar *avatar = (Avatar *)agent->getLinkedData();
1889− avatar->simulate(deltaTime);
1890− }
1891− }
1892− agentList->unlock();
1893−
1894− myAvatar.setGravity(getGravity(myAvatar.getPosition()));
1895− myAvatar.simulate(deltaTime);
1896−
1897− // Update audio stats for procedural sounds
1898− audio.setLastAcceleration(myAvatar.getThrust());
1899− audio.setLastVelocity(myAvatar.getVelocity());
1900−
1901− glutPostRedisplay();
1902− lastTimeIdle = check;
1903− }
1904−}
1905−
1906−void reshape(int width, int height) {
1907− ::screenWidth = width;
1908− ::screenHeight = height;
1909− aspectRatio = ((float)width/(float)height); // based on screen resize
1910−
1911− // get the lens details from the current camera
1912− Camera& camera = ::viewFrustumFromOffset ? (::viewFrustumOffsetCamera) : (::myCamera);
1913− float nearClip = camera.getNearClip();
1914− float farClip = camera.getFarClip();
1915− float fov;
1916−
1917− if (::oculusOn) {
1918− // more magic numbers; see Oculus SDK docs, p. 32
1919− camera.setAspectRatio(aspectRatio *= 0.5);
1920− camera.setFieldOfView(fov = 2 * atan((0.0468 * ::oculusDistortionScale) / 0.041) * (180 / PI));
1921−
1922− // resize the render texture
1923− if (::oculusTextureID != 0) {
1924− glBindTexture(GL_TEXTURE_2D, ::oculusTextureID);
1925− glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ::screenWidth, ::screenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1926− glBindTexture(GL_TEXTURE_2D, 0);
1927− }
1928− } else {
1929− camera.setAspectRatio(aspectRatio);
1930− camera.setFieldOfView(fov = 60);
1931− }
1932−
1933− // Tell our viewFrustum about this change
1934− ::viewFrustum.setAspectRatio(aspectRatio);
1935−
1936− glViewport(0, 0, width, height); // shouldn't this account for the menu???
1937−
1938− glMatrixMode(GL_PROJECTION);
1939− glLoadIdentity();
1940−
1941− // XXXBHG - If we're in view frustum mode, then we need to do this little bit of hackery so that
1942− // OpenGL won't clip our frustum rendering lines. This is a debug hack for sure! Basically, this makes
1943− // the near clip a little bit closer (therefor you see more) and the far clip a little bit farther (also,
1944− // to see more.)
1945− if (::frustumOn) {
1946− nearClip -= 0.01f;
1947− farClip += 0.01f;
1948− }
1949−
1950− // On window reshape, we need to tell OpenGL about our new setting
1951− gluPerspective(fov,aspectRatio,nearClip,farClip);
1952−
1953− glMatrixMode(GL_MODELVIEW);
1954− glLoadIdentity();
1955−}
1956−
1957−//Find and return the gravity vector at this location
1958−glm::vec3 getGravity(glm::vec3 pos) {
1959− //
1960− // For now, we'll test this with a simple global lookup, but soon we will add getting this
1961− // from the domain/voxelserver (or something similar)
1962− //
1963− if ((pos.x > 0.f) &&
1964− (pos.x < 10.f) &&
1965− (pos.z > 0.f) &&
1966− (pos.z < 10.f) &&
1967− (pos.y > 0.f) &&
1968− (pos.y < 3.f)) {
1969− // If above ground plane, turn gravity on
1970− return glm::vec3(0.f, -1.f, 0.f);
1971− } else {
1972− // If flying in space, turn gravity OFF
1973− return glm::vec3(0.f, 0.f, 0.f);
1974− }
1975−}
1976−
1977−bool menuDisplayed = false;
1978−void mouseFunc(int button, int state, int x, int y) {
1979− bool menuFound = menu.mouseClick(x, y);
1980−
1981− // If we didn't previously have the menu displayed, and we did just click on the menu, then
1982− // go into menuDisplayed mode....
1983− if (!::menuDisplayed && menuFound) {
1984− ::menuDisplayed = true;
1985− }
1986−
1987− // If the menu was displayed, and we're not over a menu, then leave menu mode
1988− if (::menuDisplayed && !menuFound) {
1989− ::menuDisplayed = false;
1990− menu.hidePopupMenu();
1991− }
1992−
1993− // In menu displayed mode use old logic
1994− if (::menuDisplayed) {
1995− if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
1996− if (state == GLUT_DOWN && !menu.mouseClick(x, y)) {
1997− mouseX = x;
1998− mouseY = y;
1999− mousePressed = 1;
2000− } else if (state == GLUT_UP) {
2001− mouseX = x;
2002− mouseY = y;
2003− mousePressed = 0;
2004− }
2005− }
2006− } else {
2007− if (button == GLUT_LEFT_BUTTON) {
2008− mouseX = x;
2009− mouseY = y;
2010−
2011− if (state == GLUT_DOWN) {
2012− mousePressed = 1;
2013− if (::mouseMode == ADD_VOXEL_MODE || ::mouseMode == COLOR_VOXEL_MODE) {
2014− addVoxelUnderCursor();
2015−
2016− } else if (::mouseMode == DELETE_VOXEL_MODE) {
2017− deleteVoxelUnderCursor();
2018− }
2019− } else if (state == GLUT_UP) {
2020− mousePressed = 0;
2021− }
2022− } else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN && ::mouseMode != NO_EDIT_MODE) {
2023− deleteVoxelUnderCursor();
2024− }
2025− }
2026−}
2027−
2028−
2029−void motionFunc(int x, int y) {
2030− mouseX = x;
2031− mouseY = y;
2032−}
2033−
2034−void mouseoverFunc(int x, int y){
2035− menu.mouseOver(x, y);
2036−
2037− mouseX = x;
2038− mouseY = y;
2039−}
2040−
2041−void attachNewHeadToAgent(Agent *newAgent) {
2042− if (newAgent->getLinkedData() == NULL) {
2043− newAgent->setLinkedData(new Avatar(false));
2044− }
2045−}
2046−
2047−#ifndef _WIN32
2048−void audioMixerUpdate(in_addr_t newMixerAddress, in_port_t newMixerPort) {
2049− audio.updateMixerParams(newMixerAddress, newMixerPort);
2050−}
2051−#endif
19+#include "Log.h"
205220
205321 int main(int argc, const char * argv[]) {
205422
@@ -2057,124 +25,4 @@ int main(int argc, const char * argv[]) { · 2 unmodified lines
205725 int exitCode = app.exec();
205826 printLog("Normal exit.\n");
205927 return exitCode;
2060−
2061−
2062−
2063− gettimeofday(&applicationStartupTime, NULL);
2064− printLog("Interface Startup:\n");
2065−
2066− voxels.setViewFrustum(&::viewFrustum);
2067−
2068− shared_lib::printLog = & ::printLog;
2069− voxels_lib::printLog = & ::printLog;
2070− avatars_lib::printLog = & ::printLog;
2071−
2072− unsigned int listenPort = AGENT_SOCKET_LISTEN_PORT;
2073− const char* portStr = getCmdOption(argc, argv, "--listenPort");
2074− if (portStr) {
2075− listenPort = atoi(portStr);
2076− }
2077− AgentList::createInstance(AGENT_TYPE_AVATAR, listenPort);
2078− enableNetworkThread = !cmdOptionExists(argc, argv, "--nonblocking");
2079− if (!enableNetworkThread) {
2080− AgentList::getInstance()->getAgentSocket().setBlocking(false);
2081− }
2082−
2083− const char* domainIP = getCmdOption(argc, argv, "--domain");
2084− if (domainIP) {
2085− strcpy(DOMAIN_IP,domainIP);
2086− }
2087−
2088− // Handle Local Domain testing with the --local command line
2089− if (cmdOptionExists(argc, argv, "--local")) {
2090− printLog("Local Domain MODE!\n");
2091− int ip = getLocalAddress();
2092− sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
2093− }
2094−
2095− // the callback for our instance of AgentList is attachNewHeadToAgent
2096− AgentList::getInstance()->linkedDataCreateCallback = &attachNewHeadToAgent;
2097−
2098− #ifndef _WIN32
2099− AgentList::getInstance()->audioMixerSocketUpdate = &audioMixerUpdate;
2100− #endif
2101−
2102−#ifdef _WIN32
2103− WSADATA WsaData;
2104− int wsaresult = WSAStartup(MAKEWORD(2,2), &WsaData);
2105−#endif
2106−
2107− // start the agentList threads
2108− AgentList::getInstance()->startSilentAgentRemovalThread();
2109− AgentList::getInstance()->startDomainServerCheckInThread();
2110− AgentList::getInstance()->startPingUnknownAgentsThread();
2111−
2112− glutInit(&argc, (char**)argv);
2113− ::screenWidth = glutGet(GLUT_SCREEN_WIDTH);
2114− ::screenHeight = glutGet(GLUT_SCREEN_HEIGHT);
2115−
2116− glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
2117− glutInitWindowSize(::screenWidth, ::screenHeight);
2118− glutCreateWindow("Interface");
2119− printLog( "Created Display Window.\n" );
2120−
2121− #ifdef _WIN32
2122− glewInit();
2123− printLog( "Glew Init complete.\n" );
2124−
2125− #endif
2126−
2127− // Before we render anything, let's set up our viewFrustumOffsetCamera with a sufficiently large
2128− // field of view and near and far clip to make it interesting.
2129− //viewFrustumOffsetCamera.setFieldOfView(90.0);
2130− viewFrustumOffsetCamera.setNearClip(0.1);
2131− viewFrustumOffsetCamera.setFarClip(500.0*TREE_SCALE);
2132−
2133−
2134− initMenu();
2135− initDisplay();
2136−
2137− glutDisplayFunc(display);
2138− glutReshapeFunc(reshape);
2139− glutKeyboardFunc(key);
2140− glutKeyboardUpFunc(keyUp);
2141− glutSpecialFunc(specialkey);
2142− glutSpecialUpFunc(specialkeyUp);
2143− glutMotionFunc(motionFunc);
2144− glutPassiveMotionFunc(mouseoverFunc);
2145− glutMouseFunc(mouseFunc);
2146− glutIdleFunc(idle);
2147− printLog( "Initialized Display.\n" );
2148−
2149−
2150− init();
2151− printLog( "Init() complete.\n" );
2152−
2153− // Check to see if the user passed in a command line option for randomizing colors
2154− if (cmdOptionExists(argc, argv, "--NoColorRandomizer")) {
2155− wantColorRandomizer = false;
2156− }
2157−
2158− // Check to see if the user passed in a command line option for loading a local
2159− // Voxel File. If so, load it now.
2160− const char* voxelsFilename = getCmdOption(argc, argv, "-i");
2161− if (voxelsFilename) {
2162− voxels.loadVoxelsFile(voxelsFilename,wantColorRandomizer);
2163− printLog("Local Voxel File loaded.\n");
2164− }
2165−
2166− // create thread for receipt of data via UDP
2167− if (enableNetworkThread) {
2168− pthread_create(&networkReceiveThread, NULL, networkReceive, NULL);
2169− printLog("Network receive thread created.\n");
2170− }
2171−
2172− myAvatar.readAvatarDataFromFile();
2173−
2174− glutTimerFunc(1000, Timer, 0);
2175− glutMainLoop();
2176−
2177− printLog("Normal exit.\n");
2178− ::terminate();
2179− return EXIT_SUCCESS;
218028 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t