|
Rope Physics |
optimusp
Member #7,858
October 2006
|
This problem seems to be a doozy. Does anyone know of any good rope physics tutorials (other than NeHe)? I have the following code, but I'm not getting any swinging motion like a pendulum:
By the way, this code is an edited version from the code on this thread: |
ImLeftFooted
Member #3,935
October 2003
|
Quote: pendulum pendulum physics is about one of (in my book) hardest problems to solve. A bunch of pendulums on end will take too much CPU time and is a bad way to do a rope. But on the other hand I've never actually solved it. So I have no idea what I'm talking about. For a walk-through on the pendulum math, read its wikipedia page: |
nonnus29
Member #2,606
August 2002
|
Quote: pendulum physics is about one of (in my book) hardest problems to solve. A bunch of pendulums on end will take too much CPU time and is a bad way to do a rope. Naw, it's easy. This is what verlet integration excels at. Google for Chris Heckers physics tutorials. Edit; wow that's almost exactly what I said in the other thread. Weird. I'm wasting WAAAY to much time on here.... |
Zaphos
Member #1,468
August 2001
|
The Advanced Character Physics article covers what you'd want -- a rope can be modeled nicely as a line of particles connected by distance constraints.
|
optimusp
Member #7,858
October 2006
|
Thank's guys. I'm using that exact article you just mentioned. I've been reading over it the past couple hours and I'll try to implement it now. Here is what I have prior to implementing the math from that article. Very basic stuff, but some neat effects. I'm using Dev-C++. You can just post this into a new project, and it should compile: 1#include <allegro.h>
2#include <math.h>
3bool up, down, left, right;
4
5class rope{
6public:
7 class joint{
8 public:
9 float x1,y1,x2,y2;
10 float velX,velY;
11
12 }joint[100];
13
14 float real_length;
15 float seg_length; //length of segments between joints
16 float air_resistance; //air resistance [negating factor on gravity {9.8}]
17 float damping; //self-explanitory
18 float speed; //didn't know what else to name this
19 float gravity;
20 bool gravity_on;
21
22 void deploy(); //initializes the rope
23 void update(bool, bool, bool, bool); //called every game-cycle
24 void draw(BITMAP *);
25}rope[20];
26
27void rope::deploy() {
28 seg_length=5;
29 air_resistance=0.0;
30 damping= 0.0;
31 speed= .41;
32 gravity = .0;
33
34 for(short i=0; i<100; i++) {
35 joint<i>.x1=SCREEN_W/2 + (i*3); joint<i>.y1=i*seg_length;
36 joint<i>.x2=SCREEN_W/2 + (i*3); joint<i>.y2=i*seg_length;
37 joint<i>.velX=0; joint<i>.velY=0;
38 }
39};
40
41void rope::update(bool up, bool down, bool left, bool right) {
42 if (left)
43 {
44 joint[0].x1--;
45 }
46 if (right)
47 {
48 joint[0].x1++;
49 }
50 if (up)
51 {
52 joint[0].y1--;
53 }
54 if (down)
55 {
56 joint[0].y1++;
57 }
58
59 for(short i=0; i<100; i++) {
60 if (i != 0)
61 {
62 float vx1=joint[i-1].x1-joint<i>.x1; //vector 1: diffrence between x's
63 float vy1=joint[i-1].y1-joint<i>.y1; //vector 1: diffrence between y's
64 int vm1= (int)sqrt(ceil(vx1*vx1+vy1*vy1)); //vector 1: magnitude
65 int ve1= (int)vm1-(int)(seg_length/1); //vector 1: extention
66
67 float vx2=joint[i-1].x1-joint<i>.x1; //vector 2: diffrence between x's
68 float vy2=joint[i-1].y1-joint<i>.y1; //vector 2: diffrence between y's
69 int vm2= (int)sqrt(ceil(vx2*vx2+vy2*vy2)); //vector 2: magnitude
70 int ve2= (int)vm2- (int)seg_length; //vector 2: extention
71
72 float vx = (vx1 / vm1 * ve1) + (vx2 / vm2 * ve2); //x's reactant
73 float vy = (vy1 / vm1 * ve1) + (vy2 / vm2 * ve2) + gravity; //y's reactant
74
75 joint<i>.velX = joint<i>.velX * damping + (vx * speed); //set velocity x accordingly
76 joint<i>.velY = joint<i>.velY * damping + (vy * speed); //set velocity y accordingly
77 joint<i>.x2 = joint<i>.x1 + joint<i>.velX; //buffer x
78 joint<i>.y2 = joint<i>.y1 + joint<i>.velY; //buffer y
79 joint<i>.x1 = joint<i>.x2; //copy buffer to physical
80 joint<i>.y1 = joint<i>.y2; //copy buffer to physical
81 } else {
82
83 float vx1=joint<i>.x1; //vector 1: diffrence between x's
84 float vy1=joint<i>.y1; //vector 1: diffrence between y's
85 int vm1= (int)sqrt(ceil(vx1*vx1+vy1*vy1)); //vector 1: magnitude
86 int ve1= (int)vm1-(int)(seg_length/1); //vector 1: extention
87
88 float vx2=joint<i>.x1; //vector 2: diffrence between x's
89 float vy2=joint<i>.y1; //vector 2: diffrence between y's
90 int vm2= (int)sqrt(ceil(vx2*vx2+vy2*vy2)); //vector 2: magnitude
91 int ve2= (int)vm2- (int)seg_length; //vector 2: extention
92
93 float vx = 0; //x's reactant
94 float vy = gravity; //y's reactant
95
96 joint<i>.velX = joint<i>.velX * damping+(vx * speed); //set velocity x accordingly
97 joint<i>.velY = joint<i>.velY - gravity; //set velocity y accordingly
98
99 joint<i>.x2 = joint<i>.x1+joint<i>.velX; //buffer x
100 joint<i>.y2 = joint<i>.y1 - joint<i>.velY; //buffer y
101 joint<i>.x1 = joint<i>.x2; //copy buffer to physical
102 joint<i>.y1 = joint<i>.y2; //copy buffer to physical
103 }
104 if (joint<i>.y1 > (SCREEN_H-50)) {
105 joint<i>.velY = abs(joint<i>.velY) * (1 - damping);
106 joint<i>.y2 = SCREEN_H-50;
107 joint<i>.y1 = SCREEN_H-50;
108 }
109 }
110
111 if (key[KEY_G])
112 {
113 if (gravity_on)
114 {
115 gravity_on = false;
116 } else {
117 gravity_on = true;
118 }
119 }
120};
121
122void rope::draw(BITMAP *buffer) {
123 for(short i=0; i<100; i++) {
124 //draw joint and lines between
125 if (i == 0)
126 {
127 circlefill(buffer, (int)joint<i>.x1, (int)joint<i>.y1, 2, makecol(255,255,255));
128 } else {
129 //circlefill(buffer, (int)joint<i>.x1, (int)joint<i>.y1, 2, makecol(i*2,i*2,255));
130 }
131 if (i != 0)
132 {
133 line(buffer, (int)joint<i>.x1, (int)joint<i>.y1,(int)joint[i-1].x1, (int)joint[i-1].y1, makecol(i*2,i*2,255));
134 this[0].real_length = this[0].real_length + (sqrt(pow(joint<i>.x1 - joint[i-1].x1, 2) + pow(joint<i>.y1 - joint[i-1].y1, 2)));
135 }
136 }
137 textprintf_ex(buffer, font, 10, SCREEN_H-10, makecol(255, 100, 200), -1, "y1: %f", joint[0].y1);
138 textprintf_ex(buffer, font, 10, SCREEN_H-20, makecol(255, 100, 200), -1, "velY: %f", joint[0].velY);
139 textprintf_ex(buffer, font, 10, SCREEN_H-30, makecol(255, 100, 200), -1, "y1: %f", this[0].real_length);
140 this[0].real_length = 0;
141};
142
143void init();
144void deinit();
145
146int main() {
147 init();
148 BITMAP *buffer = NULL;
149 FONT *font = NULL;
150 buffer = create_bitmap(640,480);
151
152
153 rope[0].deploy();
154
155 while (!key[KEY_ESC])
156 {
157 if (key[KEY_U])
158 {
159 //rope[0].update();
160 }
161 if (key[KEY_D])
162 {
163 rope[0].deploy();
164 }
165
166 if (key[KEY_LEFT])
167 {
168 left = true;
169 }
170
171 if (key[KEY_RIGHT])
172 {
173 right = true;
174 }
175
176 if (key[KEY_UP])
177 {
178 up = true;
179 }
180
181 if (key[KEY_DOWN])
182 {
183 down = true;
184 }
185
186 rope[0].update(up, down, left, right);
187
188
189 rectfill(buffer, 0, SCREEN_H, SCREEN_W, SCREEN_H - 50, makecol(100,100,100)); //ground
190 rope[0].draw(buffer);
191 blit(buffer, screen, 0,0,0,0,640,480);//Draw the buffer to the screen
192 clear_bitmap(buffer); // Clear the contents of the buffer bitmap
193 left = false;
194 right = false;
195 up = false;
196 down = false;
197 }
198
199 deinit();
200 return 0;
201}
202END_OF_MAIN()
203
204void init() {
205 int depth, res;
206 allegro_init();
207 depth = desktop_color_depth();
208 if (depth == 0) depth = 32;
209 set_color_depth(depth);
210 res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
211 if (res != 0) {
212 allegro_message(allegro_error);
213 exit(-1);
214 }
215
216 install_timer();
217 install_keyboard();
218 install_mouse();
219 /* add other initializations here */
220
221}
222
223void deinit() {
224 clear_keybuf();
225 /* add other deinitializations here */
226}
I'll post again with a zip file once I've gotten the rigid body stuff implemented. BTW: I'd like to thank X-G for this wonderful [url http://awiki.tomasu.org/bin/view/Main/Vector3D#xgl_vector_h]Vector Library[/url]. It's proved to be very useful so far. |
Goalie Ca
Member #2,579
July 2002
|
i calculated gravity to within .05m/s^2 using a pendulum once. kinda cool. anyways back to the question. what's the application? Its really good to cheat with physics and i want to know how much we can cheat. ------------- |
Neil Walker
Member #210
April 2000
|
What you need to do is allow any joint to be moved, this will allow you pull the rope from any point, including the last one to mimic swinging, or if on a joint half way down you could make it look as though the rope is tied to something and just out of reach of the player. Neil. wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie |
optimusp
Member #7,858
October 2006
|
Update: I've got a semi-working model. It's certainly mimics rope realistically, but I'm going to put some more accurate math behind it. You can adjust the number of joints and length in the code if you like. http://www.findur.com/rope3.zip This code can also be used for rigid body collisions. That's what I'll be working on next. Hopefully I'll have another update for you soon. Thanks for the help guys. Edit: By the way, a pre-compiled exe is included. Use the arrow keys to move the lead joint. Use the "U" key to constrain the lead joint to a fixed position (this will allow you to see the swinging in full effect). Edit: Added a better build. If you mess with the number of joints and the segment length, you'll notice that there is a lot of "spingyness". I'm trying to correct this. Or at the very least, make it something that's adjustable. |
Frank Drebin
Member #2,987
December 2002
|
looks cool! |
optimusp
Member #7,858
October 2006
|
Thanks. After I get it going, I'm going to use it to build and accurate 3d human body representation. Then I'll use a genetically modified neural network to teach it how to walk. If that goes well, then I'll start to move into other more complicated maneuvers. This is all for my senior Computer Science project. And I'm still a sophomore! |
|