View Issue Details

IDProjectCategoryView StatusLast Update
0006099The Dark ModCodingpublic17.02.2023 17:24
Reporterstgatilov Assigned Tostgatilov  
Status feedbackResolutionopen 
Product VersionTDM 2.05 
Target VersionTDM 2.12 
Summary0006099: Entity bounds not conservative for animated models
DescriptionAll models have so-called "referenceBounds", which are used for culling.
In case of animated models, these bounds help doing the culling without doing expensive evaluation of the whole mesh.
Of course, these bounds must be conservative, i.e. fully contain the model at all time.
That's what is broken right now.

I have verified that this is broken since at least TDM 2.05.
I won't be surprised if this is broken forever =)
Steps To ReproduceStart bakery_job FM, come close to the woman AI.
Perhaps you want to set "g_stopTime 1" to ensure she does not move.

Then there are three ways to see the problem:

A) Set "r_useEntityScissors 1".
You can see a hole in woman's neck under some angles, and you can see background through it.
That's the main reason why entity scissors were & are disabled!

B) After you know where to look, you can reproduce the same problem with culling (without scissors).
Slowly rotate camera down, and a some moment you'll see how neck disappears and you see background.

C) Set "r_checkBounds 1".
You'll see a lot of messages about wrong bounds for various models, including the woman.
Additional InformationOriginally reported here:
TagsNo tags attached.


related to 0005990 resolvedstgatilov Entity scissors sometimes loose 




17.09.2022 18:45

administrator   ~0015256

image.png (796,785 bytes)


22.12.2022 03:05

reporter   ~0015605

I'm happy to hear this may be solved at least for 2.12. Wanted to confirm here as well that "r_useEntityScissors 1" is an improvement worth fixing: I get at least +10 FPS with it in many areas. However I had to disable it due to the problems with bounds detection described here.

Currently it can cause entities to appear cut off across portals and in other areas, such as the top of a guard's helmets disappearing. Also any part of a mesh that protrudes through a portal_sky boundary appears black. I attached two screenshots from a map I'm working on showing what happens to a volume light touching a portal surface as this is probably a less noticed case.


05.02.2023 22:17

administrator   ~0015930

The bounds are computed in idAnimator::GetBounds.
They are computed as a union of two adjacent keyframes stored in idMD5Anim::bounds array, with some kind of "origin" subtracted depending on translation flags (animBits).
These bounds however, are stored in md5anim file (section "bounds"), and this is stupid.

I don't know much about MD5, but I think in general animations are expected to apply to any rigged mesh that uses compatible skeleton.
Thus, animation cannot be held responsible for knowing the bounds of any model it's going to animate!

I'm pretty sure it is possible to do some interval math in order to precompute guaranteed bounds in load time.
It can be obtained from bounding boxes of mesh pieces that are affected by each joint + joint animation data.


12.02.2023 08:16

administrator   ~0015933

The same issue with neck happens when I knockout the woman.

In ragdoll/AF mode, bounds for rendermodel are taken from idAF::AFPoseBounds.
They get into there in idAnimator::FinishAFPose, where they are computed as:
  GetBounds().Expand( POSE_BOUNDS_EXPANSION = 5.0f )

Here GetBounds is idAF::GetBounds --- a different method.
It works by taking orientation of body clipmodels, and applying it to bounding boxes of clipmodels.


12.02.2023 08:26

administrator   ~0015934

Here is how clipmodels look like for the problematic woman.

I think the problem here is caused by replaced head:
  entityDef atdm:ai_townsfolk_female
    "inherit" "atdm:ai_humanoid_newskel"
    "ragdoll" "guard_base_newskel"
    "model" "tdm_ai_townsfolk_female"
    "def_head" "atdm:ai_head_female02_base_brunette"
    "offsetHeadModel" "1.7 0 -1.2"

The head gets a bit detached from the body, which results in inconsistency between clipmodels and rendered model, and between animation-precomputed bounds and rendered model...


12.02.2023 10:06

administrator   ~0015935

Also, the only cases of idAFAttachment seem to be heads and helmets.
I suppose helmets are attached to heads which are attached to the rest of the body =)
And the only cases of wrong scissoring that I remember are only heads and helmets.


12.02.2023 13:34

administrator   ~0015936

Joint transforms are copied from body to head in CopyJointsFromBodyToHead method.
Local transforms of two non-root joints are copied there... I guess it can also cause wrong bounds.

I see two ways to proceed:
1) Set bounds or bounds increase manually in .def file.
  Like we say guard is (60 60 150) size and hope that regarding of all the animation flexibility, everything will fit these bounds.
2) Always compute all joints transforms, even for far off-screen animated models.
  Then we can combine bounding boxes of individual bodies to be good and conservative bounds.
  It looks that original Doom 3 tried optimized away these computations.
  However, we always compute joint transforms in case something is attached (weapon, head or cap) to AI, so this optimizations is partly not working already.
  It seems that doing all computations increases CPU percentage of idAnimator::CreateFrame from 1.4% to 2.4%... this can probably be reduced by restoring SIMD optimizations.


13.02.2023 21:54

administrator   ~0015937

I decided to follow approach 2:
  r10269. Use per-joint bounds and fully evaluated skeleton to compute bounds of animated model.

