# Nif Format/Mopp

From NifTools

## What is a mopp

A mopp appears to be a script used by the engine to speed up collision detection of arbitrary (not necessarily convex) shapes. In Oblivion they are stored in the "Mopp Data" field of bhkMoppBvTreeShape blocks. As far as we understand, the script can quickly decide which triangles are in the neightborhood of a given point in space.

What is certain about mopps:

- a mopp is a binary decision tree
- the final nodes of this decision tree are triangles, and they make up all triangles of the mesh

Some theories of what mopps do:

- a mopp divides up space into regions that have a particular triangle
- a mopp first divides the non-convex mesh into groups of triangles that are convex, and then hulls each part into a K-DOP (K discrete oriented polytope)
- a mopp a bounding volume tree made up of AABB nodes, K-DOP nodes, & leaf nodes. The binary bounding volume tree is hierarchical and each binary split reduces the bounding volume of the triangle primitives. leaf node confines only one triangle primitive.

Note that in each mopp the space is discretized on a 256x256x256 grid.

## Mopp syntax

Each command in a mopp consists of an opcode (a byte), followed by zero or more arguments (each of which is also a byte). These are all opcodes used in Oblivion mopps, along with their function:

`0x01 a b c`

: unknown test`0x02 a b c`

: unknown test`0x03 a b c`

: unknown test`0x04 a b c`

: unknown test

`0x05 a`

: jump`a`

bytes`0x06 a b`

: jump`a*256 + b`

bytes

`0x09 a`

: increment triangle offset by`a`

`0x0A a b`

: increment triangle offset by`a*256 + b`

`0x0B a b c d`

: set triangle offset to`c*256 + d`

;`a`

seems always 1, and`b`

seems always 0

`0x10 a b c`

: if x>a then execute block`c`

bytes further; if x<=a and x>=b then execute next block and block`c`

bytes further; if x<b then only execute next block`0x11 a b c`

: like`0x10`

but for y`0x12 a b c`

: like`0x10`

but for z`0x13 a b c`

: like`0x10`

but for y + z`0x14 a b c`

: like`0x10`

but for y - z`0x15 a b c`

: like`0x10`

but for x + z`0x16 a b c`

: like`0x10`

but for x - z`0x17 a b c`

: like`0x10`

but for x + y`0x18 a b c`

: like`0x10`

but for x - y`0x19 a b c`

: like`0x10`

but for x + y + z`0x1A a b c`

: like`0x10`

but for x + y - z`0x1B a b c`

: like`0x10`

but for x - y + z`0x1C a b c`

: like`0x10`

but for x - y - z

`0x20 a b`

: execute next block and/or block at`b`

bytes further depending on result of an unknown test involving`a`

`0x21 a b`

: like`0x20`

`0x22 a b`

: like`0x20`

`0x23 a b c d e f`

: execute block`c*256 + d`

bytes further and/or block`e*256 + f`

bytes further depending on result of an unknown test involving`a`

and`b`

`0x24 a b c d e f`

: like`0x23`

`0x25 a b c d e f`

: like`0x23`

`0x26 a b`

: exit if`x<a`

or`x>b`

`0x27 a b`

: exit if`y<a`

or`y>b`

`0x28 a b`

: exit if`z<a`

or`z>b`

`0x30`

...`0x4F`

: select triangle`0+offset`

...`31+offset`

and exit`0x50 a`

: select triangle`a+offset`

and exit`0x51 a b`

: select triangle`a*256+b+offset`

and exit`0x53 a b c d`

: select triangle`c*256+d+offset`

and exit