diff --git a/cloud.cpp b/cloud.cpp new file mode 100644 index 0000000000..a0bdcceec3 --- /dev/null +++ b/cloud.cpp @@ -0,0 +1,132 @@ +// +// cloud.cpp +// interface +// +// Created by Philip Rosedale on 11/17/12. +// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// + +#include +#include "cloud.h" +#include "util.h" + +Cloud::Cloud(int num, + glm::vec3 box, + int wrap) { + // Create and initialize particles + int i; + bounds = box; + count = num; + wrapBounds = wrap; + particles = new Particle[count]; + + for (i = 0; i < count; i++) { + particles[i].position.x = randFloat()*box.x; + particles[i].position.y = randFloat()*box.y; + particles[i].position.z = randFloat()*box.z; + + particles[i].velocity.x = 0; //randFloat() - 0.5; + particles[i].velocity.y = 0; //randFloat() - 0.5; + particles[i].velocity.z = 0; //randFloat() - 0.5; + + } +} + + +void Cloud::render() { + + float particle_attenuation_quadratic[] = { 0.0f, 0.0f, 2.0f }; + + glEnable( GL_TEXTURE_2D ); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, particle_attenuation_quadratic ); + + float maxSize = 0.0f; + glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); + glPointSize( maxSize ); + glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize ); + glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 0.001f ); + + glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE ); + glEnable( GL_POINT_SPRITE_ARB ); + glBegin( GL_POINTS ); + for (int i = 0; i < count; i++) + { + glVertex3f(particles[i].position.x, + particles[i].position.y, + particles[i].position.z); + } + glEnd(); + glDisable( GL_POINT_SPRITE_ARB ); + glDisable( GL_TEXTURE_2D ); +} + +void Cloud::simulate (float deltaTime) { + int i; + float verts[3], fadd[3], fval[3]; + for (i = 0; i < count; ++i) { + + // Update position + //particles[i].position += particles[i].velocity*deltaTime; + particles[i].position += particles[i].velocity; + + + // Drag: decay velocity + const float CONSTANT_DAMPING = 1.0; + particles[i].velocity *= (1.f - CONSTANT_DAMPING*deltaTime); + + // Read from field + verts[0] = particles[i].position.x; + verts[1] = particles[i].position.y; + verts[2] = particles[i].position.z; + field_value(fval, &verts[0]); + particles[i].velocity.x += fval[0]; + particles[i].velocity.y += fval[1]; + particles[i].velocity.z += fval[2]; + + // Add back to field + const float FIELD_COUPLE = 0.0000001; + fadd[0] = particles[i].velocity.x*FIELD_COUPLE; + fadd[1] = particles[i].velocity.y*FIELD_COUPLE; + fadd[2] = particles[i].velocity.z*FIELD_COUPLE; + field_add(fadd, &verts[0]); + + if (wrapBounds) { + // wrap around bounds + if (particles[i].position.x > bounds.x) + particles[i].position.x -= bounds.x; + else if (particles[i].position.x < 0.0f) + particles[i].position.x += bounds.x; + + if (particles[i].position.y > bounds.y) + particles[i].position.y -= bounds.y; + else if (particles[i].position.y < 0.0f) + particles[i].position.y += bounds.y; + + if (particles[i].position.z > bounds.z) + particles[i].position.z -= bounds.z; + else if (particles[i].position.z < 0.0f) + particles[i].position.z += bounds.z; + } else { + // Bounce at bounds + if (particles[i].position.x > bounds.x + || particles[i].position.x < 0.f) { + if (particles[i].position.x > bounds.x) particles[i].position.x = bounds.x; + else particles[i].position.x = 0.f; + particles[i].velocity.x *= -1; + } + if (particles[i].position.y > bounds.y + || particles[i].position.y < 0.f) { + if (particles[i].position.y > bounds.y) particles[i].position.y = bounds.y; + else particles[i].position.y = 0.f; + particles[i].velocity.y *= -1; + } + if (particles[i].position.z > bounds.z + || particles[i].position.z < 0.f) { + if (particles[i].position.z > bounds.z) particles[i].position.z = bounds.z; + else particles[i].position.z = 0.f; + particles[i].velocity.z *= -1; + } + } + } + } diff --git a/cloud.h b/cloud.h new file mode 100644 index 0000000000..575501be25 --- /dev/null +++ b/cloud.h @@ -0,0 +1,32 @@ +// +// cloud.h +// interface +// +// Created by Philip Rosedale on 11/17/12. +// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// + +#ifndef interface_cloud_h +#define interface_cloud_h + +#include "field.h" + +class Cloud { +public: + Cloud(int num, + glm::vec3 box, + int wrap); + + void simulate(float deltaTime); + void render(); + +private: + struct Particle { + glm::vec3 position, velocity; + } *particles; + unsigned int count; + glm::vec3 bounds; + bool wrapBounds; +}; + +#endif diff --git a/field.h b/field.h index ca62f91cec..2d0dbac757 100644 --- a/field.h +++ b/field.h @@ -29,15 +29,4 @@ void field_render(); void field_add(float* add, float *loc); void field_simulate(float dt); -class Field { -public: - static void init (); - static int addTo (const glm::vec3 &pos, glm::vec3 &v); - -private: - const static unsigned int fieldSize = 1000; - const static float fieldScale; // defined in cpp – inline const float definitions not allowed in standard C++?! (allowed in C++0x) - static glm::vec3 field[fieldSize]; -}; - #endif diff --git a/head.cpp b/head.cpp index bb0e71d010..f2132e788d 100644 --- a/head.cpp +++ b/head.cpp @@ -178,6 +178,7 @@ void Head::render() } glPopMatrix(); + // Mouth glPushMatrix(); glTranslatef(0,-0.3,0.75); diff --git a/interface.xcodeproj/project.pbxproj b/interface.xcodeproj/project.pbxproj index 7b58f146e6..910b2dbd70 100644 --- a/interface.xcodeproj/project.pbxproj +++ b/interface.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ B6BDADE315F44AB0002A07DF /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BDADDA15F444C9002A07DF /* AudioToolbox.framework */; }; B6BDADE415F44AC7002A07DF /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BDADDC15F444D3002A07DF /* AudioUnit.framework */; }; B6BDAE4415F6BE53002A07DF /* particle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6BDAE4315F6BE53002A07DF /* particle.cpp */; }; + D409B98A165849180099B0B3 /* cloud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D409B989165849180099B0B3 /* cloud.cpp */; }; D40BDFD513404BA300B0BE1F /* GLUT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40BDFD413404BA300B0BE1F /* GLUT.framework */; }; D40BDFD713404BB300B0BE1F /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40BDFD613404BB300B0BE1F /* OpenGL.framework */; }; D40FD5FB164AF1C200878184 /* int-texture256-v2.png in CopyFiles */ = {isa = PBXBuildFile; fileRef = D40FD5FA164AF1A700878184 /* int-texture256-v2.png */; }; @@ -66,6 +67,8 @@ B6BDAE4115F6BE4D002A07DF /* particle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = particle.h; sourceTree = ""; }; B6BDAE4315F6BE53002A07DF /* particle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = particle.cpp; sourceTree = ""; }; C6859E8B029090EE04C91782 /* test_c_plus.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = test_c_plus.1; sourceTree = ""; }; + D409B988165849030099B0B3 /* cloud.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cloud.h; sourceTree = ""; }; + D409B989165849180099B0B3 /* cloud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cloud.cpp; sourceTree = ""; }; D40BDFD413404BA300B0BE1F /* GLUT.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLUT.framework; path = /System/Library/Frameworks/GLUT.framework; sourceTree = ""; }; D40BDFD613404BB300B0BE1F /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; D40FD5FA164AF1A700878184 /* int-texture256-v2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "int-texture256-v2.png"; sourceTree = SOURCE_ROOT; }; @@ -134,6 +137,8 @@ isa = PBXGroup; children = ( 08FB7796FE84155DC02AAC07 /* main.cpp */, + D409B988165849030099B0B3 /* cloud.h */, + D409B989165849180099B0B3 /* cloud.cpp */, D4EE3BC015E746E900EE4C89 /* world.h */, B6BDAE4315F6BE53002A07DF /* particle.cpp */, B6BDAE4115F6BE4D002A07DF /* particle.h */, @@ -261,6 +266,7 @@ D4EFE3D0162A2DA000DC5C59 /* hand.cpp in Sources */, F68135561648617D003040E3 /* texture.cpp in Sources */, F681358B1648896D003040E3 /* lodepng.cpp in Sources */, + D409B98A165849180099B0B3 /* cloud.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/interface.xcodeproj/project.xcworkspace/xcuserdata/philip.xcuserdatad/UserInterfaceState.xcuserstate b/interface.xcodeproj/project.xcworkspace/xcuserdata/philip.xcuserdatad/UserInterfaceState.xcuserstate index 6c983b0f10..9cf966bff8 100644 Binary files a/interface.xcodeproj/project.xcworkspace/xcuserdata/philip.xcuserdatad/UserInterfaceState.xcuserstate and b/interface.xcodeproj/project.xcworkspace/xcuserdata/philip.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/main.cpp b/main.cpp index 21fa1edf39..cf2ecbac8a 100644 --- a/main.cpp +++ b/main.cpp @@ -49,6 +49,8 @@ #include "texture.h" +#include "cloud.h" + //TGAImg Img; using namespace std; @@ -74,6 +76,8 @@ int bytescount = 0; int target_x, target_y; int target_display = 0; +int head_mirror = 0; // Whether to mirror the head when viewing it + unsigned char last_key = 0; double ping = 0; @@ -98,7 +102,10 @@ ParticleSystem balls(0, 0.0 // Gravity ); - +Cloud cloud(0, // Particles + box, // Bounding Box + false // Wrap + ); // FIELD INFORMATION // If the simulation 'world' is a box with 10M boundaries, the offset to a field cell is given by: @@ -113,11 +120,9 @@ ParticleSystem balls(0, #define RENDER_FRAME_MSECS 10 #define SLEEP 0 -#define NUM_TRIS 100000 +#define NUM_TRIS 250000 struct { float vertices[NUM_TRIS * 3]; -// float normals [NUM_TRIS * 3]; -// float colors [NUM_TRIS * 3]; float vel [NUM_TRIS * 3]; glm::vec3 vel1[NUM_TRIS]; glm::vec3 vel2[NUM_TRIS]; @@ -154,7 +159,7 @@ int display_head = 0; int display_hand = 0; int display_field = 0; -int display_head_mouse = 1; // Display sample mouse pointer controlled by head movement +int display_head_mouse = 1; // Display sample mouse pointer controlled by head movement int head_mouse_x, head_mouse_y; int head_lean_x, head_lean_y; @@ -446,10 +451,17 @@ void update_pos(float frametime) float measured_fwd_accel = avg_adc_channels[2] - adc_channels[2]; // Update avatar head position based on measured gyro rates - myHead.addYaw(measured_yaw_rate * 0.25 * frametime); - myHead.addPitch(measured_pitch_rate * -0.25 * frametime); - myHead.addLean(measured_lateral_accel * frametime * 0.05, measured_fwd_accel*frametime * 0.05); - + const float HEAD_ROTATION_SCALE = 0.10; + const float HEAD_LEAN_SCALE = 0.02; + if (head_mirror) { + myHead.addYaw(measured_yaw_rate * HEAD_ROTATION_SCALE * frametime); + myHead.addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); + myHead.addLean(measured_lateral_accel * frametime * HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); + } else { + myHead.addYaw(measured_yaw_rate * -HEAD_ROTATION_SCALE * frametime); + myHead.addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); + myHead.addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); + } // Decay avatar head back toward zero //pitch *= (1.f - 5.0*frametime); //yaw *= (1.f - 7.0*frametime); @@ -608,24 +620,25 @@ void display(void) glPointSize( maxSize ); glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize ); glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 0.001f ); + glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE ); - glEnable( GL_POINT_SPRITE_ARB ); - if (!display_head) { - glBegin( GL_POINTS ); - { - for (i = 0; i < NUM_TRIS; i++) + if (!display_head) { + glBegin( GL_POINTS ); { - glVertex3f(tris.vertices[i*3], - tris.vertices[i*3+1], - tris.vertices[i*3+2]); + for (i = 0; i < NUM_TRIS; i++) + { + glVertex3f(tris.vertices[i*3], + tris.vertices[i*3+1], + tris.vertices[i*3+2]); + } } - } - glEnd(); + glEnd(); } glDisable( GL_POINT_SPRITE_ARB ); glDisable( GL_TEXTURE_2D ); + if (!display_head) cloud.render(); // Show field vectors if (display_field) field_render(); @@ -800,6 +813,7 @@ void idle(void) myHead.simulate(1.f/FPS); myHand.simulate(1.f/FPS); balls.simulate(1.f/FPS); + cloud.simulate(1.f/FPS); if (!step_on) glutPostRedisplay(); last_frame = check;