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:
1 | #include <allegro.h> |
2 | #include <math.h> |
3 | bool up, down, left, right; |
4 | |
5 | class rope{ |
6 | public: |
7 | class joint{ |
8 | public: |
9 | float x1,y1,x2,y2; |
10 | float velX,velY; |
11 | }joint[40]; |
12 | |
13 | float seg_length; //length of segments between joints |
14 | float air_resistance; //air resistance [negating factor on gravity {9.8}] |
15 | float damping; //self-explanitory |
16 | float speed; //didn't know what else to name this |
17 | |
18 | void deploy(); //initializes the rope |
19 | void update(bool, bool, bool, bool); //called every game-cycle |
20 | void draw(BITMAP *); |
21 | }rope[20]; |
22 | |
23 | void rope::deploy() { |
24 | seg_length=5; |
25 | air_resistance=0.0; |
26 | damping=.10; |
27 | speed=0.2; |
28 | |
29 | for(short i=0; i<40; i++) { |
30 | joint<i>.x1=SCREEN_W/2; joint<i>.y1=i*seg_length; |
31 | joint<i>.x2=SCREEN_W/2; joint<i>.y2=i*seg_length; |
32 | joint<i>.velX=0; joint<i>.velY=0; |
33 | } |
34 | }; |
35 | |
36 | void rope::update(bool up, bool down, bool left, bool right) { |
37 | if (left) |
38 | { |
39 | joint[0].x1--; |
40 | } |
41 | if (right) |
42 | { |
43 | joint[0].x1++; |
44 | } |
45 | if (up) |
46 | { |
47 | joint[0].y1--; |
48 | } |
49 | if (down) |
50 | { |
51 | joint[0].y1++; |
52 | } |
53 | |
54 | for(short i=0; i<40; i++) { |
55 | if (i != 0) |
56 | { |
57 | float vx1=joint[i-1].x1-joint<i>.x1; //vector 1: diffrence between x's |
58 | float vy1=joint[i-1].y1-joint<i>.y1; //vector 1: diffrence between y's |
59 | int vm1= (int)sqrt(ceil(vx1*vx1+vy1*vy1)); //vector 1: magnitude |
60 | int ve1= (int)vm1-(int)(seg_length/1); //vector 1: extention |
61 | |
62 | float vx2=joint[i-1].x1-joint<i>.x1; //vector 2: diffrence between x's |
63 | float vy2=joint[i-1].y1-joint<i>.y1; //vector 2: diffrence between y's |
64 | int vm2= (int)sqrt(ceil(vx2*vx2+vy2*vy2)); //vector 2: magnitude |
65 | int ve2= (int)vm2- (int)seg_length; //vector 2: extention |
66 | |
67 | float vx=(vx1/vm1*ve1)+(vx2/vm2*ve2); //x's reactant |
68 | float vy=(vy1/vm1*ve1)+(vy2/vm2*ve2)+9.8; //y's reactant |
69 | |
70 | joint<i>.velX=joint<i>.velX*damping+(vx*speed); //set velocity x accordingly |
71 | joint<i>.velY=joint<i>.velY*damping+(vy*speed); //set velocity y accordingly |
72 | joint<i>.x2=joint<i>.x1+joint<i>.velX; //buffer x |
73 | joint<i>.y2=joint<i>.y1+joint<i>.velY; //buffer y |
74 | joint<i>.x1=joint<i>.x2; //copy buffer to physical |
75 | joint<i>.y1=joint<i>.y2; //copy buffer to physical |
76 | } |
77 | } |
78 | }; |
79 | |
80 | void rope::draw(BITMAP *buffer) { |
81 | for(short i=0; i<40; i++) { |
82 | //draw joint and lines between |
83 | if (i == 0) |
84 | { |
85 | circlefill(buffer, (int)joint<i>.x1, (int)joint<i>.y1, 2, makecol(255,255,255)); |
86 | } else { |
87 | circlefill(buffer, (int)joint<i>.x1, (int)joint<i>.y1, 2, makecol(i*2,i*2,255)); |
88 | } |
89 | if (i != 0) |
90 | { |
91 | 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)); |
92 | } |
93 | } |
94 | }; |
95 | |
96 | void init(); |
97 | void deinit(); |
98 | |
99 | int main() { |
100 | init(); |
101 | BITMAP *buffer = NULL; |
102 | buffer = create_bitmap(640,480); |
103 | |
104 | |
105 | rope[0].deploy(); |
106 | |
107 | while (!key[KEY_ESC]) |
108 | { |
109 | if (key[KEY_U]) |
110 | { |
111 | //rope[0].update(); |
112 | } |
113 | if (key[KEY_D]) |
114 | { |
115 | rope[0].deploy(); |
116 | } |
117 | |
118 | if (key[KEY_LEFT]) |
119 | { |
120 | left = true; |
121 | } |
122 | |
123 | if (key[KEY_RIGHT]) |
124 | { |
125 | right = true; |
126 | } |
127 | |
128 | if (key[KEY_UP]) |
129 | { |
130 | up = true; |
131 | } |
132 | |
133 | if (key[KEY_DOWN]) |
134 | { |
135 | down = true; |
136 | } |
137 | |
138 | rope[0].update(up, down, left, right); |
139 | rope[0].draw(buffer); |
140 | blit(buffer, screen, 0,0,0,0,640,480);//Draw the buffer to the screen |
141 | clear_bitmap(buffer); // Clear the contents of the buffer bitmap |
142 | left = false; |
143 | right = false; |
144 | up = false; |
145 | down = false; |
146 | } |
147 | |
148 | deinit(); |
149 | return 0; |
150 | } |
151 | END_OF_MAIN() |
152 | |
153 | void init() { |
154 | int depth, res; |
155 | allegro_init(); |
156 | depth = desktop_color_depth(); |
157 | if (depth == 0) depth = 32; |
158 | set_color_depth(depth); |
159 | res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0); |
160 | if (res != 0) { |
161 | allegro_message(allegro_error); |
162 | exit(-1); |
163 | } |
164 | |
165 | install_timer(); |
166 | install_keyboard(); |
167 | install_mouse(); |
168 | /* add other initializations here */ |
169 | |
170 | } |
171 | |
172 | void deinit() { |
173 | clear_keybuf(); |
174 | /* add other deinitializations here */ |
175 | } |
By the way, this code is an edited version from the code on this thread:
http://www.allegro.cc/forums/thread/574094
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:
http://en.wikipedia.org/wiki/Pendulum_%28mathematics%29
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....
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.
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:
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.
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.
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.
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.
looks cool!
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!