From 86d9230181fc585fed349aa8dd070860d5511ea1 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 17 Nov 2012 17:00:56 -0800 Subject: [PATCH] Partial commit to switch sprite rendering to new Cloud class --- cloud.cpp | 132 ++++++++++++++++++ cloud.h | 32 +++++ field.h | 11 -- head.cpp | 1 + interface.xcodeproj/project.pbxproj | 6 + .../UserInterfaceState.xcuserstate | Bin 101447 -> 101370 bytes main.cpp | 52 ++++--- 7 files changed, 204 insertions(+), 30 deletions(-) create mode 100644 cloud.cpp create mode 100644 cloud.h 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 6c983b0f1039261b38ae49102b70dda728b186b1..9cf966bff86303aa87ea0c9963c3cc86906f6585 100644 GIT binary patch delta 27342 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 delta 27352 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 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;