Simulation of deformation of colliding objects using particle systems by Shirish Raghunath Koti A thesis submitted in partial fulfillment of the requirements for the degree of Master of Science in Computer Science Montana State University © Copyright by Shirish Raghunath Koti (1989) Abstract: Physically-based modeling has become important as a useful tool in realistically animating the complex motions of objects. Much of the work centers around a mathematical development of the model and quite often involves the complexity associated with such a model. This project uses particle systems to model the objects whose deformation during collision is simulated. One of the greatest advantages of this approach is its mathematical simplicity. Since the object is considered as a collection of a large number of independent particles, connected to the corresponding neighboring particles by pseudosprings, the object is never viewed as one entity. This simplifies the process of calculating deformations at any part of the object. Another advantage is obvious when objects of different and arbitrary shapes have to be considered. Flexibility of shape of the objects is inherent to this model. Since it is the pseudo-springs that determine the deformation of the object, the characteristics of only the pseudo-springs need to be changed in order to simulate collisions of different types i.e., elastic or inelastic. The same holds true when objects with different physical properties have to be used in the simulation. In this sense, this model is far more general than many others. SIMULATION OF DEFORMATION OF COLLIDING OBJECTS USING PARTICLE SYSTEMS by Shirish Raghunath Koti A thesis submitted in partial fulfillment of the requirements for the degree 1 of Master of Science in Computer Science MONTANA STATE UNIVERSITY Bozeman, Montana August 1989 $ ii APPROVAL of a thesis submitted by Shirish Raghunath Koti This thesis has been read by each member of the thesis committee and has been found to be satisfactory regarding content, English usage, format, citations, bibliographic style, and consistency, and is ready for submission to the College of Graduate Studies. Z ^ Date <a-=r_jQ. f Chairperson, Graduate Committee Approved for the Major Department Date Head, !Major Department ^ Approved for the College of Graduate Studies bate 7 3 / 7 /fc T ? Graduate Dean Ill STATEMENT OF PERMISSION TO USE In presenting this thesis in partial fulfillment of the requirements for a master’s degree at Montana State University, I agree that the Library shall make it available to borrowers under rules of the Library. Brief quotations from this thesis are allowable without special permission, provided that accurate acknowledgement of source is made. Permission for extensive quotation from or reproduction of this thesis may be granted by my major Professor, or in his absence, by the Dean of Libraries when, in the opinion of either, the proposed use of the material is for scholarly purposes. Any copying or use of the material in this thesis for financial gain shall not be allowed without my written permission. Signature Date ZS-, S I iv TABLE OF CONTENTS Page v ABSTRACT ............................................................................................... ...... vi 1. INTRODUCTION ....................................................................................... I ................................ ............................................ 5 Modeling The Object ............................................................................. Role Of The Peripheral Particles ...................................................... Attributes Of The Object Modeling The Scene ....... Modeling The Deformation 5 7 2. SIMULATION MODEL 3. IMPLEMENTATION OO O s Os LIST OF FIGURES .......................................................................................... ................................................................................ 13 Major Data Structures ............................................................................ Creating Particles ................................ :................................................ Detecting Collision ................................................................................ Updating Particle Attributes Before Collision ...................................... Computing Time Step ............................................................................. Updating Particle Attributes During Collision ...................................... Checking For Errors .................... 13 14 16 17 18 20 23 4. ADAPTING FOR 3-D ......................... 5. RESULTS AND CONCLUSIONS ........ General Observations ............................................................ Conclusions ...................................................................................... 24 26 27 29 REFERENCES CITED ........................................ 30 APPENDIX ........................................................................................................ 32 L V Q LIST OF FIGURES Figure Page 1. Creating Particles ............................................................................... 2. Head-on Collision ............................................................ 6 3. Collision At An Angle .................................................................................... 28 4. Program Listing ....................................................................................... 5. Input Sample - I .................................................... ....................................... 86 6. Input Sample - 2 ...................... ..................................................................... 87 33 ABSTRACT Physically-based modeling has become important as a useful tool in realistically animating the complex motions of objects. Much of the work centers around a mathematical development of the model and quite often involves the complexity associated with such a model. This project uses particle systems to model the objects whose deformation during collision is simulated. One of the greatest advantages of this approach is its mathematical simplicity. Since the object is considered as a collection of a large number of independent particles, connected to the corresponding neighboring particles by pseudo­ springs, the object is never viewed as one entity. This simplifies the process of calculating deformations at any part of the object. Another advantage is obvious when objects of different and arbitrary shapes have to be considered. Flexibility of shape of the objects is inherent to this model. Since it is the pseudo-springs that determine the deformation of the object, the characteristics of only the pseudo-springs need to be changed in order to simulate collisions of different types i.e., elastic or inelastic. The same holds true when objects with different physical properties have to be used in the simulation. In this sense, this model is far more general than many others. CHAPTER I INTRODUCTION Over the past few years, physically-based modeling has become an important area of computer graphics research. In particular, many researchers have studied mechanisms for realistically animating colliding objects [1], [2] and [3], An approach based on particle systems, a relatively new technique in computer graphics, is taken in this project to simulate deformation of colliding objects. Collision of two or more objects is an extremely common phenomenon in day-to-day life. A game of billiards or tennis, collision of molecules in a fluid being heated, vehicle accidents are all examples of collision. A collision is invariably accompanied by deformation of the objects involved. The shape, extent and duration of the deformation depend on the properties of the objects and the nature of the collision. Although deformation of the ball during a game of tennis is not likely to evoke much interest from the players, analysis and prediction of deformation nevertheless are necessary - at least useful - in many cases. Machine shop operations, tool design, vehicle accidents and protective ordnance are some applications where an analysis finds immense use. A graphical representation of the results of such an analysis greatly enhances the usefulness of the entire exercise. 2 Most of the earlier approaches to solving this problem of predicting deformation involve severe mathematical complexity. The deforming object is modeled [4] as a body in an inertial frame of reference. The energy stored in the body due to the deformation is expressed in terms of the displacement of the geometric points in the body using differential equations. To solve for displacement of any point, a set of these equations needs to be solved. The complex theory involved in deriving and using these differential equations is quite often a serious limitation. Particle systems were first introduced by Reeves [5] to animate such fuzzy objects as explosions, fire, cloud and smoke. A particle in such a system is an extremely small part of the object having certain attributes as color, position and velocity. Attributes of a particle are determined stochastically, and every particle has a finite life-span which is less than the life-span of the object i.e., particles are created and destroyed during the animation of the object. Randomness is inherent to a particle system of this nature. The purpose of this project is to simulate deformation of two colliding objects using particle systems. The concept of particle system is modified for this purpose by eliminating the randomness of the attribute values. Tliese particles are created when the simulation begins and they exist as long as the simulation lasts. The attribute values acquired by the particles are not random but definite. 3 The object consists of a large number of particles. Each particle is independent in that it can have its own values for such attributes as position and velocity. Each particle is connected to all its neighbors by pseudo-springs which provide the restoring forces. This is the basic model used here. The movement of the particles as a result of the impact forces and the restoring forces determines the deformation of the object when viewed in its entirety. The fact that the pseudo-springs control the deformation of the object and that the shape of the object is inconsequential allows the objects to take arbitrary shapes. The characteristics of the pseudo-springs determine the type of the collision, i.e. elastic or plastic, and also simulate the physical properties of the objects like modulus of elasticity. For example, increasing the stiffness of the pseudo-spring amounts to increasing the rigidity of the object. The ability to simulate a wide variety of conditions by varying only one parameter, viz. the stiffness and characteristics of the pseudo-springs, makes this model very general. Absence of mathematical complexity is probably the greatest advantage of this model. Changes to positions and velocities of the particles due to the interplay of restoring and impact forces are determined by using elementary laws of motion which further makes the model simpler. Since deformation is simulated by the movements of the individual particles, the overall shape of the object is unimportant. Consequently, objects of arbitrary shape can be used in the simulation without making any changes in the model. The large number of 4 particles, however makes this model inherently computationally expensive. A detailed description of the model is provided in Chapter 2. The process of translating the model into an executable system is explained in Chapter 3. The model used in this project simulates objects in two dimensions. Chapter 4 covers the modifications necessary to extend the model to three dimensional objects. Finally, Chapter 5 discusses results and conclusions. 5 CHAPTER 2 SIMULATION MODEL The objects, scene, and the deformation all have their own models. Though these models are related to each other one way or the other, they will be dealt with separately in the subsequent sections. The models and implementations discussed in this project are for two dimensional objects, although extending them for three dimensional objects is relatively straight forward. In fact, work to that effect is already in progress. Modeling The Object The object is assumed to be composed of a large number of particles. A particle is an entity resembling a geometric point, having a definite position and its own mass, and other attributes. In this respect, all particles are identical. The particles are formed by conceptually placing a grid over the object and selecting those grid points that fall on or inside the object boundary. A grid of a predetermined size is chosen for this purpose. Although it is not required during modeling, a square grid is used to simplify implementation. Hereafter, the word grid always implies a square grid. The grid is big enough to completely enclose the entire object when placed over it. Figure I shows the 6 process of creating particles pictorially. The grid is shown to be very coarse (small grid size) in Figure I for the purpose of clarity. Discarded Gnd-point Pseudo-spring Peripheral Pamc Ic The Object Figure I Creating Particles Every grid point is checked to see if it falls outside, on or inside the object boundary. All the grid points falling on or inside the object form particles belonging to the object; the rest are discarded. Particles which lie inside the boundary of the object are the nonperipheral particles, and those which lie on the boundary of the object are the peripheral particles. Peripheral particles have a special role which will be discussed in the following section. The status of a particle as to whether it is peripheral or nonperipheral stays unchanged in most t I cases. Under special circumstances, however, where the object in collision undergoes fracture, a nonperipheral particle may become peripheral. Each particle, whether peripheral or nonperipheral, has its own set of attributes. Identity of the particle, which is unique in a given object, position, velocity and acceleration of the particle, and status of the particle as to whether the particle is peripheral or nonperipheral are some of the attributes necessary for every particle. Every particle is conceptually connected to four other particles - its left, right, top and the bottom neighbors. Each connection is a pseudo-spring. The spring offers certain resistance to compression and elongation, and in general the values for compression and elongation are different. The same springs can also be made to withstand forces up to a limit without having any deformation and then completely fail for any force above this limit. This kind of a behavior can be used to model objects like an egg shell. These springs have no use until a collision with some other object occurs since until then there is no relative displacement between any two particles. Once a collision occurs, however, these springs prove to be the heart of simulation of deformation. Role Of Peripheral Particles Peripheral particles are no different from nonperipheral particles as far as the attribute values or the change in the attribute values are concerned. 8 However, they do find a special role in detection of collision and such other tasks. A collision can occur only if boundaries (i.e. peripheral particles) of two objects come in contact. It is therefore only necessary to check if the peripheral particles are colliding. Since an object has a very small number of peripheral particles compared to nonperipheral particles, a considerable amount of computation is saved. A similar saving in computation is achieved when only peripheral particles are used to check if an object is leaving the scene. Another advantage of identifying a particle as peripheral or nonperipheral is evident while determining the neighbors of a particle. A nonperipheral particle must have all the four neighbors while a peripheral particle can have one, two or at most three neighbors. Attributes Of The Object The impact time, impact forces and consequently, the extent and shape of deformation are largely governed by physical properties of the material of the object, such as modulus of elasticity and Poisson’s ratio [6]. The size of the object, mass of the object and initial velocity of the object also make a significant difference in the final results. Another important attribute which directly influences the end result is the stiffness of the pseudo-spring connecting two particles. There are several other attributes like color of the object which do not affect the simulation in a significant way, but are nevertheless necessary. 9 Modeling The Scene The lower and upper extents of the scene define its boundary. The scene is divided into a predetermined number of square boxes. It may take several boxes to contain an object completely, and a given box may contain parts of several objects including none at all. Size of the box is small enough not to contain an object completely in one box or else the savings in computations achieved by dividing the scene would not be worth the effort. Peripheral particles of an object in a given box are considered for detection of collision with peripheral particles of another object only in that box. In other words, a check to detect a collision is made from one box at a time, and only peripheral particles of different objects contained in that box are considered. AU the boxes which contain peripheral particles of only one object or no object at aU are skipped. This way a great deal of computation is saved while checking for occurrence of coUision. This method is very similar to that of space-division adopted by Glassner [7]. Modeling The Deformation Once a coUision occurs, it lasts for a very smaU but definite amount of time. This contact duration for coUision of two spheres is given by [8] 10 x ( 4 . 53 ) 2 l-gi2 ^ I-M22 m xm2 5 R x+R2 [ I i 1TC E2K m \+m2 V0R xR2 ( 2 . 1) where g,, g2 are Poisson’s ratio for the materials of the objects, E 1, E2 are moduli of elasticity for the material of the objects, m u m2 are the masses of the objects, R y, R2 are the radii of the objects (spheres), and v0 is the relative velocity between the two objects. The contact duration is divided into a large number of intervals and for every interval, position and velocity of each particle are updated taking into account the external and the internal forces acting on each of the particles. The new position and the velocity are given by w = ut + (2.2) and v = u + at (2.3) where w is the change in the value of the x or y component of the position, u is the initial value of the corresponding component of velocity, a is the value of the corresponding component of acceleration, and t is the time interval for which updating is carried out. The direction of the external force is given by the position vector joining the two peripheral particles in collision. The magnitude depends on the time that has elapsed since collision started. The magnitude of this force is given by [8] 11 (2.4) where 2 5 1 5 jtvo Om = E 1K E 1K 16 mi,+/W2 m Itn1 R X^R1 5 RiR2 and all the other symbols have the same meaning as in equation 2.1. As can be seen from the equation, the external force is absent at the start and the end of collision, and it varies sinusoidally during the collision. Before a collision occurs, all particles in an object move with the same velocity at any given time. When a collision occurs, those peripheral particles involved in the collision experience the impact forces. At this time, the rest of the particles are not even aware of a collision. Because of the impact forces, which by definition oppose the initial motion, an acceleration opposing the velocity is introduced in the peripheral particles involved in collision. This acceleration changes the velocity, and consequently the displacement of these particles compared to that of the rest of the particles. The distances between a particle involved in collision and its neighbors are not the same as they were under no-collision conditions. The deviation from the normal distance causes the pseudo-spring to stretch or compress as the case may be, and the particle in collision and its neighbors experience the restoring forces of the pseudo-springs. 12 These forces are called internal forces. The direction of the internal force is given by the position vector of the two particles in question. The magnitude is given by /,• = k&l (2.5) where k is the spring constant with the pseudo-spring in compression or elongation and M is the change in the length of the pseudo-spring The internal forces are experienced by every particle of the object at some point in time or the other. In fact, it is due to the internal forces that a particle far away from a peripheral particle in collision and initially unaware of the collision is eventually affected by the collision. Thus, in the duration that a collision lasts, all the particles experience internal forces of different magnitudes and consequently experience a deviation from their normal displacements. The deviation from the normal displacement is more pronounced for particles closer to the particles involved in collision, and progressively decreases for particles away from the particles in collision. A macroscopic view of the deviation of each particle from the normal displacement results in simulation of the deformation of the object. 13 CHAPTER 3 IMPLEMENTATION The entire program is divided into different logical modules consistent with the tasks performed within each module. Some of the data structures are common to all the modules. These data structures will be discussed here in brief before describing the functioning of the various modules. Major Data Structures The scene has a structure, struct scene st, associated with it that contains information like the upper and lower extents of the scene and the number of objects in the scene. Every object has information like the physical properties, dimensions, initial velocity, number of particles in that object, and serial number of that object. AU this information is stored in a structure, struct obj st. This structure also has a pointer to where information on aU its particles is stored dynamicaUy. Another part of this structure is a pointer to a structure, struct rowptr st, which is basicaUy a linked list of addresses of rows of particles along with the first and the last column beyond which a particle cannot be found in that row. This linked list is useful in determining the neighbors of a given particle. 14 Every particle of an object has a structure, struct part st, associated with it to contain information about position, velocity, acceleration and status of the particle. Status tells whether a particle is peripheral or nonperipheral. When a collision is detected, information about the objects in collision and the particular particles in collision is stored in a structure, struct coli st. A linked list of this structure is maintained if more than one pair of peripheral particles are in collision. As mentioned in the earlier chapter, the entire scene is divided into a number of boxes. The information about the peripheral particles of all the objects in a given box is maintained as a multidimensional array of linked lists of a structure, struct box st. Creating Particles The function of this module is to determine which particles belong to the given object and to assign values to all the attributes of every particle. The overall dimensions of the object, its initial velocity and the grid size to be used for that object are known through the data file supplied as input to the program. The top, left, right and bottom extremes of the object are determined. As seen earlier in Figure I, imaginary horizontal scan-lines are drawn through the top extreme of the object progressing towards and including the 15 bottom extreme. Vertical scan-lines are drawn through the left extreme progressing towards and including the right extreme. An intersection of a horizontal scan-line with a vertical scan-line constitutes a grid point. AU the scan-lines are equaUy spaced as a result of which the distance between any two neighboring grid points is the same. The number of horizontal scan-lines is the same as that of vertical scan-line and are both equal to the grid size for the object. Every grid point is checked to see if it lies outside, on or inside the object boundary. For an object that is a circle, this reduces to solving the equation of the circle using the grid point as a point. AU the grid points that lie outside the object boundary are discarded. If a grid points faUs on the boundary, its status is set to peripheral. A given row of particles must have at least one peripheral particle. If the grid point under consideration is the first peripheral particle in that row then the address of this new row is added to the linked list of rowaddresses, along with the first and last valid columns of this row. The status of a particle that lies inside the boundary is set to nonperipheral. Irrespective of its status, every particle initiaUy has the same velocity as that of the entire object. The position of each particle is set to the x and y coordinates of the corresponding grid point. The acceleration is set to zero for every particle in this implementation, although including initial acceleration for the object and hence for aU the particles is a trivial modification. The identity of every particle is obtained by assigning two numbers to the particle. The two 16 numbers indicate the row and the column used to obtain the grid point corresponding to this particle. This scheme of identifying particles enables each particle to be identified uniquely in a given object. While attributes are assigned to every particle, the linked list of peripheral particles in a given box is also extended if the particle under consideration is peripheral. In other words, if a particle is peripheral then the box in which this particle lies is determined. There is one linked list for every object whose peripheral particles lie in this box. If the peripheral particle under consideration is the first one for this object in this box, a new linked list is created. Otherwise, the existing linked list is simply extended. When all the grid points are considered, the number of particles in the object is known. With the mass of the object known through the data file, the mass of each particle is determined. Detecting Collision The function of this module is to check every object against every other object in the scene to determine if the two objects have collided. A proper value is returned depending on whether or not a collision is detected. The distance between a peripheral particle of one object in a given box and a peripheral particle of another object in the same box is determined using their 17 positions. If this distance is less than a predetermined limit, a collision is assumed to have occurred. If the distance is greater, another pair is tested. All possible pairs of peripheral particles in the same box are tested. Two peripheral particles of the same object are not tested even if they are in the same box, since an object can only collide with another object, and never with itself. If all combinations in a box are exhausted, the process is repeated for other boxes. If all boxes are exhausted and no collision is detected, an appropriate value indicating this condition is returned. If a collision is detected, the serial numbers of the two objects in collision, pointers to the two peripheral particles involved, and the box in which collision is detected are stored. If more than one pair are involved in a collision, a linked list is created. Thus, if a collision is detected, a linked list of this kind with one or more elements is created. A pointer to this linked list is returned when a collision is detected. Updating Particle .Attributes Before Collision This is a relatively straight-forward function. A time step is chosen as discussed in the following section. Positions of all the particles are updated using this time step and their velocities. Since no collision has occurred, all particles, have the same velocities. Consequently, every particle undergoes the same displacement when time is advanced through this time step. 18 When particle positions are updated, some peripheral particles might cross the box boundaries. It is therefore necessary to update the box information for every peripheral particle. The linked lists of peripheral particles are completely recreated, instead of being updated each time this function is invoked. In addition to the above which causes permanent changes to attribute values, this module also performs the task of temporarily updating the peripheral particles while checking to make sure two objects do not intersect each other. Computing Time Step The decision as to whether a collision has occurred is based solely on whether the smallest distance between any two peripheral particles of different objects is less than a predetermined limit. If the time step is not small enough, two objects could intersect and still a collision wouldn’t be detected, or a collision would be detected but particles in collision would be incorrectly identified. Such a situation would be catastrophic to the entire simulation and should be avoided at any cost. It is therefore extremely important to have a time step that is small enough. On the other hand, if a time step is too small, too many computations are involved for a precision that is not required. This function takes a big time step initially. With this time step, all the peripheral particles are updated which is a temporary change. It is not 19 necessary to update the nonperipheral particles since they do not take part in collision detection. After updating peripheral particles for all the objects, a test as described below is made to see if two objects have intersected. If any two objects have intersected, the initial time step is halved and the entire process repeated until no two objects intersect. At this point, attributes of all the peripheral particles are restored to their original values and the latest value of time step is returned. If two particles cross their paths and are in opposite planes after an update then both their x and y direction ratios change signs. For example, if two particles are to the left and right of a plane and after update go to the right and left of the plane respectively then the sign of x and y directions ratios after the update would be the opposite of their counterparts before the update. It is this fact that is used to determine if two objects have intersected. The magnitude of direction ratios or distance between particles are not useful here. The x and y direction ratios of every pair of peripheral particles belonging to different objects but in the same box are computed before and after the temporary update. If there is a change in sign of both the x and y direction ratios for any pair then the objects are intersecting, indicating that the time step is too big. 20 Updating Particle Attributes During Collision As soon as collision is detected, the contact duration is computed using equation 2-1, even before this module is executed. When a collision is detected, the relevant information about all the particles involved in the collision is made available to this module. AU the particles involved in the coUision for the two objects are marked to be peripheral, which they must be, and affected. At this point, the contact duration is divided into a predetermined number of intervals. The foUowing procedure is then repeated for every interval. First, the positions and velocities of aU the particles - peripheral or nonperipheral - are updated using equations 2-2 and 2-3 respectively. AU the particles that have not been affected yet by the coUision have the same velocity and no acceleration. It is computationaUy economical to compute the new positions of these particles separately. Next, aU the particles that are neighbors of an affected particle are marked as affected. The structure struct rowptr st mentioned earlier stores information about the starting address of each row and the first and last useful column in that row. This data structure makes the task of finding neighbors of a given particle easier and more efficient. The grid size used in creating particles determines the maximum number of particles in a row or a column. When the 21 number of intervals numerically exceeds twice the grid size, all of the particles in an object are guaranteed to be affected by the collision. At this stage, accelerations of all the particles need to be calculated. All of the particles which are involved in the collision experience the impact force resulting in acceleration. This acceleration is termed as the external acceleration. By virtue of the pseudo-springs, all the particles experience a force resulting in an acceleration. This acceleration is termed as internal acceleration. To obtain external acceleration, first the force due to impact is calculated . using equation 2-4. The magnitude of this force is divided by as many pairs of peripheral particles as the ones involved in the collision. This is then further divided by the mass of a particle. This is the magnitude of external acceleration experienced by any particle in collision. An assumption that the total force of impact is equally divided among all the particles of an object in collision is implicit here. The direction of external acceleration is obtained by computing the direction cosines of the position vector between the pair of particles under consideration. >The direction cosines then readily produce the x and y components of external acceleration, with the magnitude already known. Internal acceleration is caused by the change in the length of the pseudo­ spring. A particle is connected to four neighbors and therefore to four springs. Each spring has its own force acting on the particle. The distance between the 22 particle under consideration and one of its neighbors is calculated using their positions. The difference berween this distance and the normal distance between any two particles is the compression or elongation of the pseudo-spring. The force is then obtained using equation 2-5. The spring constant chosen for this depends on whether die pseudo-spring is in compression or tension. This force is then divided by mass of the particle to obtain magnitude of internal acceleration. The position vector between the particle and the neighbor determines direction of the acceleration. The direction cosines then readily produce die x and y components of the internal acceleration, with the magnitude already known. It is important to choose an appropriate position vector depending on whether die pseudo-spring is in compression or tension. This procedure is repeated for all the neighbors of the particle. The * and y components of internal accelerations due to each of the neighbors are added. This then becomes the internal acceleration of the particle. Once the process of updating positions and velocities, marking the particles newly affected by collision and computing external and internal accelerations is completed for all the particles of both ,he objects, the particles are displayed. This entire cycle is then repeated for ,he next interval. Display is carried out on HP SRX-350 work station using ,he HP-UX Starbase graphics package. / 23 Checking For Errors The primary function of this module is to make sure that the program is terminated whenever an object leaves the scene. Checks are also made in the beginning as soon as the data file is read to ensure that there are no inconsistencies in the data. To ensure that every object is within the scene, the positions of the peripheral particles are checked against the scene boundaries. Since no nonperipheral particle can leave the scene before a peripheral particle leaves, it is not necessary to check positions of nonperipheral particles. 24 CHAPTER 4 ADAPTING FOR 3-D Currently this program has been implemented for the two dimensional case. However, there are hardly any conceptual differences between the two and the three dimensional cases. The minor differences in the implementation are discussed below. The attributes such as position, velocity and the acceleration will now require the z component. Modules used for computing the time step and the accelerations make use of direction ratios and direction cosines of the position vector. They now will have to take the z coordinate also into account. When particles are created, scan-lines are drawn from the top to the bottom and from the left to the right of the object to determine the grid points that constitute particles. In the three dimensional case, similar scan-lines will have to be drawn but not just in one plane. Rather, every plane between the front and the back will have to be covered. The distance between two successive planes can be the same as that between two successive scan-lines. The scene is currently divided into boxes of equal size. In the two dimensional case, these should rather be called squares. The same needs to be extended by dividing the three dimensional scene into cubes or boxes of equal size (i.e. voxels). 25 Some of the modules will need modification. The module that gets a neighbor of a given particle should be capable of finding a neighbor in the front of or behind the particle, since the particle will now have six neighbors instead of four. Similarly, the module that computes the internal acceleration will have contribution from two more neighbors. Some changes will be necessary in the module that displays the objects since a three dimensional rather than a two dimensional picture will have to be displayed. The need to modify the program for a three dimensional case can hardly be understated. If the simulation has to have any practical value, then objects must be three dimensional. The two dimensional simulation serves as a good model and makes visualization easier. As pointed out in the preceding sections, extending the model to the three dimensional case is relatively trivial. 26 CHAPTER 5 RESULTS AND CONCLUSIONS As discussed earlier, the efforts in this project have been focused on two dimensional objects. -Simulation was carried out on two circular objects by using different values for the various parameters like stiffness of the pseudosprings, velocities, masses, positions, and the material properties of the objects. The simulation was done on a DECstation 3100 and displayed on a HP SRX-350 workstation. The entire software is written in C. A listing of the program appears in Figure 4 in the Appendix. Figure 2 shows a picture of the two objects colliding head-on with each other. The values used for the various parameters are obtained through the data file supplied as input to the program. Relevant portions of this data file are shown in Figure 5 in the Appendix. Figure 3 shows a picture of the two objects in collision such that the velocity vectors are not parallel, i.e. the collision is not head-on. Figure 6 in the Appendix shows relevant portions of the data file used for this simulation. Deformation can clearly be observed in both the objects in both of the cases above. As expected, deformation is limited to a very small depth from the surface compared to the dimensions of the objects. A conical pattern with the apex towards the center of the object can be observed on both the objects. This 27 pattern indicates the path taken by the wave due to the impact as it travels from one end of the object to the other. The aliasing effect seen in both the pictures was not eliminated in order to preserve the above mentioned conical pattern. General Observations As it is to be expected, the more the steps into which the impact time is divided, the better are the results. Obviously, the amount of computation increases, although linearly, with the increased number of steps. An appropriate trade-off is therefore necessary. The same holds true for the grid size which ultimately determines the number of particles in the object. An increased number of particles has another drawback - increased memory requirement. Although it appears that the number of steps into which the impact time is divided and the grid size are unrelated quantities, simulation shows that number of steps should be at least an order of magnitude greater than the grid size. The relation between the two becomes obvious if the following is taken into account: a small number of time steps means a larger time interval. Since the impact force depends on time, as can be seen from equation 2-4, this means that larger impact forces give rise to larger displacements of particles. If the displacement of a particle with respect to another particle is much larger than the normal distance between the two, i.e. if the compression or elongation of the pseudo­ spring is much larger than its normal length, the spring model breaks down. 28 I Figure 2 Head-on Collision Figure 3 Collision At An Angle 29 Conclusions The goal of this project was to use a simpler model to simulate deformation of colliding objects. This model is conceptually one of the simplest and is far more general than other models, and the simulation based on this model has produced promising results. There is still a lot of effort needed before collision of three dimensional objects of arbitrary shape can be simulated to obtain accurate deformations. REFERENCES CITED 31 REFERENCES 1. Hahn J.K., Realistic Animation Of Rigid Bodies, Computer Graphics, Vol.22, No.4, Aug 88, pp299-308. 2. Platt J.C., Barr A.H., Constraint Methods For Flexible Models, Computer Graphics, Vol.22, No.4, Aug 88, pp279-288. 3. Moore M., Wilhelms J., Collision Detection And Response For Computer Animation, Computer Graphics, Vol.22, No.4, Aug 88, pp289-298. 4. Terzopoulos D., Fleischer K., Modeling Inelastic Deformation: Viscoelasticity, Plasticity, Fracture, Computer Graphics, Vol.22, No.4, Aug 88, pp269-278. 5. Reeves W.T., Particle Systems - A Technique For Modeling A Class Of Fuzzy Objects, ACM Transactions On Graphics, Vol.2, No.2, April 83, pp359-376. 6. Crandall S.H., Dahl N.C., Lardner T.J., An Introduction To The Mechanics Of Solids, McGraw-Hill International Book Company, 1978, pp280-286. 7. Glassner A.S., Space Subdivision For Fast Ray Tracing, IEEE Computer Graphics And Applications, Vol.4, No. 10, Oct 84, pp!5-22. 8. Goldsmith W., Impact, Edward Arnold Publishers Ltd., 1960, pp82-91. APPENDIX 33 Figure 4 Program Listing /******************************************************************** * * * T h i s f i l e ' :c o l l i d e . c (main) * O t h e r files: p a r t s . c * updates.c * display.c * globals.h • * * * * * • * * * This file contains functions main(), readdata(), * e r r o r _ c h e c k (), a n d c o m p u t e _ i m p a c t _ f o r c e (). n u l l _ p o i n t e r s . () , * * * * ******************************************************************** / #include #include #include #include #include < s t d i o .h> < m a t h .h > < m a l l o c .h > <strings.h> "globals.h" m a i n ( a r g c , argv) int argc; char *argv[]; int int int i; fildes; srno_fst, char double obj_s c o l l _s a n s [5]; delta_ t i m e , dummy; o b j e c t [ M A X O B J ] , c o l l _ o b j e c t [2]; *save_coll, *collptr; coll_s part_s void e c k () ; void * c o l l i s i o n _ d e t e c t (); * g e t _ n e i g h b o u r (); r e a d d a t a (), c r e a t e _ p a r t i c l e s (), srno_sec; /* f i l e d e s c r i p t o r f o r d i s p l a y */ /* s r .no. o f o b j e c t s i n c o l l i s i o n */ b e f o r e _ c o l l i s i o n _ u p d a t e (), x null_jpointers (),e r r o r _ c h d u r i n g _ c o l l i s i o n _ u p d a t e () ; 34 Figure double int void if 4 (contd.) c o m p u t e _ t i m e _ s t e p () , c o m p u t e _ i m p a c t _ f o r c e (); d i s p l a y _ i n i t i a l i z e (); d i s p l a y _ p i c t u r e (); (argc < 2) fprintf ( st de r r, "\nUsage : %s < d a t a f i l e > \ n \ n n , a r g v [0]), e x i t (I) ; r e a d d a t a ( a r g v [I],o b j e c t ); e r r o r _ c h e c k () ; for (i-0;i<MAXOBJ;i++) n u l l _ p o i n t e r s (i); /* a l l p o i n t e r s t o n u l l /* S T D _ D E L T A _ T I M E is t h e i n i t i a l delta_time = STD_DELTA_TIME; for ' seed' to c o m p u t e */ delta time */ (i«0;i<scene.nobjects;i++) c r e a t e _ p a r t i c l e s ( S o b j e c t [ i ] ); fildes - d i s p l a y _ i n i t i a l i z e (); /* w h i l e (I) s goes out simulates of the screen. the m o t i o n This forever until one c o n d i t i o n m a y be of the object c h a n g e d if s i m u l a t i o n is desired for a s p e ci fic period. */ while (I) ( collision_in_progress_global delta_time if = FALSE; = compute_time_step(object,delta_time); ( ( s a v e _ c o l l - c o l l p t r = c o l l i s i o n _ d e t e c t ()) == (coll s *)NUL L) { for (i=0;i<scene.nobjects;i++) { b e f o r e _ c o l l i s i o n _ u p d a t e ( o b j e c t [ i ] ,d e l t a _ t i m e , P E R M A N E N T ) ; e r r o r c h e c k (); 35 Figure 4 (contd.) /* i - 0 - > c l e a r t h e s c r e e n */ f o r (i— 0 ; i < s c e n e .n o b j e c t s ; i++) d i s p l a y j p i c t u r e (fildes,o b j e c t [ i ] ,i ) ; else { /* c o l l i s i o n h a s occured */ /* t h e t w o o b j e c t s i n c o l l i s i o n arno_fst - collptr->srno_fs t ; srno_sec = collptr->srno_sec; /* not now, compute only impact */ time -> interval - ZERO (dummy used) (this f u n c t i o n a l s o s e t s c o l l i s i o n _ i n _ p r o g r e s s g l o b a l t */ d u m m y - c o m p u t e _ i m p a c t _ f o r c e ( o b j e c t [ s r n o _ f s t ] , o b j e c t [srno se c ] ,Z E R O ) ; o TRUE) /* f o r a l l o b j e c t s o t h e r t h a n t h e o n e s i n c o l l i s i o n */ f o r (i— 0 ; i < s c e n e .n o b j e c t s ;i++) ( i f ( ( o b j e c t [ i ] .s r n o != c o l l p t r - > s r n o fst) && ( o b j e c t [ i ] .s r n o !- c o l l p t r - > s r n o sec)) { b e f o r e _ c o l l i s i o n _ u p d a t e ( o b j e c t [ i ] ,d e l t a _ t i m e , P E R M A N E N T e r r o r _ c h e c k (); } ) /* now, d i s p l a y t h e o b j e c t s n o t i n c o l l i s i o n */ f o r ( i = 0 ; i < s c e n e . n o b j e c t s ; i++) i f ( (object [i] . s r n o !=» c o l l p t r - > s r n o _ f st) && ( o b j e c t [ i ] .s r n o != c o l l p t r - > s r n o sec)) display_picture(fildes,object[i],i); /* for the two objects i n v o l v e d in collision, update the p ositions and display, continuously throughout the impact duratio n ( d i s p l a y j p i c t u r e () is i n v o k e d i n d u r i n g c o l l i s i o n u p d a te () ) */ for (i-0;i<scene.nobjects;i++) ( i f ( o b j e c t [ i ] .s r n o = = c o l l p t r - > s r n o _ f st) c o l l _ o b j e c t [0] = o b j e c t [i]; i f ( o b j e c t [ i ] .s r n o = = c o l l p t r - > s r n o _ s e c ) c o l l _ o b j e c t [1] = o b j e c t [i]; } / 36 Figure 4 (contd.) d u r i n g _ c o l l i s i o n _ u p d a t e (fildes,coll_object,c o l l p t r ) ; e r r o r c h e c k (); /* n o w t h a t impact s i m u l a t i o n is over, do a normal update on all the objects ciently so t h a t the two objects in collision move suffi far away from ea c h other: t h i s w a y c o l l i s i o n _ d e t e c t () w i l l not w r o n g l y announce another collision. */ delta_time = RECVRY_FCTR*impact_time_global; for (i=0;i<scene.nobjects;i++) { b e f o r e _ c o l l i s i o n _ u p d a t e ( o b j e c t [ i ] ,d e l t a _ t i m e , P E R M A N E N T ) ; e r r o r _ c h e c k (); } for (i=0;i<scene.nobjects;i++) d i s p l a y _ p i c t u r e ( f i l d e s , o b j e c t [ i ] ,i ) ; /* n u l l t h e p o i n t e r , t o o c o l l p t r = (coll_s * ) N U L L ; delta_time */ - STD_DELTA_TIME; ) ) ) /************************* E n d o f m a i n () ************************ **/ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Name * Input * : readdata() : N a m e o f d a t a file Po in t e r to an a r r a y of o b jects 37 Figure 4 (contd.) * Output : None * Function : Read data * * file * * *******************************************************************/ v o i d r e a d d a t a ( f n a m e , o b j) char * fname; * o b j; o b j_s int char FILE if i; b u f [85]; *fp; ( (fp — f o p e n ( f n a m e , " r " ) ) — — NULL) f p r i n t f ( s t d e r r , " X n C a n ' t o p e n % s \ n \ n " , f n a m e ) , e x i t (I); /* g e t r i d o f a l l t h e t e xt: d a t a ( fgets(buf,85,fp ) ; b u f [ strlen(buf) - I ] - ' N O ' ; ) w h i l e (s t r c m p ( b u f , "$") !- 0); starts after the $ sign */ do /* l o w e r e x t e n t s o f t h e s c e n e */ f s c a n f ( f p , " % f % f % f " , & ( s c e n e .l o w e x . x ) , & ( s c e n e .l o w e x . y ) , & ( s c e n e . I o w e x • z) ) ; f g e t s (buf,8 5 , f p ) ; /* u p p e r e x t e n t s o f t h e s c e n e */ f s c a n f ( f p , " % f % f % f ", & ( s c e n e . u p p e x . x ) , & ( s c e n e . u p p e x . y ) , & ( s c e n e . u p p e x . z )) ; f g e t s (buf,8 5 , f p ) ; /* no. o f o b j e c t s */ f s c a n f ( f p , " % d " , & ( s c e n e . n o b j e c t s ) ); f g e t s (buf,8 5 , f p ) ; /* no. o f i n t e r v a l s i n t o w h i c h i m p a c t t i m e f s c a n f (fp," % l d " , & n u m _ i n t e r v a l s _ g l o b a l ) ; f g e t s (buf,8 5 , f p ) ; s h o u l d b e d i v i d e d */ /* r e a l - t i m e s i m u l a t i o n (I) o r s t o r e d a t a o n d i s k f s c a n f ( f p , n% d n , & r e a l _ t i m e _ g l o b a l ) ; f g e t s (buf,8 5 , f p ) ; /* n o w i n f o a b o u t X ea c h of the o b j e c t s */ (0) */ 38 Figure 4 (contd.) for (i-0; K s c e n e .n o b jects; i++, o b j++) /* d a t a for an ob j e c t { follows the $ line: get r i d of t h e line */ f s c a n f ( f p , n% s n ,b u f ); /* n a m e o f t h e o b j e c t ( d i s c a r d h e r e ) , a n d o b j e c t f s c a n f ( f p , " % s n ,b u f ); f s c a n f ( f p , n % d " , & ( o b j - > i d ) ); fgets(buf,85,fp); o b j - > s r n o = i; /* s t a r t sr.no. f r o m O */ id */ /* c e n t r e a n d t h e r a d i u s */ f s c a n f ( f p , " % f % f % f ", & ( o b j - > c e n t r e . x ) , & (obj - > c e n t r e . y ) , & (obj - > c e n t r e .z ) ); f s c a n f ( f p , " % f ", & ( o b j - > r a d i u s ) ); f g e t s (buf,8 5 , f p ) ; /* c o l o u r o f t h e o b j e c t : red, g r e e n , b l u e */ f s c a n f ( f p , " % f % f % f n , & (obj - > c o l o u r [ 0 ] ) , & (obj - > c o l o u r [ 1 ] ) , & ( o b j-> c o l o u r [2])); f g e t s (buf,8 5 , f p ) ; /* g r i d w i d t h : this determines no. of p a r t i c l e s in the objec t. For t symmetry purposes, t h i s m u s t be even. If not, force i ! */ f s c a n f ( f p , " % d " , & (obj - > g r i d ) ); f g e t s (buf,8 5 , f p ) ; i f ( o b j - > g r i d % 2 = = I) o b j - > g r i d + = I; /* n o r m a l distance between two particles (of t h e sam e object) */ obj->dnot = (2 * o b j - > r a d i u s ) / (obj->grid) ; /* s p r i n g c o n s t a n t i n c o m p r e s s i o n a n d e x t e n s i o n f s c a n f ( f p , " % f % f ", & (obj - > k _ c o m p ) , & (obj - > k _ e x t n ) ); f g e t s (buf,8 5 , f p ) ; */ /* i n i t i a l v e l o c i t y o f t h e o b j e c t */ f s c a n f ( f p , " % f % f % f " , & ( o b j - > v e l . x ) , & ( o b j - > v e l . y ) , & ( o b j - > v e l . z ) ); f g e t s (buf,8 5 , f p ) ; /* m a s s o f t h e o b j e c t */ f s c a n f ( f p , " % f " , & ( o b j - > m a s s ) ); f g e t s (buf,8 5 , f p ) ; /* P o i s s o n ' s r a t i o f o r t h e m a t e r i a l o f t h e f s c a n f ( f p , " % f " , & ( o b j - > m u ) ); object */ 39 Figure 4 (contd.) f g e t s ( b u f , 8 5 , fp) ; /* M o d u l u s o f e l a s t i c i t y f o r t h e m a t e r i a l f s c a n f (fp, " % f , & ( o bj->elast) ) ; f g e t s (buf,8 5 , f p ) ; /* i n i t i a l i z e t h e p o i n t e r t o n u l l o b j - > s t a r t = (part_s * )NULL; of the object */ */ } ) /***************** End of readdata() **************/ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Name Input Output Function * : n u l l _ p o i n t e r s () :S e r i a l n u m b e r of o b j e c t :N o n e N u l l t h e l i n k e d list of p e r i p h e r a l boxes particles in all * * *******************************************************************/ v o i d n u l l _ p o i n t e r s ( o b j_srno) int o b j srno; /* f o r w h i c h o b j e c t is t h i s to be don e */ ( register int /* R E M E M B E R : /* for i, j, k; b e f o r e _ c o l l i s i o n _ u p d a t e () a l s o u s e s t h i s for e r r o r - c h e c k i n g purposes, ( i = 0 ;i < B 0 X N U M + l ;i++) f o r (j - 0 ; j < B O X N U M + l ; j + + ) i,j,k should go to function */ B O X N U M + I */ 40 Figure 4 (contd.) A NOTE : Change t h i s O N E t o B O X N U M for 3 - d A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A for (k=0;k<ONE+l;k++) b o x [ i ] [j ] [ k ] .s t a r t [ o b j_srno] - (part_s ^J *)NULL; ) /********************* E n d of n u l l_pointers() ******************* / /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Name Input Output Function * : e r r o r _ c h e c k () None : None : C h e c k for dat a i n c o n s i s t e n c i e s the ob je cts leaves the scene * * and to see if a n y of * *******************************************************************/ v o i d e r r o r _ c h e c k () { s t a t i c int in t float part_s /* w h e n t h i s first time=TRUE; i, j, k, m; x, y, z; *perphptr; f u n c t i o n is invoked for the first t i me, c h e c k if t h e data furnished by the if user has any inconsistency (first_time) { i f ( (f a b s ( s c e n e .I o w e x .x - s c e n e . u p p e x . x ) */ < EPSILON) || 41 Figure 4 (contd.) ( f a b s ( s c e n e .l o w e x . y - s c e n e .u p p e x . y ) < E P S I L O N ) || ( f a b s ( s c e n e .l o w e x . z - s c e n e . u p p e x . z ) < E P S I L O N ) ) f p r i n t f ( s t d e r r , "\nImproper scene extents: p r o g r a m terminated .\ n \ n " ) , e x i t (I); if ( s c e n e .n o b j e c t s > M A X O B J ) f p r i n t f ( s t d e r r , "\nToo m a n y objects m i n a t e d . \ n \ n n ) , e x i t (I); ( s c e n e .n o b j e c t s < = 0) f p r i n t f ( s t d e r r , n\ n N o o b j e c t s d . \ n \ n " ) , e x i t (I); in the scene: program ter if in the s cene: (B O X N U M - - 0) f p r i n t f ( s t d e r r , " \ n B O X N U M shou l d be nonzero: e d . \ n \ n " ) , e x i t (I); program terminate if program terminat f i r s t t i m e = F ALSE; } /* c h e c k if a f t e r u p d a t e a n y o f t h e p e r i p h e r a l p a r t i c l e s o f a n y of the o b j e c t s h a s g o n e o u t o f s c e n e */ else { /* for e r r o r - c h e c k i n g purposes, for i,j,k s h o u l d g o t o B O X N U M + I */ (i=0;i<BOXNUM+l;i++) f o r (j = 0 ; j < B 0 X N U M + l ; j + + ) NOTE : Change the ONE to BOXNUM for the AA*y/ for (k=0;k<ONE+l;k++) /* f o r e v e r y o b j e c t i n t h e s c e n e f o r ( m = 0 ; m < s c e n e .n o b j e c t s ; m + + ) ( */ p e r p h p t r = b o x [ i ] [j] [k] .s t a r t [ m ] ; while (perphptr != ( part_s x = perphptr->posn.x; y = perphptr->posn.y; z = perphptr->posn.z; * )NULL) { 3-d case 42 Figure 4 (contd.) if ( (x < s c e n e . l o w e x . x || x > s c e n e .uppex.x) (y < s c e n e .I o w e x .y || y > s c e n e .uppex.y) (z < s c e n e .I o w e x .z || z > s c e n e .u p p e x .z) f p r i n t f ( a t d e r r , " \ n O b j e c t %d l e a v i n g scene: o g r a m t e r m i n a t e d . \ n \ n n , m + l ) , e x i t (I); II ) Pr perphptr — perphptr->next; ) } } } / **************** Name Input * Output Function * Theory ******************y : : * * * E n d o f e r r o r _ c h e c k () c o m p u t e _ i m p a c t _ f o r c e () * The two objects involved in collision * T h e i n t e r v a l f o r w h i c h i m p a c t f o r c e is d e s i r e d * : N o ne, w h e n t h i s f u n c t i o n is i n v o k e d f o r t h e f i r s t t i m e * M a g n i t u d e o f i m p a c t f orce, o n s u b s e q u e n t i n v o c a t i o n s * : W h e n i n v o k e d f or t h e f i r s t time, * calculate the impact time * set t h e p a r a m e t e r t o s a y c o l l i s i o n is i n p r o g r e s s * c a l c u l a t e all q u a n t i t i e s to ca l c u l a t e forces later * W h e n i n v o k e d for the s e c o n d t i m e or later, * calculate the magnitude of impact force on every * particle involved in collision * : Force and the contact-duration onimpact I .1 4 * v n o t A 2 contact force I .0 6 8 * v _ n o t * t o t i m e (------------------------ ) * 43 Figure 4 (contd.) * k_one*alpha_m alpha_m * * * * * (Ref. page 83-90 of IMPACT by W e r n e r Goldsmith) * * * ******************************************************************** d o u b l e c o m p u t e _ i m p a c t _ f o r c e (obj e c t _ o n e , o b j e c t _ t w o , i n t e r v a l ) obj_s object_one, object_two; int interval; ( static double static double static double double double t a r t e d */ double double if k_one; alpha_m, v_not; t_const, f_const; delta_one, delta_two; totime; /* t o t a l t i m e force magn=0.0; ml, m2, rl, r2, just d e t e c t e d : collision /* m a g n i t u d e o f t h e f o r c e mul , mu2 , el, e2, t e mp; /* C o l l i s i o n is i n p r o g r e s s : c a l c u l a t e (collision_in_progress_global) { t o time = t_const * interval; force_magn = f_const * sin(totime); /* C o l l i s i o n is else { since the impact calculate the s */ f o r c e n o w */ impact time now */ c o l l i s i o n _ i n _ p r o g r e s s _ g l o b a l - TRUE; /* c a l c u l a t e the various q u a n t i t i e s to get t _ c o n s t and f_cons t */ mul - o b ject_one.mu; m u 2 = o b ject_two.mu; ml - o b ject_one.mass; m2 — o b ject_two.mass; rl — o b j e c t _ o n e .r a d i u s ; r2 = o b j e c t _ t w o .ra d i u s ; el = o b j e c t _ o n e .e l a s t ; e2 = o b j e c t _ t w o .e l ast; /* v _ n o t is t h e r e l a t i v e s p e e d b e t w e e n t h e t w o o b j e c t s */ v not p o w ( (double) ( o b j e c t _ o n e . v e l . x - o b j e c t _ t w o . v e l . x ) , 2. 0 ) 44 Figure 4 (contd.) + p o w ( (double) (o b je c t _ o n e .v e I .y - o b j e c t _ t w o . v e l . y ) , 2. 0 ) + p o w ( (double) (obj e c t _ o n e .v e l .z - o b j e c t _ t w o .v e l .z) , 2. 0 ); v_not = p o w (v _ n o t ,0.5); delta_one = delta_two = (I - m u l * m u l ) / ( e l * P I ) ; (I - m u 2 * m u 2 ) / (e2*PI) ; k _ o n e - (ml + m 2 ) / ( m l * m 2 ) ; t e m p = ( (15*PI*v_not*v_no.t* ( d e l t a _ o n e + d e l t a _ t w o ) *ml*m2) / (16* (ml +m2) ) ) ; t e m p = p o w ( t e m p , 2/5.0); a l p h a _ m = t e m p * p o w ( (rl+r2)/ (rl*r2),1/5.0); impact_time_global t_const - 2.9432*alpha_m/v_not; = PI/num_intervals_global; f const = ( ( 1 . 1 4 0 * v n o t * v not) / ( k _ o n e * a l p h a _ m ) ); ) return(force_magn); } /******************* *★**/ E n d of c o m p u t e _ i m p a c t _ f o r c e () ************** 45 Figure 4 (contd.) /******************************************************************* * * * Thi s file :p a r t s . c * O t h e r f iles: c o l l i d e . c (main) * updates.c * display.c * globals.h * * * * * * * * This file conta in s f u n c t i o n s c r e a t e _ p a r t i c l e s (), * c o l l i s i o n _ d e t e c t (), a n d d i s t a n c e (). * * * * *******************************************************************/ ♦include <stdio.h> ♦include <math.h> ♦include <malloc.h> ♦include "globals.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Naune * Input * * Output * Function * * * * * * : c r e a t e _ p a r t i c l e s () * : Pointer to a structure containing info about the object under consideration * * : None * : C r e a t e all p a r t i c l e s for the g i v e n o b j e c t b y a s s i g n i n g the p o s i t i o n and o ther a t t r i b u t e s to each* particle * C r e a t e a l i n k e d l i s t of a l l p e r i p h e r a l p a r t i c l e s in* every box * *****************************************************************/ void c r e a t e _ p a r t i c l e s (obj) obj_s *obj; I int row, col, plane; /* o f t h e p a r t i c l e */ 46 Figure 4 (contd.) int o n g s */ int c i r c l e */ float p a r t i c l e */ brow. bcol, bplane; /* h o w m a n y t i m e s times _visited; x, scan line entered - a prospective /* o f a g r i d p o i n t z; y, /* o f t h e b o x t o w h i c h p a r t i c l e b e l int long float float obj_3rno; grid_points; o b j _ c e n t r e _ x , o b j _ c e n t r e _ y , o b j _ c e n t r e _ z , o b j_radius; scene_lowex_x, scene_uppex_y, scene_uppex_z; float float float float part_s part_s rowptr_s x m in, ymin, zmin, xmax, y m ax, zmax; d e l t a _ x , 'delta_y, d e l t a _ z ; value; boxsize_x, boxsize_y, boxsize_z; *blockptr; *l a t e s t ; *rowptr; NAAAAAAAAAAAAAAAAA / * A A A A A A A A A A A A A A A / AAAAAAA A NOTE : 3-d version needs modi f i c a t i o n from this point to th e end A of this AAAAAAA^l f / /* w i t h ts function. start, middle and end-points included, o b j - > g r i d +1 p o i n (or g r i d nodes) f o r e a c h o f t h e t h r e e d i m e n s i o n s */ g r i d _ p o i n t s = (obj->g r i d + 1 ) * (obj->grid + 1 ) * (ONE); /* m a l l o c s p a c e t o s t o r e t h e p a r t i c l e i n f o */ b l o c k p t r = ( p a r t s *)m a l l o c ( s i z e o f ( p a r t _ s ) * g r i d j p o i n t s ) ; if ( b l o c k p t r = = (part_s * ) NULL) f p r i n t f ( s t d e r r , " N n C o u l d n ' t m a l l o c s p a c e f o r p a r t i c l e info: prog r a m t e r m i n a t e d .\ n " ) , e x i t (I); g r i d _ p o i n t s = (obj->g r i d + 1 ) * (ONE); /* m a l l o c s p a c e t o s t o r e t h e a d d r e s s e s ne */ rowptr — if (ro w p t r (rowptr == of e v e r y row in e v e r y pl a s *)m a l l o c ( s i z e o f (r o w p t r _s ) * g r i d _p o i n t s ) , (rowptr_s * ) NULL) 47 Figure 4 (contd.) fprintf( s td er r ,"XnCouldn't malloc r o g r a m t e r m i n a t e d . \ n " ) , e x i t (I); space for row-address info: p obj->start = blockptr; o b j - > r o w p t r = rowptr; /* s i z e ) voxels Note loop) */ boxsize_x boxsize_y boxsize z of the bo x : this : scene is d i v i d e d i n t o is r e c i p r o c a l (B O X N U M x B O X N U M x B O X N U M of a c t u a l b o x s i z e (to s p e e d u p t h e = B O X N U M / ( s c e n e .u p p e x . x - s c e n e . l o w e x . x ) ; = B O X N U M / ( s c e n e .u p p e x .y - s c e n e .I o w e x .y ) ; = B O X N U M / (scene.uppex.z - scene.lowex.z); /* r e d u c e a c c e s s t i m e ! */ s c e n e I o w e x _ x = s c e n e .l o w e x . x ; s c e n e _ u p p e x _ y = s c e n e . u p p e x . y; o b j _ c e n t r e _ x = o b j->centre.x; o b j _ c e n t r e _ y = o b j - > c e n t r e .y; o b j _ c e n t r e _ z = o b j - > c e n t r e .z ; obj_radius = obj->radius; obj_srno = obj->srno; /* xmin ymin zmin xmax ymax zmax de t e r m i n e exte nt s of the circle =■ o b j _ c e n t r e _ x - o b j _ r a d i u s ; = obj _ c e n t r e _ y - obj_radius; = obj_centre_z - obj_radius; = o b j _ c entre_x + obj_radius; = o b j _ c entre_y + obj_radius; = obj_centre_z + obj_radius; delta x = delta_y = deltaz - (xmax - x m i n ) / (obj->grid) ; (ymax - y m i n ) / (obj - > g r i d ) ; (zmax - z m i n ) / (obj - > g r i d ) ; obj->pcount fo r */ = 0; (row=0;row<=obj->grid;row++) ( /* t o i n c l u d e e n d point, row< */ y = ymax - (row * d e l t a _ y ) ; /* e x p e c t i n g f i r s t t i m e s v i s i t e d = 0; intersection : a peripheral particle */ 48 Figure 4 (contd.) for ol<= (c o l = 0 ;c o l < = o b j - > g r i d ; c o l + + ) ( /* t o i n c l u d e e n d p oint, c */ x = xmin + value value value if = += -= (col * d e l t a _ x ) ; ( x - o b j _ c e n t r e _ x ) * (x - o b j _ c e n t r e _ x ) ; (y - o b j _ c e n t r e _ y ) * (y - o b j _ c e n t r e _ y ) ; ( o b j _ r a d i u s ) * (obj _ r a d i u s ) ; /* i f p o i n t is o n o r i n s i d e t h e (value < E P S I LO N ) { circle */ t i m e s _ v i s it e d + + ; b l o c k p t r - > i d [0] blockptr->id[l] b l o c k p t r - > i d [2] ZERO = row; = col; = ZERO; /* f o r t h e b l o c k p t r - > p o s n . x = x; b l o c k p t r - > p o s n .y = y; /* i n i t i a l l y , a l l p a r t i c l e s bject 2-D version, id[2]= */ have the s a m e v e l o c i t y as o */ blockp t r - > v e l = obj->vel; /* i n i t i a l l y , a l l p a r t i c l e s h a v e z e r o a c c e l e r a t i o n */ b l o c k p t r - > a c c n . x = b l o c k p t r - > a c c n .y — b l o c k p t r - > a c c n . z = 0 .0; /* b o x no. t top in w h i c h the part i c l e l i es. Box (0,0) is I e f */ brow = b l o c k p t r - > b o x n o [0] = ( i n t ) ( (x - s c e n e _ l o w e x _ x ) * b bcol = b l o c k p t r - > b o x n o [1] = ( i n t ) ( ( s c e n e _ u p p e x _ y - y ) *b oxsize_x); oxsize_y); b p l a n e = b l o c k p t r - > b o x n o [2] if /* f i r s t i n t e r s e c t i o n ( t i m e s _ v i s i t e d = = I) /* a l l plane = ZERO; ? if yes, { r o w a d d r e s s e s t o be peripheral particle */ s t o r e d i n a I-D a r r a y . has o b j - > g r i d + l r o w s i n it. i'th row in j'th p l a n e => (obj - > g r i d + l ) * j + i */ r o w p t r [ ( (obj->grid+l)*ZERO) r o w p t r [ ( (obj->grid+l)*ZER0) + row + row blockptr->status = PERIPHERAL; ].next = blockptr; ] . f s t _ c o l = col; I 49 Figure 4 (contd.) /* a d d t o t h e linked li s t of p e r i p h e r a l par t i c l e s * / = if * ) NULL) (part_s /* F irst, f i n d o u t t h e l a t e s t p e r i p h e r a l p a r t i c l e */ ((la t e s t = b o x [ b r o w ] [ b c o l ] [ Z E R O ] .s t a r t [ o b j _ s r n o ] ) ! { w h i l e ( l a t e s t - > n e x t != (part_s *)NULL) latest = l a t e s t - > n e x t ; /* now, st add the new p e r i p h e r a l p a r t i c l e to the Ii */ latest->next = blockptr; } /* e l s e : for t h i s b o x - a n d - o b j e c t , t h i s is t h e f i r s t peripheral particle */ else b o x[brow][bcol][ZERO].start[obj _srno] - blockptr; } /* e l s e : t h i s is n o t a p e r i p h e r a l p a r t i c l e else blockptr->status ■ NON_PERIPHERAL; */ /* p e r i p h e r a l o r not, n u l l t h e l i n k b l o c k p t r - > n e x t = (part_s *)NULL; for now */ ( o b j - > p c o u n t ) ++; in the object /* no. blockptr++; of pa r t i c l e s /* r e a d y for the next particle */ */ } } /* the last one in this row (unless t h i s r o w is t h e first one or last if o n e a m o n g t h e s c a n rows) ( t i m e s _ v i s i t e d > I) { was a peripheral particle */ (blockptr-1)->status - PERIPHERAL; /* c r e a t e s or ex t e n d the l i n k e d lis t o f p e r i p h e r a l p a r t i c l e : Note valid */ ; brow,bcol are from previous iteration, but still 50 Figure 4 (contd.) latest if iat = b o x [ b r o w ] [ b c o l ] [ Z E R O ] .s t a r t [ o b j _ s r n o ] ; (latest = = (part_s *)NULL) /* first one : create the I */ b o x [ b r o w ] [ b c o l ] [ Z E R O ] .s t a r t [ o b j _ s r n o ] else { /* list already exists — blockptr-1; : e x t e n d it */ /* F i r s t , f i n d o u t t h e l a t e s t p e r i p h e r a l w h i l e ( l a t e s t - > n e x t != (part_s *)NULL) latest = latest->next; particle */ /* now, a d d t h e n e w p e r i p h e r a l p a r t i c l e t o t h e l i s t latest->next = blockptr-1; */ > > /* s t o r e l a s t c o l u m n in t h i s r o w */ r o w p t r [ ( (obj->grid+l)*ZERO) + row ].last_col - (blockptr-1)->i not a l l a r e u s ed, d [I ] ; } /* m a s s o f e a c h o f t h e p a r t i c l e s */ o b j - > p a r t _ m a s s = (obj - > m a s s ) / ( o b j - > p c o u n t ) ; /* a l t h o u g h g r i d _ p o i n t s b l o c k s w e r e m a l l o c e d , free the u n u s e d blocks. */ free((char *)blockptr); return; } /* * * * * * * * * * * * * * * * * * * * * * * / E n d o f c r e a t e _ p a r t i c l e s () ***************** 51 Figure 4 (contd.) /****************************************************************** * * * * * * * Name Input Output : c o l l i s i o n _ d e t e c t () :N o n e :P o i n t e r t o a l i n k e d l i s t c o n t a i n i n g c o l l i s i o n i n f o N u l l p o i n t e r if n o c o l l i s i o n is d e t e c t e d : C h e c k if a n y t w o o b j e c t s i n t h e s c e n e h a v e c o l l i d e d Function * * * * * * * ****************************************************************** / coll_s * c o l l i s i o n _ d e t e c t () { int int coll_s coll_s part_s a r t i c l e s */ double i, j, k, m, n, d; first_time=TRUE; * r e t _ p t r - ( c o l l _ s *) N U L L ; /* r e t u r n p o i n t e r */ *current, *newblock; *pp f s t , *p p s e c ; /* t h e t w o ( p o t e n t i a l l y ) c o l l i d i n g p d i s t a n c e () ; /* T h e s e 7 l o o p s th e boxes. The following ! : The ou t e r m o s t for a n d w h i l e 3 for l o o p s loo p are to t a k e are t o cover all care of an objec t a n d all p e r i , p a r t .s in t h a t o b j e c t (in a p a r t i c u l a r box) resp. The next for a n d w h i l e loo p do the same for a n o t h e r o b j e c t w i t h w h i c h col l i s i o n is c h e c k e d for. */ for (i-0;i<BOXNUM;i++) for { (j - 0 ; j < B O X N U M ; j + + ) { KAAAAAAAAAAAA /* A A A A A A A / A NOTE : Change t h e O N E t o B O X N U M for t h e 3 - d case. 52 Figure 4 (contd.) AAAA/NAAAAAAA/ ^A A A A A A A A A A A A A A A A A A A A A A A A A A / " * / for ( k - 0 ; k < O N E ; k++) for { ( m = 0 ; m < s c e n e .n o b j e c t s - l ; m + + ) /* a d d r . of { 1st p e r i . p a rt, of object m i n b o x [ i ] [j ] [k] */ ppfst while for = b o x [ i ] [j ] [ k ] .s t a r t [ m ] ; (ppfst != (part_s { (n=m+l; n O c e n e .n o b j e c t s ;n++) /* addr. j][k] * ) NULL) of 1st p e ri. part, { of object n i n b o x [i ][ */ p p s e c = b o x [ i ] [j ] [ k ] .s t a r t [ n ] ; while if pace (ppsec !— (part_s * ) NULL) { ( d i s t a n c e (pp f s t - > p o s n , p p s e c - > p o s n ) < D N O T ) ( n e w b l o c k = (coll_s *)m a l l o c ( s i z e o f ( c o l l _ s ) ); if ( n e w b l o c k = = (coll_s * ) NULL) f p r i n tf(stderr,n\ n % s \ n n,"Couldn't malloc s for\ s t o r i n g c o l l i s i o n info: d ."), program terminate e x i t (I); if ( f irst_time) ( f i r s t _ t i m e — FALSE; ret_ptr — current ■ newblock; I else ked list { /* a n o t h e r collision : extend the Iin */ current->next = newblock; current = c u r r e n t - > n e x t ; ct /* f i l l i n t h e c o l l i s i o n i n f o */ c u r r e n t - > s r n o _ f st - m; /* s r n o o f first c u r r e n t - > s r n o _ s e c = n; s e c o n d o bj obje */ ect */ nfo */ nfo */ current->ppfst /* srno of = ppfst; /* p t r t o p a r t i c l e i c u r r e n t - > p p s e c = ppsec; /* p t r t o p a r t i c l e i c u r r e n t - > b o x _ i d [0] = i; c u r r e n t - > b o x id[l] = j; 53 Figure 4 (contd.) c u r r e n t - > b o x _ i d [2] /* n o m o r e t = k; collisions : s t o p t h e l i n k e d Iis */ current->next = (coll_s *)N U L L ; } ppsec = ppsec->next; /* t r y n e x t p e ri. part. */ } } ppfst = ppfst->next; /* t r y n e x t p e r i . p a r t . */ } return(ret_ptr); /******************** * * */ E n d o f c o l l i s i o n _ d e t e c t () * * * Name * : d i s t a n c e () ***************** 54 Figure 4 (contd.) * Input The two points * Output The * Function Compute i n q u e s t i o n (structs, with x y z member 3) * distance * the d i s t a n c e b e t w e e n the two given points * * * ****************************************************************** * * * / d o u b l e d i s t a n c e ( p _ o n e , p_two) point p_one, p_two; { double double result; p o w (); result p o w ((double)(p_one.x + pow((double)(p_one.y + pow((double)(p_one.z result p o w ( r e s u l t , 0.5); p _ t w o . x ) ,2.0) p _ t w o . y ) ,2.0) p _ t w o . z ) , 2 .0); return(result); } /******************** E n d o f d i s t a n c e () ********************/ 55 Figure 4 (contd.) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This file : u p d a t e s .c * O t h e r files: c o l l i d e . c * p a r t s .c * d i s p l a y .c * g l o b a l s .h * * (main) * * * * * * T h i s f i l e c o n t a i n s f u n c t i o n s b e f o r e _ c o l l i s i o n _ u p d a t e (), * d u r i n g _ c o l l i s i o n _ u p d a t e (), i n t e r n a l _ a c c e l e r a t i o n (), g e t _ * n e i g h b o u r (), e x t e r n a l _ a c c e l e r a t i o n () , a n d c o m p u t e _ t i m e _ s t e p () . * * * * * *******************************************************************/ ♦include <stdio.h> ♦include <math.h> ♦include <malloc.h> ♦ i n c l u d e " g l o b a l s . h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Name * Input * * : b e f o r e _ c o l l i s i o n _ u p d a t e () : Struct containing info about the object T i m e step to be u s e d for u p d a t i n g M o d e , w h e t h e r c h a n g e is t o b e p e r m a n e n t * Output * Function * * * * * * * : None : (This f u n c t i o n is i n v o k e d w h e n t h e r e is n o c o l l i s i o n ) * U p d at e posi t i o n s of all p a r ticles * R e c r e a t e l i n k e d l i s t o f peri, p a r t i c l e s i n e a c h b o x I f m o d e is PERMANENT, above c h a n g e s are p e r m a n e n t F O R W A R D J T E M P , above chan g e s are t e m p o r a r y B A C K W A R D J T E M P , above changes are t e m p o r a r y and nullify changes due to FORWARDJTEMP in question or temporary *******************************************************************/ void before_collisionjipdate(object,delta_time,mode) 56 Figure o b j_s double int only temp) object; delta_time; mode; 4 (contd.) /* a l l p a r t i c l e s peripheral */ to be u p d a t e d (permanently), f o r w a r d or p e r i p h e r a l b a c k w a r d ( { int int o n g s */ float float float float part_s void i, sign; b r ow, b c ol, bplane; /* o f t h e b o x t o w h i c h p a r t i c l e b e l disp_x, disp_y, disp_z; b o x s i z e _ x , b o x s i z e y, b o x s i z e scene_lowex_x, scene_uppex_y, x, y, z; * b l o c k p t r , *l a t e s t ; n u l l _ p o i n t e r s () ; z; s c e n e u p p e x z; - blockptr - object.start; sign - (mode — /* a l l drsp_x disp_y = disp_z - PERMANENT Note — FORWARD TEMP) ? I; p a r t i c l e s still have the same vel -> same ( o b j e c t . v e l . x ) * d e l t a _ t i m e * sign; ( o b j e c t . v e l . y) * d e l t a _ t i m e * sign; ( o b j e c t .v e l .z) * d e l t a _ t i m e * sign; /* s i z e o f t h e b o x ) voxels loop) || m o d e : this is ; scene is d i v i d e d i n t o reciprocal -I; displacement */ (BOXNUMxBOXNUMxBOXNUM of actual boxsize (to s p e e d up t h e */ boxsize_x = B O X N U M / (scene.uppex.x - scene.lowex.x); boxsi z e _ y = B O X N U M / (scene.uppex.y - scene.lowex.y); b o x s i z e _ z = B O X N U M / ( s c e n e .u p p e x . z - s c e n e .I o w e x .z ) ; scene_lowex_x = scene.lowex.x; s c e n e _ u p p e x _ y = s c e n e .u p p e x . y; scene_uppex_z = scene.uppex.z; /* N U L L a l l t h e b o x [ ] [ ] [ ] . s t a r t [] a b o x */ n u l l _ p o i n t e r s ( o b j e c t .srno) ; for tides (i-0; /* */ : l i n k e d list i < o b j e c t .p c o u n t ; ! + + , b l o c k p t r + + ) in case of t e m p o r a r y updating, o f P E R I P H E R A L in { skip all n o n —p e r i p h e r a l par 57 Figure 4 (contd.) if ( (mode != P E R M A N E N T ) continue; && (blockptr->status != P E R I P H E R A L ) ) x = b l o c k p t r - > p o s n .x + = d i a p _ x ; y — b l o c k p t r - > p o s n .y + = d i s p y ; z = b l o c k p t r - > p o s n . z += disp_z; /* u p d a t e b o x n u m b e r o f t h e p a r t i c l e */ brow — b l o c k p t r - > b o x n o [0] — (int) ( (x - s c e n e _ l o w e x _ x ) * b o x s i z e _x) ; bcol - b l o c k p t r - > b o x n o [I ] — ( i n t ) ( (scene_uppex_y - y ) *boxsize _y); b p l a n e = b l o c k p t r - > b o x n o [2] rticles if = ZERO; /* if P E R I P H E R A L , a d d / c r e a t e t h e l i n k e d l i s t */ (blockptr->status = PERIPHERAL) ( of p e r i p h e r a l pa /* F i r s t , f i n d out t h e l a t e s t p e r i p h e r a l p a r t i c l e */ if ((la t e s t = b o x [ b r o w ] [ b c o l ] [ Z E R O ] . s t a r t [ o b j e c t . s r n o ] ) part_s !- ( * ) NULL) ( w h i l e ( l a t e s t - > n e x t != (part_s * ) NULL) latest = latest->next; /* now, a d d t h e n e w p e r i p h e r a l p a r t i c l e latest->next = blockptr; to the list */ } /* e l s e : for thi s box- a n d - o b j e c t , peripheral particle */ this is t h e else b o x [ b r o w ] [ b c o l ] [ Z E R O ] .s t a r t [ o b j e c t .srno] first - blockptr; /* n u l l t h e l i n k f o r n o w */ b l o c k p t r - > n e x t =■ (part_s *) N U L L ; ) } ) /********************** E n d o f b e f o r e _ c o l l i s i o n _ u p d a t e () ******** 58 Figure 4 (contd.) ★ ★ *****/ y /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ************************************** * * * Name * Input * * * Output * Function * * * * : d u r i n g _ c o l l i s i o n _ u p d a t e () * : File d e s c r i p t o r for t h e d i s p l a y d e v i c e T h e t w o o b j e c t s i n v o l v e d in c o l l i s i o n (their s t r u c t s ) * L i n k e d list h a v i n g info about p a r t i c l e s in c o l l i s i o n * * : None : (This f u n c t i o n is i n v o k e d w h e n c o l l i s i o n h a s o c c u r e d ) * Upd ate p o s i t i o n s of all p a r t i c l e s * C a l c u l a t e t h e v e l o c i t i e s a n d a c cn. o f e a c h p a r t i c l e * R e p e a t t h e s e t w o s t e p s for n u m _ i n t e r v a l s _ g l o b a l t i m e s * * *******************************************************************/ v o i d d u r i n g _ c o l l i s i o n _ u p d a t e (fildes,o b j e c t , collptr) int fi l d e s ; /* f i l e d e s c r i p t o r f o r d i s p l a y d e v i c e */ obj_s o b j e c t []; /* t h e t w o o b j e c t s - i n f o s t r u c t u r e */ /* p o i n t e r t o c o l l i s i o n i n f o s t r u c t u r e coll s *collptr; / ( in t in t char double float point part_s coll_s point part_s void i, i n t e r v a l , u p _ l i m [ 2 ] , side; c c o u n t , sr; ans[5]; tv; d i s p _ x [2], d i s p _ y [ 2 ] , d i s p _ z [ 2 ] ; temp_accn; *blockptr, *nebrptr; *save_coll; e x t e r n a l a c c e l e r a t i o n (), i n t e r n a l _ a c c e l e r a t i o n (); * g e t _ n e i g h b o u r (); d i s p l a y _ p i c t u r e () ; save_coll = collptr; c c o u n t = 0; w h i le (collptr ccount++; != ( coll_s *)NULL) ( /* no. of p a r t i c l e - p a i r s in colli 59 Figure 4 (contd.) sion */ collptr = collptr->next; } collptr - /* save_coll; store collision /* info, restore it !! */ for b o t h t h e o b j e c t s (ppfst a n d ppsec) */ while (collptr != (coll_s collptr->ppfst->status *)NULL) { = PERIJTECTED; /* PERIpheral and afFEC ^ c o l l p t r - > p p f s t - > a c c n = e x t e r n a l _ a c c e l e r a t i o n ( o b j e c t [0 ] , collptr, ccount,ONE); collptr = collptr->next; } collptr - save_coll; /* restore it !! */ w h i l e ( c o l l p t r != (coll_s * ) NULL) ( collptr->ppsec->status = PERI_FECTED; c o l l p t r - > p p s e c - > a c c n = e x t e r n a l a c c e l e r a t i o n ( o b j e c t [ 1 ] , coll p t r , ccount,O N E ) ; collptr = collptr->next; > /* D i v i d e t h e impact time in n u m _ i n t e r v a l s _ g l o b a l p o s i t i o n of e v e r y particle. w h i c h are n e i g h b o u r s celeratron^ positions. ^ T h e n display. Up T h e n m a r k the part of the A F F E C T E D particles. the AFFECTED particles. intervals. Back into the Then find ac loop to update */ /* t v u s e d r e p e a t e d l y i n t h e l o o p / tv - impact_time_global/num_intervals_global; /* if p a r t i c l e is n o t A F F E C T E D , i t s v e l o c i t y is g o i n g t o be t h e s a m e as *. that of the entire object ' for ( s r - 0 ; s r < 2 ; sr++) ( d i s p _ x [ s r ] = o b j e c t [ s r ] . v e l . x * tv; d i s p _ y [ s r ] = o b j e c t [ s r].v e l . y * tv; d i s p _ z [ s r ] = o b j e c t [ s r ] . v e l . z * tv; 60 Figure 4 (contd.) /* m a x . n o . o f l o o p s n e e d e d f o r a l l p a r t i c l e s t o g e t A F F E C T E D */ y^a a a a a a a a a a a a a a a Aa a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a A NOTE: Change '2 * ____' t o '3 * ____ ' f o r 3-D A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A * for 2-D ( s r = 0 ; s r < 2 ; sr++) { u p_lim[sr] = 2 * object[sr].grid; /* for */ } fo r (interval=!; interval<=num_intervals_global; for ( s r = 0 ; s r < 2 ; sr++) interval++) ( ( /* U p d a t e a l l t h e p o s i t i o n s */ f o r ( i = 0 , b l o c k p t r = o b j e c t [ s r ] .s tart; i < o b j e c t [ s r ] .pcount; i + + , b lockptr++) { if (blockpt r - > s t a t u s == A F F E C T E D | I b l o c k p t r - > s t a t u s =- P E R I _ F E C T E D ) ( /* u p d a t e t h e p o s i t i o n u s i n g N e w t o n ' s law: s = ut + (atA 2 ) /2 */ b l o c k p t r - > p o s n .x + = ( b l o c k p t r - > v e l .x ) * t v + ( b l o c k p t r - > a c c n .x ) * t v b l o c k p t r - > p o s n .y + = ( b l o c k p t r - > v e l .y ) * t v + ( b l o c k p t r - > a c c n .y ) * t v blockptr->posn.z ( b l o c k p t r - > v e l .z ) * t v + (blockptr->accn.z)*tv *tv/2; *tv/2; += *tv/2; /* now, u p d a t e t h e v e l o c i t i e s u s i n g v = u + at blockp t r - > v e l . x += (blockptr->accn.x)*tv; b l o c k p t r - > v e l .y + = ( b l o c k p t r - > a c c n . y ) * t v ; b l o c k p t r - > v e l .z + = ( b l o c k p t r - > a c c n . z ) * t v ; */ } else { /* p a r t i c l e is n o t A F F E C T E D : blockptr - > p o s n . x += d i s p _ x [ s r ] ; b l o c k p t r - > p o s n .y + = d i s p _ y [ s r ] ; blockptr->posn.z += d i s p _ z [ s r ] ; } ) no a c c e l e r a t i o n yet */ 61 Figure 4 (contd.) /* M a r k the particles w h i c h are n e i g h b o u r s of AFFECTED parti cle FECTED To avoid newly mar k e d AFFECTED particles as o r i g i n a l l y A F particles, as A F F E C T E D T E M P first m a r k all the neighbours */ r loop a£ter if (interval else , ,. 'uP - I i m 7 loops, , { fof /* all p a r t i c l e s ski p fo > up_lim[sr]) some p a r t i c l e s m a y not have b e e n A F F E C T E D yet (i_ 0 , b l o c k p t r - o b j e c t [ s r ] .s tart; ^DXOCkpt 27+4*) { if are AFFECTED: (blockptr->status -= AFFECTED */ K o b j e c t [srj.pcount; || b l o c k p t r - > s t a t u s i+ —— P E R I ECTED) for (Side=RIGHT; side<=OUTWARD; sid e + + ) ( n e b r p t r = g e t _ n e i g h b o u r ( o b j e c t [ s r ] ,b l o c k p t r , s i d e ) ; i f ( n e b r p t r = = (part_s *)NULL) else if ( ( n e b r p t r - > s t a t u s != P E R I _ F E C T E D ) ( n e b r p t r - > s t a t u s != A F F E C T E D ) ) n e b r p t r - > s t a t u s = A F F E C T E D T E MP; && ) } ) /* m a r k all the t e m p o r a r i l y a f f e c t e d es as ( A F F E C T E D TEMP) — partial AFFECTED */ if (interval for +,blockptr++) if ) <= up_lim[sr]) { (i=0,blockptr=object[sr].start; i < o b j e c t [ s r ] .pcount; (blockptr->status == AFFECTED_TEMP) blockptr->status = AFFECTED; — i+ F 62 Figure 4 (contd.) /* F i n d a c c e l e r a t i o n o f a l l t h e A F F E C T E D p a r t i c l e s /* F i rst, external */ a c c e l e r a t i o n of a l l P E R I _ F E C T E D p a r t i c l e s */ collptr = save_coll; /* r e s t o r e it !! */ if ( c o l l p t r - > s r n o _ f st = = o b j e c t [ s r ] .srno) { w h i l e ( c o l l p t r !- (coll_s * ) NULL) { c o l l p t r - > p p f s t - > a c c n = e x t e r n a l _ a c c e l e r a t i o n ( o b j e c t [s r ],c ollptr,ccount,interval); collptr = collptr->next; I ) else { w h i l e ( c o l l p t r != (coll_s * ) NULL) ( c o l l p t r - > p p s e c - > a c c n =» e x t e r n a l _ a c c e l e r a t i o n ( o b j e c t [s r ] , c o l l p tr,ccount,interval); collptr = collptr->next; } } /* now, cles i n t e r n a l accn. of all A F F E C T E D and PERI_FECTED parti */ for lockptr++) if if ( i = 0 , b l o c k p t r = o b j e c t [ s r ] .s tart; ( K o b j e c t [ s r ] .pcount; ( b l o c k p t r - > s t a t u s =— A F F E C T E D ) blockptr->accn = internal_acceleration(object[sr],blockptr); /* P E R I _ F E C T E D p a r t i c l e s a l r e a d y h a v e a n a c c n . (blockptr->status =— PERI_FECTED) ( ( f rom i mpact) t e m p _ a c c n = i n t e r n a l _ a c c e l e r a t i o n ( o b j e c t [sr] , b l o c k p t r ) ; b l o c k p t r - > a c c n .x + : t e m p _ a c c n . x ; b l o c k p t r - > a c c n . y +■■ t e m p _ a c c n . y ; b l o c k p t r - > a c c n . z +' t e m p _ a c c n . z ; ) ) > i++,b */ 63 Figure 4 (contd.) /* now, d i s p l a y b o t h t h e o b j e c t s (sr = 0 = > c l e a r f o r (sr=*0; sr<2; sr++) d i s p l a y _ p i c t u r e ( f i l d e s , o b j e c t [ s r ] , sr) ; screen) */ ) ) /***************** E n d o f d u r i n g _ c o l l i s i o n _ u p d a t e () *************** ****/ /******************************************************************* * * * * * * Name input : i n t e r n a l _ _ a c c l e r a t i o n () : Str u c t for the object in w h i c h t his p a r t i c l e lies Pointer to particle info of this object Output :S t r u c t u r e c o n t a i n i n g x y z c o m p o n e n t s o f a c c e l e r a t i o n * F u n c t i o n :F i n d n e t a c c e l e r a t i o n e x p e r i e n c e d b y a p a r t i c l e due to its n e igh b o u r s * * * * * *******************************************************************/ point i n t e r n a l _ a c c e l e r a t i o n ( o b j e c t , blockptr) o b j_s part_s int float float double double float object; *blockptr; side; k_val; x_dc, y _dc, z_dc; d i st, d e l t a _ d i s t ; min_dist; accn_magn; /* s p r i n g c o n s t a n t */ /* d i r e c t i o n c o s i n e s */ /* a c c e l e r a t i o n m a g n i t u d e */ 64 Figure 4 (contd.) aeon; *nebrptr; d i s t a n c e (); point part_s double c l e s O */ part_s /* a c c e l e r a t i o n v e c t o r */ /* n e i g h b o u r i n g - p a r t i c l e p o i n t e r */ /* see fil e c o n t a i n i n g c r e a t e _ p a r t i * g e t _ n e i g h b o u r () ; a c c n . x = a c c n . y = a c c n . z = 0.0; /* u s e d i n t h e l o o p t o a v o i d a r o u n d - o f f e r r o r m i n _ d i s t = o b j e c t .d n o t / 1 0 0 0 ; for (side=RIGHT; if * ) NULL) side<=OUTWARD; side++) */ { /* c h e c k if a n e i g h b o u r e x i s t s o n t h e s i d e 'side' */ ( ( n e b r p t r = g e t _ n e i g h b o u r ( o b j e c t , b l o c k p t r , s i d e ) ) =— /* n e i g h b o u r o n t h i s else ( side does exist (part_s */ /* g e t d i s t a n c e b e t w e e n t h e p a r t i c l e a n d i t s n e i g h b o u r dist = distanc e ( b l o c k p t r - > p o s n , n e b r p t r - > p o s n ) ; /* d i s t > o b j e c t .d n o t — > t h e the s p r i n g is i n e x t e n s i o n ; */ select right s p r i n g constant, a n d get the d i r e c t i o n cosi n e s (signs i m p o r t a n t !) */ if (dist > o b j e c t . dnot) { k _ v a l = o b j e c t .k _ e x t n ; x _ d c = ( n e b r p t r - > p o s n . x - b l o c k p t r - > p o s n . x ) / dist; y _ d c = ( n e b r p t r - > p o s n . y - b l o c k p t r - > p o s n .y ) / d i s t ; z _ d c = ( n e b r p t r - > p o s n . z - b l o c k p t r - > p o s n . z ) / dist; ) /* d i s t < o b j e c t .dnot = > t h e right spring constant, (signs i m p o r t a n t !) */ else { k_val = object.k_comp; x_dc = (blockptr->posn.x y ~ d c = ( b l o c k p t r - > p o s n .y z dc = ( b l o c kptr->posn.z s p r i n g is i n c o m p r e s s i o n ; selec a n d get t h e d i r e c t i o n c o s i n e s - n e b r p t r - > p o s n .x ) / d i s t ; - n e b r p t r - > p o s n . y ) /dist; - n e b r p t r - > p o s n . z ) /dist; /* c h a n g e i n s p r i n g l e n g t h */ d e l t a d i s t = f a b s ( d i s t - ( d o u b l e ) o b j e c t .d n o t ) ; 65 Figure 4 (contd.) /* i n s t e a d o f ,d e l t a _ d i s t = = 0.0': k_val is so high, it m a kes a difference e v e n if 0.0 is r e p r e s e n t e d is 0 . 0 0 0 0 0 0 1 ! */ if (delta_dist < min_dist) else ( /* m a g n i t u d e o f t h e a c c e l e r a t i o n */ a c c n _ m a g n = (k_val * d e l t a _ d i s t ) / o b j e c t . p a r t _ m a s s ; /* a d d t h e a c c e l e r a t i o n c o m p o n e n t s accn.x += (accn_magn * x _ d c ) ; accn.y += (accn_magn * y _ d c ) ; accn.z += (accnjmagn * z _ d c ) ; */ } ) } r e t u r n (accn); ) /********************** E n d o f i n t e r n a l _ a c c e l e r a t i o n () ********** *****/ /******************************************************************** * * * : g e t _ n e i g h b o u r () * Name 66 Figure 4 (contd.) * l n P ut * 0 u t P ut * * Function * * • S t r u c t u r e c o n t a i n i n g i n f o a b o u t t h e o b j e c t in q u e s t i o n * Po in ter to parti c l e info of this object * S i d e f o r w h i c h n e i g h b o u r is d e s i r e d * : P o i n t e r t o s t r u c t u r e o n p a r t i c l e w h i c h is t h e d e s i r e d * neighbour * :F i n d t h e n e i g h b o u r f o r t h e p a r t i c l e in q u e s t i o n on * the side d e s i r e d * * / p a r t _ s * g e t _ n e i g h b o u r ( o b j e c t , b l o c k p t r , side) o b j_s object; /* o b j e c t s t r u c t u r e */ part_s *blockptr; /* p a r t i c l e i n q u e s t i o n */ int side; /* w h i c h s i d e n e i g h b o u r : R I G H T int rowptr_s /* n l y one etc. V indx; rowptr; first r o w a n d last row require special attention: p a r t i c l e e a c h i n t h e s e rows, a n d b l o c k p t r - 1 spectively) for t h e s e cases w o u l d not be m e a n i n g f u l t h e r e is o & blockptr+I (re */ /* t */ if for first (O'th) row, R I GHT, LEF T or TOP ( ( b l o c k p t r - > i d [ 0 ] = = 0) && (side ==- R I G H T | | s i d e — - L E F T r e t u r n ( (p a r t _ s * ) N U L L ) ; neighbour can't exis | | s i d e - = TOP) ) /* f o r l a s t (grid+l'th) row, R I G H T , L E F T o r B O T T O M n e i g h b o u r c a n 't e x i s t */ i f ( ( b l o c k p t r - > i d [0] = = o b j e c t . g r i d ) && (side — RIGHT I s i d e = = L E F T || s i d e = = B O T T O M ) ) r e t u r n ( ( p a r t s *)N U L L ) ; /* now, switch rest (side) of the particles */ { /* if a p a r t i c l e has a neighbour to its R IGHT, r o w no. of 67 Figure case RIGHT case LEFT 4 (contd.) t h e n e x t p a r t i c l e (id[0]) s h o u l d b e t h e s a m e if ( ( b l o c k p t r + 1 ) - > i d [ 0 ] =-= b l o c k p t r - > i d [ 0 ] ) return(blockptr+1); r e t u r n ( (part_s * ) N U L L ) ; */ : /* if a p a r t i c l e h a s a n e i g h b o u r t o its LEFT, r o w no. of t h e p r e v i o u s p a r t i c l e (id[0]) s h o u l d be t h e s a m e */ : if ( ( b l o c k p t r - 1 ) - > i d [ 0 ] blockptr->id[0]) return(blockptr-1); r e t u r n ( (part_s * ) N U L L ) ; /* t h i s p a r t i c l e is o n p l a n e i d[2], row i d [ 0 ] : every plane contains grid+1 r o ws: address of thi s r o w is therefore indx'th element i n o b j e c t .r o w p t r [ ] array TOP ■> previous row => ind x - 1 * / c ase TOP p t r - > i d [0]; : indx — ( o b j e c t .g r i d + 1 ) * ( b l o c k p t r - > i d [2]) + block r o w p t r = o b j e c t .r o w p t r [ i n d x - 1 ] ; /* c h e c k i f i n d e e d t h e r e is a p a r t i c l e v e r t i c a Ily above this one ! */ if ( ( b l o c k p t r - > i d [I] < r o w p t r .fst_c o l ) I I ( b l o c k p t r - > i d [ l ] > r o w p t r .l a s t _ c o l ) ) r e t u r n ( (part_s * ) N U L L ) ; /* now, dresses col is i d[l]: add the difference in ad */ r e t u r n ( r o w p t r .n e x t + ( b l o c k p t r - > i d [I ] - r o w p t r . f s t _ c o l ) ); /* i n d x + 1 */ case BOTTOM ptr->id[0]; : (see c o m m e n t indx — for TOP) B O T T O M => next ( o b j e c t .g r i d + 1 ) * ( b l o c k p t r - > i d [2]) row => + block rowptr — o b ject.rowptr[indx+1]; /* c h e c k if i n d e e d t h e r e is a p a r t i c l e v e r t i c a Ily below this one ! */ if ( ( b l o c k p t r - > i d [ l ] < r o w p t r .fst_ c o l ) I I ( b l o c k p t r - > i d [1] > r o w p t r .l a s t _ c o l ) ) r e t u r n ( (part_s * ) N U L L ) ; 68 Figure 4 (contd.) /* now, .col is dresses i d [1]: add the difference in ad */ r e t u r n ( r o w p t r .n e x t + ( b l o c k p t r - > i d [I ] - r o w p t r . f st c o l ) ); y^AAAAAAAAZ* A NOTE: case Cases break; INWARD case OUTWARD I N W A R D a n d O U T W A R D n e e d t o b e m o d i f i e d f o r 3 -D : break; } return ( (pa r t _ s *)N U L L ) ; > /********************* *** / E n d o f g e t n e i g h b o u r () ******************* /******************************************************************** : e x t e r n a l _ a c c e l e r a t i o n () * : S t r u c t u r e c o n t a i n i n g info about the obje c t in que s t i o n * P o i nter to l inked list of particles in collision * N u m b e r of p a i r s of p a r t i c l e s i n v o l v e d in c o l l i s i o n * I n t e r v a l (max. = n u m _ i n t e r v a l s _ g l o b a l ) * Output :S t r u c t u r e c o n t a i n i n g x y z c o m p o n e n t s o f a c c e l e r a t i o n * F u n c t i o n ' : Compute acceleration on each particle involved in * * Name * Input 69 Figure 4 (contd.) * collision due to the impact * * * ******************************************************************** / point •§ 01I Tl e x t e r n a l _ a c c e l e r a t i o n ( o b j e c t , c o l l p t r , c c o u n t ,i n t e r v a l ) object; /* o n e o f t h e t w o o b j e c t s i n c o l l i s i o n */ *collptr; coll_s /* p t r t o l i n k e d l i s t o f c o l l i s i o n i n f o */ ccount; int /* no. o f p a r t i c l e s i n c o l l i s i o n o f a g i v e n o b j e c t */ interval; int /* h o w m a n y ' t h i n t e r v a l is t h i s */ { double erval) */ double o l l i s i o n */ float float point */ ob j s t ! */ double double accn_magn; /* m a g n i t u d e o f a ccn. dist; /* d i s t a n c e b e t w e e n t h e t w o p a r t i c l e s x _ d c , y _ dc; z_dc ; accn; /* x, ./* a c c e l e r a t i o n v e c t o r dummy; /* n o i n p u t n e e d e d , y, p e r p a r t i c l e p e r int z direction cosines but in c */ (of e v e r y p a r t i c l e ) function expects i d i s t a n c e (); c o m p u t e_impact__fo r c e (); /* a s s u m p t i o n : n e t a c c e l e r a t i o n (magnitude) i n a g i v e n i n t e r v a l is equallydivided into all the particles involved in collision. */ a c c n _ m a g n = ((c o m p u t e _ i m p a c t _ f o r c e ( d u m m y , d u m m y , i n t e r v a l ) /o b j e c t .p a rt_mass)/ccount); dist = distance (collptr->pp£st->posn,collptr->ppsec->posn); /* d i r e c t i o n o f aeon, depends on which object is b e i n g c o n s i d e r e d */ if ( c o l l p t r - > s r n o _ f st — object x_dc = (collptr->ppfst->posn y_dc = (collptr->ppfst->posn z dc = (collptr->ppfst->posn ,srno) { x - c o l l p t r - > p p s e c - > p o s n .x ) /d i s t ; ,y - c o l i p t r - > p p s e c - > p o s n . y ) / d i s t ; ,z - c o l l p t r - > p p s e c - •>posn. z) /dist;. } else ( x_dc y_dc z_dc } ( c o l l p t r - > p p s e c - > p o s n x - c o l l p t r - > p p f st- - > p o s n ; x ) / d i s t ; ( c o l l p t r - > p p s e c - > p o s n ,y - c o l l p t r - > p p f st' - > p o s n . y ) / dist; ( c o l l p t r - > p p s e c - > p o s n ,z - c o l l p t r - > p p f st' - > p o s n . z ) / dist; 70 Figure 4 (contd.) /* now, t h e c o m p o n e n t s */ a c c n . x = (accn_magn * x _ d c ) ; a c c n . y = (accn_magn * y _ d c ) ; accn.z = (accn_magn * z d c ) ; r e t u r n (accn); /******************** E n d o f e x t e r n a l _ a c c e l e r a t i o n () ************ ******I /******************************************************************* * * * Name * Input * * Output * Function c o m p u t e _ t i m e _ s t e p () Struct containing info about the object in question T i m e s t e p u s e d as a ' seed/ Time step to be used by before_collision_update Compute a time step small enough that two objects will not go into each other * * * * * * * * * *******************************************************************/ d o u b l e c o m p u t e _ t i m e _ s t e p ( o b j e c t ,d e l t a _ t i m e ) obj_s o b j e c t []; double delta_time; { int int double a n d z */ double coll s i, j, k, m, n, d, c o u n t = 0 ; f o u n d _ p a i r [2]; d r x [2], d r y [2], d r z [ 2 ] ; dist, s m a l l e s t [2]; *clostpr; /* a p a i r f o u n d i n a b o x */ /* d i r e c t i o n r a t i o s i n x, y /* c l o s e s t p a i r (of p e r i p h e r a l p a r t 71 Figure 4 (contd.) i d e s ) */ part_s a r t i c l e s */ double void *pp f s t , *ppsec; /* t h e t w o (po t e n t i a l l y ) colliding p d i s t a n c e (), fa b s (); b e f o r e _ c o l l i s i o n _ u p d a t e (); /* just t w o - p a i r s - o f - p a r t i c l e s i n f o n e e d s t o b e s t o r e d */ i f ( ( c l o s t p r = (coll_s * ) m a l l o c ( 2 * s i z e o f ( c o l l _ s ) )) — (coll_s *)N U L L) f p r i n t f ( s t d e r r , "XnCouldn't m a l l o c : p r o g r a m t e r m i n a t e d \ n " ) , exit (i); /* m e a s u r e t h e s m a l l e s t d i s t a n c e b e t w e e n a n y o f t h e p a i r s o f p e r ipheral particles, t e m p o r a r i l y upd a t e onl y the p e r i p h e r a l pa r t i c l e s a nd measure the distance a g a i n . (the t w o p a i r s o f p a r t i c l e s - b e f o r e t h e temporary upd ate a n d af te r - don't have to be the s a m e ) . check the dir ection r a t i o s t o m a k e s u r e o b j e c t s h a v e n o t g o n e i n t o e a c h o ther. */ er while */ (count < 2) { /* c o u n t - 0 -> before temp.update, I - > a ft s m a l l e s t[count] = INFINITY; f o u n d _ p a i r [ c o u n t ] = F A LSE; /* T h e s e the boxes. bject and The 7 loops!: following all peri, . The The o u t e r m o s t for a n d w h i l e p a r t .s i n t h a t 3 for l o o p s a r e t o c o v e r a l l loops are to t a k e object care of an o (in a p a r t i c u l a r box) resp next for a n d w h i l e loops do the ich collision is c h e c k e d for. */ for ( i = 0 ; i < B O X N U M ; i++) ( for (j=0;j<BOXNUM;j++) ( sa m e for a n o t h e r o b j e c t w i t h w h 72 Figure 4 (contd.) / * # a a a a a a a a a a a a a a a a a a a a NOTE : Change t h e ONE t o BOXNUM for t h e 3 - d case. AAAA*/ for (k-0;k<ONE;k++) for (m =0;m <scene. n o b je c ts -l;m + + ) /* addr. of 1st p eri, p art. PPf St = b o x [ i ] [ j ] [ k ] . s t a r t [m]; w h ile (ppfst for !« (part_s { of * ) NULL) object addr. of 1st p eri, m in b o x [ i ] [j ] [ { ( n = m + l ; n < s c e n e . n o b j e c t s ; n++) /* [ j ] [k] { p art. ( of object n in b o x [i ] */ ppsec - w h ile (ppsec if sm a llest[co u n t]) b o x [i][j][k ].sta r t[n ]; ( (d ist !«* (part_s *)NULL) { = d i s t a n c e (ppfst-> p o sn ,p p sec-> p o sn ) ) < { sm allest[cou n t] = d is t; f o u n d _ p a i r [ c o u n t ] = TRUE; */ t /* f i l l in th e ' c lo s e s t p air' c l o s t p r - > s r n o _ f s t - m; /* srno in fo */ of first clo stp r-> srn o _ sec srno of second = n; /* object objec */ clo stp r-> p p fst - ppfst; /* ptr to p a rticle in f clostp r-> p p sec = ppsec; /* ptr to p article in f clostp r-> b ox_id [0] clo stp r-> b o x _ id [I ] c l o s t p r - > b o x _ i d [2] = i; = j; = k; /* not r e a lly n ecessary, but ju st c l o s t p r - > n e x t = ( c o l l _ s * ) NULL; in case */ part. */ } ppsec = ppsec->next; /* try next p eri. 73 Figure 4 (contd.) } } p p f s t = p p f s t - > n e x t ; /* t r y n e x t p e r i . p a r t . */ > } } > } if /* t e m p o r a r y u p d a t e n e e d e d o n l y o n c e (c o u n t = = 0) { ! */ clostpr++; /* t e m p o r a r i l y u p d a t e a l l t h e p e r i p h e r a l p a r t i c l e s t o m a k e sure that in the next update the objects don't go into each other FORWARD_TEMP => a d v a n c e : update particles */ for ( i = 0 ; K s c e n e .n o b j e c t s ;i++) b e f o r e _ c o l l i s i o n _ u p d a t e ( o b j e c t [ i ] ,d e l t a _ _ t i m e , F O R W A R D _ T E M P ) } count++; /* i f a p a i r o f p a r t i c l e s from different objects is n o t found in any if o f t h e b o x e s b o t h b e f o r e t e m p o r a r y u p d a t e a n d after, d e l t a _ t i m e is d e f i n i t e l y ok: r e t u r n it */ ( !fo u n d _ p a i r [0] && !fo u n d _ p a i f [I ] ) .{ for this (i=0;i<scene.nobjects;i++) b e f o r e _ e o l l i s i o n _ u p d a t e ( o b j e c t [ i ] ,d e l t a _ t i m e , B A C K W A R D _ T E M P ) ; return(delta_time); 74 Figure 4 (contd.) /* i f a p a i r o f p a r t i c l e s is n o t f o u n d in a b o x b e f o r e update, ( but is f o u n d a f t e r update) then compute direction ratios by calcu lating positions of the closest particles one delta_time before */ if ( !fo u n d _ p a i r [0] ) { ( c l o s t p r - > p p f s t - > p o s n .x - c l o s t p r - > p p f s t - > v e l .x * d e l d r x [0]. = ta_time) - (clostpr->ppsec->posn.x - clostpr->ppsec->vel.x * del ta_time); d r y [0] ta_time) ( c l o s t p r - > p p f s t - > p o s n .y - c l o s t p r - > p p f s t - > v e l .y * d e l = - ( c l o s t p r - > p p s e c - > p o s n . y - c l o s t p r - > p p s e c - > v e l .y * d e l ta_time); d r z [0] ta_time) (clostpr->ppfst->posn.z - c l o s t p r - > p p f s t - > v e l .z * d e l - (clostpr->ppsec->posn.z - c l o s t p r - > p p s e c - > v e l .z * d e l = ta_time); } else { clostpr— d r x [0] d r y [0] d r z [0] ; = c l o s t p r — > p p f s t - > p o s n . x - c l o s t p r - > p p s e c - > p o s n .x; = c l o s t p r - > p p f s t - > p o s n .y - c l o s t p r - > p p s e c - > p o s n .y ; = clostpr->ppfst->posn.z - clostpr->ppsec->posn.z; clostpr++; } /* d i r e c t i o n ratios after time-increment */ d r x [I ] = c l o s t p r - > p p f s t - > p o s n . x - c l o s t p r - > p p s e c - > p o s n . x ; d r y [I ] = c l o s t p r - > p p f s t - > p o s n .y - c l o s t p r - > p p s e c - > p o s n .y ; d r z [1] = c l o s t p r - > p p f s t - > p o s n . z - c l o s t p r - > p p s e c - > p o s n .z ; /* i f t h e p a i r o f o b j e c t s h a v i n g c l o s e s t porary d i s t a n c e b e f o r e t h e tern 75 Figure 4 (contd.) update is not the s a m e as t h a t after, lot m o r e w o r k is r e q u i r ed to determine a "good" time-step. f o r now, d e l t a _ t i m e / 1 0 .0 s erve s as a g o o d a s s u m p t i o n (?) t o t a k e c a r e o f t h i s v e r y r a r e p o s s i b i l i t y (for t h i s t o h a p p e n , c l o s e s t p a i r m u s t b e f o u n d b e f o r e a n d a fter) */ if ( ( ( c l o s t p r - > s r n o _ f st != ( c l o s t p r - 1 ) - > s r n o _ f s t ) I I ( c l o s t p r - > s r n o _ s e c != ( c l o s t p r - 1 ) - > s r n o _ s e c ) ) && ( f o u n d _ p a i r [0] && f o u n d _ p a i r [1] ) ) ( for ( i - 0 ;i < s c e n e .n o b j e c t s ; i++) b e f o r e _ c o l l i s i o n _ u p d a t e ( o b j e c t [ i ] ,d e l t a _ t i m e , B A C K W A R D _ T E M P ) ; r e t u r n ( d e l t a _ t i m e / 10.0) ; } /* as l o n g as at least o n e o f x, y or z direction ratios hasn't changed sign, ( !( ( i t ' s o k t o h a v e t h i s d e l t a _ t i m e : r e t u r n it */ ( d r x [0] > = 0.0 && d r x [I ] < 0.0) II (drx[0] < 0.0 && d r x [I ] > 0.0) I I ( f a b s ( d r x [ 0 ] ) < 0 . 0 0 0 0 1 && f a b s ( d r x [ l ] ) < 0 . 0 0 0 0 1 ) ( ( d r y [0] > - 0.0 && d r y [1] < 0.0) II ( d r y [0] < 0.0 && d r y [I ] > 0.0) I I ( f a b s ( d r y [0]) < 0 . 0 0 0 0 1 && f a b s ( d r y [1]) < 0 . 0 0 0 0 1 ) if ) && ) ) ) ( /* A A A A A A A / A NOTE: In c a s e o f 3-d, include the A && ( (drz[0] >- 0.0 && drz[1] < ) A following condition 0.0) || 0.0 && drz [1] >- 0.0) II A (drz[0] < A ( f a b s (drz[0]) < 0.00001 && f a b s (drz[1]) < 0.00001) A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A AAAA*/ for (i-0; K s c e n e .n o b jects; i++) b e f o r e _ c o l l i s i o n _ u p d a t e ( o b j e c t [ i ] ,d e I t a _ t i m e ,B A C K W A R D _ T E M P ) ; return(delta_time); /* a l l d i r e c t i o n h ot h e r . ratios have changed -> objects pass t h r o u g h eac 76 Figure 4 (contd.) restore particle positions, I o ! behold! recursion! halve delta_time, and */ else { /* r e s t o r e all the peripheral particles to t h e i r original pos itions FALSE => restore */ for ( i = 0 ; K s c e n e .n o b jects; i++) b e f o r e _ c o l l i s i o n _ u p d a t e (object [i], d e I t a _ t i m e , B A C K W A K D _ T E M P ).; free(clostpr-1); r e t u r n ( c o m p u t e _ t i m e _ s t e p ( o b j e c t ,d e l t a _ t i m e / 2 .0)); /********************** *******/ E n d o f c o m p u t e _ t i m e _ s t e p () ************** 77 Figure 4 (contd.) y******************************************************************* * * * This file : d i s p l a y .c * O t h e r f i l e s : c o l l i d e .c * p a r t s .c * u p d a t e s .c * g l o b a l s .h * * * * * (main) * * * This file contains functions * d i s p l a y _ j p i c t u r e () . d i s p l a y _ i n i t i a l i z e (), and * * * *******************************************************************/ #include #include # include #include ^include <stdio.h> <math.h> < f c n t l .h > O t a r b a s e .c .h > "globals.h" /******************************************************************* * * * * * Name Input Output Function : : : : d i s p l a y _ i n i t i a l i z e () None None Initialize the display device run in real time * * * * if p r o g r a m is t o b e * * * *******************************************************************/ i n t d i s p l a y _ i n i t i a l i z e () { int if fildes; (r e a l _ t i m e _ g l o b a l ) { p r i n t f ("\33h\33J"), ff l u s h (stdout); 78 Figure 4 (contd.) ■if ( (fi l d e s = g o p e n ( n / d e v / c r t n , O U T D E V , nh p 9 8 7 2 1 n , I N i T | THRE E _ D ) -I) fprintf(stderr,"XnCouldn't open output d e v i c e \ n n ) , e x i t (-1); v i e w _ w i n d o w (fildes, - O'. 0 5 * s c e n e .u p p e x . x , - 0 . 0 5 * s c e n e .u p p e x . y , I .05*s c e n e . u p p e x . x , I .05*s c e n e . u p p e x . y ) ; return(fildes); } else r e t u r n (-1); /******************* E n d o f d i s p l a y i n i t i a l i z e () **************** ******/ /******************************************************************** ** * * * Name Input : d i s p l a y _ p i c t u r e () : File descriptor of the display device * * Structure containing info about the object in question * * * * Output * * Function Mode, to determine if scr e e n s h o u l d be cleared : None : D is play the object in question . ******************************************************************** •k-kJ 79 Figure 4 (contd.) v o i d d i s p l a y _ p i c t u r e (fildes,object,mode) int fildes; obj_s object; int mode; r e g i s t e r int s t a t i c int int static char char float float part_s s t a t i c int static FILE if i; ' frame=0, filenum=0; limit; • f i l e n a m e [20]; comnd[100]; x, y, z; delta; *blockptr; fdes; *fp; ( o b j e c t .s r n o = = frame++; 0) /* d i s p l a y o n l y 50 f r a m e s */ limit = num_intervals_global/50; if ( (c ol lision_in_progress_global) return; if (real_time_global) if && (frame%limit '= 0 ) ) { (mode = = 0) clear_view_surface(fildes) ; u r [ 2 ] ) ^':Lne- c o l o r (f i l des7 o b j e c t .c o l o u r [0], o b j e c t .c o l o u r [I ], o b j e c t .c o l o b l o c k p t r = o b j e c t .s tart; delta = DNOT/100; for (i=0; i < o b j e c t .pcount; /* s o m e i++,blockptr++) small distance */ { m o v e 2 d ( f i l d e s , b l o c k p t r - > p o s n .x , b l o c k p t r - > p o s n .y ); x = b l o c k p t r - > p o s n .x + d e l t a ; Y = b l o c k p t r - > p o s n .y + d e l t a ; /* c h e c k is a l r e a d y m a d e t o s e e t h a t outside the scene extents draw2d(fildes,x,y); no p a r t i c l e falls */ 80 Figure 4 (contd.) > m a k e _ p i c t u r e _ c u r r e n t (fildes) ; } /* n o t else { real t i m e : data /* o p e n n e w th file needs to be if t h e first stored on (0 th) file object */ is b e i n g d e a l t w i */ if ( o b j e c t . s r n o = = 0) { filenum++; s pr i n t f(filename,"c_p.%d",filenum); if ( (fp = f o p e n ( f i l e n a m e , " r " ) ) —— (FILE * ) NULL) fp = f o p e n ( f i l e n a m e , " w " ) ; else f p r i n t f ( s t d e r r , n%s e x i s t s " , f i l e n a m e ) , e x i t (I); } /* since every frame is sto r e d in d i f f e r e n t file, pcount is t he o n l y info needed to separate one object f p r i n t f (fp," % l d \ n " , o b j e c t . p c o u n t ) ; from the other */ b l o c k p t r = o b j e c t .start; for (i=0; i k o b j e c t .pcount; i + + , b l o c k p t r + + ) f p r i n t f ( f p , " % . 3 f % . 3 f \ n " ,b l o c k p t r - > p o s n .x , b l o c k p t r - > p o s n .y ) ; if ( o b j e c t .s r n o = = s c e n e .n o b j e c t s - 1 ) ( fc l o s e (fp); s p r i n t f (comnd,"compress % s " ,filename); s y s t e m (comnd); } > /*********************** ********/ E n d o f d i s p l a y _ p i c t u r e () *************** 81 Figure 4 (contd.) /************************************************'******************* * * This file : * Other files: * * * * globals.h c o l l i d e .c p a r t s .c u p d a t e s .c d i s p l a y .c * * * * * * * (main) * This file contains defines, * parts of the program. typedefs and variables common to all* * * * *******************************************************************/ #ifndef MULTI DEFINE #define #define ♦define ♦define ♦define ♦define TRUE FALSE ZERO INFINITY ONE PI I 6 ■ 0 I . OeSO 1 3.14159265358979 /* c o n s t a n t s d e n o t i n g s t a t u s o f a p a r t i c l e ♦define PERIPHERAL I ♦define NON_PERIPHERAL 2 ♦define AFFECTED 3 ♦define AFFECTEDJTEMP 4 /* P E R I p h e r a l a n d a f F E C T E D */ ♦define PERI FECTED 5 */ /* a m a x o f 6 n e i g h b o u r s (in 3-D) p o s s i b l e b n t h e s e s i d e s C A U T I O N : d o n ' t a l t e r t h e s e ! (this o r d e r is u s e d i n f o r loops) I RIGHT ♦define 2 LEFT ♦define 3 TOP ♦define 4 BOTTOM ♦define 5 INWARD ♦define 6 OUTWARD ♦define /* m o d e ♦define ♦define for updating: PERMANENT FORWARD TEMP f u n c t i o n b e f o r e _ c o l l i s i o n _ u p d a t e () */ I 2 */ 82 Figure 4 (contd.) #define BACKWARD /* t w o p a r t i c l e s l i s i o n */ ♦define DNOT TEMP 3 (of d i f f e r e n t objects) are c l o s e r t h a n t h i s = > c ol 0.1 /* d i s t a n c e (tolerance) ♦define EPSILON to decide particle 0.0 1 in or out /* s t a n d a r d d e l t a - t i m e : as l o n g as o b j e c t s d o n ' t oth e r , t h i s is u s e d as t h e t i m e - s t e p */ ♦define STD D E L T A TIME 0. 0 5 /* r e c o v e r y f a c t o r : It w i t h */ ♦define RECVRY FCTR used pass through each just a f t e r o n e c o l l i s i o n 'is c o m p l e t e l y d e a 100 /* m a x i m u m n u m b e r o f o b j e c t s p e r m i t t e d i n t h e ♦define MAXOBJ 2 /* 3 - d s c e n e is d i v i d e d i n t o ♦define BOXNUM 8 struct point_st float x; float y; float z; */ scene */ (B O X N U M x B O X N U M x B O X N U M ) voxels */ { }; typedef /* struct point_st structure point; containing information about a given particle struct part_st { int id[3]; o b j e c t */ point posn; point ve l ; /* row, column, /* p o s i t i o n , /* v e l o c i t y , p l a n e of p a r t i c l e changes with time changes with time */ */ */ : unique in an 83 Figure 4 (contd.) accn; point char status; etc. */ int b o x n o [3]; c l e is */ /* a c c e l e r a t i o n , c h a n g e s w i t h t i m e */ /* w h e t h e r t h i s p a r t i c l e is P E R I P H E R A L , /* row, col, plane AFFECTED of the b o x in w h i c h this p a r t i /* p o i n t e r t o t h e n e x t p e r i p h e r a l p a r t i c l e s a m e b o x */ struct part_st *next; of t h i s object in the }; typedef struct pa rt _ s t part_s; /* s t r u c t u r e c o n t a i n i n g s t a r t i n g a d d r e s s o f e v e r y r o w o f p a r t i c l e s and related info.: us ef u l in fi nd i n g the n e i g h b o u r s of a g i v e n p a r t i c l e s */ struct rowptr_st { part_s *next; es */ int f st_col; o l u m n */ int last_col; m n */ /* p o i n t e r t o t h e s t a r t i n g of a r o w of p a r t i a l /* f i r s t p a r t i c l e in this /* l a s t p a r t i c l e in this row s t a r t s at t h i s r o w e n d s at t h i s c colu }; typedef struct rowptr_st rowptr_s; /* structure contai n i n g information about an object NOTE : This structure needs modification in location details anything o t h e r t h a n c i r c l e (or s phere) is u s ed. */ s t r u c t o b j st { id; int srno; int centre; point radius; float c o l o u r [3]; float g r id; in t t i d e s */ dnot ; double k_comp; float k extn; float vel; point /* e.g. c i r c l e = I, r e c t a n g l e = 2 etc. */ /* h o w m a n y ' t h o b j e c t is t h i s i n t h e s c e n e /* r , g , b : o f t h e o b j e c t */ /* s i z e o f c u b o i d ( g r i d X g r i d X g r i d ) /* /* /* ' /* if */ to create p n o r m a l d i s t a n c e b e t w e e n t w o p a r t i c l e s */ v a l u e o f s p r i n g c o n s t a n t i n c o m p r e s s i o n */ v a l u e o f s p r i n g c o n s t a n t i n e x t e n s i o n */ i n i t i a l v e l o c i t y o f t h e o b j e c t */ 84 Figure 4 (contd.) long part_s float double ount) */ float ject */ float / pcount; *s t a r t ; mass; par t mass; /* /* /* /* mu; /* P o i s s o n ' s elast; /* E, M o d u l u s no. o f p a r t i c l e s i n t h i s o b j e c t */ p o i n t e r t o w h e r e p a r t i c l e i n f o is s t o r e d */ m a s s o f t h e o b j e c t */ m a s s o f o n e p a r t i c l e ( o b j e c t . m a s s / o b j e c t .p c ratio for the m a t e r i a l of this ob of elasticity for the material * /* I - D a r r a y o f p o i n t e r s s u c h t h a t r o w p t r [ ( o b j - > g r i d ) * j + i] p o i n at t h e b e g i n n i n g of i / t h ro w of p a r t i c l e s in j'th p l a n e . (for t h e 3D case) */ rowptr_s * rowptr; ts }; typedef /* struct structure obj_st o bj_s; containing information about s t r u c t s e n st { nobjects; int lowex; point uppex; point the scene /* no. o f o b j e c t s */ /* l o w e r e x t e n t i.e. x m in. /* u p p e r e x t e n t i.e. xmax. */ ymin, ymax. z m i n */ z m a x */ }; typedef /* struct s e n st scn__s;- structure contai n i n g information about each b o x in the scene : p o i n t e r t o t h e f i r s t p e r i p h e r a l p a r t i c l e o f a n o b j e c t is s t o r e d in start[i] . Remaining peripheral particles of that object red as a linked list u s i n g p a r t _ s .n e x t . */ struct box_st { part_s *start[MAXOBJ]; }; typedef struct box_st box_s; /* o n e for eac h of t h e objects */ are s to 85 Figure 4 (contd.) /* structure containing info about s t r u c t c o l l st { int part_s o l l i s i o n */ int */ part_s o l l i s i o n */ int / s t r u c t c o l l St o l l i d e */ collision once it is d e t e c t e d */ srno f s t ; *p p f s t ; /* f i r s t o b j e c t i n c o l l i s i o n */ /* w h i c h p a r t i c l e (of t h i s object) srno /* i d o f t h e sec; second object in c in c o l l i s i on *pp s e c ; /* w h i c h p a r t i c l e b o x i d [3]; /* b o x i n w h i c h c o l l i s i o n is d e t e c t e d * *next; /* i f m o r e t h a n o n e p a i r o f p a r t i c l e s (of t h i s object) in c c }; typedef struct /* s c e n e i n f o sen s s cene; coll_st coll_s; : stays the s a m e t h r o u g h o u t t h e p r o g r a m 4*/ /* b o x i n f o : c o m m o n t o t h e e n t i r e p r o g r a m , a l t h o u g h c h a n g e s w i t h t ime (dimensions for a r r a y b o x n e e d to be B O X N U M + I r a t h e r t h a n B O X N U M for e r r o r - c h e c k i n g purposes) */ A AAAAAAAA A NOTE AAAAAAAAAjt box s int . double : Change ONE to BOX N U M for the j box[BOXNUM+1][BOXNUM+1][ONE+1]; collision_in_progress_global; impact_time_global; /* w h e n t w o b o d i e s t t i m e */ long num_intervals_global; t i m e */ int real_time_global; o n d e s i r e d (or not) */ #endif 3-d case /* no. /* I of steps to (or 0 ) w h e t h e r collide, the impac divide the impact real-time simulati f 86 Figure 5 Input S a m p l e - I $ 0.0 0.0 0.0 16 . 0 1 6 . 0 16. 0 2 50 0 0 0 /* /* /* /* /* lower ex t e n t s of the scene upper extents of the scene number of objects no. o f i n t e r v a l s 0 = o n file, I = r e a l - t i m e */ */ */ */ */ Object I 6.6 5 . 2 0 . 0 1.5 1.0 0 . 0 0.0 125 5 . 0 e 9 5 . 0e9 1.0 0 . 0 0.0 3. Ie6 0.28 2 0 0 . 0e9 /* /* /* /* /* /* /* /* c e n t r e x y z, a n d r a d i u s colour components grid size spring stiffness velocity mass P oisson's ratio Modulus of elasticity */ */ */ */ */ */ */ */ Object 2 10 . 8 5 . 2 0.0 0.0 1.0 0.0 125 6 . 0e9 6 . 0 e 9 - 2 . 5 0.0 0.0 3 . 61e 6 0. 2 8 2 0 0 . 0e9 c e n t r e x y z, a n d r a d i u s /* colour components /* g r i d size /* spring stiffness /* velocity /* mass /* /* . P o i s s o n ' s r a t i o Modulus of elasticity /* */ */ */ 2.0 V */ */ */ */ / I 87 Figure 6 Input Sa m p l e - 2 $ 0.0 0 . 0 0.0 1 6 . 0 1 6 . 0 16 . 0 2 5000 0 $ Object I 6.6 5 . 2 0 . 0 1.5 1.0 0 . 0 0.0 125 5 . 0e8 5 . 0e8 4.0 1.00.0 3. Ie6 0.28 2 0 0 . 0e9 $ Object 2 1 0 . 8 8.2 0 . 0 2.0 0.0 1.0 0.0 125 6 . 0e8 6 . 0e8 - 2 . 5 0 . 0 0.0 3 . 61e6 0. 2 8 2 0 0 . 0e9 /* /* /* /* /* lo w e r e x t e n t s of the scene upper extents of the scene number of objects no. o f i n t e r v a l s 0 = .on file, I = r e a l - t i m e */ */ */ */ */ /* /* /* /* /* /* /* c e n t r e x y z, a n d r a d i u s colour components g r i d size spring stiffness velocity mass Poisson's ratio M o d u l u s of e l a s t i c i t y */ */ */ */ */ */ */ */ /* /* /* /* /* /* /*/* c e n t r e x y z, a n d r a d i u s colour components g r i d size spring stiffness velocity mass Poi s s on ' s ratio Modulus of elasticity */ */ */ */ */ */ */ */ /*■ v V