Level Of Detail system Introduction XDM allows player models to utilize body groups to change level of detail based on viewer distance. When a model is rendered, all its triangles are drawn by the videocard. If the model is close to the screen, it is fair, but when it's far away, it can take only few pixels on the screen, but the rendering process remains the same. Obviously, this is bad performance-wise. The "Level Of Detail" or LOD system is the design-time solution for this problem. It allows model to have different variants with different complexities (polycount) that are selected for drawing based on distance between the model and the viewer. Before you start Make sure you understand how models for HL are made, what are QC script commands and how studiomdl program work. It also helps a lot to understand what is high-to-low modelling method is. System described in this document only applies to player models because bodygroups of other models have different user-defined meaning. Typically, some environment/props may have many completely different meshes compiled in one model to share same textures. How it works Usually, player models have structure similar to this: $body body "../common/player_suit_male" $body head "../Gordon/head_gordon" Note that $body works like $bodygroup with only one mesh, so here we have two groups overall. All of these groups are drawn together all the time. Models are usually divided to overcome limit of polycount for individual SMDs and it's a common practice in HL. In Half-Life 1 SDK player models have structure that incorporates two meshes in a body group: the low-res and the hi-res for manual selection: $bodygroup body { studio "../dmatch/lowcount/gordon/DM_Gordon_Head1" studio "../dmatch/highcount/gordon/Gordon_Hi-ResDM1" } This means, the model has one group with two switchable meshes, which can only be drawn one at a time. In Half-Life 1, players could choose to use one of these groups by using cl_himodels console variable. But that meant players cound only choose to always see either hi-res or low-res models all the time. XDM features advanced LOD system that decides what mesh to display dynamically, and its behavior can be tuned by r_lod_dist console variable. XDM uses model structure like this: $body body "../ElfArcher/xdm_ElfArcherF_reference_body" $body armor "../ElfArcher/xdm_ElfArcherF_reference_armor" $bodygroup detail { blank studio "../ElfArcher/xdm_ElfArcherF_reference_detail0" } Here we have 3 body groups with the last one having 2 meshes. Note that all indexes start with 0. XDM allows every group to have multiple meshes. They are switched based on distance from the viewer. The least detailed version goes first, while most detailed is the last one. This is made so it would be compatible with all standard HL player models. In the example above, mesh #0 in group #2 is blank. It literally means nothing is there. Mesh #1 is the detail mesh which has some things that are visible only when the model is really close. In total we have 2 LOD levels here. But we are not limited by this number: $bodygroup detail { blank studio "../ElfArcher/xdm_ElfArcherF_reference_detail2" studio "../ElfArcher/xdm_ElfArcherF_reference_detail1" studio "../ElfArcher/xdm_ElfArcherF_reference_detail0" } We can have multiple LODs for any bodygroup, and those numbers can differ for different groups. This approach allows you to NOT to redraw your entire models many times to have LOD meshes. Instead, you may only separate your model into "base" and "detail" meshes, which is very convenient. NOTE: it will be helpful if you put "_detail" at the end of the group name (not mesh!) for future game enhancements. Test case Let's combine two examples above and see what'll happen: $bodygroup body { studio "../ElfArcher/xdm_ElfArcherF_reference_body_lowpoly" studio "../ElfArcher/xdm_ElfArcherF_reference_body" } $body armor "../ElfArcher/xdm_ElfArcherF_reference_armor" $bodygroup detail { blank studio "../ElfArcher/xdm_ElfArcherF_reference_detail2" studio "../ElfArcher/xdm_ElfArcherF_reference_detail1" studio "../ElfArcher/xdm_ElfArcherF_reference_detail0" } Imagine a player using that model is standing infront of you. Let fDist be distance between player1 and player2 in game units. There can be 4 scenarios in total: 1) fDist < r_lod_dist Players are very close to each other. Drawn meshes are: "xdm_ElfArcherF_reference_body" "xdm_ElfArcherF_reference_armor" "xdm_ElfArcherF_reference_detail0" 2) fDist < r_lod_dist * 2 Player2 is in LOD zone 1. Drawn meshes are: "xdm_ElfArcherF_reference_body_lowpoly" "xdm_ElfArcherF_reference_armor" "xdm_ElfArcherF_reference_detail1" 3) fDist < r_lod_dist * 3 Player2 is in LOD zone 2. Drawn meshes are: "xdm_ElfArcherF_reference_body_lowpoly" "xdm_ElfArcherF_reference_armor" "xdm_ElfArcherF_reference_detail2" 4) fDist >= r_lod_dist * 3 Player2 is in LOD zone 3. Drawn meshes are: "xdm_ElfArcherF_reference_body_lowpoly" "xdm_ElfArcherF_reference_armor" Note that "xdm_ElfArcherF_reference_armor" has no variants and is drawn all the time, "xdm_ElfArcherF_reference_body" is maxed out in zone 1 and total number of LODs is equal to the largetst number of variants among all bodygroups (4). By changing r_lod_dist players can individually decide how soon LODs will change (how long LOD zones are).