5.4. Patterns
Prev | Chapter 5. Internals | Next

## 5.4. Patterns

### 5.4.1. Reducing memory usage

### Yvo Smellenbergh

MegaPOV introduces a new patch named 'LESS_MEMORY_IN_PATTERNS_PATCH' to reduce the amount of memory needed for each pattern. This is done by replacing the structs in the union `Vals` by pointers. The original size of `Vals` was about 104 bytes, occupied by the crackle pattern.

By using pointers, the size is reduced to 4 bytes plus the size of the data required for a specific pattern. If for example Function pattern is used, the size of `Vals` is 4 plus the size for the 2 pointers which is 8. This total of 12 is a whole lot less than the original 104! This patch will increase the amount of memory used if only crackle is used. However, this is unlikely to happen.

#### 5.4.1.1. Adding new patterns

Because MegaPOV is designed to turn on and off each patch separately, you must be careful whenever a patch is added. This patch changes many parts of the code and especially the definition of `TPATTERN_FIELDS` is a bit tricky. For example, the ANGLE_OF_INCIDENCE_PATCH is added to the `TPATTERN_FIELDS` definition like this in `frame.h`. First you define it like this:

    #ifdef ANGLE_OF_INCIDENCE_PATCH
      #ifdef LESS_MEMORY_IN_PATTERNS_PATCH
        typedef struct  {  VECTOR AOI_origin;  unsigned char pt_fixed;
        }AOI, *AOIPTR ;
        #define AngleOfIncidenceDef  AOIPTR Aoi;
      #else
       #define AngleOfIncidenceDef struct { VECTOR AOI_origin; unsigned char pt_fixed; } Aoi;
      #endif
    #else //ANGLE_OF_INCIDENCE_PATCH
      #define AngleOfIncidenceDef
     #endif

and then add it to the `TPATTERN_FIELDS` definition like this:

    #define TPATTERN_FIELDS       \
     unsigned short Type, Wave_Type, Flags; \
     :            \
     union {                     \
       DENSITY_FILE *Density_File; \
       : \
       AngleOfIncidenceDef \
       : \
       ProjectionDef \
     } Vals;

`AngleOfIncidenceDef` is always defined to avoid two definitions for `TPATTERN_FIELDS`. If ANGLE_OF_INCIDENCE_PATCH isn't defined, `AngleOfIncidenceDef` is empty and is ignored, if ANGLE_OF_INCIDENCE_PATCH is defined, `AngleOfIncidenceDef` is a pointer or a struct, depending on whether LESS_MEMORY_IN_PATTERNS_PATCH is defined or not.

This leaves us with the problem of accessing the members of the members of `Vals`. In `frame.h` LESS_MEMORY_PATCH_MO is defined like this:

    #ifdef LESS_MEMORY_IN_PATTERNS_PATCH
      #define LESS_MEMORY_PATCH_MO ->
    #else
      #define LESS_MEMORY_PATCH_MO .
    #endif

Whenever you access a member from an element of `Vals` you use

    New->Vals.Crackle LESS_MEMORY_PATCH_MO lastseed = 0x8000000;

which results in

    New->Vals.Crackle.lastseed = 0x8000000;
    or
    New->Vals.Crackle->lastseed = 0x8000000;

depending on the state of the switch LESS_MEMORY_IN_PATTERNS_PATCH.

For each pattern added, which uses a pointer, memory is allocated in the following functions:

- `parstxtr.cpp` - Parse_Pattern();
- `pattern.cpp` - Copy_TPat_Fields();

Memory is freed for each new pattern in:

- `pattern.cpp` - Destroy_TPat_Fields();

The best way to find all necessary changes is to find all occurrences of one patch and take a look on how it is implemented.

Prev | Up | Next
5.3. Parser | Home | 5.5. Expressions