This has several benifits:
o The silly issue with alias model pitches being backwards is kept out
of the renderer (it's a quakec thing: entites do their pitch
backwards, but originally, only alias models were rotated. Hipnotic
did brush entity rotations in the correct direction).
o Angle to frame vector conversions are done only when the entity's
angles vector changes, rather than every frame. This avoids a lot of
unnecessary trig function calls.
o Once transformed, an entity's frame vectors are always available.
However, the vectors are left handed rather than right handed (ie,
forward/left/up instead of forward/right/up): just a matter of
watching the sign. This avoids even more trig calls (flag models in
qw).
o This paves the way for merging brush entity surface rendering with the
world model surface rendering (the actual goal of this patch).
o This also paves the way for using quaternions to represent entity
orientation, as that would be a protocol change.
The error was quite valid: setting GL_TEXTURE_MAX_ANISOTROPY_EXT to 0 is
incorrect. The problem was caused by the call to glTexParameterf being
before the gl_anisotropy cvar was initialized. Thus, move all of the setup
code in GL_Init_Common() to after all the checks and, more importantly,
after the call to GL_Common_Init_Cvars().
It turns out that due to the way we do fullbrights, nothing special needs
to be done to get the fullbright texture blended with the model even when
fog is enabled.
There are some problems with menus and the console messing up the key_dest
state (they assume console/menu or game, nothing else), but otherwise
things seem to work.
in_bind_imt is now gone. I guess mercury was right in that it was a poor
design. However, it was (and still is necessary) to support "bind" and
"unbind". Now, instead, they work only with the IMT_MOD table. IMT_MOD sits
below IMT_0 in the imt hierarchy. If the key is not bound in IMT_0+, then
IMT_MOD will be checked. This way, "bind" and "unbind" can never mess with
a user's more sophisticated binding setup.
The backquote is not always usable for toggling the console, and the new
bind system doesn't automatically bind a key to both game and console imts
(by design). Thus create a cvar that allows the "always works" console
toggle to be specified in eg $fs_globalcfg. While I'm at it, do one for the
menus, too.
If the default sound device does not support mmap access, retry with
plughw. However, assume the user knows best and do not retry if snd_device
has been set to anything, including "default".
QF alsa support now works out of the box with pulseaudio.
Due to quake's original sound engine using a push model, the actual place
to which the sound data should be written is not necessarily where the
"hardware" dma cursor is, but rather where the last write finished off.
Thus, the correct output location is indicated by snd_paintedtime rather
than snd_shm->framepos.
I've had enough of this for the moment, but I'm pretty sure the test needs
some more consideration, and I'll probably forget about it if I don't mark
it.
I found wolfram's line-line intersection page and noticed their equation
for the time of intersection was rather different to mine. After analyzing
the differences, it turns out they produce exactly the same results (when
the lines are coplanar), but their method allows me to eliminate one dot
product (4->3). Not only that, but it turns out that their method works
equally well for skew lines (ie, non-coplanar).
mine:
CxA.CxA
-------
CxA.AxB
theirs:
CxA.AxB
-------
AxB.AxB
While unit normals aren't needed, they were too big for sane math. Now
epsilon can be used for the distance tests. One of the two new tests passes
now :).
When the trace stradles a plane in the current leaf, check the other side
of the portal, too, as it is possible that leaf will restrict the movement
of the trace.
All current tests pass! However, I can think of some situations (and I
already have a solution) where things will fail, but that's next.
It turns out that the box trace CAN get out of the solid from that location
(though a similar point trace can not). This is because of my decision to
allow non-points to touch a plane from either side without crossing the
plane, whereas a point touching a plane is always considered to be on the
front side of the plane as there is no further information to disambiguate
on which side of the plane the point is.
The trace is moved as far into the leaf as possible without leaving the
other side of the leaf. This ensures that trace_contents is started from a
good location. There is currently a problem with traces that stradle a
plane getting, but this has cleared up all the current contents related
tests.
When visiting a leaf in box mode, use trace_contents() to get the highest
priority contents of any leafs touched by the box in the current location.
I'm now down to one failing test case, and it's an "allsolid" issue that
might be an incorrect assumption in my test case.
If trace is null or point type, or the hull doesn't have portals, or the
first node is a leaf, MOD_HullContents operates in point mode (exactly the
same way as SV_HullPointContents()). However, in box mode, all leafs
touched by the trace are checked for their contents. The contents field of
trace (a bit field) will indicate the contents type of all touched leafs.
The returned contents value indicates the most important contents:
solid > lava > slime > water > empty
The one's complement value of the contents type is the bit number of the
contents bit field. I'm not sure how useful this will be as getting the
amount of overlap is currently not supported.
The code itself seems to work now. There are still some problems: the box
faces are using unit vectors for the edges, or I should go back to unit
vectors for the portal edges; starting in a solid corner won't always work;
etc. However, that's just mopping up: the main algorithm seems to be
working.
When the portals are too big, floats break down and break the tests. This
might not be much of an issue in real maps, but my tests use "infinite"
planes.
Unfortunately, Pythagorus and binary don't play well together, so rounding
errors are inevetible when testing with a slope. However, 1e-6 seems to be
a good epsilon (printf's %g hides it nicely :).
If the trace hits a portal on the plane that brought us to the leaf, then
we actually are in the leaf (otherwise, we shouldn't be here and thus
should ignore the leaf). At least, that's my thinking.
Many point tests fail (but they're really using box clipping with a zero
sized box) and two box tests fail.
I got rather tired of there being multiple definitions of mostly compatible
plane types (and I need a common type anyway). dplane_t still exists for
now because I want to be careful when messing with the actual bsp format.
This one demonstrates the need for more information in the bsp tree
(surface polygons). When the box collides with a corner where one side is
flat and the other angled, but there's a partition plane cutting the two,
the box can instead collide with the angled side before it hits the corner.
When the trace collides with something on both sides of a plane, the nearer
collision is required. The code now correctly checks both sides and keeps
the nearer collision.
However, there is still a problem with moves where the box is always cut
by the plane: both sides need to be tested (done), but when the first side
checked allows longer motion than the second, but still collides, only the
first side is checked. The shorter motion is required.
I'm not sure the end point needs to be moved at all, but I'll leave it
alone for now. I have a couple of failing test cases that seem to be caused
by not handling moves where the box is always cut by the plane.