So now when we load MD5 mesh, we compute per-joint bounds.
For every joint, we take all vertices/weights that are affected by it, and store bounding box of them all.
Then in order to compute bounds of the whole model, we transform these bounds according to joint locations, and compute total bounding box.

A few points to consider:
1) This computation method is correct (i.e. surely contains the mesh) only when vertex weights are nonnegative and sum of weights is 1.0 for every vertex.
  It seems to be true, but who knows...
2) In order to compute bounds, we always compute location of all joints (i.e. call CreateFrame), which takes some time.
  So this solution is a bit slower than the old one.

The old behavior can be enabled by setting cvar "r_animatedBounds 0".

At the start of AT1:Lucy map (which has a lot of AIs), I see 3.9% spent in idAnimator::GetBounds, out of 34% of game modelling time.
This is not totally negligible, but not a major thing either.
I think I can reduce this time by implementing SIMD versions of skeleton processing.


13.02.2023 21:55

administrator   ~0015938

Last edited: 13.02.2023 21:56

Let's recall the "r_checkBounds" debug cvar.
When I enabled it, I noticed that particle systems often don't pass the check.
That's usually the viewer-oriented billboard particles of rather large size.

So I slightly increased the bounds of particles to make them conservative:
  r10270. Enlarge particle bounds by 40% larger margin due to size.

Now when I enable r_checkBounds, I see not errors (at least on several large maps).


14.02.2023 02:33

developer   ~0015939

Thus far, with these changes I have not found any AI with cutoff rendering or missing areas.
That said, there are some pretty serious hall-of-mirrors artifacts in the skybox. Sometimes just moving around
will cause them to cure themselves shortly after but other times they persist no matter what.

Perhaps a hack to exclude skybox or portalsky entities from the optimization?


14.02.2023 06:24

administrator   ~0015940

Yeah, I noticed that.
I'll look into MirceaKitsune's issue next, then into skybox issue.


16.02.2023 08:01

administrator   ~0015947

The skybox is broken by some wrong scissoring code in this specific case.
I simply deleted it:
  r10271 Deleted R_PortalRender case with r_useEntityScissors.

Then enabled scissors by default:
  r10272. r_useEntityScissors is now enabled by default.

I think new backend uses the scissors in depth prepass, but does not use them for interactions rendering.
Maybe the old backend benefits from it more for that reason.

P.S. As for MirceaKitsune's case, there is no way to reproduce it for me.
So I guess I'll wait for feedback on future dev builds.



17.02.2023 16:16

developer   ~0015951

Last edited: 17.02.2023 17:22

Everything works as expected.

I vaguely recall enabling r_useEntityScissors and seeing some performance gains "somewhere" before this change.
I am struggling to find a mission where performance improves or changes but that is probably because the benefits
are GPU fillrate related and my GPU is overpowered at 1080P ?

( Just tested for 2x FBO size and no difference in performance found for r_useEntityScissors thus far... )

I'll keep looking for a good example scenario for the sake of documenting the change for 2.12

Thus far, I am also unable to re-locate any missions where r_useEntityScissors improves 2.11 vanilla.


17.02.2023 17:24

administrator   ~0015952

Yes, I did not see any performance improvements either.
Maybe there is something on old backend and/or on AMD...

Issue History

Date Modified Username Field Change
17.09.2022 18:44 stgatilov New Issue
17.09.2022 18:45 stgatilov Relationship added related to 0005099
17.09.2022 18:45 stgatilov Relationship deleted related to 0005099
17.09.2022 18:45 stgatilov Relationship added related to 0005990
17.09.2022 18:45 stgatilov Note Added: 0015256
17.09.2022 18:45 stgatilov File Added: image.png
13.12.2022 18:50 nbohr1more Target Version TDM 2.11 => TDM 2.12
22.12.2022 03:05 MirceaKitsune Note Added: 0015605
22.12.2022 03:05 MirceaKitsune File Added: olam (2022-12-08 22-59-54) (396.32 -1095.95 116.25).jpg
22.12.2022 03:05 MirceaKitsune File Added: olam (2022-12-08 22-59-59) (396.32 -1095.95 116.25).jpg
05.02.2023 22:17 stgatilov Note Added: 0015930
12.02.2023 08:16 stgatilov Note Added: 0015933
12.02.2023 08:26 stgatilov Note Added: 0015934
12.02.2023 08:26 stgatilov File Added: bakery_job (2023-02-12 09-22-24) (1687.21 27.51 34.25).jpg
12.02.2023 10:06 stgatilov Note Added: 0015935
12.02.2023 13:34 stgatilov Note Added: 0015936
13.02.2023 21:48 stgatilov Assigned To => stgatilov
13.02.2023 21:48 stgatilov Status new => assigned
13.02.2023 21:54 stgatilov Note Added: 0015937
13.02.2023 21:55 stgatilov Note Added: 0015938
13.02.2023 21:56 stgatilov Note Edited: 0015938
14.02.2023 02:33 nbohr1more Note Added: 0015939
14.02.2023 06:24 stgatilov Note Added: 0015940
16.02.2023 08:01 stgatilov Note Added: 0015947
16.02.2023 08:02 stgatilov Status assigned => feedback
17.02.2023 16:16 nbohr1more Note Added: 0015951
17.02.2023 17:22 nbohr1more Note Edited: 0015951
17.02.2023 17:24 stgatilov Note Added: 0015952