Check out Half-Life Re-imagined competition results!
Check out Skewing textures in Hammer, our newest tutorial!
Welcome, akn, our newest member!
IntroductionFirst of all, what do I mean by a fabric? This model I'm describing can be used for any surface that can bend, so it can be a flag, some curtains or anything else you want it to be. This fabric will follow some basic rules such as gravity and elasticity. The physics model is pretty solid, but uses TRIapi to draw, so due to some bugs and limitations in the engine there will be problems. Put your cursor over any blue highlighted text to view an example. So here goes:
The Grid:The grid will be made up of points arranged in either a trigonal or rectangular structure. I advise going for a rectangular grid to begin with. Then once you have a working model and understand exactly how it works, switch to a grid made up of triangles.I advise using multiple arrays, each holding a different property. eg.
vec3_t gOrigin[20][20]; vec3_t gVelocity[20][20]; vec3_t gForce[20][20]; //The constant forces applied to the fabric(gravity, wind etc.) float gSprPosX[20][20]; //I'll explain these later float gSprPosY[20][20]; These are the basic arrays needed. I only picked the value of 20 because this is a suitable value for the size of a flag. So the grid would have 20 rows and 20 columns. The distance between the points is up to you. It is a trade-off between being able to see the individual polygons, so the fabric looks smooth, and rendering speed. Organisation of CodeI would suggest dividing the code into different parts.
InitialisationThis is called on start-up. It consists of a loop that defines every point's starting point, velocity and constant forces (eg. gravity). It also assigns every point's texture location (I'll come to this later).PhysicsFor particles it is sufficient to use the same loop for physics and rendering, but it will not work for fabrics. This loop will go through every point and work out the physics -- both the interactions with other points and gravity and wind. I call this function every frame before the rendering but to lighten the load you could call it less frequently.RenderingThis is yet another loop that draws the fabric. Use triangles to draw it, even if you are using a rectangular grid. If you don't, some of the surfaces will be invalid because every point wont lie on the same plane. If you have followed my recommendation of only trying this after doing a particle engine, you should have a deeper understanding of this process.The mathsI'll assume you have a knowledge of basic mechanics and pure mathmatics.Interactions between points: Now take away the distance you want between your points. If the result is positive, the points need to go together; negative, they need to move apart. Using this value, the force that has to be exerted on the points is worked out. To do this, the position from the first point is subtracted from the second to get the direction. This is then multiplied by the result obtained earlier, which gives the force its direction and magnitude. This force then needs to act upon the two particles. Add the force to the velocity for one point and take it away from the other.
This section is very difficult to get right because one bit of confusion over whether a value is + or - can result in the points repelling instead of attacting or the other way round. The interval between this function being called depends on the frame-rate. So without any correction, the flag will flap far faster on a system with a frame-rate of 72fps than on a system with only 20fps. So a way is needed to regulate the speed. This is done by moving the flag less per calculation, if there is a higher frame-rate. To do this I recommend working out the time since the last time the function was called. Then use this value to work out how big a force is needed and everything. ||||||||WARNING||||||||
During each step you will need to multiply the vectors by a certain factor. If the force vector is too large, the points will pass each other during their movement. Think about the consequences of this. From now on these particles will push away from each other to try and return to their proper positions. This can cause extremely unpredictable results, sually involving every point travelling away from every other point at an exponential velocity. Make sure this doesn't happen! Using a loop, this function will have to be applied to every point for each of its neighbours. The purpose of this interaction is to keep the fabric in the shape you want it. To make the fabric elastic, just make the reaction force less strong, so the grid is allowed to stretch a little. Fabric TextureThis section will explain how to place your chosen texture onto your fabric. Normally to place a sprite on a surface you would have the texture position commands as 1 and 0, which defines the corners of the texture, so the whole texture is drawn. Sadly, it's not as simple as that because there are many polygons, so the positions have to be assigned for each polygon. That's what those mysterious arrays were for at the beginning. Each point has its own (x, y) which defines where the point maps onto the texture. This value is defined in the initialisation function. I'll let you do the maths. An obvious product of this is that the texture will be back-to-front if viewed from the wrong side. There is no easy work-around for this, unless your sprite is symmetrical or you want it to be back-to front.Example of how the points map onto a texture. In addition to the triangle and upside-down triangles, you also need to draw some triangles at the sides to avoid a zig-zag pattern. If you do all this you're left with the corners having a bit cut off, but that's barely noticeable, especially when the fabric's flapping about in the wind. Other ForcesThe inter-point forces are the most important, but without the influence of other forces the fabric will go to a certain shape and position and just stop, it will not move and be pretty boring. So I advise adding gravity and some wind. Even with gravity and wind, the fabric will reach equilibrium and stay at rest. So, as in real life, you have to make the wind change its direction and magnitude for a realistic effect. How you do this is up to you.Another important force is a dampening force, this force will allow the effect of air resistance. It also ensures that if there are any slight problems in the maths, the fabric wont start doing unexpected things. To add this dampening force just multiply the velocity by a certain factor, very close to 1. Getting StartedHopefully you've at least half understood the physics model so far, but that's a long way from being able to make one yourself. I'd advise you to first make a 2D example, which is just a piece of string swinging about. It uses exactly the same principles as the fabric, but it's simpler to program.Once you've got a working version of that then you should understand far more how the system works. Possible ProblemsThese are just a few of the problems I've run into:
ConclusionIf you have understood it all then well-done. I hope you will find it useful. If you do succeed in coding it then please E-mail me with some screenshots and include my name in the read-me. Don't E-mail me with coding problems, because it's doubtful if I could help you even if I had the time. If there's any bits that after a few times reading you can't understand then please tell me, so I can improve the article.Good Luck! |