The plant growing module is responsible for the growth of the plants in the environment, and it makes use of the collision detection module for determining when a plant's growth will cause a collision with an object in the environment. Once it has the collision information from the collision detection module, it can make the plant react/grow appropriately.
Figure: Basic loop of the plant growing module
Figure
shows the basic loop of the plant growing module.
First, each plant is grown by calling the appropriate growing function.
Currently there is only the one type of plant implemented (the vine type),
however different types of plants with different generation and growth
algorithms can be added. Each plant contains information about itself that
defines it and allows it to be grown, and it contains pointers to the objects
that actually produce its "physical" representation in the simulation
environment. The values of the various data fields (containing the information
) of a plant define the state
of the plant, and the growing functions are responsible for updating the state
of the plant, ready for the next time frame. This updating also includes
updating the objects that represent the plant, and preparing them to be passed
to the collision detection module.
Once all the plants have been updated for the next time frame, the database
containing all objects (environment objects and plant objects) is passed to the
collision detection module. This module will check for any collisions
occurring within this time frame (each time frame is defined as the interval
), and will return the time in this interval at which
the database is in a valid state with no object interpenetrations occurring.
If there is no contact, the time t, returned will be t = 1, otherwise the
time returned will be
and information about the objects in
contact will also be returned.
The global state of the database where all objects are placed in the global reference, defines the scene at this point in time. If required, it is now written out to the output file ready to be processed and displayed (actually only the objects representing the plants are written out because the environment objects don't change and are thus the original .obj files).
Then the loop continues again with the next time frame, where the plants are grown taking into account the information passed back from the collision detection module.
A vine plant
(refer to appendix
plants.h for the type
definitions), is made up of a list of growing vine segments, a list of stopped
vine segments, a list of growing leaves, a list of stopped leaves, and a list
of potential leaves. Vine segments are defined by a starting and ending point,
and a scale (they also contain other information useful to creating new vine
segments, and growing the vine segment). They are represented physically by
a cylinder, with a transform to the global reference frame consisting of
scaling, rotation to the required orientation, and movement to the correct
position. The vine segment grows from its starting point, to its ending point,
and this is achieved by changing the scaling applied to the cylinder at each
time step. A vine segment's growth is over once it reaches its end point where
it will have achieved its full size. A segment will also stop growing if it
comes into contact with something else in the environment. Once it has stopped
growing, the segment is moved to the list of stopped segments (which no longer
undergo any changes), and an attempt at creating a new segment (starting from
the end of the current one) is made. In addition, an entry is added to the
potential leaf list, for a leaf to be grown from this segment at a later time
period.
Figure: Transformations of leaves and cylinders
Leaves are handled in a similar matter --- with a point of attachment in the global frame, and a transformation that orientates it, and growth being achieved via scaling the object that represents the leaf (the object being made up of two back-to-back diamond shaped polygons).
Each vine segment has at most one leaf attached to it, and starts growing (if at all) after a user definable time period has passed since the vine segment stopped growing.
The creation of vine segments is based upon the method by Arvo [AK]. A vine plant is grown by the use of "Environment-Sensitive Automata" (ESA). These are particles that travel through the environment, sensing conditions and reacting according to a set of rules. The skeleton of the plant (upon which the vine segments and leaves are placed) is actually the path that the ESA have traversed through the environment.
The ESA sample the environment by casting a number of random rays, and decide upon their movement based upon the information returned. For example an ESA won't move in a certain direction if it's path is blocked by some obstacle, and it won't head in a direction if there is no surface to "cling" to there.
Figure: Outline of algorithm for growing vines
Figure
is a pseudo code outline of the algorithm used to
generate new vine segments. P_k is the end point of the previous
segment, and is thus the starting point of this new segment; N_k
is the normal of the nearby surface that P_k was generated from;
...
are user definable constants.
The algorithm proceeds by first randomly sampling a number of directions in
the tangent plane, until we can move to a new position Q without
interference (for the purposes of the pseudo code, we can define a function
Interfere which is capable of determining this fact). From the point
Q we randomly sample directions, looking to create a new point P.
Set Intersect to be a function that returns the normal N of the
first surface the ray R hits, as well as the distance to this surface
;
while Angle is a function that returns the angle between two given
vectors.
At this new point P we test to see whether the angle formed between the new vine segment and the previous one from which this one is starting, isn't too large, giving rise to an unnatural looking vine. If it is, then this point P is ignored, and another one is tried. The purpose of the score is to rank the desirability of the trial points P. The three criteria a point is judged on are: closeness to Q, growth towards the Light source, and growth against the direction of gravity. Different growth characteristics can be obtained by changing the weightage applied to each of these three factors.
If the distance from Q to the surface is too large (greater than c_4 ) then a new point Q is tried, otherwise interference between P_k and P_k+1 is checked for. The function TestVineSeg makes sure that the addition of this new vine segment doesn't cause any problems with collision detection (it checks by using the function test4Intersection from the collision detection module). This is needed because new segments cannot start from nothing (a scale of zero) as the inverse transform isn't defined for a matrix with a scale of 0. Thus a new vine segment is added with a small initial size. This addition may violate the collision module's requirement that there be no intersection between any of the objects at t = 0.

: ESA movement through the environment
After it goes through all these tests, we now have a new segment which can be
added to the vine plant's list of growing vine segments. The constant
is the probability that no new segments will be grown from this one, while
is the probability that this segment will have two segments grown from
it. At this point the collision interest matrix is updated so that this new
segment is tested against all other objects in the environment, except for the
previous vine segment (the parent), that this one has grown from, and any
sibling segment that shares the same parent.
Creation of a leaf involves randomly choosing a face from the parent vine
segment, and then rotating it so that it lies along the normal of the chosen
face. Then the leaf is rotated again, such that the normal of the leaf is
best aligned towards the light source, and then the leaf is finally attached
at one of the points on the face. Again, addition of this leaf must be
checked to see whether it will cause problems in its current position. If it
does, then the leaf is rotated slightly and checked again with this process
being carried out
times. If this fails, then another face is
randomly selected and the testing of the placement of the leaf continues. The
program will give up after trying
random faces of the vine segment,
so this leaf isn't added. Again, the collision interest matrix is updated so
the leaf is tested against all other objects except for the vine segment it
is attached to.
The values of these growth variables (including the position of the light
source, the direction of gravity, delay before growing a leaf and various other
factors) are set in the growth configuration file (see appendix
for details).