mirror of
https://github.com/bearstonem/openmohaa-vr.git
synced 2026-10-18 06:00:24 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bba5abece | ||
|
|
bdcb6c42b6 | ||
|
|
0fe01d23d6 | ||
|
|
fc675e4064 | ||
|
|
a29af7c3f6 | ||
|
|
732872f433 | ||
|
|
04b5fdb934 | ||
|
|
e23ce01d19 | ||
|
|
648dc395e7 | ||
|
|
ab2a26a14e | ||
|
|
238e94b4d5 | ||
|
|
0c18e0e26c | ||
|
|
7085d60d02 | ||
|
|
3933e63044 | ||
|
|
342552c349 | ||
|
|
9addff08ce | ||
|
|
2ff1071115 | ||
|
|
49f4ac66ab | ||
|
|
7761cbd74c | ||
|
|
103debcf6b | ||
|
|
526ab8071c | ||
|
|
ac45f20fa6 | ||
|
|
a45b36f2f3 | ||
|
|
bea35d28fc | ||
|
|
bb71f84985 | ||
|
|
2f62e61dc8 | ||
|
|
dceceb976d | ||
|
|
59bf9fbd54 | ||
|
|
a1cd6f2746 | ||
|
|
76178064a0 | ||
|
|
31ac3f7096 | ||
|
|
545dc19811 | ||
|
|
5f598cf1f9 | ||
|
|
4e66f2482f | ||
|
|
f873fd447f | ||
|
|
a4123f65b3 | ||
|
|
93e56d968e | ||
|
|
b4e22d3040 | ||
|
|
351f601986 | ||
|
|
41fdd28d8b | ||
|
|
d7c6cc0157 | ||
|
|
f1b83f1dab | ||
|
|
bb401d8d3c | ||
|
|
8bb9cd46f8 | ||
|
|
c27695247e | ||
|
|
7b9835a118 | ||
|
|
2dc75b7527 | ||
|
|
6c577a7251 | ||
|
|
5031402c2c | ||
|
|
a4bd37af8c | ||
|
|
4dc60b9aa4 | ||
|
|
ce89399824 | ||
|
|
b92d2972f6 | ||
|
|
f53680983b | ||
|
|
d6fd337a07 | ||
|
|
95230a8d0a | ||
|
|
04524e9de9 | ||
|
|
df4f6f9515 | ||
|
|
e9c7a1f959 | ||
|
|
c4502469f4 | ||
|
|
c2cb15a1d1 | ||
|
|
4d108a272f | ||
|
|
f523c32044 | ||
|
|
5ac5632e59 | ||
|
|
80f3296854 | ||
|
|
1b1433dd1b | ||
|
|
7647bbaf36 | ||
|
|
f00fd281b3 | ||
|
|
b5ea1ddb53 | ||
|
|
b16ce90be3 | ||
|
|
4c0f7a34de | ||
|
|
2e11cd4ea2 | ||
|
|
c2ad608508 | ||
|
|
5ec8c901e2 | ||
|
|
e6bbbdb79e | ||
|
|
f5fa8d15d1 | ||
|
|
7aee02ba8d | ||
|
|
cf51e14cf5 | ||
|
|
7fb383c810 | ||
|
|
34f66963e3 | ||
|
|
6059063b67 | ||
|
|
8bf57017ac | ||
|
|
9f1d35a11b | ||
|
|
aa51987077 | ||
|
|
64055d2580 | ||
|
|
45e82c590e | ||
|
|
0c92890ef2 | ||
|
|
03e8a64283 | ||
|
|
4e14535f08 | ||
|
|
356e7c51fc | ||
|
|
52a146d664 | ||
|
|
76f107230c | ||
|
|
4a49b15649 | ||
|
|
6c448694b6 | ||
|
|
34a1cee89b | ||
|
|
29239dadfa | ||
|
|
e5a4574f92 | ||
|
|
2d70547f9d | ||
|
|
f6279e8c17 | ||
|
|
18ade839c6 | ||
|
|
b72eb8c6cc | ||
|
|
e0446db81d | ||
|
|
a8bb9aaa77 | ||
|
|
6595c3c673 | ||
|
|
4ecf3195a5 | ||
|
|
02f0e309e3 | ||
|
|
0fdfcf48f9 | ||
|
|
e9b5c7efd5 | ||
|
|
2a32b75815 | ||
|
|
d966afe4ef | ||
|
|
92e2d42e19 | ||
|
|
58e5e3fd63 | ||
|
|
b61c7b3988 | ||
|
|
ee030f27e2 | ||
|
|
02df95fc21 | ||
|
|
03100b47c1 | ||
|
|
67444b0f15 | ||
|
|
f6ae9a2b43 | ||
|
|
98cd85bc9a | ||
|
|
83a83b08f6 | ||
|
|
448e9010dc | ||
|
|
ce69ed75f7 | ||
|
|
6ac70d6b7c | ||
|
|
4f588d939d | ||
|
|
f6ebdd1998 | ||
|
|
7438dd709c | ||
|
|
1207b46937 | ||
|
|
497f853171 | ||
|
|
4984f8b925 | ||
|
|
a1d581df39 |
No files matched your search
+6
-2
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(omohaaded)
|
||||
project(openmohaa)
|
||||
|
||||
include(TargetArch.cmake)
|
||||
|
||||
@@ -205,7 +205,8 @@ if(WIN32)
|
||||
endif()
|
||||
target_link_libraries(omohaaded PRIVATE wsock32 ws2_32)
|
||||
target_link_libraries(omohaaded PRIVATE winmm)
|
||||
|
||||
|
||||
INSTALL(FILES $<TARGET_PDB_FILE:fgame> DESTINATION "${TARGET_BASE_GAME}" OPTIONAL)
|
||||
INSTALL(FILES $<TARGET_PDB_FILE:omohaaded> DESTINATION "./" OPTIONAL)
|
||||
elseif(UNIX)
|
||||
find_package(Threads)
|
||||
@@ -280,6 +281,9 @@ if (WITH_CLIENT)
|
||||
|
||||
target_link_libraries(openmohaa PRIVATE wsock32 ws2_32)
|
||||
target_link_libraries(openmohaa PRIVATE winmm)
|
||||
|
||||
INSTALL(FILES $<TARGET_PDB_FILE:cgame> DESTINATION "${TARGET_BASE_GAME}" OPTIONAL)
|
||||
INSTALL(FILES $<TARGET_PDB_FILE:openmohaa> DESTINATION "./" OPTIONAL)
|
||||
elseif(UNIX)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(GLUT REQUIRED)
|
||||
|
||||
@@ -14,28 +14,38 @@
|
||||
|
||||
## Current State
|
||||
|
||||
OpenMoHAA is still in its early days.
|
||||
|
||||
### Server
|
||||
|
||||
The server version can successfully be built. There are few unimplemented stuff from the game library :
|
||||
The server version can successfully be built.
|
||||
Some stuff are not working as intended, such as Actor or Vehicle. These systems are both almost fully implemented, but not really in stable state.
|
||||
|
||||
- Actor
|
||||
- Vehicle
|
||||
Overall the server part and the game module are almost fully implemented, but the stability may vary, there may be some minor bugs and crashes.
|
||||
|
||||
### Client
|
||||
|
||||
There is currently no client build because the UI code is currently unimplemented. Here is what's missing or unimplemented :
|
||||
The client version of OpenMoHAA is partially implemented and not stable currently. The cgame module is partially implemented as well, but is compatible with the original MOH:AA game. Credits to **Heavy Metal: F.A.K.K. 2**'s SDK for the cgame module.
|
||||
|
||||
- rendering (mostly advanced)
|
||||
- sound (must be reworked)
|
||||
- UI
|
||||
Here is the current working state for each part of the engine:
|
||||
|
||||
Using CMake, the client build and successfully be built by adding `-DWITH_CLIENT=1`
|
||||
| Part name | Full | Almost | Half | Early | Bad | Not working | Comment |
|
||||
|-------------------------|------|--------|------|-------|-----|-------------|-------------------------------------------------------------------|
|
||||
| Audio | | | | | x | | Very basic implementation from Quake III |
|
||||
| CG Module | | x | | | | | Missing FX, Marks and decals |
|
||||
| Client | | | x | | | | Missing GameSpy, server list, binds, map picker, ... |
|
||||
| Collision | x | | | | | | |
|
||||
| Model/TIKI/Skeletor | x | | | | | | |
|
||||
| Renderer | | | | x | | | Missing ghost, marks, sphere lights, sky portal, sun flare, swipe |
|
||||
| Server | | x | | | | | Probably a few bugs remaining |
|
||||
| Server module (fgame) | | x | | | | | Actor, vehicle, and few gameplay bugs |
|
||||
| UI | | | | x | | | Has core features only (menu, widgets, console, hud, urc loading) |
|
||||
|
||||
The client game module (cgame) is partially implemented, and is compatible with the original MOH:AA module.
|
||||
NOTE: Both client and server version can be compiled to target **Medal of Honor: Spearhead* and **Medal of Honor: Breakthrough**.
|
||||
|
||||
## Running
|
||||
|
||||
Backup the existing **gamex86.dll** (rename it to **gamex86.bak**).
|
||||
Backup existing mohaa files, **cgamex86.dll** and **gamex86.dll** (set their extension to **.bak**)
|
||||
|
||||
a) extract archive to your MOHAA installation directory.
|
||||
|
||||
@@ -53,6 +63,8 @@ You can now start a local OpenMOHAA server or play on a server.
|
||||
|
||||
## Compiling
|
||||
|
||||
OpenMoHAA supports both x86 and x64 architectures, and although the target platform is Windows, it still can be compiled for other platforms, and even other architectures.
|
||||
|
||||
These are the tools required for all platforms :
|
||||
- CMake >= 3.5
|
||||
- Flex and Bison (currently not used)
|
||||
@@ -60,6 +72,8 @@ These are the tools required for all platforms :
|
||||
|
||||
The installation directory can be set to MOHAA directory.
|
||||
|
||||
The client build can be built by adding `-DWITH_CLIENT=1` to the CMake command line. This will compile the cgame module and the full app with rendering, ui and sound suppport, alongside the dedicated server version.
|
||||
|
||||
### Linux
|
||||
|
||||
These are the tools required on Unix :
|
||||
@@ -73,6 +87,12 @@ These are the tools required on Unix :
|
||||
|
||||
Visual Studio (2019 or 2022) is generally preferred.
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
## Third party
|
||||
|
||||
### SDL
|
||||
@@ -109,8 +129,8 @@ https://xiph.org/vorbis/
|
||||
|
||||
https://opus-codec.org/
|
||||
|
||||
## URL
|
||||
## URLs and communities
|
||||
|
||||
- https://openmohaa.sourceforge.net/
|
||||
- https://github.com/openmoh/openmohaa/
|
||||
- https://mohaaaa.co.uk/AAAAMOHAA/index.php
|
||||
- https://x-null.net/
|
||||
|
||||
+188
-36
@@ -1795,6 +1795,10 @@ void ClientGameCommandManager::SetAlignStretch(Event* ev)
|
||||
void ClientGameCommandManager::SetDecalRadius(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->cgd.decal_radius = ev->GetFloat(1);
|
||||
}
|
||||
|
||||
@@ -1806,6 +1810,10 @@ void ClientGameCommandManager::SetDecalOrientation(Event* ev)
|
||||
{
|
||||
str deg;
|
||||
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
deg = ev->GetString(1);
|
||||
|
||||
if (!deg.icmp("random")) {
|
||||
@@ -1820,6 +1828,10 @@ void ClientGameCommandManager::SetDecalOrientation(Event* ev)
|
||||
//===============
|
||||
void ClientGameCommandManager::SetBounceDecal(Event* ev)
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->cgd.flags2 |= T2_BOUNCE_DECAL;
|
||||
if (ev->NumArgs() > 1) {
|
||||
m_spawnthing->cgd.maxbouncecount = ev->GetInteger(1);
|
||||
@@ -1837,8 +1849,11 @@ void ClientGameCommandManager::SetBounceDecal(Event* ev)
|
||||
// SetParallel
|
||||
//===============
|
||||
void ClientGameCommandManager::SetParallel(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->cgd.flags2 |= T2_PARALLEL;
|
||||
}
|
||||
|
||||
@@ -1846,10 +1861,13 @@ void ClientGameCommandManager::SetParallel(Event* ev)
|
||||
// PhysicsRate
|
||||
//===============
|
||||
void ClientGameCommandManager::SetPhysicsRate(Event* ev)
|
||||
|
||||
{
|
||||
str rate;
|
||||
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
rate = ev->GetString(1);
|
||||
|
||||
if (!rate.icmp(rate, "every")) {
|
||||
@@ -1863,8 +1881,11 @@ void ClientGameCommandManager::SetPhysicsRate(Event* ev)
|
||||
// SetLightstyle
|
||||
//===============
|
||||
void ClientGameCommandManager::SetLightstyle(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->cgd.lightstyle = CG_RegisterLightStyle(ev->GetString(1));
|
||||
}
|
||||
|
||||
@@ -1872,8 +1893,11 @@ void ClientGameCommandManager::SetLightstyle(Event* ev)
|
||||
// SetBeamSphere
|
||||
//===============
|
||||
void ClientGameCommandManager::SetBeamSphere(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->numspherebeams = ev->GetInteger(1);
|
||||
m_spawnthing->beamflags = BEAM_SPHERE_EFFECT;
|
||||
}
|
||||
@@ -1882,8 +1906,11 @@ void ClientGameCommandManager::SetBeamSphere(Event* ev)
|
||||
// SetBeamSpread
|
||||
//===============
|
||||
void ClientGameCommandManager::SetSpread(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->spreadx = ev->GetFloat(1);
|
||||
m_spawnthing->spready = ev->GetFloat(2);
|
||||
}
|
||||
@@ -1892,8 +1919,11 @@ void ClientGameCommandManager::SetSpread(Event* ev)
|
||||
// SetUseLastTraceEnd
|
||||
//===============
|
||||
void ClientGameCommandManager::SetUseLastTraceEnd(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->use_last_trace_end = qtrue;
|
||||
}
|
||||
|
||||
@@ -1901,8 +1931,11 @@ void ClientGameCommandManager::SetUseLastTraceEnd(Event* ev)
|
||||
// SetSubdivisions
|
||||
//===============
|
||||
void ClientGameCommandManager::SetSubdivisions(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->numSubdivisions = ev->GetInteger(1);
|
||||
}
|
||||
|
||||
@@ -1910,8 +1943,11 @@ void ClientGameCommandManager::SetSubdivisions(Event* ev)
|
||||
// SetBeamPersist
|
||||
//===============
|
||||
void ClientGameCommandManager::SetBeamPersist(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->beamflags |= BEAM_PERSIST_EFFECT;
|
||||
}
|
||||
|
||||
@@ -1919,8 +1955,11 @@ void ClientGameCommandManager::SetBeamPersist(Event* ev)
|
||||
// SetBeamOffsetEndponts
|
||||
//===============
|
||||
void ClientGameCommandManager::SetBeamOffsetEndpoints(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->beamflags |= BEAM_OFFSET_ENDPOINTS;
|
||||
}
|
||||
|
||||
@@ -1928,8 +1967,11 @@ void ClientGameCommandManager::SetBeamOffsetEndpoints(Event* ev)
|
||||
// SetBeamDelay
|
||||
//===============
|
||||
void ClientGameCommandManager::SetBeamDelay(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev->NumArgs() > 1) {
|
||||
str r = ev->GetString(1);
|
||||
if (r.icmp("random")) {
|
||||
@@ -1945,8 +1987,11 @@ void ClientGameCommandManager::SetBeamDelay(Event* ev)
|
||||
// SetBeamToggleDelay
|
||||
//===============
|
||||
void ClientGameCommandManager::SetBeamToggleDelay(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->beamflags |= BEAM_TOGGLE;
|
||||
if (ev->NumArgs() > 1) {
|
||||
str r = ev->GetString(1);
|
||||
@@ -1964,8 +2009,11 @@ void ClientGameCommandManager::SetBeamToggleDelay(Event* ev)
|
||||
// SetBeamLength
|
||||
//===============
|
||||
void ClientGameCommandManager::SetLength(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->length = ev->GetFloat(1);
|
||||
}
|
||||
|
||||
@@ -1973,8 +2021,11 @@ void ClientGameCommandManager::SetLength(Event* ev)
|
||||
// SetShader
|
||||
//===============
|
||||
void ClientGameCommandManager::SetShader(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->cgd.shadername = ev->GetString(1);
|
||||
}
|
||||
|
||||
@@ -1982,8 +2033,11 @@ void ClientGameCommandManager::SetShader(Event* ev)
|
||||
// SetMinOffset
|
||||
//===============
|
||||
void ClientGameCommandManager::SetMinOffset(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->min_offset = ev->GetInteger(1);
|
||||
}
|
||||
|
||||
@@ -1991,8 +2045,11 @@ void ClientGameCommandManager::SetMinOffset(Event* ev)
|
||||
// SetSubdivisions
|
||||
//===============
|
||||
void ClientGameCommandManager::SetMaxOffset(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->max_offset = ev->GetInteger(1);
|
||||
}
|
||||
|
||||
@@ -2000,8 +2057,11 @@ void ClientGameCommandManager::SetMaxOffset(Event* ev)
|
||||
// SetAnim
|
||||
//===============
|
||||
void ClientGameCommandManager::SetAnim(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->animName = ev->GetString(1);
|
||||
}
|
||||
|
||||
@@ -2009,8 +2069,11 @@ void ClientGameCommandManager::SetAnim(Event* ev)
|
||||
// AnimateOnce
|
||||
//===============
|
||||
void ClientGameCommandManager::AnimateOnce(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->cgd.flags |= T_ANIMATEONCE;
|
||||
}
|
||||
|
||||
@@ -2018,8 +2081,11 @@ void ClientGameCommandManager::AnimateOnce(Event* ev)
|
||||
// EmitterStartOff
|
||||
//===============
|
||||
void ClientGameCommandManager::EmitterStartOff(Event* ev)
|
||||
|
||||
{
|
||||
if (!m_spawnthing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spawnthing->startoff = qtrue;
|
||||
}
|
||||
|
||||
@@ -4732,6 +4798,15 @@ void ClientGameCommandManager::SpawnTempModel(int mcount, int timeAlive)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure to not spawn the world model as a tempmodel
|
||||
// Of course it would become extremely confusing...
|
||||
if (!(p->cgd.flags & T_DLIGHT) && p->ent.reType == RT_MODEL && !p->ent.hModel)
|
||||
{
|
||||
Com_Printf("^~^~^ not spawning tempmodel because it is using the world as a brush model\n");
|
||||
FreeTempModel(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5064,7 +5139,7 @@ void ClientGameCommandManager::LoopSound(Event* ev)
|
||||
|
||||
// Get the real sound to play
|
||||
|
||||
if (current_tiki) {
|
||||
if (current_tiki && current_tiki->a->alias_list) {
|
||||
name = cgi.Alias_ListFindRandom((AliasList_t*)current_tiki->a->alias_list,
|
||||
sound_name.c_str(), &soundAlias);
|
||||
}
|
||||
@@ -5093,7 +5168,7 @@ void CacheResource(const char* stuff)
|
||||
{
|
||||
str real_stuff;
|
||||
|
||||
if (!stuff) {
|
||||
if (!stuff || !stuff[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5151,10 +5226,37 @@ void AliasResource(dtiki_t* pmdl, const char* alias, const char* realname,
|
||||
}
|
||||
}
|
||||
|
||||
int bLoadForMap__FPCcT0(char* psMapsBuffer, char* name)
|
||||
qboolean bLoadForMap(const char* psMapsBuffer, const char* name)
|
||||
{
|
||||
// FIXME: stub
|
||||
return 0;
|
||||
const char* token;
|
||||
const char* mapname;
|
||||
const char* override;
|
||||
|
||||
mapname = cgs.mapname;
|
||||
if (!strncmp("test", mapname, strlen("test"))) {
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
token = COM_GetToken((char**)&psMapsBuffer, qtrue);
|
||||
override = token;
|
||||
if (token && *token)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (!Q_stricmpn(token, mapname, strlen(token)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
token = COM_GetToken((char**)&psMapsBuffer, qtrue);
|
||||
if (!token || !token[0]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Com_Printf("ERROR bLoadForMap: %s alias with empty maps specification.\n", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===============
|
||||
@@ -5164,8 +5266,9 @@ void ClientGameCommandManager::AliasCache(Event* ev)
|
||||
|
||||
{
|
||||
int i;
|
||||
char parmbuffer[512]; // this holds the parameters to be passed into the
|
||||
char parmbuffer[2048]; // this holds the parameters to be passed into the
|
||||
// alias command
|
||||
const char* psMapsBuffer;
|
||||
|
||||
if (ev->NumArgs() < 2) {
|
||||
return;
|
||||
@@ -5176,14 +5279,23 @@ void ClientGameCommandManager::AliasCache(Event* ev)
|
||||
// any additional parameters are in arguments 3-n
|
||||
|
||||
parmbuffer[0] = 0;
|
||||
psMapsBuffer = NULL;
|
||||
|
||||
for (i = 3; i <= ev->NumArgs(); i++) {
|
||||
strcat(parmbuffer, ev->GetToken(i));
|
||||
strcat(parmbuffer, " ");
|
||||
if (strcmp(ev->GetToken(i).c_str(), "maps")) {
|
||||
strcat(parmbuffer, ev->GetToken(i));
|
||||
strcat(parmbuffer, " ");
|
||||
}
|
||||
else {
|
||||
psMapsBuffer = ev->GetToken(i++);
|
||||
}
|
||||
}
|
||||
|
||||
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
|
||||
CacheResource(ev->GetString(2));
|
||||
if (bLoadForMap(psMapsBuffer, ev->GetString(1)))
|
||||
{
|
||||
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
|
||||
CacheResource(ev->GetString(2));
|
||||
}
|
||||
}
|
||||
|
||||
//===============
|
||||
@@ -5193,8 +5305,10 @@ void ClientGameCommandManager::Alias(Event* ev)
|
||||
|
||||
{
|
||||
int i;
|
||||
char parmbuffer[512]; // this holds the parameters to be passed into the
|
||||
char parmbuffer[2048]; // this holds the parameters to be passed into the
|
||||
// alias command
|
||||
qboolean subtitle;
|
||||
const char* psMapsBuffer;
|
||||
|
||||
if (ev->NumArgs() < 2) {
|
||||
return;
|
||||
@@ -5204,14 +5318,43 @@ void ClientGameCommandManager::Alias(Event* ev)
|
||||
// real path is argument 2
|
||||
// any additional parameters are in arguments 3-n
|
||||
|
||||
parmbuffer[0] = 0;
|
||||
parmbuffer[0] = 0;
|
||||
subtitle = qfalse;
|
||||
psMapsBuffer = NULL;
|
||||
|
||||
for (i = 3; i <= ev->NumArgs(); i++) {
|
||||
strcat(parmbuffer, ev->GetToken(i));
|
||||
strcat(parmbuffer, " ");
|
||||
}
|
||||
for (i = 3; i <= ev->NumArgs(); i++)
|
||||
{
|
||||
if (strcmp(ev->GetToken(i).c_str(), "maps"))
|
||||
{
|
||||
if (!subtitle)
|
||||
{
|
||||
if (!Q_stricmp(ev->GetToken(i), "subtitle")) {
|
||||
subtitle = qtrue;
|
||||
strcat(parmbuffer, ev->GetToken(i));
|
||||
}
|
||||
else {
|
||||
strcat(parmbuffer, ev->GetToken(i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat(parmbuffer, "\"");
|
||||
strcat(parmbuffer, ev->GetToken(i));
|
||||
strcat(parmbuffer, "\"");
|
||||
subtitle = qfalse;
|
||||
}
|
||||
|
||||
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
|
||||
strcat(parmbuffer, " ");
|
||||
}
|
||||
else {
|
||||
psMapsBuffer = ev->GetToken(i++);
|
||||
}
|
||||
}
|
||||
|
||||
if (bLoadForMap(psMapsBuffer, ev->GetString(1)))
|
||||
{
|
||||
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void CacheAliasList(AliasList_t* alias_list, str& name)
|
||||
@@ -6354,6 +6497,7 @@ qboolean CG_Command_ProcessFile(const char* filename, qboolean quiet, dtiki_t *c
|
||||
char* buffer;
|
||||
const char* bufstart;
|
||||
char com_token[MAX_STRING_CHARS];
|
||||
char tempName[MAX_QPATH + 1];
|
||||
|
||||
if (cgi.FS_ReadFile(filename, (void**)&buffer, quiet) == -1) {
|
||||
return qfalse;
|
||||
@@ -6366,6 +6510,10 @@ qboolean CG_Command_ProcessFile(const char* filename, qboolean quiet, dtiki_t *c
|
||||
// we are not setting up for a tiki
|
||||
current_tiki = NULL;
|
||||
|
||||
// Update the loading screen
|
||||
sprintf(tempName, "m%s", filename);
|
||||
cgi.LoadResource(tempName);
|
||||
|
||||
bufstart = buffer;
|
||||
|
||||
while (1) {
|
||||
@@ -6400,10 +6548,14 @@ qboolean CG_Command_ProcessFile(const char* filename, qboolean quiet, dtiki_t *c
|
||||
|
||||
ev->AddToken(com_token);
|
||||
}
|
||||
commandManager.ProcessEvent(ev);
|
||||
commandManager.SelectProcessEvent(ev);
|
||||
}
|
||||
cgi.FS_FreeFile((void*)bufstart);
|
||||
|
||||
// Update the loading screen
|
||||
sprintf(tempName, "o%s", filename);
|
||||
cgi.LoadResource(tempName);
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ enum class vsstypes_t : unsigned char {
|
||||
NUM_VSS_TYPES
|
||||
};
|
||||
|
||||
class cvssource_t : public Class
|
||||
class cvssource_t
|
||||
{
|
||||
public:
|
||||
cvssource_t* next;
|
||||
@@ -309,7 +309,7 @@ public:
|
||||
qboolean lastValid;
|
||||
};
|
||||
|
||||
class cvssourcestate_t : public Class
|
||||
class cvssourcestate_t
|
||||
{
|
||||
public:
|
||||
Vector origin;
|
||||
|
||||
@@ -558,8 +558,7 @@ int CG_WeaponCommandButtonBits(void)
|
||||
{
|
||||
int iShiftedWeaponCommand;
|
||||
|
||||
iShiftedWeaponCommand = cg.iWeaponCommand;
|
||||
if (!iShiftedWeaponCommand) {
|
||||
if (!cg.iWeaponCommand) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -568,5 +567,6 @@ int CG_WeaponCommandButtonBits(void)
|
||||
cg.iWeaponCommand = 0;
|
||||
}
|
||||
|
||||
return (iShiftedWeaponCommand << 7) & WEAPON_COMMAND_MASK;
|
||||
iShiftedWeaponCommand = cg.iWeaponCommand << 7;
|
||||
return iShiftedWeaponCommand & WEAPON_COMMAND_MASK;
|
||||
}
|
||||
+30
-14
@@ -414,6 +414,25 @@ void CG_Portal(centity_t* cent)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
BG_EvaluateTrajectory
|
||||
================
|
||||
*/
|
||||
void BG_EvaluateTrajectory(const trajectory_t* tr, int atTime, const vec3_t base, vec3_t result) {
|
||||
float deltaTime;
|
||||
|
||||
if (atTime > cg_smoothClientsTime->integer + tr->trTime) {
|
||||
atTime = cg_smoothClientsTime->integer + tr->trTime;
|
||||
}
|
||||
|
||||
deltaTime = (float)(atTime - tr->trTime) / 1000.0;
|
||||
|
||||
result[0] = tr->trDelta[0] * deltaTime + base[0];
|
||||
result[1] = tr->trDelta[1] * deltaTime + base[1];
|
||||
result[2] = tr->trDelta[2] * deltaTime + base[2];
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CG_CalcEntityLerpPositions
|
||||
@@ -477,8 +496,8 @@ void CG_CalcEntityLerpPositions( centity_t *cent )
|
||||
|
||||
// this will linearize a sine or parabolic curve, but it is important
|
||||
// to not extrapolate player positions if more recent data is available
|
||||
BG_EvaluateTrajectory(¢->currentState.pos, cg.snap->serverTime, current);
|
||||
BG_EvaluateTrajectory(¢->nextState.pos, cg.nextSnap->serverTime, next);
|
||||
BG_EvaluateTrajectory(¢->currentState.pos, cg.snap->serverTime, cent->currentState.origin, current);
|
||||
BG_EvaluateTrajectory(¢->nextState.pos, cg.nextSnap->serverTime, cent->nextState.origin, next);
|
||||
|
||||
cent->lerpOrigin[0] = current[0] + f * (next[0] - current[0]);
|
||||
cent->lerpOrigin[1] = current[1] + f * (next[1] - current[1]);
|
||||
@@ -494,17 +513,11 @@ void CG_CalcEntityLerpPositions( centity_t *cent )
|
||||
QuatToMat(quat, mat);
|
||||
MatrixToEulerAngles(mat, cent->lerpAngles);
|
||||
}
|
||||
|
||||
// Lerp legs, torso, and head angles
|
||||
for (i = 0; i < 3; i++) {
|
||||
cent->lerpAngles[i] = LerpAngle(current[i], next[i], f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// just use the current frame and evaluate as best we can
|
||||
BG_EvaluateTrajectory(¢->currentState.pos, cg.time, cent->lerpOrigin);
|
||||
BG_EvaluateTrajectory(¢->currentState.pos, cg.time, cent->currentState.origin, cent->lerpOrigin);
|
||||
VectorCopy(cent->currentState.angles, cent->lerpAngles);
|
||||
//BG_EvaluateTrajectory(¢->currentState.apos, cg.time, cent->lerpAngles);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,10 +558,10 @@ void CG_AddCEntity(centity_t* cent)
|
||||
CG_ModelAnim(cent, qtrue);
|
||||
break;
|
||||
case ET_PLAYER:
|
||||
CG_Player(cent);
|
||||
case ET_ITEM:
|
||||
case ET_EXEC_COMMANDS:
|
||||
CG_ModelAnim(cent, qfalse);
|
||||
CG_Player(cent);
|
||||
CG_Splash(cent);
|
||||
case ET_ITEM:
|
||||
CG_ModelAnim(cent, qfalse);
|
||||
break;
|
||||
case ET_GENERAL:
|
||||
CG_General(cent);
|
||||
@@ -575,7 +588,10 @@ void CG_AddCEntity(centity_t* cent)
|
||||
break;
|
||||
case ET_ROPE: // skip
|
||||
CG_Rope(cent);
|
||||
break;
|
||||
break;
|
||||
case ET_EXEC_COMMANDS:
|
||||
CG_ModelAnim(cent, qfalse);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -495,7 +495,7 @@ void CG_SetLightStyle( int num, const char *s )
|
||||
cg_lightstyle[ num ].map[ k ][ 1 ] = t / 255.0f;
|
||||
k++;
|
||||
}
|
||||
n = max( n, k );
|
||||
n = Q_max( n, k );
|
||||
}
|
||||
while( k < MAX_LIGHTSTYLE_LENGTH )
|
||||
{
|
||||
@@ -518,7 +518,7 @@ void CG_SetLightStyle( int num, const char *s )
|
||||
cg_lightstyle[ num ].map[ k ][ 2 ] = t / 255.0f;
|
||||
k++;
|
||||
}
|
||||
n = max( n, k );
|
||||
n = Q_max( n, k );
|
||||
}
|
||||
while( k < MAX_LIGHTSTYLE_LENGTH )
|
||||
{
|
||||
@@ -541,7 +541,7 @@ void CG_SetLightStyle( int num, const char *s )
|
||||
cg_lightstyle[ num ].map[ k ][ 3 ] = t / 255.0f;
|
||||
k++;
|
||||
}
|
||||
n = max( n, k );
|
||||
n = Q_max( n, k );
|
||||
}
|
||||
while( k < MAX_LIGHTSTYLE_LENGTH )
|
||||
{
|
||||
|
||||
+16
-7
@@ -297,15 +297,21 @@ typedef struct {
|
||||
qboolean testGun;
|
||||
|
||||
// farplane parameters
|
||||
float farplane_distance;
|
||||
float farplane_distance;
|
||||
float farplane_bias;
|
||||
vec3_t farplane_color;
|
||||
qboolean farplane_cull;
|
||||
qboolean farplane_cull;
|
||||
int skyboxFarplane;
|
||||
qboolean renderTerrain;
|
||||
float farclipOverride;
|
||||
vec3_t farplaneColorOverride;
|
||||
|
||||
// portal sky parameters
|
||||
qboolean sky_portal;
|
||||
float sky_alpha;
|
||||
vec3_t sky_origin;
|
||||
vec3_t sky_axis[3]; // rotation vectors
|
||||
vec3_t sky_axis[3]; // rotation vectors
|
||||
int skyboxSpeed;
|
||||
|
||||
// weapon viewkick recoil
|
||||
float viewkick[2];
|
||||
@@ -371,8 +377,9 @@ typedef struct {
|
||||
int fraglimit;
|
||||
int timelimit;
|
||||
int maxclients;
|
||||
int cinematic;
|
||||
char mapname[MAX_QPATH];
|
||||
int cinematic;
|
||||
int mapChecksum;
|
||||
char mapname[MAX_QPATH];
|
||||
|
||||
//
|
||||
// locally derived information from gamestate
|
||||
@@ -475,6 +482,7 @@ int CG_LastAttacker( void );
|
||||
void CG_Init( clientGameImport_t *imported, int serverMessageNum, int serverCommandSequence, int clientNum );
|
||||
void CG_Shutdown( void );
|
||||
void CG_ServerRestarted( void );
|
||||
void CG_ParseFogInfo(const char* str);
|
||||
|
||||
//
|
||||
// cg_modelanim.cpp
|
||||
@@ -590,6 +598,7 @@ void CG_PredictPlayerState( void );
|
||||
//
|
||||
// cg_ents.c
|
||||
//
|
||||
void BG_EvaluateTrajectory(const trajectory_t* tr, int atTime, const vec3_t base, vec3_t result);
|
||||
void CG_SetEntitySoundPosition( centity_t *cent );
|
||||
void CG_AddPacketEntities( void );
|
||||
void CG_Beam( centity_t *cent );
|
||||
@@ -632,8 +641,8 @@ void CG_ImpactMarkSimple(
|
||||
);
|
||||
void CG_InitTestTreadMark();
|
||||
int CG_PermanentMark(
|
||||
vec_t* origin,
|
||||
vec_t* dir,
|
||||
const vec3_t origin,
|
||||
const vec3_t dir,
|
||||
float orientation,
|
||||
float fSScale,
|
||||
float fTScale,
|
||||
|
||||
+50
-20
@@ -194,23 +194,22 @@ called during a precache command
|
||||
*/
|
||||
void CG_RegisterSounds( void )
|
||||
{
|
||||
int startTime; // esi MAPDST
|
||||
int endTime; // eax MAPDST
|
||||
char filename[64]; // [esp+28h] [ebp-40h] BYREF
|
||||
int startTime;
|
||||
int endTime;
|
||||
char filename[MAX_QPATH];
|
||||
|
||||
Com_Printf("\n\n-----------PARSING UBERSOUND------------\n");
|
||||
Com_Printf(
|
||||
"Any SetCurrentTiki errors means that tiki wasn't prefetched and "
|
||||
"tiki-specific sounds for it won't work. To fix prefe"
|
||||
"tch the tiki. Ignore if you don't use that tiki on this level.\n");
|
||||
Com_sprintf(filename, 64, "ubersound/ubersound.scr");
|
||||
Com_sprintf(filename, sizeof(filename), "ubersound/ubersound.scr");
|
||||
|
||||
startTime = cgi.Milliseconds();
|
||||
CG_Command_ProcessFile(filename, 0, 0);
|
||||
endTime = cgi.Milliseconds();
|
||||
|
||||
Com_Printf("Parse/Load time: %f seconds.\n",
|
||||
(double)((long double)(endTime - startTime) / 1000.0));
|
||||
Com_Printf("Parse/Load time: %f seconds.\n", (endTime - startTime) / 1000.0f);
|
||||
|
||||
Com_Printf("-------------UBERSOUND DONE---------------\n\n");
|
||||
Com_Printf("\n\n-----------PARSING UBERDIALOG------------\n");
|
||||
@@ -218,14 +217,13 @@ void CG_RegisterSounds( void )
|
||||
"Any SetCurrentTiki errors means that tiki wasn't prefetched and "
|
||||
"tiki-specific sounds for it won't work. To fix prefe"
|
||||
"tch the tiki. Ignore if you don't use that tiki on this level.\n");
|
||||
Com_sprintf(filename, 64, "ubersound/uberdialog.scr");
|
||||
Com_sprintf(filename, sizeof(filename), "ubersound/uberdialog.scr");
|
||||
|
||||
startTime = cgi.Milliseconds();
|
||||
CG_Command_ProcessFile(filename, 0, 0);
|
||||
endTime = cgi.Milliseconds() - startTime;
|
||||
|
||||
Com_Printf("Parse/Load time: %f seconds.\n",
|
||||
(double)((long double)endTime / 1000.0));
|
||||
Com_Printf("Parse/Load time: %f seconds.\n", endTime / 1000.0f);
|
||||
Com_Printf("-------------UBERDIALOG DONE---------------\n\n");
|
||||
}
|
||||
|
||||
@@ -302,16 +300,7 @@ void CG_ProcessConfigString(int num)
|
||||
cg.matchStartTime = atoi(str);
|
||||
return;
|
||||
case CS_FOGINFO:
|
||||
sscanf
|
||||
(
|
||||
str,
|
||||
"%d %f %f %f %f",
|
||||
&cg.farplane_cull,
|
||||
&cg.farplane_distance,
|
||||
&cg.farplane_color[0],
|
||||
&cg.farplane_color[1],
|
||||
&cg.farplane_color[2]
|
||||
);
|
||||
CG_ParseFogInfo(str);
|
||||
return;
|
||||
case CS_SKYINFO:
|
||||
sscanf
|
||||
@@ -366,7 +355,7 @@ void CG_ProcessConfigString(int num)
|
||||
}
|
||||
else if (num >= CS_SOUNDS && num < CS_SOUNDS + MAX_SOUNDS)
|
||||
{
|
||||
int len = strlen(str);
|
||||
size_t len = strlen(str);
|
||||
if (len)
|
||||
{
|
||||
qboolean streamed;
|
||||
@@ -778,4 +767,45 @@ void Com_Printf( const char *msg, ... ) {
|
||||
|
||||
#endif
|
||||
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
|
||||
void CG_ParseFogInfo(const char* str) {
|
||||
sscanf(
|
||||
str,
|
||||
"%d %f %f %f %f %f %f %f %d %f %f %f %f",
|
||||
&cg.farplane_cull,
|
||||
&cg.farplane_distance,
|
||||
&cg.farplane_bias,
|
||||
&cg.skyboxFarplane,
|
||||
&cg.skyboxSpeed,
|
||||
&cg.farplane_color[0],
|
||||
&cg.farplane_color[1],
|
||||
&cg.farplane_color[2],
|
||||
&cg.renderTerrain,
|
||||
&cg.farclipOverride,
|
||||
&cg.farplaneColorOverride[0],
|
||||
&cg.farplaneColorOverride[1],
|
||||
&cg.farplaneColorOverride[2]
|
||||
);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void CG_ParseFogInfo(const char* str) {
|
||||
cg.farclipOverride = 0.0;
|
||||
cg.farplaneColorOverride[0] = -1.0;
|
||||
cg.farplaneColorOverride[1] = -1.0;
|
||||
cg.farplaneColorOverride[2] = -1.0;
|
||||
sscanf
|
||||
(
|
||||
str,
|
||||
"%d %f %f %f %f",
|
||||
&cg.farplane_cull,
|
||||
&cg.farplane_distance,
|
||||
&cg.farplane_color[0],
|
||||
&cg.farplane_color[1],
|
||||
&cg.farplane_color[2]
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -444,8 +444,8 @@ void CG_AddTreadMarks()
|
||||
}
|
||||
|
||||
int CG_PermanentMark(
|
||||
vec_t* origin,
|
||||
vec_t* dir,
|
||||
const vec3_t origin,
|
||||
const vec3_t dir,
|
||||
float orientation,
|
||||
float fSScale,
|
||||
float fTScale,
|
||||
|
||||
@@ -956,7 +956,7 @@ void CG_ModelAnim(centity_t* cent, qboolean bDoShaderTime)
|
||||
VectorCopy(model.origin, cg.sky_origin);
|
||||
}
|
||||
|
||||
model.reType = ET_MODELANIM_SKEL;
|
||||
model.reType = RT_MODEL;
|
||||
if (!(s1->renderfx & RF_DONTDRAW))
|
||||
{
|
||||
cgi.R_Model_GetHandle(model.hModel);
|
||||
|
||||
+467
-6
@@ -64,7 +64,7 @@ static void CG_MakeBulletHole(vec3_t i_vPos, vec3_t i_vNorm, int iLarge, trace_t
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
static void CG_MakeBubbleTrail(vec3_t i_vStart, vec3_t i_vEnd, int iLarge)
|
||||
static void CG_MakeBubbleTrail(vec3_t i_vStart, vec3_t i_vEnd, int iLarge, float alpha = 1.0f)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
@@ -79,7 +79,7 @@ static void CG_MakeBulletTracerInternal(vec3_t i_vBarrel, vec3_t i_vStart, vec3_
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
static void CG_MakeBulletTracer(vec3_t i_vBarrel, vec3_t i_vStart, vec3_t* i_vEnd, int i_iNumBullets, qboolean iLarge, int iTracerVisible, qboolean bIgnoreEntities) {
|
||||
static void CG_MakeBulletTracer(vec3_t i_vBarrel, vec3_t i_vStart, vec3_t* i_vEnd, int i_iNumBullets, qboolean iLarge, int iTracerVisible, qboolean bIgnoreEntities, float alpha = 1.0f) {
|
||||
bullet_tracer_t* bullet_tracer;
|
||||
int i;
|
||||
|
||||
@@ -306,6 +306,463 @@ void CG_MakeVehicleEffect(vec3_t i_vStart, vec3_t i_vEnd , vec3_t i_vDir) {
|
||||
cgi.R_DebugLine(vFrom, trace.endpos, 1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
|
||||
void CG_ParseCGMessage()
|
||||
{
|
||||
int i;
|
||||
int iType;
|
||||
int iLarge;
|
||||
int iInfo;
|
||||
int iCount;
|
||||
char* szTmp;
|
||||
vec3_t vStart, vEnd, vTmp;
|
||||
vec3_t vEndArray[MAX_IMPACTS];
|
||||
float alpha;
|
||||
int value;
|
||||
|
||||
qboolean bMoreCGameMessages = qtrue;
|
||||
while (bMoreCGameMessages) {
|
||||
iType = cgi.MSG_ReadBits(6);
|
||||
|
||||
switch (iType)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 5:
|
||||
if (iType == 1)
|
||||
{
|
||||
vTmp[0] = cgi.MSG_ReadCoord();
|
||||
vTmp[1] = cgi.MSG_ReadCoord();
|
||||
vTmp[2] = cgi.MSG_ReadCoord();
|
||||
}
|
||||
vStart[0] = cgi.MSG_ReadCoord();
|
||||
vStart[1] = cgi.MSG_ReadCoord();
|
||||
vStart[2] = cgi.MSG_ReadCoord();
|
||||
|
||||
if (iType != 1)
|
||||
{
|
||||
vTmp[0] = vStart[0];
|
||||
vTmp[1] = vStart[1];
|
||||
vTmp[2] = vStart[2];
|
||||
}
|
||||
|
||||
vEndArray[0][0] = cgi.MSG_ReadCoord();
|
||||
vEndArray[0][1] = cgi.MSG_ReadCoord();
|
||||
vEndArray[0][2] = cgi.MSG_ReadCoord();
|
||||
iLarge = cgi.MSG_ReadBits(2);
|
||||
if (cgi.MSG_ReadBits(1)) {
|
||||
int iAlpha = cgi.MSG_ReadBits(10);
|
||||
alpha = (float)iAlpha / 512.0;
|
||||
if (alpha < 0.002) {
|
||||
alpha = 0.002;
|
||||
}
|
||||
} else {
|
||||
alpha = 1.0f;
|
||||
}
|
||||
|
||||
if (iType == 1) {
|
||||
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha);
|
||||
}
|
||||
else if (iType == 2) {
|
||||
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha);
|
||||
}
|
||||
else {
|
||||
CG_MakeBubbleTrail(vStart, vEndArray[0], iLarge, alpha);
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
if (iType == 3)
|
||||
{
|
||||
vTmp[0] = cgi.MSG_ReadCoord();
|
||||
vTmp[1] = cgi.MSG_ReadCoord();
|
||||
vTmp[2] = cgi.MSG_ReadCoord();
|
||||
iInfo = cgi.MSG_ReadBits(6);
|
||||
}
|
||||
else
|
||||
{
|
||||
iInfo = 0;
|
||||
}
|
||||
|
||||
vStart[0] = cgi.MSG_ReadCoord();
|
||||
vStart[1] = cgi.MSG_ReadCoord();
|
||||
vStart[2] = cgi.MSG_ReadCoord();
|
||||
iLarge = cgi.MSG_ReadBits(2);
|
||||
if (cgi.MSG_ReadBits(1)) {
|
||||
int iAlpha = cgi.MSG_ReadBits(10);
|
||||
alpha = (float)iAlpha / 512.0;
|
||||
if (alpha < 0.002) {
|
||||
alpha = 0.002;
|
||||
}
|
||||
} else {
|
||||
alpha = 1.0f;
|
||||
}
|
||||
|
||||
iCount = cgi.MSG_ReadBits(6);
|
||||
for (i = 0; i < iCount; ++i)
|
||||
{
|
||||
vEndArray[i][0] = cgi.MSG_ReadCoord();
|
||||
vEndArray[i][1] = cgi.MSG_ReadCoord();
|
||||
vEndArray[i][2] = cgi.MSG_ReadCoord();
|
||||
}
|
||||
|
||||
if (iCount) {
|
||||
CG_MakeBulletTracer(vTmp, vStart, vEndArray, iCount, iLarge, iInfo, qtrue, alpha);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
vStart[0] = cgi.MSG_ReadCoord();
|
||||
vStart[1] = cgi.MSG_ReadCoord();
|
||||
vStart[2] = cgi.MSG_ReadCoord();
|
||||
cgi.MSG_ReadDir(vEnd);
|
||||
iLarge = cgi.MSG_ReadBits(2);
|
||||
|
||||
switch (iType)
|
||||
{
|
||||
case 6:
|
||||
if (wall_impact_count < MAX_IMPACTS)
|
||||
{
|
||||
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
|
||||
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
|
||||
wall_impact_large[wall_impact_count] = iLarge;
|
||||
wall_impact_type[wall_impact_count] = -1;
|
||||
wall_impact_count++;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (wall_impact_count < MAX_IMPACTS)
|
||||
{
|
||||
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
|
||||
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
|
||||
wall_impact_large[wall_impact_count] = iLarge;
|
||||
wall_impact_type[wall_impact_count] = 6;
|
||||
wall_impact_count++;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (flesh_impact_count < MAX_IMPACTS)
|
||||
{
|
||||
// negative
|
||||
VectorNegate(vEnd, vEnd);
|
||||
VectorCopy(vStart, flesh_impact_pos[flesh_impact_count]);
|
||||
VectorCopy(vEnd, flesh_impact_norm[flesh_impact_count]);
|
||||
flesh_impact_large[flesh_impact_count] = iLarge;
|
||||
flesh_impact_count++;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
if (flesh_impact_count < MAX_IMPACTS)
|
||||
{
|
||||
// negative
|
||||
VectorNegate(vEnd, vEnd);
|
||||
VectorCopy(vStart, flesh_impact_pos[flesh_impact_count]);
|
||||
VectorCopy(vEnd, flesh_impact_norm[flesh_impact_count]);
|
||||
flesh_impact_large[flesh_impact_count] = iLarge;
|
||||
flesh_impact_count++;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (wall_impact_count < MAX_IMPACTS)
|
||||
{
|
||||
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
|
||||
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
|
||||
wall_impact_large[wall_impact_count] = iLarge;
|
||||
wall_impact_type[wall_impact_count] = 2;
|
||||
wall_impact_count++;
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
if (wall_impact_count < MAX_IMPACTS)
|
||||
{
|
||||
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
|
||||
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
|
||||
wall_impact_large[wall_impact_count] = iLarge;
|
||||
wall_impact_type[wall_impact_count] = 4;
|
||||
wall_impact_count++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case 12:
|
||||
vStart[0] = cgi.MSG_ReadCoord();
|
||||
vStart[1] = cgi.MSG_ReadCoord();
|
||||
vStart[2] = cgi.MSG_ReadCoord();
|
||||
vEnd[0] = cgi.MSG_ReadCoord();
|
||||
vEnd[1] = cgi.MSG_ReadCoord();
|
||||
vEnd[2] = cgi.MSG_ReadCoord();
|
||||
CG_MeleeImpact(vStart, vEnd);
|
||||
break;
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
vStart[0] = cgi.MSG_ReadCoord();
|
||||
vStart[1] = cgi.MSG_ReadCoord();
|
||||
vStart[2] = cgi.MSG_ReadCoord();
|
||||
CG_MakeExplosionEffect(vStart, iType);
|
||||
break;
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
case 25:
|
||||
vStart[0] = cgi.MSG_ReadCoord();
|
||||
vStart[1] = cgi.MSG_ReadCoord();
|
||||
vStart[2] = cgi.MSG_ReadCoord();
|
||||
cgi.MSG_ReadDir(vEnd);
|
||||
|
||||
sfxManager.MakeEffect_Normal(iType + 67, vStart, vEnd);
|
||||
break;
|
||||
|
||||
case 26:
|
||||
case 27:
|
||||
{
|
||||
str sEffect;
|
||||
char cTmp[8];
|
||||
vec3_t axis[3];
|
||||
|
||||
vStart[0] = cgi.MSG_ReadCoord();
|
||||
vStart[1] = cgi.MSG_ReadCoord();
|
||||
vStart[2] = cgi.MSG_ReadCoord();
|
||||
iLarge = cgi.MSG_ReadByte();
|
||||
// get the integer as string
|
||||
snprintf(cTmp, sizeof(cTmp), "%d", iLarge);
|
||||
|
||||
if (iType == 23) {
|
||||
sEffect = "models/fx/crates/debris_";
|
||||
}
|
||||
else {
|
||||
sEffect = "models/fx/windows/debris_";
|
||||
}
|
||||
|
||||
sEffect += cTmp;
|
||||
sEffect += ".tik";
|
||||
|
||||
VectorSet(axis[0], 0, 0, 1);
|
||||
VectorSet(axis[1], 0, 1, 0);
|
||||
VectorSet(axis[2], 1, 0, 0);
|
||||
|
||||
cgi.R_SpawnEffectModel(sEffect.c_str(), vStart, axis);
|
||||
}
|
||||
break;
|
||||
|
||||
case 28:
|
||||
vTmp[0] = cgi.MSG_ReadCoord();
|
||||
vTmp[1] = cgi.MSG_ReadCoord();
|
||||
vTmp[2] = cgi.MSG_ReadCoord();
|
||||
vStart[0] = cgi.MSG_ReadCoord();
|
||||
vStart[1] = cgi.MSG_ReadCoord();
|
||||
vStart[2] = cgi.MSG_ReadCoord();
|
||||
vEndArray[0][0] = cgi.MSG_ReadCoord();
|
||||
vEndArray[0][1] = cgi.MSG_ReadCoord();
|
||||
vEndArray[0][2] = cgi.MSG_ReadCoord();
|
||||
iLarge = cgi.MSG_ReadBits(2);
|
||||
if (cgi.MSG_ReadBits(1)) {
|
||||
int iAlpha = cgi.MSG_ReadBits(10);
|
||||
alpha = (float)iAlpha / 512.0;
|
||||
if (alpha < 0.002) {
|
||||
alpha = 0.002;
|
||||
}
|
||||
} else {
|
||||
alpha = 1.0f;
|
||||
}
|
||||
|
||||
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qtrue, qtrue, alpha);
|
||||
break;
|
||||
|
||||
case 29:
|
||||
memset(vTmp, 0, sizeof(vTmp));
|
||||
vStart[0] = cgi.MSG_ReadCoord();
|
||||
vStart[1] = cgi.MSG_ReadCoord();
|
||||
vStart[2] = cgi.MSG_ReadCoord();
|
||||
vEndArray[0][0] = cgi.MSG_ReadCoord();
|
||||
vEndArray[0][1] = cgi.MSG_ReadCoord();
|
||||
vEndArray[0][2] = cgi.MSG_ReadCoord();
|
||||
iLarge = cgi.MSG_ReadBits(1);
|
||||
if (cgi.MSG_ReadBits(1)) {
|
||||
int iAlpha = cgi.MSG_ReadBits(10);
|
||||
alpha = (float)iAlpha / 512.0;
|
||||
if (alpha < 0.002) {
|
||||
alpha = 0.002;
|
||||
}
|
||||
} else {
|
||||
alpha = 1.0f;
|
||||
}
|
||||
|
||||
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha);
|
||||
break;
|
||||
|
||||
case 30:
|
||||
iInfo = cgi.MSG_ReadByte();
|
||||
strcpy(cgi.HudDrawElements[iInfo].shaderName, cgi.MSG_ReadString());
|
||||
cgi.HudDrawElements[iInfo].string[0] = 0;
|
||||
cgi.HudDrawElements[iInfo].pFont = NULL;
|
||||
cgi.HudDrawElements[iInfo].fontName[0] = 0;
|
||||
// set the shader
|
||||
CG_HudDrawShader(iInfo);
|
||||
break;
|
||||
|
||||
case 31:
|
||||
iInfo = cgi.MSG_ReadByte();
|
||||
cgi.HudDrawElements[iInfo].iHorizontalAlign = cgi.MSG_ReadBits(2);
|
||||
cgi.HudDrawElements[iInfo].iVerticalAlign = cgi.MSG_ReadBits(2);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
iInfo = cgi.MSG_ReadByte();
|
||||
cgi.HudDrawElements[iInfo].iX = cgi.MSG_ReadShort();
|
||||
cgi.HudDrawElements[iInfo].iY = cgi.MSG_ReadShort();
|
||||
cgi.HudDrawElements[iInfo].iWidth = cgi.MSG_ReadShort();
|
||||
cgi.HudDrawElements[iInfo].iHeight = cgi.MSG_ReadShort();
|
||||
break;
|
||||
|
||||
case 33:
|
||||
iInfo = cgi.MSG_ReadByte();
|
||||
cgi.HudDrawElements[iInfo].bVirtualScreen = cgi.MSG_ReadBits(1);
|
||||
break;
|
||||
|
||||
case 34:
|
||||
iInfo = cgi.MSG_ReadByte();
|
||||
cgi.HudDrawElements[iInfo].vColor[0] = cgi.MSG_ReadByte() / 255.0;
|
||||
cgi.HudDrawElements[iInfo].vColor[1] = cgi.MSG_ReadByte() / 255.0;
|
||||
cgi.HudDrawElements[iInfo].vColor[2] = cgi.MSG_ReadByte() / 255.0;
|
||||
break;
|
||||
|
||||
case 35:
|
||||
iInfo = cgi.MSG_ReadByte();
|
||||
cgi.HudDrawElements[iInfo].vColor[3] = cgi.MSG_ReadByte() / 255.0;
|
||||
break;
|
||||
|
||||
case 36:
|
||||
iInfo = cgi.MSG_ReadByte();
|
||||
cgi.HudDrawElements[iInfo].hShader = 0;
|
||||
strcpy(cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString());
|
||||
break;
|
||||
|
||||
case 37:
|
||||
iInfo = cgi.MSG_ReadByte();
|
||||
strcpy(cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString());
|
||||
cgi.HudDrawElements[iInfo].hShader = 0;
|
||||
cgi.HudDrawElements[iInfo].shaderName[0] = 0;
|
||||
// load the font
|
||||
CG_HudDrawFont(iInfo);
|
||||
break;
|
||||
|
||||
case 38:
|
||||
case 39:
|
||||
{
|
||||
int iOldEnt;
|
||||
|
||||
iOldEnt = current_entity_number;
|
||||
current_entity_number = cg.snap->ps.clientNum;
|
||||
if (iType == 36) {
|
||||
commandManager.PlaySound(
|
||||
"dm_kill_notify",
|
||||
NULL,
|
||||
CHAN_LOCAL,
|
||||
2.0,
|
||||
-1,
|
||||
-1,
|
||||
1
|
||||
);
|
||||
}
|
||||
else {
|
||||
commandManager.PlaySound(
|
||||
"dm_hit_notify",
|
||||
NULL,
|
||||
CHAN_LOCAL,
|
||||
2.0,
|
||||
-1,
|
||||
-1,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
current_entity_number = iOldEnt;
|
||||
}
|
||||
break;
|
||||
|
||||
case 40:
|
||||
{
|
||||
int iOldEnt;
|
||||
|
||||
vStart[0] = cgi.MSG_ReadCoord();
|
||||
vStart[1] = cgi.MSG_ReadCoord();
|
||||
vStart[2] = cgi.MSG_ReadCoord();
|
||||
iLarge = cgi.MSG_ReadBits(1);
|
||||
iInfo = cgi.MSG_ReadBits(6);
|
||||
szTmp = cgi.MSG_ReadString();
|
||||
|
||||
iOldEnt = current_entity_number;
|
||||
|
||||
if (iLarge) {
|
||||
current_entity_number = iInfo;
|
||||
|
||||
commandManager.PlaySound(
|
||||
szTmp,
|
||||
vStart,
|
||||
CHAN_LOCAL,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
0
|
||||
);
|
||||
}
|
||||
else {
|
||||
current_entity_number = cg.snap->ps.clientNum;
|
||||
|
||||
commandManager.PlaySound(
|
||||
szTmp,
|
||||
vStart,
|
||||
CHAN_AUTO,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
current_entity_number = iOldEnt;
|
||||
}
|
||||
break;
|
||||
case 41:
|
||||
vStart[0] = cgi.MSG_ReadCoord();
|
||||
vStart[1] = cgi.MSG_ReadCoord();
|
||||
vStart[2] = cgi.MSG_ReadCoord();
|
||||
vEnd[0] = cgi.MSG_ReadCoord();
|
||||
vEnd[1] = cgi.MSG_ReadCoord();
|
||||
vEnd[2] = cgi.MSG_ReadCoord();
|
||||
cgi.MSG_ReadByte();
|
||||
cgi.MSG_ReadByte();
|
||||
VectorSubtract(vEnd, vStart, vTmp);
|
||||
|
||||
// FIXME: unimplemented
|
||||
// ?? can't figure out what is this
|
||||
break;
|
||||
default:
|
||||
cgi.Error(ERR_DROP, "CG_ParseCGMessage: Unknown CGM message type");
|
||||
break;
|
||||
}
|
||||
|
||||
bMoreCGameMessages = cgi.MSG_ReadBits(1);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void CG_ParseCGMessage()
|
||||
{
|
||||
int i;
|
||||
@@ -580,13 +1037,15 @@ void CG_ParseCGMessage()
|
||||
cgi.HudDrawElements[iInfo].bVirtualScreen = cgi.MSG_ReadBits(1);
|
||||
break;
|
||||
|
||||
case 31:
|
||||
case 31:
|
||||
iInfo = cgi.MSG_ReadByte();
|
||||
cgi.HudDrawElements[iInfo].vColor[0] = cgi.MSG_ReadByte() / 255.0;
|
||||
cgi.HudDrawElements[iInfo].vColor[1] = cgi.MSG_ReadByte() / 255.0;
|
||||
cgi.HudDrawElements[iInfo].vColor[2] = cgi.MSG_ReadByte() / 255.0;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
case 32:
|
||||
iInfo = cgi.MSG_ReadByte();
|
||||
cgi.HudDrawElements[iInfo].vColor[3] = cgi.MSG_ReadByte() / 255.0;
|
||||
break;
|
||||
|
||||
@@ -682,10 +1141,12 @@ void CG_ParseCGMessage()
|
||||
current_entity_number = iOldEnt;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cgi.Error(ERR_DROP, "CG_ParseCGMessage: Unknown CGM message type");
|
||||
break;
|
||||
}
|
||||
|
||||
bMoreCGameMessages = cgi.MSG_ReadBits(1);
|
||||
}
|
||||
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
#endif
|
||||
@@ -25,6 +25,58 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
#include "cg_local.h"
|
||||
|
||||
static const char* IsWeaponAllowed(int dmFlags, int flags) {
|
||||
return (dmFlags & flags) ? "0" : "1";
|
||||
}
|
||||
|
||||
static qboolean QueryLandminesAllowed2(const char* mapname, int dmflags) {
|
||||
if (dmflags & DF_WEAPON_NO_LANDMINE) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
if (dmflags & DF_WEAPON_LANDMINE_ALWAYS) {
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (!Q_stricmpn(mapname, "obj/obj_", 8u))
|
||||
return qfalse;
|
||||
if (!Q_stricmpn(mapname, "dm/mohdm", 8u))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "DM/MP_Bahnhof_DM"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "obj/MP_Ardennes_TOW"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "DM/MP_Bazaar_DM"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "obj/MP_Berlin_TOW"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "DM/MP_Brest_DM"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "obj/MP_Druckkammern_TOW"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "DM/MP_Gewitter_DM"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "obj/MP_Flughafen_TOW"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "DM/MP_Holland_DM"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "DM/MP_Malta_DM"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "DM/MP_Stadt_DM"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "DM/MP_Unterseite_DM"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "DM/MP_Verschneit_DM"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "lib/mp_ship_lib"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "DM/MP_Verschneit_DM"))
|
||||
return qfalse;
|
||||
if (!Q_stricmp(mapname, "lib/mp_ship_lib"))
|
||||
return qfalse;
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_ParseServerinfo
|
||||
@@ -39,6 +91,7 @@ void CG_ParseServerinfo(void)
|
||||
const char* mapname;
|
||||
char map[MAX_QPATH];
|
||||
char* spawnpos;
|
||||
const char* version;
|
||||
|
||||
info = CG_ConfigString(CS_SERVERINFO);
|
||||
cgs.gametype = atoi(Info_ValueForKey(info, "g_gametype"));
|
||||
@@ -48,6 +101,13 @@ void CG_ParseServerinfo(void)
|
||||
cgs.timelimit = atoi(Info_ValueForKey(info, "timelimit"));
|
||||
cgs.maxclients = atoi(Info_ValueForKey(info, "sv_maxclients"));
|
||||
|
||||
version = Info_ValueForKey(info, "version");
|
||||
if (strstr(version, "Spearhead")) {
|
||||
cgi.Cvar_Set("g_servertype", "1");
|
||||
} else {
|
||||
cgi.Cvar_Set("g_servertype", "2");
|
||||
}
|
||||
|
||||
cgi.Cvar_Set("cg_gametype", Info_ValueForKey(info, "g_gametype"));
|
||||
cgi.Cvar_Set("cg_fraglimit", Info_ValueForKey(info, "fraglimit"));
|
||||
cgi.Cvar_Set("cg_timelimit", Info_ValueForKey(info, "timelimit"));
|
||||
@@ -60,9 +120,18 @@ void CG_ParseServerinfo(void)
|
||||
cgi.Cvar_Set("cg_obj_axistext3", Info_ValueForKey(info, "cg_obj_axistext3"));
|
||||
cgi.Cvar_Set("cg_scoreboardpic", Info_ValueForKey(info, "g_scoreboardpic"));
|
||||
cgi.Cvar_Set("cg_scoreboardpicover", Info_ValueForKey(info, "g_scoreboardpicover"));
|
||||
cgs.mapChecksum = Info_ValueForKey(info, "sv_mapChecksum");
|
||||
|
||||
mapname = Info_ValueForKey(info, "mapname");
|
||||
|
||||
cgi.Cvar_Set("cg_weapon_rifle", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_RIFLE));
|
||||
cgi.Cvar_Set("cg_weapon_sniper", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_SNIPER));
|
||||
cgi.Cvar_Set("cg_weapon_mg", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_MG));
|
||||
cgi.Cvar_Set("cg_weapon_smg", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_SMG));
|
||||
cgi.Cvar_Set("cg_weapon_rocket", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_ROCKET));
|
||||
cgi.Cvar_Set("cg_weapon_shotgun", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_SHOTGUN));
|
||||
cgi.Cvar_Set("cg_weapon_landmine", QueryLandminesAllowed2(mapname, cgs.dmflags) ? "1" : "0");
|
||||
|
||||
spawnpos = strchr(mapname, '$');
|
||||
if (spawnpos) {
|
||||
Q_strncpyz(map, mapname, spawnpos - mapname + 1);
|
||||
@@ -152,7 +221,7 @@ CG_Stopwatch_f
|
||||
*/
|
||||
static void CG_Stopwatch_f()
|
||||
{
|
||||
if (cgi.Argc() != 3) {
|
||||
if (cgi.Argc() < 3) {
|
||||
Com_Error(1, "stopwatch didn't have 2 parameters");
|
||||
}
|
||||
|
||||
|
||||
+179
-12
@@ -46,7 +46,40 @@ static const char* AnimPrefixList[] =
|
||||
"bazooka",
|
||||
"panzerschreck",
|
||||
"shotgun",
|
||||
"unarmed"
|
||||
"unarmed",
|
||||
//
|
||||
// Team Assault and Team Tactics weapons
|
||||
"mg42portable",
|
||||
"webley",
|
||||
"nagantrev",
|
||||
"beretta",
|
||||
"enfield",
|
||||
"svt",
|
||||
"mosin",
|
||||
"g43",
|
||||
"enfieldl42a1",
|
||||
"carcano",
|
||||
"delisle",
|
||||
"thompson",
|
||||
"sten",
|
||||
"ppsh",
|
||||
"moschetto",
|
||||
"fg42",
|
||||
"vickers",
|
||||
"breda",
|
||||
"f1grenade",
|
||||
"millsgrenade",
|
||||
"nebelhandgranate",
|
||||
"m18smokegrenade",
|
||||
"rdg1smokegrenade",
|
||||
"bomba",
|
||||
"bombabreda",
|
||||
"mine",
|
||||
"minedetector",
|
||||
"minedetectoraxis",
|
||||
"detonator",
|
||||
"kar98mortar",
|
||||
"PIAT"
|
||||
};
|
||||
|
||||
enum animPrefix_e
|
||||
@@ -69,7 +102,39 @@ enum animPrefix_e
|
||||
WPREFIX_BAZOOKA,
|
||||
WPREFIX_PANZERSCHRECK,
|
||||
WPREFIX_SHOTGUN,
|
||||
WPREFIX_UNARMED
|
||||
WPREFIX_UNARMED,
|
||||
//
|
||||
// Team Assault and Team Tactics weapons
|
||||
WPREFIX_MG42_PORTABLE,
|
||||
WPREFIX_WEBLEY,
|
||||
WPREFIX_NAGANTREV,
|
||||
WPREFIX_BERETTA,
|
||||
WPREFIX_ENFIELD,
|
||||
WPREFIX_SVT,
|
||||
WPREFIX_MOSIN,
|
||||
WPREFIX_G43,
|
||||
WPREFIX_ENFIELDL42A,
|
||||
WPREFIX_CARCANO,
|
||||
WPREFIX_DELISLE,
|
||||
WPREFIX_STEN,
|
||||
WPREFIX_PPSH,
|
||||
WPREFIX_MOSCHETTO,
|
||||
WPREFIX_FG42,
|
||||
WPREFIX_VICKERS,
|
||||
WPREFIX_BREDA,
|
||||
WPREFIX_F1_GRENADE,
|
||||
WPREFIX_MILLS_GRENADE,
|
||||
WPREFIX_NEBELHANDGRANATE,
|
||||
WPREFIX_M18_SMOKE_GRENADE,
|
||||
WPREFIX_RDG1_SMOKE_GRENADE,
|
||||
WPREFIX_BOMBA,
|
||||
WPREFIX_BOMBA_BREDA,
|
||||
WPREFIX_MINE,
|
||||
WPREFIX_MINE_DETECTOR,
|
||||
WPREFIX_MINE_DETECTOR_AXIS,
|
||||
WPREFIX_DETONATOR,
|
||||
WPREFIX_KAR98_MORTAR,
|
||||
WPREFIX_PIAT
|
||||
};
|
||||
|
||||
int CG_GetVMAnimPrefixIndex()
|
||||
@@ -83,7 +148,9 @@ int CG_GetVMAnimPrefixIndex()
|
||||
if (iWeaponClass & WEAPON_CLASS_ANY_ITEM)
|
||||
{
|
||||
if (!Q_stricmp(szWeaponName, "Papers"))
|
||||
return WPREFIX_PAPERS;
|
||||
return WPREFIX_PAPERS;
|
||||
if (!Q_stricmp(szWeaponName, "Packed MG42 Turret"))
|
||||
return WPREFIX_MG42_PORTABLE;
|
||||
}
|
||||
else if (iWeaponClass & WEAPON_CLASS_PISTOL)
|
||||
{
|
||||
@@ -92,7 +159,19 @@ int CG_GetVMAnimPrefixIndex()
|
||||
if (!Q_stricmp(szWeaponName, "Walther P38"))
|
||||
return WPREFIX_P38;
|
||||
if (!Q_stricmp(szWeaponName, "Hi-Standard Silenced"))
|
||||
return WPREFIX_HISTANDARD;
|
||||
return WPREFIX_HISTANDARD;
|
||||
|
||||
//
|
||||
// Team Assault and Team Tactics
|
||||
//
|
||||
if (!Q_stricmp(szWeaponName, "Webley Revolver"))
|
||||
return WPREFIX_WEBLEY;
|
||||
if (!Q_stricmp(szWeaponName, "Nagant Revolver"))
|
||||
return WPREFIX_NAGANTREV;
|
||||
if (!Q_stricmp(szWeaponName, "Beretta"))
|
||||
return WPREFIX_BERETTA;
|
||||
|
||||
return WPREFIX_COLT45;
|
||||
}
|
||||
else if (iWeaponClass & WEAPON_CLASS_RIFLE)
|
||||
{
|
||||
@@ -103,28 +182,97 @@ int CG_GetVMAnimPrefixIndex()
|
||||
if (!Q_stricmp(szWeaponName, "KAR98 - Sniper"))
|
||||
return WPREFIX_KAR98SNIPER;
|
||||
if (!Q_stricmp(szWeaponName, "Springfield '03 Sniper"))
|
||||
return WPREFIX_SPRINGFIELD;
|
||||
return WPREFIX_SPRINGFIELD;
|
||||
|
||||
//
|
||||
// Team Assault and Team Tactics
|
||||
//
|
||||
if (!Q_stricmp(szWeaponName, "Lee-Enfield"))
|
||||
return WPREFIX_SPRINGFIELD;
|
||||
if (!Q_stricmp(szWeaponName, "SVT 40"))
|
||||
return WPREFIX_SVT;
|
||||
if (!Q_stricmp(szWeaponName, "Mosin Nagant Rifle"))
|
||||
return WPREFIX_MOSIN;
|
||||
if (!Q_stricmp(szWeaponName, "G 43"))
|
||||
return WPREFIX_G43;
|
||||
if (!Q_stricmp(szWeaponName, "Enfield L42A1"))
|
||||
return WPREFIX_ENFIELD;
|
||||
if (!Q_stricmp(szWeaponName, "Carcano"))
|
||||
return WPREFIX_CARCANO;
|
||||
if (!Q_stricmp(szWeaponName, "DeLisle"))
|
||||
return WPREFIX_DELISLE;
|
||||
|
||||
return WPREFIX_GARAND;
|
||||
}
|
||||
else if (iWeaponClass & WEAPON_CLASS_SMG)
|
||||
{
|
||||
if (!Q_stricmp(szWeaponName, "Thompson"))
|
||||
return WPREFIX_THOMPSON;
|
||||
if (!Q_stricmp(szWeaponName, "MP40"))
|
||||
return WPREFIX_MP40;
|
||||
return WPREFIX_MP40;
|
||||
//
|
||||
// Team Assault and Team Tactics
|
||||
//
|
||||
if (!Q_stricmp(szWeaponName, "Sten Mark II"))
|
||||
return WPREFIX_STEN;
|
||||
if (!Q_stricmp(szWeaponName, "PPSH SMG"))
|
||||
return WPREFIX_PPSH;
|
||||
if (!Q_stricmp(szWeaponName, "Moschetto"))
|
||||
return WPREFIX_MOSCHETTO;
|
||||
|
||||
return WPREFIX_THOMPSON;
|
||||
}
|
||||
else if (iWeaponClass & WEAPON_CLASS_MG)
|
||||
{
|
||||
if (!Q_stricmp(szWeaponName, "BAR"))
|
||||
return WPREFIX_BAR;
|
||||
if (!Q_stricmp(szWeaponName, "StG 44"))
|
||||
return WPREFIX_MP44;
|
||||
return WPREFIX_MP44;
|
||||
//
|
||||
// Team Assault and Team Tactics
|
||||
//
|
||||
if (!Q_stricmp(szWeaponName, "FG 42"))
|
||||
return WPREFIX_MP44;
|
||||
if (!Q_stricmp(szWeaponName, "Vickers-Berthier"))
|
||||
return WPREFIX_MP44;
|
||||
if (!Q_stricmp(szWeaponName, "Breda"))
|
||||
return WPREFIX_MP44;
|
||||
|
||||
return WPREFIX_BAR;
|
||||
}
|
||||
else if (iWeaponClass & WEAPON_CLASS_GRENADE)
|
||||
{
|
||||
if (!Q_stricmp(szWeaponName, "Frag Grenade"))
|
||||
return WPREFIX_FRAGGRENADE;
|
||||
if (!Q_stricmp(szWeaponName, "Stielhandgranate"))
|
||||
return WPREFIX_STIELHANDGRANATE;
|
||||
return WPREFIX_STIELHANDGRANATE;
|
||||
//
|
||||
// Team Assault and Team Tactics
|
||||
//
|
||||
if (!Q_stricmp(szWeaponName, "F1 Grenade"))
|
||||
return WPREFIX_F1_GRENADE;
|
||||
if (!Q_stricmp(szWeaponName, "Mills Grenade"))
|
||||
return WPREFIX_MILLS_GRENADE;
|
||||
if (!Q_stricmp(szWeaponName, "Nebelhandgranate"))
|
||||
return WPREFIX_NEBELHANDGRANATE;
|
||||
if (!Q_stricmp(szWeaponName, "M18 Smoke Grenade"))
|
||||
return WPREFIX_M18_SMOKE_GRENADE;
|
||||
if (!Q_stricmp(szWeaponName, "RDG-1 Smoke Grenade"))
|
||||
return WPREFIX_RDG1_SMOKE_GRENADE;
|
||||
if (!Q_stricmp(szWeaponName, "Bomba A Mano"))
|
||||
return WPREFIX_BOMBA;
|
||||
if (!Q_stricmp(szWeaponName, "Bomba A Mano Breda"))
|
||||
return WPREFIX_BOMBA_BREDA;
|
||||
if (!Q_stricmp(szWeaponName, "LandmineAllies"))
|
||||
return WPREFIX_MINE;
|
||||
if (!Q_stricmp(szWeaponName, "LandmineAxis"))
|
||||
return WPREFIX_MINE;
|
||||
if (!Q_stricmp(szWeaponName, "Minensuchgerat"))
|
||||
return WPREFIX_MINE_DETECTOR_AXIS;
|
||||
if (!Q_stricmp(szWeaponName, "Minedetector"))
|
||||
return WPREFIX_MINE_DETECTOR;
|
||||
|
||||
return WPREFIX_FRAGGRENADE;
|
||||
}
|
||||
else if (iWeaponClass & WEAPON_CLASS_HEAVY)
|
||||
{
|
||||
@@ -133,7 +281,14 @@ int CG_GetVMAnimPrefixIndex()
|
||||
if (!Q_stricmp(szWeaponName, "Panzerschreck"))
|
||||
return WPREFIX_PANZERSCHRECK;
|
||||
if (!Q_stricmp(szWeaponName, "Shotgun"))
|
||||
return WPREFIX_SHOTGUN;
|
||||
return WPREFIX_SHOTGUN;
|
||||
//
|
||||
// Team Assault and Team Tactics
|
||||
//
|
||||
if (!Q_stricmp(szWeaponName, "PIAT"))
|
||||
return WPREFIX_PIAT;
|
||||
|
||||
return WPREFIX_BAZOOKA;
|
||||
}
|
||||
|
||||
return WPREFIX_UNARMED;
|
||||
@@ -226,10 +381,22 @@ void CG_ViewModelAnimation(refEntity_t* pModel)
|
||||
case VM_ANIM_LADDERSTEP:
|
||||
pszAnimSuffix = "ladderstep";
|
||||
break;
|
||||
case VM_ANIM_IDLE:
|
||||
case VM_ANIM_IDLE_0:
|
||||
pszAnimSuffix = "idle0";
|
||||
break;
|
||||
case VM_ANIM_IDLE_1:
|
||||
pszAnimSuffix = "idle1";
|
||||
break;
|
||||
case VM_ANIM_IDLE_2:
|
||||
pszAnimSuffix = "idle2";
|
||||
break;
|
||||
case VM_ANIM_DISABLED:
|
||||
pszAnimSuffix = "disabled";
|
||||
break;
|
||||
default:
|
||||
pszAnimSuffix = "idle";
|
||||
break;
|
||||
case VM_ANIM_IDLE:
|
||||
pszAnimSuffix = "idle";
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(szAnimName, "%s_%s", AnimPrefixList[iAnimPrefixIndex], pszAnimSuffix);
|
||||
|
||||
@@ -145,18 +145,23 @@ void VSS_AddRepulsion(cvssource_t* pA, cvssource_t* pB)
|
||||
|
||||
cvssource_t* ClientGameCommandManager::AllocateVSSSource()
|
||||
{
|
||||
m_free_vsssources = m_free_vsssources;
|
||||
cvssource_t* pNew;
|
||||
|
||||
if (!m_free_vsssources) {
|
||||
FreeVSSSource(m_active_vsssources.prev);
|
||||
}
|
||||
|
||||
pNew = m_free_vsssources;
|
||||
m_free_vsssources = m_free_vsssources->next;
|
||||
memset(m_free_vsssources, 0, sizeof(cvssource_t));
|
||||
memset(pNew, 0, sizeof(cvssource_t));
|
||||
|
||||
m_free_vsssources->next = m_active_vsssources.next;
|
||||
m_free_vsssources->prev = &m_active_vsssources;
|
||||
pNew->next = m_active_vsssources.next;
|
||||
pNew->prev = &m_active_vsssources;
|
||||
|
||||
m_active_vsssources.next->prev = m_free_vsssources;
|
||||
m_active_vsssources.next = m_free_vsssources;
|
||||
m_active_vsssources.next->prev = pNew;
|
||||
m_active_vsssources.next = pNew;
|
||||
|
||||
return m_free_vsssources;
|
||||
return pNew;
|
||||
}
|
||||
|
||||
void ClientGameCommandManager::FreeVSSSource(cvssource_t* p)
|
||||
@@ -201,7 +206,7 @@ void ClientGameCommandManager::ResetVSSSources()
|
||||
}
|
||||
|
||||
m_vsssources = (cvssource_t*)cgi.Malloc(sizeof(cvssource_t) * m_iAllocatedvsssources);
|
||||
memset(m_vsssources, 0, sizeof(sizeof(cvssource_t) * m_iAllocatedvsssources));
|
||||
memset(m_vsssources, 0, sizeof(cvssource_t) * m_iAllocatedvsssources);
|
||||
|
||||
m_active_vsssources.next = &m_active_vsssources;
|
||||
m_active_vsssources.prev = &m_active_vsssources;
|
||||
|
||||
@@ -34,6 +34,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
// refdef flags
|
||||
#define RDF_NOWORLDMODEL 1 // used for player configuration screen
|
||||
#define RDF_FULLBRIGHT 2 // fullbright intensity
|
||||
#define RDF_HYPERSPACE 4 // teleportation effect
|
||||
|
||||
typedef struct
|
||||
|
||||
+65
-21
@@ -158,6 +158,10 @@ CL_GetSnapshot
|
||||
qboolean CL_GetSnapshot( int snapshotNumber, snapshot_t *snapshot ) {
|
||||
clSnapshot_t *clSnap;
|
||||
int i, count;
|
||||
int pnum;
|
||||
int parents[MAX_ENTITIES_IN_SNAPSHOT];
|
||||
entityState_t *s1;
|
||||
int pcount = 0;
|
||||
|
||||
if ( snapshotNumber > cl.snap.messageNum ) {
|
||||
Com_Error( ERR_DROP, "CL_GetSnapshot: snapshotNumber > cl.snapshot.messageNum" );
|
||||
@@ -187,41 +191,81 @@ qboolean CL_GetSnapshot( int snapshotNumber, snapshot_t *snapshot ) {
|
||||
snapshot->serverTime = clSnap->serverTime;
|
||||
Com_Memcpy( snapshot->areamask, clSnap->areamask, sizeof( snapshot->areamask ) );
|
||||
snapshot->ps = clSnap->ps;
|
||||
|
||||
// wombat: sounds
|
||||
count = clSnap->number_of_sounds;
|
||||
if (snapshot->number_of_sounds > MAX_SERVER_SOUNDS) {
|
||||
Com_DPrintf("CL_GetSnapshot: truncated %i sounds to %i\n", count, MAX_SERVER_SOUNDS);
|
||||
count = MAX_SERVER_SOUNDS;
|
||||
}
|
||||
|
||||
snapshot->number_of_sounds = count;
|
||||
Com_Memcpy(snapshot->sounds, clSnap->sounds, sizeof(snapshot->sounds[0])* count);
|
||||
|
||||
count = clSnap->numEntities;
|
||||
if ( count > MAX_ENTITIES_IN_SNAPSHOT ) {
|
||||
Com_DPrintf( "CL_GetSnapshot: truncated %i visible entities to %i\n", count, MAX_ENTITIES_IN_SNAPSHOT );
|
||||
count = MAX_ENTITIES_IN_SNAPSHOT;
|
||||
}
|
||||
snapshot->numEntities = count;
|
||||
|
||||
snapshot->numEntities = 0;
|
||||
for ( i = 0 ; i < count ; i++ ) {
|
||||
snapshot->entities[i] =
|
||||
cl.parseEntities[ ( clSnap->parseEntitiesNum + i ) & (MAX_PARSE_ENTITIES-1) ];
|
||||
s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + i) & (MAX_PARSE_ENTITIES - 1)];
|
||||
pnum = s1->parent;
|
||||
|
||||
if (pnum == ENTITYNUM_NONE) {
|
||||
parents[s1->number] = -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parents[pnum] == -2) {
|
||||
parents[s1->number] = -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// add it later
|
||||
parents[s1->number] = pnum;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
snapshot->entities[snapshot->numEntities++] = *s1;
|
||||
}
|
||||
|
||||
// wombat: sounds
|
||||
count = clSnap->number_of_sounds;
|
||||
if ( snapshot->number_of_sounds > MAX_SERVER_SOUNDS) {
|
||||
Com_DPrintf( "CL_GetSnapshot: truncated %i sounds to %i\n", count, MAX_SERVER_SOUNDS);
|
||||
count = MAX_SERVER_SOUNDS;
|
||||
for(pcount = 0; pcount < 8 && snapshot->numEntities != count; pcount++)
|
||||
{
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + i) & (MAX_PARSE_ENTITIES - 1)];
|
||||
pnum = parents[s1->number];
|
||||
if (pnum >= 0 && parents[pnum] == -2) {
|
||||
snapshot->entities[snapshot->numEntities++] = *s1;
|
||||
}
|
||||
}
|
||||
}
|
||||
snapshot->number_of_sounds = count;
|
||||
Com_Memcpy( snapshot->sounds, clSnap->sounds, sizeof(snapshot->sounds[0])*count );
|
||||
|
||||
// FIXME: configstring changes and server commands!!!
|
||||
if (pcount >= 8)
|
||||
{
|
||||
for (i = count; i < snapshot->numEntities; i++)
|
||||
{
|
||||
s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + i) & (MAX_PARSE_ENTITIES - 1)];
|
||||
if (parents[s1->number] >= 0) {
|
||||
Com_DPrintf(
|
||||
"CL_GetSnapshot: entity %d with parent %d and model '%s' at %.2f %.2f %.2f, could not find parent.\n",
|
||||
s1->number,
|
||||
s1->parent,
|
||||
CL_ConfigString(CS_MODELS + s1->modelindex),
|
||||
s1->origin[0],
|
||||
s1->origin[1],
|
||||
s1->origin[2]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
CL_SetUserCmdValue
|
||||
=====================
|
||||
*/
|
||||
void CL_SetUserCmdValue( int userCmdValue, float sensitivityScale ) {
|
||||
cl.cgameUserCmdValue = userCmdValue;
|
||||
cl.cgameSensitivity = sensitivityScale;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
CL_AddCgameCommand
|
||||
|
||||
@@ -1142,17 +1142,17 @@ redump:
|
||||
case ZA_SOUND_MONO:
|
||||
if (!cinTable[currentHandle].silent) {
|
||||
ssize = RllDecodeMonoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
|
||||
S_RawSamples(0, ssize, 22050, 2, 1, (byte *)sbuf, 1.0f, -1);
|
||||
S_RawSamples(0, 22050, 2, 1, (byte *)sbuf, 1.0f);
|
||||
}
|
||||
break;
|
||||
case ZA_SOUND_STEREO:
|
||||
if (!cinTable[currentHandle].silent) {
|
||||
if (cinTable[currentHandle].numQuads == -1) {
|
||||
S_Update();
|
||||
s_rawend[0] = s_soundtime;
|
||||
s_rawend = s_soundtime;
|
||||
}
|
||||
ssize = RllDecodeStereoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
|
||||
S_RawSamples(0, ssize, 22050, 2, 2, (byte *)sbuf, 1.0f, -1);
|
||||
S_RawSamples(0, 22050, 2, 2, (byte *)sbuf, 1.0f);
|
||||
}
|
||||
break;
|
||||
case ROQ_QUAD_INFO:
|
||||
@@ -1469,7 +1469,7 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi
|
||||
}
|
||||
|
||||
if (!cinTable[currentHandle].silent) {
|
||||
s_rawend[0] = s_soundtime;
|
||||
s_rawend = s_soundtime;
|
||||
}
|
||||
|
||||
return currentHandle;
|
||||
|
||||
+20
-10
@@ -566,7 +566,7 @@ CL_CmdButtons
|
||||
*/
|
||||
void CL_CmdButtons( usercmd_t *cmd ) {
|
||||
int i;
|
||||
|
||||
|
||||
//
|
||||
// figure button bits
|
||||
// send a button bit even if the key was pressed and released in
|
||||
@@ -579,18 +579,28 @@ void CL_CmdButtons( usercmd_t *cmd ) {
|
||||
in_buttons[i].wasPressed = qfalse;
|
||||
}
|
||||
|
||||
// if ( Key_GetCatcher( ) ) {
|
||||
// cmd->buttons |= BUTTON_TALK; // su44: is there a TALK button in MoHAA?
|
||||
// }
|
||||
if (UI_MenuActive() || UI_ConsoleIsOpen()) {
|
||||
cmd->buttons |= BUTTON_TALK;
|
||||
}
|
||||
|
||||
if (in_speed.active == !cl_run->integer) {
|
||||
cmd->buttons |= BUTTON_RUN;
|
||||
}
|
||||
|
||||
if (cge) {
|
||||
// send weapon commands from cg
|
||||
cmd->buttons |= cge->CG_WeaponCommandButtonBits();
|
||||
}
|
||||
|
||||
// allow the game to know if any key at all is
|
||||
// currently pressed, even if it isn't bound to anything
|
||||
if ( anykeydown && Key_GetCatcher( ) == 0 ) {
|
||||
cmd->buttons |= BUTTON_ANY;
|
||||
if ( anykeydown && Key_GetCatcher() == 0) {
|
||||
cmd->buttons |= BUTTON_ANY2;
|
||||
}
|
||||
|
||||
// su44: add weapon command bits
|
||||
cmd->buttons |= cl.cgameUserCmdValue;
|
||||
if (anykeydown) {
|
||||
cmd->buttons |= BUTTON_ANY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -855,7 +865,7 @@ void CL_WritePacket( void ) {
|
||||
for ( i = clc.reliableAcknowledge + 1 ; i <= clc.reliableSequence ; i++ ) {
|
||||
MSG_WriteByte( &buf, clc_clientCommand );
|
||||
MSG_WriteLong( &buf, i );
|
||||
MSG_WriteString( &buf, clc.reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
|
||||
MSG_WriteScrambledString( &buf, clc.reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
|
||||
}
|
||||
|
||||
// we want to send all the usercmds that were generated in the last
|
||||
@@ -924,7 +934,7 @@ void CL_WritePacket( void ) {
|
||||
clc.lastPacketSentTime = cls.realtime;
|
||||
|
||||
if ( cl_showSend->integer ) {
|
||||
Com_Printf( "%i ", buf.cursize );
|
||||
Com_Printf( "%zu ", buf.cursize );
|
||||
}
|
||||
|
||||
CL_Netchan_Transmit (&clc.netchan, &buf);
|
||||
|
||||
+15
-145
@@ -29,14 +29,10 @@ key up events are sent even if in console mode
|
||||
|
||||
*/
|
||||
|
||||
field_t historyEditLines[COMMAND_HISTORY];
|
||||
|
||||
int nextHistoryLine; // the last line in the history buffer, not masked
|
||||
int historyLine; // the line being displayed from history buffer
|
||||
// will be <= nextHistoryLine
|
||||
|
||||
field_t g_consoleField;
|
||||
field_t chatField;
|
||||
qboolean chat_team;
|
||||
|
||||
int chat_playerNum;
|
||||
@@ -55,8 +51,8 @@ qboolean alt_down;
|
||||
qboolean ctrl_down;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int keynum;
|
||||
const char *name;
|
||||
int keynum;
|
||||
} keyname_t;
|
||||
|
||||
|
||||
@@ -470,7 +466,7 @@ void Key_SetCtrlBinding( int keynum, const char *binding ) {
|
||||
Key_GetBinding
|
||||
===================
|
||||
*/
|
||||
char *Key_GetBinding( int keynum ) {
|
||||
const char *Key_GetBinding( int keynum ) {
|
||||
if ( keynum < 0 || keynum >= K_LASTKEY ) {
|
||||
return "";
|
||||
}
|
||||
@@ -525,7 +521,7 @@ Key_GetKeysForCommand
|
||||
void Key_GetKeysForCommand( const char *command, int *key1, int *key2 ) {
|
||||
int i;
|
||||
|
||||
*key1 = *key2 = 0;
|
||||
*key1 = *key2 = -1;
|
||||
|
||||
for( i = 0; i < K_LASTKEY; i++ ) {
|
||||
if( !keys[ i ].binding ) {
|
||||
@@ -951,7 +947,13 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
|
||||
ctrl_down = down;
|
||||
}
|
||||
|
||||
if( cls.state > CA_DISCONNECTED && cge && !cls.keyCatchers && cge->CG_CheckCaptureKey( key, down, time ) && key != K_ESCAPE )
|
||||
if (down && !CL_FinishedIntro())
|
||||
{
|
||||
UI_StartStageKeyEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
if( cls.state > CA_DISCONNECTED && cge && !Key_GetCatcher() && cge->CG_CheckCaptureKey( key, down, time ) && key != K_ESCAPE )
|
||||
{
|
||||
if( key != '`' && key != '~' )
|
||||
return;
|
||||
@@ -962,6 +964,7 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
|
||||
if( !down ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( Cvar_VariableIntegerValue( "ui_console" ) )
|
||||
{
|
||||
UI_ToggleConsole();
|
||||
@@ -1015,10 +1018,10 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
|
||||
}
|
||||
}
|
||||
|
||||
if( in_guimouse || key <= K_MOUSE3 || key > K_JOY1 )
|
||||
if (!in_guimouse || key <= K_MOUSE3 || key > K_JOY1)
|
||||
{
|
||||
// keys can still be used for bound actions
|
||||
if( down && ( key < 128 || key == K_MOUSE4 ) &&
|
||||
if (down && (key <= K_BACKSPACE || key == K_MOUSE4) &&
|
||||
( clc.demoplaying || cls.state == CA_CINEMATIC ) && Key_GetCatcher() == 0 ) {
|
||||
Cvar_Set( "nextdemo", "" );
|
||||
key = K_ESCAPE;
|
||||
@@ -1061,7 +1064,7 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
|
||||
UI_KeyEvent( key, time );
|
||||
} else if( cls.loading & KEYCATCH_MESSAGE ) {
|
||||
Message_Key( key );
|
||||
} else if( cls.state != CA_DISCONNECTED ) {
|
||||
} else if( cls.state != CA_DISCONNECTED || menubound[key]) {
|
||||
// send the bound action
|
||||
kb = altkeys[ key ].binding;
|
||||
if( !kb || !altkeys[ key ].down ) {
|
||||
@@ -1198,136 +1201,3 @@ Key_SetCatcher
|
||||
void Key_SetCatcher( int catcher ) {
|
||||
keyCatchers = catcher;
|
||||
}
|
||||
|
||||
// This must not exceed MAX_CMD_LINE
|
||||
#define MAX_CONSOLE_SAVE_BUFFER 1024
|
||||
#define CONSOLE_HISTORY_FILE "omhistory"
|
||||
static char consoleSaveBuffer[ MAX_CONSOLE_SAVE_BUFFER ];
|
||||
static int consoleSaveBufferSize = 0;
|
||||
|
||||
/*
|
||||
================
|
||||
CL_LoadConsoleHistory
|
||||
|
||||
Load the console history from cl_consoleHistory
|
||||
================
|
||||
*/
|
||||
void CL_LoadConsoleHistory( void )
|
||||
{
|
||||
const char *token;
|
||||
char *text_p;
|
||||
int i, numChars, numLines = 0;
|
||||
fileHandle_t f;
|
||||
|
||||
consoleSaveBufferSize = FS_FOpenFileRead( CONSOLE_HISTORY_FILE, &f, qfalse, qtrue );
|
||||
if( !f )
|
||||
{
|
||||
Com_Printf( "Couldn't read %s.\n", CONSOLE_HISTORY_FILE );
|
||||
return;
|
||||
}
|
||||
|
||||
if( consoleSaveBufferSize <= MAX_CONSOLE_SAVE_BUFFER &&
|
||||
FS_Read( consoleSaveBuffer, consoleSaveBufferSize, f ) == consoleSaveBufferSize )
|
||||
{
|
||||
text_p = consoleSaveBuffer;
|
||||
|
||||
for( i = COMMAND_HISTORY - 1; i >= 0; i-- )
|
||||
{
|
||||
if( !*( token = COM_Parse( &text_p ) ) )
|
||||
break;
|
||||
|
||||
historyEditLines[ i ].cursor = atoi( token );
|
||||
|
||||
if( !*( token = COM_Parse( &text_p ) ) )
|
||||
break;
|
||||
|
||||
historyEditLines[ i ].scroll = atoi( token );
|
||||
|
||||
if( !*( token = COM_Parse( &text_p ) ) )
|
||||
break;
|
||||
|
||||
numChars = atoi( token );
|
||||
text_p++;
|
||||
if( numChars > ( strlen( consoleSaveBuffer ) - ( text_p - consoleSaveBuffer ) ) )
|
||||
{
|
||||
Com_DPrintf( S_COLOR_YELLOW "WARNING: probable corrupt history\n" );
|
||||
break;
|
||||
}
|
||||
Com_Memcpy( historyEditLines[ i ].buffer,
|
||||
text_p, numChars );
|
||||
historyEditLines[ i ].buffer[ numChars ] = '\0';
|
||||
text_p += numChars;
|
||||
|
||||
numLines++;
|
||||
}
|
||||
|
||||
memmove( &historyEditLines[ 0 ], &historyEditLines[ i + 1 ],
|
||||
numLines * sizeof( field_t ) );
|
||||
for( i = numLines; i < COMMAND_HISTORY; i++ )
|
||||
Field_Clear( &historyEditLines[ i ] );
|
||||
|
||||
historyLine = nextHistoryLine = numLines;
|
||||
}
|
||||
else
|
||||
Com_Printf( "Couldn't read %s.\n", CONSOLE_HISTORY_FILE );
|
||||
|
||||
FS_FCloseFile( f );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_SaveConsoleHistory
|
||||
|
||||
Save the console history into the cvar cl_consoleHistory
|
||||
so that it persists across invocations of q3
|
||||
================
|
||||
*/
|
||||
void CL_SaveConsoleHistory( void )
|
||||
{
|
||||
int i;
|
||||
int lineLength, saveBufferLength, additionalLength;
|
||||
fileHandle_t f;
|
||||
|
||||
consoleSaveBuffer[ 0 ] = '\0';
|
||||
|
||||
i = ( nextHistoryLine - 1 ) % COMMAND_HISTORY;
|
||||
do
|
||||
{
|
||||
if( historyEditLines[ i ].buffer[ 0 ] )
|
||||
{
|
||||
lineLength = strlen( historyEditLines[ i ].buffer );
|
||||
saveBufferLength = strlen( consoleSaveBuffer );
|
||||
|
||||
//ICK
|
||||
additionalLength = lineLength + strlen( "999 999 999 " );
|
||||
|
||||
if( saveBufferLength + additionalLength < MAX_CONSOLE_SAVE_BUFFER )
|
||||
{
|
||||
Q_strcat( consoleSaveBuffer, MAX_CONSOLE_SAVE_BUFFER,
|
||||
va( "%d %d %d %s ",
|
||||
historyEditLines[ i ].cursor,
|
||||
historyEditLines[ i ].scroll,
|
||||
lineLength,
|
||||
historyEditLines[ i ].buffer ) );
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
i = ( i - 1 + COMMAND_HISTORY ) % COMMAND_HISTORY;
|
||||
}
|
||||
while( i != ( nextHistoryLine - 1 ) % COMMAND_HISTORY );
|
||||
|
||||
consoleSaveBufferSize = strlen( consoleSaveBuffer );
|
||||
|
||||
f = FS_FOpenFileWrite( CONSOLE_HISTORY_FILE );
|
||||
if( !f )
|
||||
{
|
||||
Com_Printf( "Couldn't write %s.\n", CONSOLE_HISTORY_FILE );
|
||||
return;
|
||||
}
|
||||
|
||||
if( FS_Write( consoleSaveBuffer, consoleSaveBufferSize, f ) < consoleSaveBufferSize )
|
||||
Com_Printf( "Couldn't write %s.\n", CONSOLE_HISTORY_FILE );
|
||||
|
||||
FS_FCloseFile( f );
|
||||
}
|
||||
+49
-23
@@ -32,6 +32,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "../sys/sys_loadlib.h"
|
||||
#endif
|
||||
|
||||
#include "gcdkeyc.h"
|
||||
|
||||
cvar_t *cl_nodelta;
|
||||
cvar_t *cl_debugMove;
|
||||
|
||||
@@ -1421,6 +1423,10 @@ void CL_ResetPureClientAtServer( void ) {
|
||||
CL_AddReliableCommand( va("vdr") );
|
||||
}
|
||||
|
||||
qboolean CL_Allowed_Vid_Restart() {
|
||||
return cls.state == CA_DISCONNECTED || cls.state == CA_ACTIVE;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_Vid_Restart_f
|
||||
@@ -1432,33 +1438,30 @@ because the renderer doesn't know what graphics to reload
|
||||
=================
|
||||
*/
|
||||
void CL_Vid_Restart_f( void ) {
|
||||
|
||||
// Settings may have changed so stop recording now
|
||||
if( CL_VideoRecording( ) ) {
|
||||
CL_CloseAVI( );
|
||||
if (!CL_Allowed_Vid_Restart()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(clc.demorecording)
|
||||
CL_StopRecord_f();
|
||||
Com_Printf("-------- CL_Vid_Restart_f --------\n");
|
||||
cls.vid_restart = qtrue;
|
||||
|
||||
// don't let them loop during the restart
|
||||
S_StopAllSounds( qtrue );
|
||||
S_StopAllSounds(qtrue);
|
||||
|
||||
SV_ClearSvsTimeFixups();
|
||||
|
||||
S_BeginRegistration();
|
||||
|
||||
// shutdown the renderer and clear the renderer interface
|
||||
CL_ShutdownRef();
|
||||
// shutdown the CGame
|
||||
CL_ShutdownCGame();
|
||||
// initialize the renderer interface
|
||||
CL_InitRef();
|
||||
// client is no longer pure untill new checksums are sent
|
||||
CL_ResetPureClientAtServer();
|
||||
// clear pak references
|
||||
FS_ClearPakReferences( FS_UI_REF | FS_CGAME_REF );
|
||||
// reinitialize the filesystem if the game directory or checksum has changed
|
||||
FS_ConditionalRestart( clc.checksumFeed );
|
||||
// initialize the ui library
|
||||
UI_ResolutionChange();
|
||||
|
||||
cls.rendererRegistered = qfalse;
|
||||
cls.uiStarted = qfalse;
|
||||
cls.cgameStarted = qfalse;
|
||||
|
||||
// unpause so the cgame definately gets a snapshot and renders a frame
|
||||
Com_Unpause();
|
||||
@@ -1469,6 +1472,8 @@ void CL_Vid_Restart_f( void ) {
|
||||
|
||||
S_Init();
|
||||
|
||||
cls.vid_restart = qfalse;
|
||||
Com_Printf("----- finished CL_Vid_Restart_f ----\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1776,6 +1781,7 @@ void CL_CheckForResend( void ) {
|
||||
int port, i;
|
||||
char info[MAX_INFO_STRING];
|
||||
char data[MAX_INFO_STRING];
|
||||
char buf[1024];
|
||||
|
||||
// don't send anything if playing back a demo
|
||||
if ( clc.demoplaying ) {
|
||||
@@ -1804,7 +1810,11 @@ void CL_CheckForResend( void ) {
|
||||
// }
|
||||
NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "getchallenge");
|
||||
break;
|
||||
|
||||
case CA_AUTHORIZING:
|
||||
// resend the cd key authorization
|
||||
gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_REAUTH);
|
||||
NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "authorizeThis %s", cls.gcdResponse);
|
||||
break;
|
||||
case CA_CHALLENGING:
|
||||
/*
|
||||
wombat: sending conect here: an example connect string from MOHAA looks like this:
|
||||
@@ -1817,7 +1827,11 @@ wombat: sending conect here: an example connect string from MOHAA looks like thi
|
||||
Q_strncpyz( info, Cvar_InfoString( CVAR_USERINFO ), sizeof( info ) );
|
||||
Info_SetValueForKey( info, "protocol", va("%i", PROTOCOL_VERSION ) );
|
||||
Info_SetValueForKey( info, "qport", va("%i", port ) );
|
||||
Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) );
|
||||
Info_SetValueForKey(info, "challenge", va("%i", clc.challenge));
|
||||
Info_SetValueForKey(info, "version", TARGET_GAME_VERSION);
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
Info_SetValueForKey(info, "clientType", "Breakthrough");
|
||||
#endif
|
||||
|
||||
strcpy(data, "connect ");
|
||||
// TTimo adding " " around the userinfo string to avoid truncated userinfo on the server
|
||||
@@ -2076,7 +2090,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
||||
|
||||
// challenge from the server we are connecting to
|
||||
if ( !Q_stricmp(c, "challengeResponse") ) {
|
||||
if ( cls.state != CA_CONNECTING ) {
|
||||
if ( cls.state != CA_CONNECTING && cls.state != CA_AUTHORIZING ) {
|
||||
Com_Printf( "Unwanted challenge response received. Ignored.\n" );
|
||||
} else {
|
||||
// start sending challenge repsonse instead of challenge request packets
|
||||
@@ -2141,8 +2155,12 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
||||
}
|
||||
|
||||
// cd check
|
||||
if ( !Q_stricmp(c, "keyAuthorize") ) {
|
||||
// we don't use these now, so dump them on the floor
|
||||
if ( !Q_stricmp(c, "getKey") ) {
|
||||
char buf[1024];
|
||||
|
||||
cls.state = CA_AUTHORIZING;
|
||||
gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_NEWAUTH);
|
||||
NET_OutOfBandPrint(NS_CLIENT, from, "authorizeThis %s", cls.gcdResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3294,7 +3312,7 @@ CL_ServerInfoPacket
|
||||
void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) {
|
||||
int i, type;
|
||||
char info[MAX_INFO_STRING];
|
||||
char* str;
|
||||
const char* str;
|
||||
char *infoString;
|
||||
int prot;
|
||||
|
||||
@@ -3490,7 +3508,7 @@ CL_ServerStatusResponse
|
||||
===================
|
||||
*/
|
||||
void CL_ServerStatusResponse( netadr_t from, msg_t *msg ) {
|
||||
char *s;
|
||||
const char *s;
|
||||
char info[MAX_INFO_STRING];
|
||||
int i, l, score, ping;
|
||||
int len;
|
||||
@@ -3583,7 +3601,7 @@ CL_LocalServers_f
|
||||
==================
|
||||
*/
|
||||
void CL_LocalServers_f( void ) {
|
||||
char *message;
|
||||
const char *message;
|
||||
int i, j;
|
||||
netadr_t to;
|
||||
|
||||
@@ -4307,4 +4325,12 @@ qboolean CL_CDKeyValidate( const char *key, const char *checksum ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
void TIKI_CG_Command_ProcessFile(char* filename, qboolean quiet, dtiki_t* curTiki)
|
||||
{
|
||||
if (cge) {
|
||||
cge->CG_Command_ProcessFile(filename, quiet, curTiki);
|
||||
return;
|
||||
}
|
||||
|
||||
Com_Printf("NO CGE \n");
|
||||
}
|
||||
+38
-17
@@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "client.h"
|
||||
#include "cl_ui.h"
|
||||
|
||||
char *svc_strings[256] = {
|
||||
const char *svc_strings[256] = {
|
||||
"svc_bad",
|
||||
|
||||
"svc_nop",
|
||||
@@ -41,7 +41,7 @@ char *svc_strings[256] = {
|
||||
|
||||
msg_t *cl_currentMSG;
|
||||
|
||||
void SHOWNET( msg_t *msg, char *s) {
|
||||
void SHOWNET( msg_t *msg, const char *s) {
|
||||
if ( cl_shownet->integer >= 2) {
|
||||
Com_Printf ("%3i:%s\n", msg->readcount-1, s);
|
||||
}
|
||||
@@ -75,8 +75,7 @@ void CL_DeltaEntity (msg_t *msg, clSnapshot_t *frame, int newnum, entityState_t
|
||||
if ( unchanged ) {
|
||||
*state = *old;
|
||||
} else {
|
||||
// FIXME: frametime
|
||||
MSG_ReadDeltaEntity( msg, old, state, newnum, 0.0);
|
||||
MSG_ReadDeltaEntity( msg, old, state, newnum, cls.serverFrameTime);
|
||||
}
|
||||
|
||||
if ( state->number == (MAX_GENTITIES-1) ) {
|
||||
@@ -117,7 +116,7 @@ void CL_ParsePacketEntities( msg_t *msg, clSnapshot_t *oldframe, clSnapshot_t *n
|
||||
|
||||
while ( 1 ) {
|
||||
// read the entity index number
|
||||
newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
|
||||
newnum = MSG_ReadEntityNum(msg);
|
||||
|
||||
if ( newnum == (MAX_GENTITIES-1) ) {
|
||||
break;
|
||||
@@ -274,11 +273,10 @@ void CL_ParseSnapshot( msg_t *msg ) {
|
||||
|
||||
// read playerinfo
|
||||
SHOWNET(msg, "playerstate");
|
||||
// FIXME: frametime
|
||||
if ( old ) {
|
||||
MSG_ReadDeltaPlayerstate( msg, &old->ps, &newSnap.ps, 0.0 );
|
||||
MSG_ReadDeltaPlayerstate( msg, &old->ps, &newSnap.ps, cls.serverFrameTime );
|
||||
} else {
|
||||
MSG_ReadDeltaPlayerstate( msg, NULL, &newSnap.ps, 0.0);
|
||||
MSG_ReadDeltaPlayerstate( msg, NULL, &newSnap.ps, cls.serverFrameTime);
|
||||
}
|
||||
|
||||
// read packet entities
|
||||
@@ -446,6 +444,28 @@ static void CL_ParseServerInfo(void)
|
||||
sizeof(clc.sv_dlURL));
|
||||
}
|
||||
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
|
||||
char* MSG_ReadGameStateChar(msg_t* msg) {
|
||||
return MSG_ReadScrambledBigString(msg);
|
||||
}
|
||||
|
||||
float MSG_ReadServerFrameTime(msg_t* msg) {
|
||||
return MSG_ReadFloat(msg);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
char* MSG_ReadGameStateChar(msg_t* msg) {
|
||||
return MSG_ReadString(msg);
|
||||
}
|
||||
|
||||
float MSG_ReadServerFrameTime(msg_t* msg) {
|
||||
return 1.f / atof(Info_ValueForKey(cl.gameState.stringData + cl.gameState.stringOffsets[CS_SYSTEMINFO], "sv_fps"));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_ParseGamestate
|
||||
@@ -488,7 +508,7 @@ void CL_ParseGamestate( msg_t *msg ) {
|
||||
if ( i < 0 || i >= MAX_CONFIGSTRINGS ) {
|
||||
Com_Error( ERR_DROP, "configstring > MAX_CONFIGSTRINGS" );
|
||||
}
|
||||
s = MSG_ReadString( msg );
|
||||
s = MSG_ReadGameStateChar( msg );
|
||||
len = strlen( s );
|
||||
|
||||
if ( len + 1 + cl.gameState.dataCount > MAX_GAMESTATE_CHARS ) {
|
||||
@@ -499,7 +519,7 @@ void CL_ParseGamestate( msg_t *msg ) {
|
||||
Com_Memcpy( cl.gameState.stringData + cl.gameState.dataCount, s, len + 1 );
|
||||
cl.gameState.dataCount += len + 1;
|
||||
} else if ( cmd == svc_baseline ) {
|
||||
newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
|
||||
newnum = MSG_ReadEntityNum(msg);
|
||||
if ( newnum < 0 || newnum >= MAX_GENTITIES ) {
|
||||
Com_Error( ERR_DROP, "Baseline number out of range: %i", newnum );
|
||||
}
|
||||
@@ -516,6 +536,7 @@ void CL_ParseGamestate( msg_t *msg ) {
|
||||
clc.clientNum = MSG_ReadLong(msg);
|
||||
// read the checksum feed
|
||||
clc.checksumFeed = MSG_ReadLong( msg );
|
||||
cls.serverFrameTime = MSG_ReadServerFrameTime(msg);
|
||||
|
||||
// parse serverId and other cvars
|
||||
CL_SystemInfoChanged();
|
||||
@@ -527,6 +548,7 @@ void CL_ParseGamestate( msg_t *msg ) {
|
||||
// reinitialize the filesystem if the game directory has changed
|
||||
FS_ConditionalRestart( clc.checksumFeed );
|
||||
|
||||
cls.state = CA_LOADING;
|
||||
if (!com_sv_running->integer)
|
||||
{
|
||||
const char *info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_SERVERINFO];
|
||||
@@ -726,7 +748,7 @@ void CL_ParseCommandString( msg_t *msg ) {
|
||||
int index;
|
||||
|
||||
seq = MSG_ReadLong( msg );
|
||||
s = MSG_ReadString( msg );
|
||||
s = MSG_ReadScrambledString( msg );
|
||||
|
||||
// see if we have already executed stored it off
|
||||
if ( clc.serverCommandSequence >= seq ) {
|
||||
@@ -763,10 +785,9 @@ void CL_ParseLocationprint( msg_t *msg ) {
|
||||
|
||||
x = MSG_ReadShort( msg );
|
||||
y = MSG_ReadShort( msg );
|
||||
string = MSG_ReadString(msg);
|
||||
string = MSG_ReadScrambledString(msg);
|
||||
|
||||
// FIXME
|
||||
//UI_UpdateLocationPrint( x, y, string, 1.0 );
|
||||
UI_UpdateLocationPrint( x, y, string, 1.0 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -777,10 +798,10 @@ CL_ParseCenterprint
|
||||
void CL_ParseCenterprint( msg_t *msg ) {
|
||||
char *string;
|
||||
|
||||
string = MSG_ReadString( msg );
|
||||
string = MSG_ReadScrambledString( msg );
|
||||
|
||||
// FIXME
|
||||
//UI_UpdateCenterPrintf( string, 1.0 );
|
||||
UI_UpdateCenterPrint( string, 1.0 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -792,7 +813,7 @@ void CL_ParseServerMessage( msg_t *msg ) {
|
||||
int cmd;
|
||||
//Com_Printf( "ParseServerMessage: %i\n", msg->cursize );
|
||||
if ( cl_shownet->integer == 1 ) {
|
||||
Com_Printf ("%i ",msg->cursize);
|
||||
Com_Printf ("%zu ",msg->cursize);
|
||||
} else if ( cl_shownet->integer >= 2 ) {
|
||||
Com_Printf ("------------------\n");
|
||||
}
|
||||
|
||||
+92
-73
@@ -877,7 +877,7 @@ Key_GetBindingBuf
|
||||
====================
|
||||
*/
|
||||
static void Key_GetBindingBuf( int keynum, char *buf, int buflen ) {
|
||||
char *value;
|
||||
const char *value;
|
||||
|
||||
value = Key_GetBinding( keynum );
|
||||
if ( value ) {
|
||||
@@ -1119,7 +1119,7 @@ getNewConsole
|
||||
====================
|
||||
*/
|
||||
UIFloatingConsole* getNewConsole() {
|
||||
static constexpr char CONSOLE_NAME[] = PRODUCT_NAME_FULL " - " PRODUCT_VERSION_FULL;
|
||||
static constexpr char CONSOLE_NAME[] = PRODUCT_NAME " console version " PRODUCT_VERSION;
|
||||
|
||||
UIFloatingConsole* console = new UIFloatingConsole;
|
||||
console->Create(NULL, getDefaultConsoleRectangle(), CONSOLE_NAME, UWindowColor, UHudColor);
|
||||
@@ -1881,7 +1881,7 @@ void UI_Update(void) {
|
||||
{
|
||||
UI_ForceMenuOff(true);
|
||||
UI_DeactiveFloatingWindows();
|
||||
UI_ForceMenu("");
|
||||
UI_ForceMenu(ui_sCurrentLoadingMenu);
|
||||
uWinMan.showCursor(false);
|
||||
}
|
||||
|
||||
@@ -3638,8 +3638,8 @@ void UI_WantsKeyboard() {
|
||||
}
|
||||
|
||||
struct widgettrans_s {
|
||||
char *src;
|
||||
char *dst;
|
||||
const char *src;
|
||||
const char *dst;
|
||||
};
|
||||
|
||||
static widgettrans_s s_widgettrans[ 2 ] =
|
||||
@@ -4485,8 +4485,14 @@ ScoreboardListItem::ScoreboardListItem()
|
||||
void ScoreboardListItem::DrawListItem( int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont )
|
||||
{
|
||||
DrawBox( drawRect, backColor, 1.0 );
|
||||
pFont->setColor( textColor );
|
||||
pFont->Print( drawRect.pos.x + 1, drawRect.pos.y, Sys_LV_CL_ConvertString( getListItemString( iColumn ) ), iColumn, -1 );
|
||||
pFont->setColor(textColor);
|
||||
pFont->Print(
|
||||
drawRect.pos.x + 1,
|
||||
drawRect.pos.y,
|
||||
Sys_LV_CL_ConvertString(getListItemString(iColumn)),
|
||||
-1,
|
||||
qfalse
|
||||
);
|
||||
|
||||
if( bTitleItem )
|
||||
{
|
||||
@@ -4588,10 +4594,11 @@ void UI_SetScoreBoardItem( int iItemNumber,
|
||||
{
|
||||
cge->CG_GetScoreBoardPosition( &x, &y, &w, &h );
|
||||
|
||||
if( scoreboard_x == x
|
||||
|| scoreboard_y == y
|
||||
|| scoreboard_w == w
|
||||
|| scoreboard_h == h
|
||||
// Recreate the scoreboard if it has different rect
|
||||
if( scoreboard_x != x
|
||||
|| scoreboard_y != y
|
||||
|| scoreboard_w != w
|
||||
|| scoreboard_h != h
|
||||
|| scoreboard_header != cge->CG_GetScoreBoardDrawHeader() )
|
||||
{
|
||||
delete scoreboardlist;
|
||||
@@ -4606,11 +4613,12 @@ void UI_SetScoreBoardItem( int iItemNumber,
|
||||
|
||||
if( scoreboardlist )
|
||||
{
|
||||
if( iItemNumber + 1 > scoreboardlist->getNumItems() ) {
|
||||
if (iItemNumber + 1 > scoreboardlist->getNumItems()) {
|
||||
pItem = new ScoreboardListItem;
|
||||
scoreboardlist->AddItem( pItem );
|
||||
} else {
|
||||
pItem = ( ScoreboardListItem * )scoreboardlist->GetItem( iItemNumber );
|
||||
scoreboardlist->AddItem(pItem);
|
||||
}
|
||||
else {
|
||||
pItem = (ScoreboardListItem*)scoreboardlist->GetItem(iItemNumber + 1);
|
||||
}
|
||||
|
||||
if( pItem )
|
||||
@@ -4877,7 +4885,7 @@ static void SaveConsoleRectangle( void ) {
|
||||
if( !fakk_console->IsMinimized() ) {
|
||||
r = fakk_console->getFrame();
|
||||
|
||||
Cvar_Set( "ui_consoleposition", va( "%d %d %d %d", r.pos.x, r.pos.y, r.size.width, r.size.height ) );
|
||||
Cvar_Set( "ui_consoleposition", va( "%d %d %d %d", (int)r.pos.x, (int)r.pos.y, (int)r.size.width, (int)r.size.height ) );
|
||||
|
||||
if( wasMinimized ) {
|
||||
fakk_console->ProcessEvent( UIFloatingWindow::W_MinimizePressed );
|
||||
@@ -5484,7 +5492,7 @@ qboolean UI_IsResourceLoaded( const char *name ) {
|
||||
case 104:
|
||||
return TIKI_FindTikiAnim( name + 1 ) != NULL;
|
||||
case 103:
|
||||
return SkeletorCacheFindFilename( name + 1, NULL ) != NULL;
|
||||
return SkeletorCacheFindFilename( name + 1, NULL );
|
||||
case 107:
|
||||
return S_IsSoundRegistered( name + 1 );
|
||||
case 110:
|
||||
@@ -5565,23 +5573,23 @@ UI_LoadResource
|
||||
====================
|
||||
*/
|
||||
void UI_LoadResource( const char *name ) {
|
||||
if( cls.loading == SS_DEAD ) {
|
||||
if (cls.loading == SS_DEAD) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( cls.loading == 3 )
|
||||
if (cls.loading == SS_GAME)
|
||||
{
|
||||
UI_EndLoadResource();
|
||||
UI_EndLoadResource( name );
|
||||
UI_EndLoadResource(name);
|
||||
UI_BeginLoadResource();
|
||||
}
|
||||
else if( cls.loading == 2 )
|
||||
else if (cls.loading == SS_LOADING2)
|
||||
{
|
||||
UI_RegisterLoadResource( name );
|
||||
Cvar_SetValue( "loadingbar", currentLoadTime / totalLoadTime );
|
||||
UI_RegisterLoadResource(name);
|
||||
Cvar_SetValue("loadingbar", (float)currentLoadTime / (float)totalLoadTime);
|
||||
}
|
||||
|
||||
UI_TestUpdateScreen( 333u );
|
||||
UI_TestUpdateScreen(333u);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5746,7 +5754,65 @@ void UI_BeginLoad( const char *pszMapName ) {
|
||||
UI_ForceMenuOff( true );
|
||||
UI_DeactiveFloatingWindows();
|
||||
|
||||
if( !ui_pLoadingMenu )
|
||||
if (ui_pLoadingMenu)
|
||||
{
|
||||
if (!developer->integer && UI_ConsoleIsVisible()) {
|
||||
UI_CloseConsole();
|
||||
}
|
||||
|
||||
ui_pLoadingMenu->PassEventToWidget("continuebutton", new Event(EV_Widget_Disable));
|
||||
|
||||
loadName = "maps/";
|
||||
loadName += pszMapName;
|
||||
loadName += ".min";
|
||||
mapfile = loadName + ".bsp";
|
||||
|
||||
if (UI_ArchiveLoadMapinfo(mapfile)) {
|
||||
cls.loading = SS_LOADING2;
|
||||
}
|
||||
else {
|
||||
cls.loading = SS_GAME;
|
||||
}
|
||||
|
||||
if (cls.loading == SS_LOADING2)
|
||||
{
|
||||
ui_pLoadingMenu->PassEventToWidget("loadingflasher", new Event(EV_Widget_Disable));
|
||||
ui_pLoadingMenu->PassEventToWidget("loadingbar", new Event(EV_Widget_Enable));
|
||||
ui_pLoadingMenu->PassEventToWidget("loadingbar_border", new Event(EV_Widget_Enable));
|
||||
|
||||
currentLoadTime = 0;
|
||||
Cvar_SetValue("loadingbar", 0);
|
||||
|
||||
L_ProcessPendingEvents();
|
||||
|
||||
lastTime = Sys_Milliseconds();
|
||||
if (com_sv_running->integer) {
|
||||
SCR_UpdateScreen();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui_pLoadingMenu->PassEventToWidget("loadingflasher", new Event(EV_Widget_Enable));
|
||||
ui_pLoadingMenu->PassEventToWidget("loadingbar", new Event(EV_Widget_Disable));
|
||||
ui_pLoadingMenu->PassEventToWidget("loadingbar_border", new Event(EV_Widget_Disable));
|
||||
|
||||
UI_BeginLoadResource();
|
||||
loadCountLow = 0;
|
||||
loadCountHigh = 0;
|
||||
loadHead = NULL;
|
||||
loadNumber = 0;
|
||||
|
||||
cls.loading = SS_LOADING;
|
||||
|
||||
L_ProcessPendingEvents();
|
||||
lastTime = Sys_Milliseconds();
|
||||
|
||||
if (com_sv_running->integer) {
|
||||
SCR_UpdateScreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cls.loading = SS_LOADING;
|
||||
|
||||
@@ -5755,56 +5821,9 @@ void UI_BeginLoad( const char *pszMapName ) {
|
||||
|
||||
lastTime = Sys_Milliseconds();
|
||||
|
||||
if( com_sv_running->integer ) {
|
||||
if (com_sv_running->integer) {
|
||||
SCR_UpdateScreen();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( !developer->integer && UI_ConsoleIsVisible() ) {
|
||||
UI_CloseConsole();
|
||||
}
|
||||
|
||||
ui_pLoadingMenu->PassEventToWidget( "continuebutton", new Event( EV_Widget_Disable ) );
|
||||
|
||||
loadName = "maps/";
|
||||
loadName += pszMapName;
|
||||
loadName += ".min";
|
||||
mapfile = loadName + ".bsp";
|
||||
|
||||
if( UI_ArchiveLoadMapinfo( mapfile ) ) {
|
||||
cls.loading = SS_LOADING2;
|
||||
} else {
|
||||
cls.loading = SS_GAME;
|
||||
}
|
||||
|
||||
if( cls.loading != SS_LOADING2 )
|
||||
{
|
||||
ui_pLoadingMenu->PassEventToWidget( "loadingflasher", new Event( EV_Widget_Enable ) );
|
||||
ui_pLoadingMenu->PassEventToWidget( "loadingbar", new Event( EV_Widget_Disable ) );
|
||||
ui_pLoadingMenu->PassEventToWidget( "loadingbar_border", new Event( EV_Widget_Disable ) );
|
||||
|
||||
UI_BeginLoadResource();
|
||||
loadCountLow = 0;
|
||||
loadCountHigh = 0;
|
||||
loadHead = NULL;
|
||||
loadNumber = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui_pLoadingMenu->PassEventToWidget( "loadingflasher", new Event( EV_Widget_Disable ) );
|
||||
ui_pLoadingMenu->PassEventToWidget( "loadingbar", new Event( EV_Widget_Enable ) );
|
||||
ui_pLoadingMenu->PassEventToWidget( "loadingbar_border", new Event( EV_Widget_Enable ) );
|
||||
|
||||
currentLoadTime = 0;
|
||||
Cvar_SetValue( "loadingbar", 0 );
|
||||
}
|
||||
|
||||
L_ProcessPendingEvents();
|
||||
lastTime = Sys_Milliseconds();
|
||||
|
||||
if( com_sv_running->integer ) {
|
||||
SCR_UpdateScreen();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ void CL_ShutdownUI( void );
|
||||
//
|
||||
extern inventory_t client_inv;
|
||||
extern bind_t client_bind;
|
||||
extern cvar_t* cl_greenfps;
|
||||
|
||||
const char *CvarGetForUI( const char *name, const char *defval );
|
||||
void UI_ClearState( void );
|
||||
|
||||
@@ -29,8 +29,8 @@ public:
|
||||
|
||||
SoundPickerClass();
|
||||
|
||||
void FileSelected( str ¤tDirectory, str &partialName, str &fullname );
|
||||
void FileChosen( str ¤tDirectory, str &partialName, str &fullname );
|
||||
void FileSelected( str ¤tDirectory, str &partialName, str &fullname ) override;
|
||||
void FileChosen( str ¤tDirectory, str &partialName, str &fullname ) override;
|
||||
};
|
||||
|
||||
#endif /* __CL_UISOUNDPICKER_H__ */
|
||||
+385
-12
@@ -438,7 +438,178 @@ void UIFakkLabel::LayoutRenderModelAnim( Event *ev )
|
||||
|
||||
void UIFakkLabel::DrawStatbar( float frac )
|
||||
{
|
||||
// FIXME: stub
|
||||
vec4_t col;
|
||||
float alpha;
|
||||
|
||||
col[0] = col[1] = col[2] = col[3] = 1.0;
|
||||
|
||||
switch (m_statbar_or)
|
||||
{
|
||||
case L_STATBAR_CIRCULAR:
|
||||
DrawStatCircle(frac);
|
||||
return;
|
||||
case L_STATBAR_NEEDLE:
|
||||
DrawStatNeedle(frac);
|
||||
return;
|
||||
case L_STATBAR_ROTATOR:
|
||||
DrawStatRotator(frac);
|
||||
return;
|
||||
case L_STATBAR_COMPASS:
|
||||
DrawStatCompass(frac);
|
||||
return;
|
||||
case L_STATBAR_SPINNER:
|
||||
case L_STATBAR_HEADING_SPINNER:
|
||||
DrawStatSpinner(frac);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!frac) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (frac != m_lastfrac) {
|
||||
m_flashtime = uid.time;
|
||||
}
|
||||
m_lastfrac = frac;
|
||||
|
||||
alpha = 1.0 - ((float)uid.time - m_flashtime) / 1500.0;
|
||||
if (alpha < 0.0) alpha = 0.0;
|
||||
else if (alpha > 1.0) alpha = 1.0;
|
||||
|
||||
col[3] = alpha;
|
||||
|
||||
if (m_statbar_material)
|
||||
{
|
||||
if (m_flags & WF_TILESHADER)
|
||||
{
|
||||
switch (m_statbar_or)
|
||||
{
|
||||
case L_STATBAR_HORIZONTAL:
|
||||
{
|
||||
float width = frac * m_frame.size.width;
|
||||
|
||||
m_statbar_material->ReregisterMaterial();
|
||||
re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material->GetMaterial());
|
||||
|
||||
if (alpha != 0.0 && m_statbar_material_flash)
|
||||
{
|
||||
re.SetColor(col);
|
||||
m_statbar_material_flash->ReregisterMaterial();
|
||||
re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material_flash->GetMaterial());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case L_STATBAR_VERTICAL:
|
||||
case L_STATBAR_VERTICAL_REVERSE:
|
||||
case L_STATBAR_VERTICAL_STAGGER_EVEN:
|
||||
case L_STATBAR_VERTICAL_STAGGER_ODD:
|
||||
{
|
||||
float y = m_frame.size.height * (1.0 - frac);
|
||||
|
||||
m_statbar_material->ReregisterMaterial();
|
||||
re.DrawTilePic(0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material->GetMaterial());
|
||||
|
||||
if (alpha != 0.0 && m_statbar_material_flash)
|
||||
{
|
||||
re.SetColor(col);
|
||||
m_statbar_material_flash->ReregisterMaterial();
|
||||
re.DrawTilePic(0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material_flash->GetMaterial());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (m_statbar_or)
|
||||
{
|
||||
case L_STATBAR_HORIZONTAL:
|
||||
{
|
||||
float width = frac * m_frame.size.width;
|
||||
|
||||
m_statbar_material->ReregisterMaterial();
|
||||
re.DrawStretchPic(0.0, 0.0, width, m_frame.size.height, 0.0, 0.0, 1.0, 1.0, m_statbar_material->GetMaterial());
|
||||
|
||||
if(alpha != 0.0 && m_statbar_material_flash)
|
||||
{
|
||||
re.SetColor(col);
|
||||
m_statbar_material_flash->ReregisterMaterial();
|
||||
re.DrawStretchPic(0.0, 0.0, width, m_frame.size.height, 0.0, 0.0, 1.0, 1.0, m_statbar_material_flash->GetMaterial());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case L_STATBAR_VERTICAL:
|
||||
case L_STATBAR_VERTICAL_STAGGER_EVEN:
|
||||
case L_STATBAR_VERTICAL_STAGGER_ODD:
|
||||
{
|
||||
float y = m_frame.size.height * (1.0 - frac);
|
||||
float height = m_frame.size.height * frac;
|
||||
|
||||
m_statbar_material->ReregisterMaterial();
|
||||
re.DrawStretchPic(0.0, y, m_frame.size.width, height, 0.0, 1.0 - frac, 1.0, 1.0, m_statbar_material->GetMaterial());
|
||||
|
||||
if (alpha != 0.0 && m_statbar_material_flash)
|
||||
{
|
||||
re.SetColor(col);
|
||||
m_statbar_material_flash->ReregisterMaterial();
|
||||
re.DrawStretchPic(0.0, y, m_frame.size.width, height, 0.0, 1.0 - frac, 1.0, 1.0, m_statbar_material_flash->GetMaterial());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case L_STATBAR_VERTICAL_REVERSE:
|
||||
{
|
||||
float height = m_frame.size.height * frac;
|
||||
|
||||
m_statbar_material->ReregisterMaterial();
|
||||
re.DrawStretchPic(0.0, 0.0, m_frame.size.width, height, 0.0, 0.0, 1.0, frac, m_statbar_material->GetMaterial());
|
||||
|
||||
if (alpha != 0.0 && m_statbar_material_flash)
|
||||
{
|
||||
re.SetColor(col);
|
||||
m_statbar_material_flash->ReregisterMaterial();
|
||||
re.DrawStretchPic(0.0, 0.0, m_frame.size.width, height, 0.0, 0.0, 1.0, frac, m_statbar_material_flash->GetMaterial());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (m_statbar_or)
|
||||
{
|
||||
case L_STATBAR_VERTICAL:
|
||||
case L_STATBAR_VERTICAL_STAGGER_EVEN:
|
||||
case L_STATBAR_VERTICAL_STAGGER_ODD:
|
||||
DrawBox(
|
||||
0.0,
|
||||
m_frame.size.height * (1.0 - frac),
|
||||
m_frame.size.width,
|
||||
m_frame.size.height,
|
||||
m_foreground_color,
|
||||
1.0
|
||||
);
|
||||
break;
|
||||
case L_STATBAR_HORIZONTAL:
|
||||
DrawBox(
|
||||
0.0,
|
||||
0.0,
|
||||
frac * m_frame.size.width,
|
||||
m_frame.size.height,
|
||||
m_foreground_color,
|
||||
1.0
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIFakkLabel::DrawStatCircle( float frac )
|
||||
@@ -458,7 +629,212 @@ void UIFakkLabel::DrawStatRotator( float frac )
|
||||
|
||||
void UIFakkLabel::DrawStatCompass( float frac )
|
||||
{
|
||||
// FIXME: stub
|
||||
vec4_t col;
|
||||
float fTargAng;
|
||||
float fSinVal, fCosVal;
|
||||
vec2_t vCenter;
|
||||
vec2_t vVerts[3];
|
||||
vec2_t vTexCoords[3];
|
||||
vec2_t vCompassDir;
|
||||
vec2_t vSideDir;
|
||||
|
||||
col[0] = col[1] = col[2] = col[3] = 1.0;
|
||||
|
||||
if (!cge) {
|
||||
return;
|
||||
}
|
||||
|
||||
static int iLastCompassTime = -9999, iLastTimeDelta = 0;
|
||||
static float fLastPitch = 0, fLastYaw = 0, fLastYawDelta = 0;
|
||||
static float fYawOffset = 0, fYawSpeed = 0;
|
||||
static float fNeedleOffset = 0, fNeedleSpeed = 0;
|
||||
int iTimeCount, iTimeDelta;
|
||||
float fYawDelta, fYawDeltaDiff;
|
||||
vec3_t vViewAngles;
|
||||
|
||||
cge->CG_EyeAngles(&vViewAngles);
|
||||
|
||||
vViewAngles[1] -= cl.snap.ps.stats[STAT_COMPASSNORTH] / 182.0f;
|
||||
|
||||
iTimeCount = uid.time - iLastCompassTime;
|
||||
if (iTimeCount <= 1000)
|
||||
{
|
||||
fYawDelta = AngleSubtract(vViewAngles[1], fLastYaw);
|
||||
if (fYawDelta > 0.1)
|
||||
{
|
||||
if ((fYawDelta > 0.0 && fLastYawDelta < fYawDelta)
|
||||
|| (fYawDelta < 0.0 && fLastYawDelta > fYawDelta))
|
||||
{
|
||||
|
||||
fYawSpeed += (fYawDelta - fLastYawDelta) * 0.75;
|
||||
fYawOffset += (fYawDelta - fLastYawDelta) * 0.75;
|
||||
}
|
||||
|
||||
if (fYawSpeed > 90.0) {
|
||||
fYawSpeed = 90.0;
|
||||
}
|
||||
else if (fYawSpeed < 0.05) {
|
||||
fYawSpeed = 0.05;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
while (iTimeCount > 0)
|
||||
{
|
||||
iTimeDelta = iTimeCount;
|
||||
if (iTimeCount > 15) {
|
||||
iTimeDelta = 15;
|
||||
}
|
||||
iTimeCount -= iTimeDelta;
|
||||
|
||||
if (fabs(fYawOffset) >= 0.1 || fabs(fYawSpeed) >= 0.01)
|
||||
{
|
||||
fYawOffset += fYawSpeed * iTimeDelta;
|
||||
if (fYawOffset > 0.0) {
|
||||
fYawSpeed -= iTimeDelta * 0.00175;
|
||||
}
|
||||
else if (fYawOffset < 0.0) {
|
||||
fYawSpeed += iTimeDelta * 0.00175;
|
||||
}
|
||||
|
||||
if (fYawOffset > 40.0) {
|
||||
fYawOffset = 40.0;
|
||||
fYawSpeed = 0.0;
|
||||
}
|
||||
else if (fYawOffset < -40.0) {
|
||||
fYawOffset = -40.0;
|
||||
fYawSpeed = 0.0;
|
||||
}
|
||||
|
||||
fYawSpeed -= iTimeDelta * 0.003;
|
||||
if (fYawSpeed > 0.0) {
|
||||
fYawSpeed -= iTimeDelta * 0.0004;
|
||||
}
|
||||
else {
|
||||
fYawSpeed += iTimeDelta * 0.0004;
|
||||
if (fYawSpeed > 0.0) {
|
||||
fYawSpeed = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iTimeCount = 0;
|
||||
fYawOffset = 0.0;
|
||||
fYawSpeed = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
fLastYawDelta = fYawDelta;
|
||||
iLastTimeDelta = uid.time - iLastCompassTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
fLastYawDelta = 0;
|
||||
fYawOffset = 0;
|
||||
fYawSpeed = 0;
|
||||
iLastTimeDelta = 0;
|
||||
}
|
||||
|
||||
fLastPitch = vViewAngles[0];
|
||||
fLastYaw = vViewAngles[1];
|
||||
iLastCompassTime = uid.time;
|
||||
|
||||
if (iLastTimeDelta)
|
||||
{
|
||||
if (fabs(fLastYawDelta) > 0.1) {
|
||||
fNeedleOffset -= fLastYawDelta;
|
||||
}
|
||||
|
||||
iTimeCount = iLastTimeDelta;
|
||||
while (iTimeCount > 0)
|
||||
{
|
||||
iTimeDelta = iTimeCount;
|
||||
if (iTimeCount > 15) {
|
||||
iTimeDelta = 15;
|
||||
}
|
||||
iTimeCount -= iTimeDelta;
|
||||
|
||||
if (fabs(fNeedleOffset) >= 0.1 || fabs(fNeedleSpeed) >= 0.01) {
|
||||
|
||||
fNeedleOffset += iTimeDelta * fNeedleSpeed;
|
||||
if (fNeedleOffset > 180.0) {
|
||||
fNeedleOffset -= 360.0;
|
||||
}
|
||||
else if (fNeedleOffset < -180.0) {
|
||||
fNeedleOffset += 360.0;
|
||||
}
|
||||
|
||||
if (fNeedleOffset > 0.0) {
|
||||
fNeedleSpeed -= iTimeDelta * 0.00175;
|
||||
}
|
||||
else if (fNeedleOffset < 0.0) {
|
||||
fNeedleSpeed += iTimeDelta * 0.00175;
|
||||
}
|
||||
|
||||
fNeedleSpeed -= fNeedleSpeed * 0.0025 * iTimeDelta;
|
||||
if (fNeedleSpeed > 0.0) {
|
||||
fNeedleSpeed -= iTimeDelta * 0.00035;
|
||||
if (fNeedleSpeed < 0.0) {
|
||||
fNeedleSpeed = 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fNeedleSpeed += iTimeDelta * 0.00035;
|
||||
if (fNeedleSpeed > 0.0) {
|
||||
fNeedleSpeed = 0.0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iTimeCount = 0;
|
||||
fNeedleOffset = 0.0;
|
||||
fNeedleSpeed = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fNeedleOffset = 0.0;
|
||||
fNeedleSpeed = 0.0;
|
||||
}
|
||||
|
||||
fSinVal = sin(anglemod(fNeedleOffset + fLastYaw) / (180 / M_PI));
|
||||
fCosVal = cos(anglemod(fNeedleOffset + fLastYaw) / (180 / M_PI));
|
||||
|
||||
vCompassDir[0] = fSinVal;
|
||||
vCompassDir[1] = -fCosVal;
|
||||
|
||||
vCenter[0] = m_frame.size.width * 0.5;
|
||||
vCenter[1] = m_frame.size.height * 0.5;
|
||||
vTexCoords[0][0] = 0.0;
|
||||
vTexCoords[0][1] = 0.0;
|
||||
vTexCoords[1][0] = 1.0;
|
||||
vTexCoords[1][1] = 0.0;
|
||||
vTexCoords[2][0] = 0.0;
|
||||
vTexCoords[2][1] = 1.0;
|
||||
|
||||
vVerts[0][0] = vCenter[0] + vCompassDir[0] * vCenter[0] - fCosVal * vCenter[1];
|
||||
vVerts[1][0] = vCenter[0] + vCompassDir[0] * vCenter[0] + fCosVal * vCenter[1];
|
||||
vVerts[2][0] = vCenter[0] - vCompassDir[0] * vCenter[0] - fCosVal * vCenter[1];
|
||||
vVerts[0][1] = vCenter[1] + vCompassDir[1] * vCenter[1] - fSinVal * vCenter[0];
|
||||
vVerts[1][1] = vCenter[1] + vCompassDir[1] * vCenter[1] + fSinVal * vCenter[0];
|
||||
vVerts[2][1] = vCenter[1] - vCompassDir[1] * vCenter[1] - fSinVal * vCenter[0];
|
||||
|
||||
m_statbar_material->ReregisterMaterial();
|
||||
re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial());
|
||||
|
||||
vVerts[0][0] = vVerts[2][0];
|
||||
vVerts[0][1] = vVerts[2][1];
|
||||
vTexCoords[0][0] = vTexCoords[2][0];
|
||||
vTexCoords[0][1] = vTexCoords[2][1];
|
||||
vTexCoords[2][0] = 1.0;
|
||||
vTexCoords[2][1] = 1.0;
|
||||
|
||||
vVerts[2][0] = vCenter[0] + fCosVal * vCenter[1] - vCompassDir[0] * vCenter[0];
|
||||
vVerts[2][1] = vCenter[1] * fSinVal + vCenter[0] - vCompassDir[1] * vCenter[1];
|
||||
|
||||
m_statbar_material->ReregisterMaterial();
|
||||
re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial());
|
||||
}
|
||||
|
||||
void UIFakkLabel::DrawStatSpinner( float frac )
|
||||
@@ -506,7 +882,7 @@ void UIFakkLabel::Draw( void )
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_stat != -1 )
|
||||
if( m_stat == -1 )
|
||||
{
|
||||
float scale;
|
||||
qhandle_t handle;
|
||||
@@ -516,7 +892,7 @@ void UIFakkLabel::Draw( void )
|
||||
vec3_t angles;
|
||||
vec3_t offset;
|
||||
vec3_t rotateoffset;
|
||||
vec3_t color;
|
||||
vec4_t color;
|
||||
str sAnimName;
|
||||
float height;
|
||||
|
||||
@@ -686,23 +1062,20 @@ _shitlabel01:
|
||||
|
||||
float frac;
|
||||
|
||||
if( m_maxstat )
|
||||
if( m_maxstat >= 0 )
|
||||
{
|
||||
frac = delta / ( m_statbar_max - m_statbar_min );
|
||||
frac = (float)delta / (float)cl.snap.ps.stats[m_maxstat];
|
||||
}
|
||||
else
|
||||
{
|
||||
frac = delta / cl.snap.ps.stats[ m_maxstat ];
|
||||
frac = (float)delta / (float)(m_statbar_max - m_statbar_min);
|
||||
}
|
||||
|
||||
if( frac > 1.0 )
|
||||
frac = 1.0;
|
||||
if( frac < 0.0 )
|
||||
frac = 0.0;
|
||||
if( frac > 1.0 ) frac = 1.0;
|
||||
else if( frac < 0.0 ) frac = 0.0;
|
||||
|
||||
DrawStatbar( frac );
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,72 @@ void View3D::DrawFPS
|
||||
)
|
||||
|
||||
{
|
||||
// FIXME: stub
|
||||
char string[128];
|
||||
|
||||
setFont("verdana-14");
|
||||
if (fps->integer == 2)
|
||||
{
|
||||
re.SetColor(UBlack);
|
||||
re.DrawBox(
|
||||
0.0,
|
||||
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 4.0,
|
||||
m_frame.pos.x + m_frame.size.width,
|
||||
m_font->getHeight(qfalse) * 4.0
|
||||
);
|
||||
}
|
||||
|
||||
sprintf(string, "FPS %4.1f", currentfps);
|
||||
if (currentfps > 23.94) {
|
||||
if (cl_greenfps->integer) {
|
||||
m_font->setColor(UGreen);
|
||||
} else {
|
||||
m_font->setColor(UWhite);
|
||||
}
|
||||
} else if (currentfps > 18.0) {
|
||||
m_font->setColor(UYellow);
|
||||
} else {
|
||||
// low fps
|
||||
m_font->setColor(URed);
|
||||
}
|
||||
|
||||
m_font->Print(
|
||||
m_font->getHeight(qfalse) * 10.0,
|
||||
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 3.0,
|
||||
string,
|
||||
-1,
|
||||
qfalse
|
||||
);
|
||||
|
||||
// Draw elements count
|
||||
if (cl_greenfps->integer) {
|
||||
m_font->setColor(UGreen);
|
||||
}
|
||||
else {
|
||||
m_font->setColor(UWhite);
|
||||
}
|
||||
|
||||
sprintf(string, "wt%5d wv%5d cl%d", cls.world_tris, cls.world_verts, cls.character_lights);
|
||||
|
||||
m_font->Print(
|
||||
m_font->getHeight(qfalse) * 10.0,
|
||||
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 2.0,
|
||||
string,
|
||||
-1,
|
||||
qfalse
|
||||
);
|
||||
|
||||
sprintf(string, "t%5d v%5d Mtex%5.2f", cls.total_tris, cls.total_verts, (float)cls.total_texels * 0.00000095367432);
|
||||
|
||||
|
||||
m_font->Print(
|
||||
m_font->getHeight(qfalse) * 10.0,
|
||||
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse),
|
||||
string,
|
||||
-1,
|
||||
qfalse
|
||||
);
|
||||
|
||||
m_font->setColor(UBlack);
|
||||
}
|
||||
|
||||
void View3D::DrawProf
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
void UpdateLocationPrint( int x, int y, const char *s, float alpha );
|
||||
qboolean LetterboxActive( void );
|
||||
void InitSubtitle( void );
|
||||
void FrameInitialized( void );
|
||||
void FrameInitialized( void ) override;
|
||||
virtual void Pressed( Event *ev );
|
||||
};
|
||||
|
||||
|
||||
+6
-10
@@ -126,10 +126,6 @@ typedef struct {
|
||||
|
||||
int joystickAxis[MAX_JOYSTICK_AXIS]; // set by joystick events
|
||||
|
||||
// cgame communicates a few values to the client system
|
||||
int cgameUserCmdValue; // current weapon to add to usercmd_t
|
||||
float cgameSensitivity;
|
||||
|
||||
// cmds[cmdNumber] is the predicted command, [cmdNumber-1] is the last
|
||||
// properly generated command
|
||||
usercmd_t cmds[CMD_BACKUP]; // each mesage will send several old cmds
|
||||
@@ -145,9 +141,6 @@ typedef struct {
|
||||
// and teleport direction changes
|
||||
vec3_t viewangles;
|
||||
|
||||
vec3_t eyeAngles;
|
||||
vec3_t eyeOrigin;
|
||||
|
||||
int serverId; // included in each client message so the server
|
||||
// can tell if it is for a prior map_restart
|
||||
// big stuff at end of structure so most offsets are 15 bits or less
|
||||
@@ -310,6 +303,7 @@ typedef struct {
|
||||
|
||||
int framecount;
|
||||
int frametime; // msec since last frame
|
||||
float serverFrameTime;
|
||||
|
||||
int realtime; // ignores pause
|
||||
int realFrametime; // ignoring pause, so console always works
|
||||
@@ -352,6 +346,11 @@ typedef struct {
|
||||
hdelement_t HudDrawElements[ MAX_HUDDRAW_ELEMENTS ];
|
||||
clientAnim_t anim;
|
||||
stopWatch_t stopwatch;
|
||||
void* savedCgameState;
|
||||
int savedCgameStateSize;
|
||||
char gcdResponse[73];
|
||||
int unknown3_0;
|
||||
int currentRate;
|
||||
qhandle_t charSetShader;
|
||||
qhandle_t whiteShader;
|
||||
qhandle_t consoleShader;
|
||||
@@ -578,9 +577,6 @@ void Con_PageDown( void );
|
||||
void Con_Top( void );
|
||||
void Con_Bottom( void );
|
||||
|
||||
void CL_LoadConsoleHistory( void );
|
||||
void CL_SaveConsoleHistory( void );
|
||||
|
||||
//
|
||||
// cl_scrn.c
|
||||
//
|
||||
|
||||
+1
-12
@@ -34,17 +34,6 @@ typedef struct {
|
||||
extern qboolean key_overstrikeMode;
|
||||
extern qkey_t keys[K_LASTKEY];
|
||||
|
||||
// NOTE TTimo the declaration of field_t and Field_Clear is now in qcommon/qcommon.h
|
||||
void Field_KeyDownEvent( field_t *edit, int key );
|
||||
void Field_CharEvent( field_t *edit, int ch );
|
||||
void Field_Draw(fontInfo_t *font, field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape );
|
||||
void Field_BigDraw(fontInfo_t *font, field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape );
|
||||
|
||||
#define COMMAND_HISTORY 32
|
||||
extern field_t historyEditLines[COMMAND_HISTORY];
|
||||
|
||||
extern field_t g_consoleField;
|
||||
extern field_t chatField;
|
||||
extern int anykeydown;
|
||||
extern qboolean chat_team;
|
||||
extern int chat_playerNum;
|
||||
@@ -53,7 +42,7 @@ extern int chat_playerNum;
|
||||
int Key_StringToKeynum( const char *str );
|
||||
void Key_WriteBindings( fileHandle_t f );
|
||||
void Key_SetBinding( int keynum, const char *binding );
|
||||
char *Key_GetBinding( int keynum );
|
||||
const char *Key_GetBinding( int keynum );
|
||||
qboolean Key_IsDown( int keynum );
|
||||
qboolean Key_GetOverstrikeMode( void );
|
||||
void Key_SetOverstrikeMode( qboolean state );
|
||||
|
||||
@@ -25,7 +25,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
/*
|
||||
** Intel/DVI ADPCM coder/decoder.
|
||||
**
|
||||
** The algorithm for this coder was taken from the IMA Compatibility Project
|
||||
** The algorithm for this coder was taken from the IMA Compatability Project
|
||||
** proceedings, Vol 2, Number 2; May 1992.
|
||||
**
|
||||
** Version 1.2, 18-Dec-92.
|
||||
@@ -278,7 +278,7 @@ void S_AdpcmGetSamples(sndBuffer *chunk, short *to) {
|
||||
|
||||
out = (byte *)chunk->sndChunk;
|
||||
// get samples
|
||||
S_AdpcmDecode((char *) out, to, SND_CHUNK_SIZE_BYTE*2, &state );
|
||||
S_AdpcmDecode( out, to, SND_CHUNK_SIZE_BYTE*2, &state );
|
||||
}
|
||||
|
||||
|
||||
@@ -310,7 +310,7 @@ void S_AdpcmEncodeSound( sfx_t *sfx, short *samples ) {
|
||||
newchunk = SND_malloc();
|
||||
if (sfx->soundData == NULL) {
|
||||
sfx->soundData = newchunk;
|
||||
} else if (chunk != NULL) {
|
||||
} else {
|
||||
chunk->next = newchunk;
|
||||
}
|
||||
chunk = newchunk;
|
||||
@@ -322,7 +322,7 @@ void S_AdpcmEncodeSound( sfx_t *sfx, short *samples ) {
|
||||
out = (byte *)chunk->sndChunk;
|
||||
|
||||
// encode the samples
|
||||
S_AdpcmEncode( samples + inOffset, (char *) out, n, &state );
|
||||
S_AdpcmEncode( samples + inOffset, out, n, &state );
|
||||
|
||||
inOffset += n;
|
||||
count -= n;
|
||||
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Quake III Arena source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
/* This file is only compiled for PowerPC builds with Altivec support.
|
||||
Altivec intrinsics need to be in a separate file, so GCC's -maltivec
|
||||
command line can enable them, but give us the option to _not_ use that
|
||||
on other files, where the compiler might then generate Altivec
|
||||
instructions for normal floating point, crashing on G3 (etc) processors. */
|
||||
|
||||
#include "client.h"
|
||||
#include "snd_local.h"
|
||||
|
||||
#if idppc_altivec
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
#include <altivec.h>
|
||||
#endif
|
||||
|
||||
void S_PaintChannelFrom16_altivec( portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE], int snd_vol, channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
|
||||
int data, aoff, boff;
|
||||
int leftvol, rightvol;
|
||||
int i, j;
|
||||
portable_samplepair_t *samp;
|
||||
sndBuffer *chunk;
|
||||
short *samples;
|
||||
float ooff, fdata[2], fdiv, fleftvol, frightvol;
|
||||
|
||||
if (sc->soundChannels <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
samp = &paintbuffer[ bufferOffset ];
|
||||
|
||||
if (ch->doppler) {
|
||||
sampleOffset = sampleOffset*ch->oldDopplerScale;
|
||||
}
|
||||
|
||||
if ( sc->soundChannels == 2 ) {
|
||||
sampleOffset *= sc->soundChannels;
|
||||
|
||||
if ( sampleOffset & 1 ) {
|
||||
sampleOffset &= ~1;
|
||||
}
|
||||
}
|
||||
|
||||
chunk = sc->soundData;
|
||||
while (sampleOffset>=SND_CHUNK_SIZE) {
|
||||
chunk = chunk->next;
|
||||
sampleOffset -= SND_CHUNK_SIZE;
|
||||
if (!chunk) {
|
||||
chunk = sc->soundData;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ch->doppler || ch->dopplerScale==1.0f) {
|
||||
vector signed short volume_vec;
|
||||
vector unsigned int volume_shift;
|
||||
int vectorCount, samplesLeft, chunkSamplesLeft;
|
||||
leftvol = ch->leftvol*snd_vol;
|
||||
rightvol = ch->rightvol*snd_vol;
|
||||
samples = chunk->sndChunk;
|
||||
((short *)&volume_vec)[0] = leftvol;
|
||||
((short *)&volume_vec)[1] = leftvol;
|
||||
((short *)&volume_vec)[4] = leftvol;
|
||||
((short *)&volume_vec)[5] = leftvol;
|
||||
((short *)&volume_vec)[2] = rightvol;
|
||||
((short *)&volume_vec)[3] = rightvol;
|
||||
((short *)&volume_vec)[6] = rightvol;
|
||||
((short *)&volume_vec)[7] = rightvol;
|
||||
volume_shift = vec_splat_u32(8);
|
||||
i = 0;
|
||||
|
||||
while(i < count) {
|
||||
/* Try to align destination to 16-byte boundary */
|
||||
while(i < count && (((unsigned long)&samp[i] & 0x1f) || ((count-i) < 8) || ((SND_CHUNK_SIZE - sampleOffset) < 8))) {
|
||||
data = samples[sampleOffset++];
|
||||
samp[i].left += (data * leftvol)>>8;
|
||||
|
||||
if ( sc->soundChannels == 2 ) {
|
||||
data = samples[sampleOffset++];
|
||||
}
|
||||
samp[i].right += (data * rightvol)>>8;
|
||||
|
||||
if (sampleOffset == SND_CHUNK_SIZE) {
|
||||
chunk = chunk->next;
|
||||
samples = chunk->sndChunk;
|
||||
sampleOffset = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
/* Destination is now aligned. Process as many 8-sample
|
||||
chunks as we can before we run out of room from the current
|
||||
sound chunk. We do 8 per loop to avoid extra source data reads. */
|
||||
samplesLeft = count - i;
|
||||
chunkSamplesLeft = SND_CHUNK_SIZE - sampleOffset;
|
||||
if(samplesLeft > chunkSamplesLeft)
|
||||
samplesLeft = chunkSamplesLeft;
|
||||
|
||||
vectorCount = samplesLeft / 8;
|
||||
|
||||
if(vectorCount)
|
||||
{
|
||||
vector unsigned char tmp;
|
||||
vector short s0, s1, sampleData0, sampleData1;
|
||||
vector signed int merge0, merge1;
|
||||
vector signed int d0, d1, d2, d3;
|
||||
vector unsigned char samplePermute0 =
|
||||
VECCONST_UINT8(0, 1, 4, 5, 0, 1, 4, 5, 2, 3, 6, 7, 2, 3, 6, 7);
|
||||
vector unsigned char samplePermute1 =
|
||||
VECCONST_UINT8(8, 9, 12, 13, 8, 9, 12, 13, 10, 11, 14, 15, 10, 11, 14, 15);
|
||||
vector unsigned char loadPermute0, loadPermute1;
|
||||
|
||||
// Rather than permute the vectors after we load them to do the sample
|
||||
// replication and rearrangement, we permute the alignment vector so
|
||||
// we do everything in one step below and avoid data shuffling.
|
||||
tmp = vec_lvsl(0,&samples[sampleOffset]);
|
||||
loadPermute0 = vec_perm(tmp,tmp,samplePermute0);
|
||||
loadPermute1 = vec_perm(tmp,tmp,samplePermute1);
|
||||
|
||||
s0 = *(vector short *)&samples[sampleOffset];
|
||||
while(vectorCount)
|
||||
{
|
||||
/* Load up source (16-bit) sample data */
|
||||
s1 = *(vector short *)&samples[sampleOffset+7];
|
||||
|
||||
/* Load up destination sample data */
|
||||
d0 = *(vector signed int *)&samp[i];
|
||||
d1 = *(vector signed int *)&samp[i+2];
|
||||
d2 = *(vector signed int *)&samp[i+4];
|
||||
d3 = *(vector signed int *)&samp[i+6];
|
||||
|
||||
sampleData0 = vec_perm(s0,s1,loadPermute0);
|
||||
sampleData1 = vec_perm(s0,s1,loadPermute1);
|
||||
|
||||
merge0 = vec_mule(sampleData0,volume_vec);
|
||||
merge0 = vec_sra(merge0,volume_shift); /* Shift down to proper range */
|
||||
|
||||
merge1 = vec_mulo(sampleData0,volume_vec);
|
||||
merge1 = vec_sra(merge1,volume_shift);
|
||||
|
||||
d0 = vec_add(merge0,d0);
|
||||
d1 = vec_add(merge1,d1);
|
||||
|
||||
merge0 = vec_mule(sampleData1,volume_vec);
|
||||
merge0 = vec_sra(merge0,volume_shift); /* Shift down to proper range */
|
||||
|
||||
merge1 = vec_mulo(sampleData1,volume_vec);
|
||||
merge1 = vec_sra(merge1,volume_shift);
|
||||
|
||||
d2 = vec_add(merge0,d2);
|
||||
d3 = vec_add(merge1,d3);
|
||||
|
||||
/* Store destination sample data */
|
||||
*(vector signed int *)&samp[i] = d0;
|
||||
*(vector signed int *)&samp[i+2] = d1;
|
||||
*(vector signed int *)&samp[i+4] = d2;
|
||||
*(vector signed int *)&samp[i+6] = d3;
|
||||
|
||||
i += 8;
|
||||
vectorCount--;
|
||||
s0 = s1;
|
||||
sampleOffset += 8;
|
||||
}
|
||||
if (sampleOffset == SND_CHUNK_SIZE) {
|
||||
chunk = chunk->next;
|
||||
samples = chunk->sndChunk;
|
||||
sampleOffset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fleftvol = ch->leftvol*snd_vol;
|
||||
frightvol = ch->rightvol*snd_vol;
|
||||
|
||||
ooff = sampleOffset;
|
||||
samples = chunk->sndChunk;
|
||||
|
||||
for ( i=0 ; i<count ; i++ ) {
|
||||
|
||||
aoff = ooff;
|
||||
ooff = ooff + ch->dopplerScale * sc->soundChannels;
|
||||
boff = ooff;
|
||||
fdata[0] = fdata[1] = 0;
|
||||
for (j=aoff; j<boff; j += sc->soundChannels) {
|
||||
if (j == SND_CHUNK_SIZE) {
|
||||
chunk = chunk->next;
|
||||
if (!chunk) {
|
||||
chunk = sc->soundData;
|
||||
}
|
||||
samples = chunk->sndChunk;
|
||||
ooff -= SND_CHUNK_SIZE;
|
||||
}
|
||||
if ( sc->soundChannels == 2 ) {
|
||||
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
|
||||
fdata[1] += samples[(j+1)&(SND_CHUNK_SIZE-1)];
|
||||
} else {
|
||||
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
|
||||
fdata[1] += samples[j&(SND_CHUNK_SIZE-1)];
|
||||
}
|
||||
}
|
||||
fdiv = 256 * (boff-aoff) / sc->soundChannels;
|
||||
samp[i].left += (fdata[0] * fleftvol)/fdiv;
|
||||
samp[i].right += (fdata[1] * frightvol)/fdiv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,237 +0,0 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Quake III Arena source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "snd_codec.h"
|
||||
|
||||
static snd_codec_t *codecs;
|
||||
|
||||
/*
|
||||
=================
|
||||
S_CodecGetSound
|
||||
|
||||
Opens/loads a sound, tries codec based on the sound's file extension
|
||||
then tries all supported codecs.
|
||||
=================
|
||||
*/
|
||||
static void *S_CodecGetSound(const char *filename, snd_info_t *info)
|
||||
{
|
||||
snd_codec_t *codec;
|
||||
snd_codec_t *orgCodec = NULL;
|
||||
qboolean orgNameFailed = qfalse;
|
||||
char localName[ MAX_QPATH ];
|
||||
const char *ext;
|
||||
char altName[ MAX_QPATH ];
|
||||
void *rtn = NULL;
|
||||
|
||||
Q_strncpyz(localName, filename, MAX_QPATH);
|
||||
|
||||
ext = COM_GetExtension(localName);
|
||||
|
||||
if( *ext )
|
||||
{
|
||||
// Look for the correct loader and use it
|
||||
for( codec = codecs; codec; codec = codec->next )
|
||||
{
|
||||
if( !Q_stricmp( ext, codec->ext ) )
|
||||
{
|
||||
// Load
|
||||
if( info )
|
||||
rtn = codec->load(localName, info);
|
||||
else
|
||||
rtn = codec->open(localName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// A loader was found
|
||||
if( codec )
|
||||
{
|
||||
if( !rtn )
|
||||
{
|
||||
// Loader failed, most likely because the file isn't there;
|
||||
// try again without the extension
|
||||
orgNameFailed = qtrue;
|
||||
orgCodec = codec;
|
||||
COM_StripExtension( filename, localName, MAX_QPATH );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something loaded
|
||||
return rtn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try and find a suitable match using all
|
||||
// the sound codecs supported
|
||||
for( codec = codecs; codec; codec = codec->next )
|
||||
{
|
||||
if( codec == orgCodec )
|
||||
continue;
|
||||
|
||||
Com_sprintf( altName, sizeof (altName), "%s.%s", localName, codec->ext );
|
||||
|
||||
// Load
|
||||
if( info )
|
||||
rtn = codec->load(altName, info);
|
||||
else
|
||||
rtn = codec->open(altName);
|
||||
|
||||
if( rtn )
|
||||
{
|
||||
if( orgNameFailed )
|
||||
{
|
||||
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s not present, using %s instead\n",
|
||||
filename, altName );
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
}
|
||||
|
||||
Com_Printf(S_COLOR_YELLOW "WARNING: Failed to %s sound %s!\n", info ? "load" : "open", filename);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_CodecInit
|
||||
=================
|
||||
*/
|
||||
void S_CodecInit()
|
||||
{
|
||||
codecs = NULL;
|
||||
|
||||
#ifdef USE_CODEC_OPUS
|
||||
S_CodecRegister(&opus_codec);
|
||||
#endif
|
||||
|
||||
#ifdef USE_CODEC_VORBIS
|
||||
S_CodecRegister(&ogg_codec);
|
||||
#endif
|
||||
|
||||
// Register wav codec last so that it is always tried first when a file extension was not found
|
||||
S_CodecRegister(&wav_codec);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_CodecShutdown
|
||||
=================
|
||||
*/
|
||||
void S_CodecShutdown()
|
||||
{
|
||||
codecs = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_CodecRegister
|
||||
=================
|
||||
*/
|
||||
void S_CodecRegister(snd_codec_t *codec)
|
||||
{
|
||||
codec->next = codecs;
|
||||
codecs = codec;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_CodecLoad
|
||||
=================
|
||||
*/
|
||||
void *S_CodecLoad(const char *filename, snd_info_t *info)
|
||||
{
|
||||
return S_CodecGetSound(filename, info);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_CodecOpenStream
|
||||
=================
|
||||
*/
|
||||
snd_stream_t *S_CodecOpenStream(const char *filename)
|
||||
{
|
||||
return S_CodecGetSound(filename, NULL);
|
||||
}
|
||||
|
||||
void S_CodecCloseStream(snd_stream_t *stream)
|
||||
{
|
||||
stream->codec->close(stream);
|
||||
}
|
||||
|
||||
int S_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
|
||||
{
|
||||
return stream->codec->read(stream, bytes, buffer);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// Util functions (used by codecs)
|
||||
|
||||
/*
|
||||
=================
|
||||
S_CodecUtilOpen
|
||||
=================
|
||||
*/
|
||||
snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
fileHandle_t hnd;
|
||||
int length;
|
||||
|
||||
// Try to open the file
|
||||
length = FS_FOpenFileRead(filename, &hnd, qtrue, qtrue);
|
||||
if(!hnd)
|
||||
{
|
||||
Com_DPrintf("Can't read sound file %s\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate a stream
|
||||
stream = Z_Malloc(sizeof(snd_stream_t));
|
||||
if(!stream)
|
||||
{
|
||||
FS_FCloseFile(hnd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy over, return
|
||||
stream->codec = codec;
|
||||
stream->file = hnd;
|
||||
stream->length = length;
|
||||
return stream;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_CodecUtilClose
|
||||
=================
|
||||
*/
|
||||
void S_CodecUtilClose(snd_stream_t **stream)
|
||||
{
|
||||
FS_FCloseFile((*stream)->file);
|
||||
Z_Free(*stream);
|
||||
*stream = NULL;
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Quake III Arena source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef _SND_CODEC_H_
|
||||
#define _SND_CODEC_H_
|
||||
|
||||
#include "../qcommon/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
|
||||
typedef struct snd_info_s
|
||||
{
|
||||
int rate;
|
||||
int width;
|
||||
int channels;
|
||||
int samples;
|
||||
int size;
|
||||
int dataofs;
|
||||
} snd_info_t;
|
||||
|
||||
typedef struct snd_codec_s snd_codec_t;
|
||||
|
||||
typedef struct snd_stream_s
|
||||
{
|
||||
snd_codec_t *codec;
|
||||
fileHandle_t file;
|
||||
snd_info_t info;
|
||||
int length;
|
||||
int pos;
|
||||
void *ptr;
|
||||
} snd_stream_t;
|
||||
|
||||
// Codec functions
|
||||
typedef void *(*CODEC_LOAD)(const char *filename, snd_info_t *info);
|
||||
typedef snd_stream_t *(*CODEC_OPEN)(const char *filename);
|
||||
typedef int (*CODEC_READ)(snd_stream_t *stream, int bytes, void *buffer);
|
||||
typedef void (*CODEC_CLOSE)(snd_stream_t *stream);
|
||||
|
||||
// Codec data structure
|
||||
struct snd_codec_s
|
||||
{
|
||||
char *ext;
|
||||
CODEC_LOAD load;
|
||||
CODEC_OPEN open;
|
||||
CODEC_READ read;
|
||||
CODEC_CLOSE close;
|
||||
snd_codec_t *next;
|
||||
};
|
||||
|
||||
// Codec management
|
||||
void S_CodecInit( void );
|
||||
void S_CodecShutdown( void );
|
||||
void S_CodecRegister(snd_codec_t *codec);
|
||||
void *S_CodecLoad(const char *filename, snd_info_t *info);
|
||||
snd_stream_t *S_CodecOpenStream(const char *filename);
|
||||
void S_CodecCloseStream(snd_stream_t *stream);
|
||||
int S_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
|
||||
|
||||
// Util functions (used by codecs)
|
||||
snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec);
|
||||
void S_CodecUtilClose(snd_stream_t **stream);
|
||||
|
||||
// WAV Codec
|
||||
extern snd_codec_t wav_codec;
|
||||
void *S_WAV_CodecLoad(const char *filename, snd_info_t *info);
|
||||
snd_stream_t *S_WAV_CodecOpenStream(const char *filename);
|
||||
void S_WAV_CodecCloseStream(snd_stream_t *stream);
|
||||
int S_WAV_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
|
||||
|
||||
// Ogg Vorbis codec
|
||||
#ifdef USE_CODEC_VORBIS
|
||||
extern snd_codec_t ogg_codec;
|
||||
void *S_OGG_CodecLoad(const char *filename, snd_info_t *info);
|
||||
snd_stream_t *S_OGG_CodecOpenStream(const char *filename);
|
||||
void S_OGG_CodecCloseStream(snd_stream_t *stream);
|
||||
int S_OGG_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
|
||||
#endif // USE_CODEC_VORBIS
|
||||
|
||||
// Ogg Opus codec
|
||||
#ifdef USE_CODEC_OPUS
|
||||
extern snd_codec_t opus_codec;
|
||||
void *S_OggOpus_CodecLoad(const char *filename, snd_info_t *info);
|
||||
snd_stream_t *S_OggOpus_CodecOpenStream(const char *filename);
|
||||
void S_OggOpus_CodecCloseStream(snd_stream_t *stream);
|
||||
int S_OggOpus_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
|
||||
#endif // USE_CODEC_OPUS
|
||||
|
||||
#endif // !_SND_CODEC_H_
|
||||
@@ -1,717 +0,0 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||
Copyright (C) 2005-2006 Joerg Dietrich <dietrich_joerg@gmx.de>
|
||||
Copyright (C) 2006 Thilo Schulz <arny@ats.s.bawue.de>
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Quake III Arena source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#if USE_CODEC_MP3
|
||||
|
||||
// includes for the Q3 sound system
|
||||
#include "client.h"
|
||||
#include "snd_codec.h"
|
||||
|
||||
// includes for the MP3 codec
|
||||
#include <mad.h>
|
||||
|
||||
#define MP3_SAMPLE_WIDTH 2
|
||||
#define MP3_PCMSAMPLES_PERSLICE 32
|
||||
|
||||
// buffer size used when reading through the mp3
|
||||
#define MP3_DATA_BUFSIZ 128*1024
|
||||
|
||||
// undefine this if you don't want any dithering.
|
||||
#define MP3_DITHERING
|
||||
|
||||
// Q3 MP3 codec
|
||||
snd_codec_t mp3_codec =
|
||||
{
|
||||
".mp3",
|
||||
S_MP3_CodecLoad,
|
||||
S_MP3_CodecOpenStream,
|
||||
S_MP3_CodecReadStream,
|
||||
S_MP3_CodecCloseStream,
|
||||
NULL
|
||||
};
|
||||
|
||||
// structure used for info purposes
|
||||
struct snd_codec_mp3_info
|
||||
{
|
||||
byte encbuf[MP3_DATA_BUFSIZ]; // left over bytes not consumed
|
||||
// by the decoder.
|
||||
struct mad_stream madstream; // uses encbuf as buffer.
|
||||
struct mad_frame madframe; // control structures for libmad.
|
||||
struct mad_synth madsynth;
|
||||
|
||||
byte *pcmbuf; // buffer for not-used samples.
|
||||
int buflen; // length of buffer data.
|
||||
int pcmbufsize; // amount of allocated memory for
|
||||
// pcmbuf. This should have at least
|
||||
// the size of a decoded mp3 frame.
|
||||
|
||||
byte *dest; // copy decoded data here.
|
||||
int destlen; // amount of already copied data.
|
||||
int destsize; // amount of bytes we must decode.
|
||||
};
|
||||
|
||||
/*************** MP3 utility functions ***************/
|
||||
|
||||
/*
|
||||
=================
|
||||
S_MP3_ReadData
|
||||
=================
|
||||
*/
|
||||
|
||||
// feed libmad with data
|
||||
int S_MP3_ReadData(snd_stream_t *stream, struct mad_stream *madstream, byte *encbuf, int encbufsize)
|
||||
{
|
||||
int retval;
|
||||
int leftover;
|
||||
|
||||
if(!stream)
|
||||
return -1;
|
||||
|
||||
leftover = madstream->bufend - madstream->next_frame;
|
||||
if(leftover > 0)
|
||||
memmove(encbuf, madstream->this_frame, leftover);
|
||||
|
||||
|
||||
// Fill the buffer right to the end
|
||||
|
||||
retval = FS_Read(&encbuf[leftover], encbufsize - leftover, stream->file);
|
||||
|
||||
if(retval <= 0)
|
||||
{
|
||||
// EOF reached, that's ok.
|
||||
return 0;
|
||||
}
|
||||
|
||||
mad_stream_buffer(madstream, encbuf, retval + leftover);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
S_MP3_Scanfile
|
||||
|
||||
to determine the samplecount, we apparently must get *all* headers :(
|
||||
I basically used the xmms-mad plugin source to see how this stuff works.
|
||||
|
||||
returns a value < 0 on error.
|
||||
=================
|
||||
*/
|
||||
|
||||
int S_MP3_Scanfile(snd_stream_t *stream)
|
||||
{
|
||||
struct mad_stream madstream;
|
||||
struct mad_header madheader;
|
||||
int retval;
|
||||
int samplecount;
|
||||
byte encbuf[MP3_DATA_BUFSIZ];
|
||||
|
||||
// error out on invalid input.
|
||||
if(!stream)
|
||||
return -1;
|
||||
|
||||
mad_stream_init(&madstream);
|
||||
mad_header_init(&madheader);
|
||||
|
||||
while(1)
|
||||
{
|
||||
retval = S_MP3_ReadData(stream, &madstream, encbuf, sizeof(encbuf));
|
||||
if(retval < 0)
|
||||
return -1;
|
||||
else if(retval == 0)
|
||||
break;
|
||||
|
||||
// Start decoding the headers.
|
||||
while(1)
|
||||
{
|
||||
if((retval = mad_header_decode(&madheader, &madstream)) < 0)
|
||||
{
|
||||
if(madstream.error == MAD_ERROR_BUFLEN)
|
||||
{
|
||||
// We need to read more data
|
||||
break;
|
||||
}
|
||||
|
||||
if(!MAD_RECOVERABLE (madstream.error))
|
||||
{
|
||||
// unrecoverable error... we must bail out.
|
||||
return retval;
|
||||
}
|
||||
|
||||
mad_stream_skip(&madstream, madstream.skiplen);
|
||||
continue;
|
||||
}
|
||||
|
||||
// we got a valid header.
|
||||
|
||||
if(madheader.layer != MAD_LAYER_III)
|
||||
{
|
||||
// we don't support non-mp3s
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!stream->info.samples)
|
||||
{
|
||||
// This here is the very first frame. Set initial values now,
|
||||
// that we expect to stay constant throughout the whole mp3.
|
||||
|
||||
stream->info.rate = madheader.samplerate;
|
||||
stream->info.width = MP3_SAMPLE_WIDTH;
|
||||
stream->info.channels = MAD_NCHANNELS(&madheader);
|
||||
stream->info.samples = 0;
|
||||
stream->info.size = 0; // same here.
|
||||
stream->info.dataofs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check whether something changed that shouldn't.
|
||||
|
||||
if(stream->info.rate != madheader.samplerate ||
|
||||
stream->info.channels != MAD_NCHANNELS(&madheader))
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Update the counters
|
||||
samplecount = MAD_NSBSAMPLES(&madheader) * MP3_PCMSAMPLES_PERSLICE;
|
||||
stream->info.samples += samplecount;
|
||||
stream->info.size += samplecount * stream->info.channels * stream->info.width;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the file pointer so we can do the real decoding.
|
||||
FS_Seek(stream->file, 0, FS_SEEK_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************ dithering functions ***************************/
|
||||
|
||||
#ifdef MP3_DITHERING
|
||||
|
||||
// All dithering done here is taken from the GPL'ed xmms-mad plugin.
|
||||
|
||||
/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */
|
||||
/* Any feedback is very welcome. For any question, comments, */
|
||||
/* see http://www.math.keio.ac.jp/matumoto/emt.html or email */
|
||||
/* matumoto@math.keio.ac.jp */
|
||||
|
||||
/* Period parameters */
|
||||
#define MP3_DITH_N 624
|
||||
#define MP3_DITH_M 397
|
||||
#define MATRIX_A 0x9908b0df /* constant vector a */
|
||||
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
|
||||
#define LOWER_MASK 0x7fffffff /* least significant r bits */
|
||||
|
||||
/* Tempering parameters */
|
||||
#define TEMPERING_MASK_B 0x9d2c5680
|
||||
#define TEMPERING_MASK_C 0xefc60000
|
||||
#define TEMPERING_SHIFT_U(y) (y >> 11)
|
||||
#define TEMPERING_SHIFT_S(y) (y << 7)
|
||||
#define TEMPERING_SHIFT_T(y) (y << 15)
|
||||
#define TEMPERING_SHIFT_L(y) (y >> 18)
|
||||
|
||||
static unsigned long mt[MP3_DITH_N]; /* the array for the state vector */
|
||||
static int mti=MP3_DITH_N+1; /* mti==MP3_DITH_N+1 means mt[MP3_DITH_N] is not initialized */
|
||||
|
||||
/* initializing the array with a NONZERO seed */
|
||||
void sgenrand(unsigned long seed)
|
||||
{
|
||||
/* setting initial seeds to mt[MP3_DITH_N] using */
|
||||
/* the generator Line 25 of Table 1 in */
|
||||
/* [KNUTH 1981, The Art of Computer Programming */
|
||||
/* Vol. 2 (2nd Ed.), pp102] */
|
||||
mt[0]= seed & 0xffffffff;
|
||||
for (mti=1; mti<MP3_DITH_N; mti++)
|
||||
mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
|
||||
}
|
||||
|
||||
unsigned long genrand(void)
|
||||
{
|
||||
unsigned long y;
|
||||
static unsigned long mag01[2]={0x0, MATRIX_A};
|
||||
/* mag01[x] = x * MATRIX_A for x=0,1 */
|
||||
|
||||
if (mti >= MP3_DITH_N) { /* generate MP3_DITH_N words at one time */
|
||||
int kk;
|
||||
|
||||
if (mti == MP3_DITH_N+1) /* if sgenrand() has not been called, */
|
||||
sgenrand(4357); /* a default initial seed is used */
|
||||
|
||||
for (kk=0;kk<MP3_DITH_N-MP3_DITH_M;kk++) {
|
||||
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
|
||||
mt[kk] = mt[kk+MP3_DITH_M] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||
}
|
||||
for (;kk<MP3_DITH_N-1;kk++) {
|
||||
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
|
||||
mt[kk] = mt[kk+(MP3_DITH_M-MP3_DITH_N)] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||
}
|
||||
y = (mt[MP3_DITH_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
|
||||
mt[MP3_DITH_N-1] = mt[MP3_DITH_M-1] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= TEMPERING_SHIFT_U(y);
|
||||
y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
|
||||
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
|
||||
y ^= TEMPERING_SHIFT_L(y);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
long triangular_dither_noise(int nbits) {
|
||||
// parameter nbits : the peak-to-peak amplitude desired (in bits)
|
||||
// use with nbits set to 2 + nber of bits to be trimmed.
|
||||
// (because triangular is made from two uniformly distributed processes,
|
||||
// it starts at 2 bits peak-to-peak amplitude)
|
||||
// see The Theory of Dithered Quantization by Robert Alexander Wannamaker
|
||||
// for complete proof of why that's optimal
|
||||
|
||||
long v = (genrand()/2 - genrand()/2); // in ]-2^31, 2^31[
|
||||
//int signe = (v>0) ? 1 : -1;
|
||||
long P = 1 << (32 - nbits); // the power of 2
|
||||
v /= P;
|
||||
// now v in ]-2^(nbits-1), 2^(nbits-1) [
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif // MP3_DITHERING
|
||||
|
||||
/************************ decoder functions ***************************/
|
||||
|
||||
/*
|
||||
=================
|
||||
S_MP3_Scale
|
||||
|
||||
Converts the signal to 16 bit LE-PCM data and does dithering.
|
||||
|
||||
- borrowed from xmms-mad plugin source.
|
||||
=================
|
||||
*/
|
||||
|
||||
/*
|
||||
* xmms-mad - mp3 plugin for xmms
|
||||
* Copyright (C) 2001-2002 Sam Clegg
|
||||
*/
|
||||
|
||||
signed int S_MP3_Scale(mad_fixed_t sample)
|
||||
{
|
||||
int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16;
|
||||
#ifdef MP3_DITHERING
|
||||
int dither;
|
||||
#endif
|
||||
|
||||
// round
|
||||
sample += (1L << (n_bits_to_loose - 1));
|
||||
|
||||
#ifdef MP3_DITHERING
|
||||
dither = triangular_dither_noise(n_bits_to_loose + 1);
|
||||
sample += dither;
|
||||
#endif
|
||||
|
||||
/* clip */
|
||||
if (sample >= MAD_F_ONE)
|
||||
sample = MAD_F_ONE - 1;
|
||||
else if (sample < -MAD_F_ONE)
|
||||
sample = -MAD_F_ONE;
|
||||
|
||||
/* quantize */
|
||||
return sample >> n_bits_to_loose;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
S_MP3_PCMCopy
|
||||
|
||||
Copy and convert pcm data until bytecount bytes have been written.
|
||||
return the position in pcm->samples.
|
||||
indicate the amount of actually written bytes in wrotecnt.
|
||||
=================
|
||||
*/
|
||||
|
||||
int S_MP3_PCMCopy(byte *buf, struct mad_pcm *pcm, int bufofs,
|
||||
int sampleofs, int bytecount, int *wrotecnt)
|
||||
{
|
||||
int written = 0;
|
||||
signed int sample;
|
||||
int framesize = pcm->channels * MP3_SAMPLE_WIDTH;
|
||||
|
||||
// add new pcm data.
|
||||
while(written < bytecount && sampleofs < pcm->length)
|
||||
{
|
||||
sample = S_MP3_Scale(pcm->samples[0][sampleofs]);
|
||||
|
||||
#ifdef Q3_BIG_ENDIAN
|
||||
// output to 16 bit big endian PCM
|
||||
buf[bufofs++] = (sample >> 8) & 0xff;
|
||||
buf[bufofs++] = sample & 0xff;
|
||||
#else
|
||||
// output to 16 bit little endian PCM
|
||||
buf[bufofs++] = sample & 0xff;
|
||||
buf[bufofs++] = (sample >> 8) & 0xff;
|
||||
#endif
|
||||
|
||||
if(pcm->channels == 2)
|
||||
{
|
||||
sample = S_MP3_Scale(pcm->samples[1][sampleofs]);
|
||||
|
||||
#ifdef Q3_BIG_ENDIAN
|
||||
buf[bufofs++] = (sample >> 8) & 0xff;
|
||||
buf[bufofs++] = sample & 0xff;
|
||||
#else
|
||||
buf[bufofs++] = sample & 0xff;
|
||||
buf[bufofs++] = (sample >> 8) & 0xff;
|
||||
#endif
|
||||
}
|
||||
|
||||
sampleofs++;
|
||||
written += framesize;
|
||||
}
|
||||
|
||||
if(wrotecnt)
|
||||
*wrotecnt = written;
|
||||
|
||||
return sampleofs;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
S_MP3_Decode
|
||||
=================
|
||||
*/
|
||||
|
||||
// gets executed for every decoded frame.
|
||||
int S_MP3_Decode(snd_stream_t *stream)
|
||||
{
|
||||
struct snd_codec_mp3_info *mp3info;
|
||||
struct mad_stream *madstream;
|
||||
struct mad_frame *madframe;
|
||||
struct mad_synth *madsynth;
|
||||
struct mad_pcm *pcm;
|
||||
int cursize;
|
||||
int samplecount;
|
||||
int needcount;
|
||||
int wrote;
|
||||
int retval;
|
||||
|
||||
if(!stream)
|
||||
return -1;
|
||||
|
||||
mp3info = stream->ptr;
|
||||
madstream = &mp3info->madstream;
|
||||
madframe = &mp3info->madframe;
|
||||
|
||||
if(mad_frame_decode(madframe, madstream))
|
||||
{
|
||||
if(madstream->error == MAD_ERROR_BUFLEN)
|
||||
{
|
||||
// we need more data. Read another chunk.
|
||||
retval = S_MP3_ReadData(stream, madstream, mp3info->encbuf, sizeof(mp3info->encbuf));
|
||||
|
||||
// call myself again now that buffer is full.
|
||||
if(retval > 0)
|
||||
retval = S_MP3_Decode(stream);
|
||||
}
|
||||
else if(MAD_RECOVERABLE(madstream->error))
|
||||
{
|
||||
mad_stream_skip(madstream, madstream->skiplen);
|
||||
return S_MP3_Decode(stream);
|
||||
}
|
||||
else
|
||||
retval = -1;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// check whether this really is an mp3
|
||||
if(madframe->header.layer != MAD_LAYER_III)
|
||||
return -1;
|
||||
|
||||
// generate pcm data
|
||||
madsynth = &mp3info->madsynth;
|
||||
mad_synth_frame(madsynth, madframe);
|
||||
|
||||
pcm = &madsynth->pcm;
|
||||
|
||||
// perform a few checks to see whether something changed that shouldn't.
|
||||
|
||||
if(stream->info.rate != pcm->samplerate ||
|
||||
stream->info.channels != pcm->channels)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// see whether we have got enough data now.
|
||||
cursize = pcm->length * pcm->channels * stream->info.width;
|
||||
needcount = mp3info->destsize - mp3info->destlen;
|
||||
|
||||
// Copy exactly as many samples as required.
|
||||
samplecount = S_MP3_PCMCopy(mp3info->dest, pcm,
|
||||
mp3info->destlen, 0, needcount, &wrote);
|
||||
mp3info->destlen += wrote;
|
||||
|
||||
if(samplecount < pcm->length)
|
||||
{
|
||||
// Not all samples got copied. Copy the rest into the pcm buffer.
|
||||
samplecount = S_MP3_PCMCopy(mp3info->pcmbuf, pcm,
|
||||
mp3info->buflen,
|
||||
samplecount,
|
||||
mp3info->pcmbufsize - mp3info->buflen,
|
||||
&wrote);
|
||||
mp3info->buflen += wrote;
|
||||
|
||||
|
||||
if(samplecount < pcm->length)
|
||||
{
|
||||
// The pcm buffer was not large enough. Make it bigger.
|
||||
byte *newbuf = Z_Malloc(cursize);
|
||||
|
||||
if(mp3info->pcmbuf)
|
||||
{
|
||||
memcpy(newbuf, mp3info->pcmbuf, mp3info->buflen);
|
||||
Z_Free(mp3info->pcmbuf);
|
||||
}
|
||||
|
||||
mp3info->pcmbuf = newbuf;
|
||||
mp3info->pcmbufsize = cursize;
|
||||
|
||||
samplecount = S_MP3_PCMCopy(mp3info->pcmbuf, pcm,
|
||||
mp3info->buflen,
|
||||
samplecount,
|
||||
mp3info->pcmbufsize - mp3info->buflen,
|
||||
&wrote);
|
||||
mp3info->buflen += wrote;
|
||||
}
|
||||
|
||||
// we're definitely done.
|
||||
retval = 0;
|
||||
}
|
||||
else if(mp3info->destlen >= mp3info->destsize)
|
||||
retval = 0;
|
||||
else
|
||||
retval = 1;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*************** Callback functions for quake3 ***************/
|
||||
|
||||
/*
|
||||
=================
|
||||
S_MP3_CodecOpenStream
|
||||
=================
|
||||
*/
|
||||
|
||||
snd_stream_t *S_MP3_CodecOpenStream(const char *filename)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
struct snd_codec_mp3_info *mp3info;
|
||||
|
||||
// Open the stream
|
||||
stream = S_CodecUtilOpen(filename, &mp3_codec);
|
||||
if(!stream || stream->length <= 0)
|
||||
return NULL;
|
||||
|
||||
// We have to scan through the MP3 to determine the important mp3 info.
|
||||
if(S_MP3_Scanfile(stream) < 0)
|
||||
{
|
||||
// scanning didn't work out...
|
||||
S_CodecUtilClose(&stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Initialize the mp3 info structure we need for streaming
|
||||
mp3info = Z_Malloc(sizeof(*mp3info));
|
||||
if(!mp3info)
|
||||
{
|
||||
S_CodecUtilClose(&stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stream->ptr = mp3info;
|
||||
|
||||
// initialize the libmad control structures.
|
||||
mad_stream_init(&mp3info->madstream);
|
||||
mad_frame_init(&mp3info->madframe);
|
||||
mad_synth_init(&mp3info->madsynth);
|
||||
|
||||
if(S_MP3_ReadData(stream, &mp3info->madstream, mp3info->encbuf, sizeof(mp3info->encbuf)) <= 0)
|
||||
{
|
||||
// we didnt read anything, that's bad.
|
||||
S_MP3_CodecCloseStream(stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_MP3_CodecCloseStream
|
||||
=================
|
||||
*/
|
||||
|
||||
// free all memory we allocated.
|
||||
void S_MP3_CodecCloseStream(snd_stream_t *stream)
|
||||
{
|
||||
struct snd_codec_mp3_info *mp3info;
|
||||
|
||||
if(!stream)
|
||||
return;
|
||||
|
||||
// free all data in our mp3info tree
|
||||
|
||||
if(stream->ptr)
|
||||
{
|
||||
mp3info = stream->ptr;
|
||||
|
||||
if(mp3info->pcmbuf)
|
||||
Z_Free(mp3info->pcmbuf);
|
||||
|
||||
mad_synth_finish(&mp3info->madsynth);
|
||||
mad_frame_finish(&mp3info->madframe);
|
||||
mad_stream_finish(&mp3info->madstream);
|
||||
|
||||
Z_Free(stream->ptr);
|
||||
}
|
||||
|
||||
S_CodecUtilClose(&stream);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_MP3_CodecReadStream
|
||||
=================
|
||||
*/
|
||||
int S_MP3_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
|
||||
{
|
||||
struct snd_codec_mp3_info *mp3info;
|
||||
int retval;
|
||||
|
||||
if(!stream)
|
||||
return -1;
|
||||
|
||||
mp3info = stream->ptr;
|
||||
|
||||
// Make sure we get complete frames all the way through.
|
||||
bytes -= bytes % (stream->info.channels * stream->info.width);
|
||||
|
||||
if(mp3info->buflen)
|
||||
{
|
||||
if(bytes < mp3info->buflen)
|
||||
{
|
||||
// we still have enough bytes in our decoded pcm buffer
|
||||
memcpy(buffer, mp3info->pcmbuf, bytes);
|
||||
|
||||
// remove the portion from our buffer.
|
||||
mp3info->buflen -= bytes;
|
||||
memmove(mp3info->pcmbuf, &mp3info->pcmbuf[bytes], mp3info->buflen);
|
||||
return bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy over the samples we already have.
|
||||
memcpy(buffer, mp3info->pcmbuf, mp3info->buflen);
|
||||
mp3info->destlen = mp3info->buflen;
|
||||
mp3info->buflen = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
mp3info->destlen = 0;
|
||||
|
||||
mp3info->dest = buffer;
|
||||
mp3info->destsize = bytes;
|
||||
|
||||
do
|
||||
{
|
||||
retval = S_MP3_Decode(stream);
|
||||
} while(retval > 0);
|
||||
|
||||
// if there was an error return nothing.
|
||||
if(retval < 0)
|
||||
return 0;
|
||||
|
||||
return mp3info->destlen;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================================================
|
||||
S_MP3_CodecLoad
|
||||
|
||||
We handle S_MP3_CodecLoad as a special case of the streaming functions
|
||||
where we read the whole stream at once.
|
||||
======================================================================
|
||||
*/
|
||||
void *S_MP3_CodecLoad(const char *filename, snd_info_t *info)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
byte *pcmbuffer;
|
||||
|
||||
// check if input is valid
|
||||
if(!filename)
|
||||
return NULL;
|
||||
|
||||
stream = S_MP3_CodecOpenStream(filename);
|
||||
|
||||
if(!stream)
|
||||
return NULL;
|
||||
|
||||
// copy over the info
|
||||
info->rate = stream->info.rate;
|
||||
info->width = stream->info.width;
|
||||
info->channels = stream->info.channels;
|
||||
info->samples = stream->info.samples;
|
||||
info->dataofs = stream->info.dataofs;
|
||||
|
||||
// allocate enough buffer for all pcm data
|
||||
// pcmbuffer = Z_Malloc(stream->info.size);
|
||||
pcmbuffer = Hunk_AllocateTempMemory(stream->info.size);
|
||||
|
||||
if(!pcmbuffer)
|
||||
{
|
||||
S_MP3_CodecCloseStream(stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info->size = S_MP3_CodecReadStream(stream, stream->info.size, pcmbuffer);
|
||||
|
||||
if(info->size <= 0)
|
||||
{
|
||||
// we didn't read anything at all. darn.
|
||||
// Z_Free(pcmbuffer);
|
||||
Hunk_FreeTempMemory(pcmbuffer);
|
||||
pcmbuffer = NULL;
|
||||
}
|
||||
|
||||
S_MP3_CodecCloseStream(stream);
|
||||
|
||||
return pcmbuffer;
|
||||
}
|
||||
#endif
|
||||
@@ -1,475 +0,0 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||
Copyright (C) 2005-2006 Joerg Dietrich <dietrich_joerg@gmx.de>
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Quake III Arena source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// OGG support is enabled by this define
|
||||
#ifdef USE_CODEC_VORBIS
|
||||
|
||||
// includes for the Q3 sound system
|
||||
#include "client.h"
|
||||
#include "snd_codec.h"
|
||||
|
||||
// includes for the OGG codec
|
||||
#include <errno.h>
|
||||
#define OV_EXCLUDE_STATIC_CALLBACKS
|
||||
#include <vorbis/vorbisfile.h>
|
||||
|
||||
// The OGG codec can return the samples in a number of different formats,
|
||||
// we use the standard signed short format.
|
||||
#define OGG_SAMPLEWIDTH 2
|
||||
|
||||
// Q3 OGG codec
|
||||
snd_codec_t ogg_codec =
|
||||
{
|
||||
"ogg",
|
||||
S_OGG_CodecLoad,
|
||||
S_OGG_CodecOpenStream,
|
||||
S_OGG_CodecReadStream,
|
||||
S_OGG_CodecCloseStream,
|
||||
NULL
|
||||
};
|
||||
|
||||
// callbacks for vobisfile
|
||||
|
||||
// fread() replacement
|
||||
size_t S_OGG_Callback_read(void *ptr, size_t size, size_t nmemb, void *datasource)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
int byteSize = 0;
|
||||
int bytesRead = 0;
|
||||
size_t nMembRead = 0;
|
||||
|
||||
// check if input is valid
|
||||
if(!ptr)
|
||||
{
|
||||
errno = EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!(size && nmemb))
|
||||
{
|
||||
// It's not an error, caller just wants zero bytes!
|
||||
errno = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!datasource)
|
||||
{
|
||||
errno = EBADF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// we use a snd_stream_t in the generic pointer to pass around
|
||||
stream = (snd_stream_t *) datasource;
|
||||
|
||||
// FS_Read does not support multi-byte elements
|
||||
byteSize = nmemb * size;
|
||||
|
||||
// read it with the Q3 function FS_Read()
|
||||
bytesRead = FS_Read(ptr, byteSize, stream->file);
|
||||
|
||||
// update the file position
|
||||
stream->pos += bytesRead;
|
||||
|
||||
// this function returns the number of elements read not the number of bytes
|
||||
nMembRead = bytesRead / size;
|
||||
|
||||
// even if the last member is only read partially
|
||||
// it is counted as a whole in the return value
|
||||
if(bytesRead % size)
|
||||
{
|
||||
nMembRead++;
|
||||
}
|
||||
|
||||
return nMembRead;
|
||||
}
|
||||
|
||||
// fseek() replacement
|
||||
int S_OGG_Callback_seek(void *datasource, ogg_int64_t offset, int whence)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
int retVal = 0;
|
||||
|
||||
// check if input is valid
|
||||
if(!datasource)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// snd_stream_t in the generic pointer
|
||||
stream = (snd_stream_t *) datasource;
|
||||
|
||||
// we must map the whence to its Q3 counterpart
|
||||
switch(whence)
|
||||
{
|
||||
case SEEK_SET :
|
||||
{
|
||||
// set the file position in the actual file with the Q3 function
|
||||
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_SET);
|
||||
|
||||
// something has gone wrong, so we return here
|
||||
if(retVal < 0)
|
||||
{
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// keep track of file position
|
||||
stream->pos = (int) offset;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEEK_CUR :
|
||||
{
|
||||
// set the file position in the actual file with the Q3 function
|
||||
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_CUR);
|
||||
|
||||
// something has gone wrong, so we return here
|
||||
if(retVal < 0)
|
||||
{
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// keep track of file position
|
||||
stream->pos += (int) offset;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEEK_END :
|
||||
{
|
||||
// set the file position in the actual file with the Q3 function
|
||||
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_END);
|
||||
|
||||
// something has gone wrong, so we return here
|
||||
if(retVal < 0)
|
||||
{
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// keep track of file position
|
||||
stream->pos = stream->length + (int) offset;
|
||||
break;
|
||||
}
|
||||
|
||||
default :
|
||||
{
|
||||
// unknown whence, so we return an error
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// stream->pos shouldn't be smaller than zero or bigger than the filesize
|
||||
stream->pos = (stream->pos < 0) ? 0 : stream->pos;
|
||||
stream->pos = (stream->pos > stream->length) ? stream->length : stream->pos;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fclose() replacement
|
||||
int S_OGG_Callback_close(void *datasource)
|
||||
{
|
||||
// we do nothing here and close all things manually in S_OGG_CodecCloseStream()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ftell() replacement
|
||||
long S_OGG_Callback_tell(void *datasource)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
|
||||
// check if input is valid
|
||||
if(!datasource)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// snd_stream_t in the generic pointer
|
||||
stream = (snd_stream_t *) datasource;
|
||||
|
||||
return (long) FS_FTell(stream->file);
|
||||
}
|
||||
|
||||
// the callback structure
|
||||
const ov_callbacks S_OGG_Callbacks =
|
||||
{
|
||||
&S_OGG_Callback_read,
|
||||
&S_OGG_Callback_seek,
|
||||
&S_OGG_Callback_close,
|
||||
&S_OGG_Callback_tell
|
||||
};
|
||||
|
||||
/*
|
||||
=================
|
||||
S_OGG_CodecOpenStream
|
||||
=================
|
||||
*/
|
||||
snd_stream_t *S_OGG_CodecOpenStream(const char *filename)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
|
||||
// OGG codec control structure
|
||||
OggVorbis_File *vf;
|
||||
|
||||
// some variables used to get informations about the OGG
|
||||
vorbis_info *OGGInfo;
|
||||
ogg_int64_t numSamples;
|
||||
|
||||
// check if input is valid
|
||||
if(!filename)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Open the stream
|
||||
stream = S_CodecUtilOpen(filename, &ogg_codec);
|
||||
if(!stream)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// alloctate the OggVorbis_File
|
||||
vf = Z_Malloc(sizeof(OggVorbis_File));
|
||||
if(!vf)
|
||||
{
|
||||
S_CodecUtilClose(&stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// open the codec with our callbacks and stream as the generic pointer
|
||||
if(ov_open_callbacks(stream, vf, NULL, 0, S_OGG_Callbacks) != 0)
|
||||
{
|
||||
Z_Free(vf);
|
||||
|
||||
S_CodecUtilClose(&stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// the stream must be seekable
|
||||
if(!ov_seekable(vf))
|
||||
{
|
||||
ov_clear(vf);
|
||||
|
||||
Z_Free(vf);
|
||||
|
||||
S_CodecUtilClose(&stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// we only support OGGs with one substream
|
||||
if(ov_streams(vf) != 1)
|
||||
{
|
||||
ov_clear(vf);
|
||||
|
||||
Z_Free(vf);
|
||||
|
||||
S_CodecUtilClose(&stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the info about channels and rate
|
||||
OGGInfo = ov_info(vf, 0);
|
||||
if(!OGGInfo)
|
||||
{
|
||||
ov_clear(vf);
|
||||
|
||||
Z_Free(vf);
|
||||
|
||||
S_CodecUtilClose(&stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the number of sample-frames in the OGG
|
||||
numSamples = ov_pcm_total(vf, 0);
|
||||
|
||||
// fill in the info-structure in the stream
|
||||
stream->info.rate = OGGInfo->rate;
|
||||
stream->info.width = OGG_SAMPLEWIDTH;
|
||||
stream->info.channels = OGGInfo->channels;
|
||||
stream->info.samples = numSamples;
|
||||
stream->info.size = stream->info.samples * stream->info.channels * stream->info.width;
|
||||
stream->info.dataofs = 0;
|
||||
|
||||
// We use stream->pos for the file pointer in the compressed ogg file
|
||||
stream->pos = 0;
|
||||
|
||||
// We use the generic pointer in stream for the OGG codec control structure
|
||||
stream->ptr = vf;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_OGG_CodecCloseStream
|
||||
=================
|
||||
*/
|
||||
void S_OGG_CodecCloseStream(snd_stream_t *stream)
|
||||
{
|
||||
// check if input is valid
|
||||
if(!stream)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// let the OGG codec cleanup its stuff
|
||||
ov_clear((OggVorbis_File *) stream->ptr);
|
||||
|
||||
// free the OGG codec control struct
|
||||
Z_Free(stream->ptr);
|
||||
|
||||
// close the stream
|
||||
S_CodecUtilClose(&stream);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_OGG_CodecReadStream
|
||||
=================
|
||||
*/
|
||||
int S_OGG_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
|
||||
{
|
||||
// buffer handling
|
||||
int bytesRead, bytesLeft, c;
|
||||
char *bufPtr;
|
||||
|
||||
// Bitstream for the decoder
|
||||
int BS = 0;
|
||||
|
||||
// big endian machines want their samples in big endian order
|
||||
int IsBigEndian = 0;
|
||||
|
||||
# ifdef Q3_BIG_ENDIAN
|
||||
IsBigEndian = 1;
|
||||
# endif // Q3_BIG_ENDIAN
|
||||
|
||||
// check if input is valid
|
||||
if(!(stream && buffer))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(bytes <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytesRead = 0;
|
||||
bytesLeft = bytes;
|
||||
bufPtr = buffer;
|
||||
|
||||
// cycle until we have the requested or all available bytes read
|
||||
while(-1)
|
||||
{
|
||||
// read some bytes from the OGG codec
|
||||
c = ov_read((OggVorbis_File *) stream->ptr, bufPtr, bytesLeft, IsBigEndian, OGG_SAMPLEWIDTH, 1, &BS);
|
||||
|
||||
// no more bytes are left
|
||||
if(c <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
bytesRead += c;
|
||||
bytesLeft -= c;
|
||||
bufPtr += c;
|
||||
|
||||
// we have enough bytes
|
||||
if(bytesLeft <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================================================
|
||||
S_OGG_CodecLoad
|
||||
|
||||
We handle S_OGG_CodecLoad as a special case of the streaming functions
|
||||
where we read the whole stream at once.
|
||||
======================================================================
|
||||
*/
|
||||
void *S_OGG_CodecLoad(const char *filename, snd_info_t *info)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
byte *buffer;
|
||||
int bytesRead;
|
||||
|
||||
// check if input is valid
|
||||
if(!(filename && info))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// open the file as a stream
|
||||
stream = S_OGG_CodecOpenStream(filename);
|
||||
if(!stream)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// copy over the info
|
||||
info->rate = stream->info.rate;
|
||||
info->width = stream->info.width;
|
||||
info->channels = stream->info.channels;
|
||||
info->samples = stream->info.samples;
|
||||
info->size = stream->info.size;
|
||||
info->dataofs = stream->info.dataofs;
|
||||
|
||||
// allocate a buffer
|
||||
// this buffer must be free-ed by the caller of this function
|
||||
buffer = Hunk_AllocateTempMemory(info->size);
|
||||
if(!buffer)
|
||||
{
|
||||
S_OGG_CodecCloseStream(stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// fill the buffer
|
||||
bytesRead = S_OGG_CodecReadStream(stream, info->size, buffer);
|
||||
|
||||
// we don't even have read a single byte
|
||||
if(bytesRead <= 0)
|
||||
{
|
||||
Hunk_FreeTempMemory(buffer);
|
||||
S_OGG_CodecCloseStream(stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
S_OGG_CodecCloseStream(stream);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#endif // USE_CODEC_VORBIS
|
||||
@@ -1,449 +0,0 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||
Copyright (C) 2005-2006 Joerg Dietrich <dietrich_joerg@gmx.de>
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Quake III Arena source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// Ogg Opus support is enabled by this define
|
||||
#ifdef USE_CODEC_OPUS
|
||||
|
||||
// includes for the Q3 sound system
|
||||
#include "client.h"
|
||||
#include "snd_codec.h"
|
||||
|
||||
// includes for the Ogg Opus codec
|
||||
#include <errno.h>
|
||||
#include <opusfile.h>
|
||||
|
||||
// samples are 16 bit
|
||||
#define OPUS_SAMPLEWIDTH 2
|
||||
|
||||
// Q3 Ogg Opus codec
|
||||
snd_codec_t opus_codec =
|
||||
{
|
||||
"opus",
|
||||
S_OggOpus_CodecLoad,
|
||||
S_OggOpus_CodecOpenStream,
|
||||
S_OggOpus_CodecReadStream,
|
||||
S_OggOpus_CodecCloseStream,
|
||||
NULL
|
||||
};
|
||||
|
||||
// callbacks for opusfile
|
||||
|
||||
// fread() replacement
|
||||
int S_OggOpus_Callback_read(void *datasource, unsigned char *ptr, int size )
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
int bytesRead = 0;
|
||||
|
||||
// check if input is valid
|
||||
if(!ptr)
|
||||
{
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!size)
|
||||
{
|
||||
// It's not an error, caller just wants zero bytes!
|
||||
errno = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!datasource)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// we use a snd_stream_t in the generic pointer to pass around
|
||||
stream = (snd_stream_t *) datasource;
|
||||
|
||||
// read it with the Q3 function FS_Read()
|
||||
bytesRead = FS_Read(ptr, size, stream->file);
|
||||
|
||||
// update the file position
|
||||
stream->pos += bytesRead;
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
// fseek() replacement
|
||||
int S_OggOpus_Callback_seek(void *datasource, opus_int64 offset, int whence)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
int retVal = 0;
|
||||
|
||||
// check if input is valid
|
||||
if(!datasource)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// snd_stream_t in the generic pointer
|
||||
stream = (snd_stream_t *) datasource;
|
||||
|
||||
// we must map the whence to its Q3 counterpart
|
||||
switch(whence)
|
||||
{
|
||||
case SEEK_SET :
|
||||
{
|
||||
// set the file position in the actual file with the Q3 function
|
||||
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_SET);
|
||||
|
||||
// something has gone wrong, so we return here
|
||||
if(retVal < 0)
|
||||
{
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// keep track of file position
|
||||
stream->pos = (int) offset;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEEK_CUR :
|
||||
{
|
||||
// set the file position in the actual file with the Q3 function
|
||||
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_CUR);
|
||||
|
||||
// something has gone wrong, so we return here
|
||||
if(retVal < 0)
|
||||
{
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// keep track of file position
|
||||
stream->pos += (int) offset;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEEK_END :
|
||||
{
|
||||
// set the file position in the actual file with the Q3 function
|
||||
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_END);
|
||||
|
||||
// something has gone wrong, so we return here
|
||||
if(retVal < 0)
|
||||
{
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// keep track of file position
|
||||
stream->pos = stream->length + (int) offset;
|
||||
break;
|
||||
}
|
||||
|
||||
default :
|
||||
{
|
||||
// unknown whence, so we return an error
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// stream->pos shouldn't be smaller than zero or bigger than the filesize
|
||||
stream->pos = (stream->pos < 0) ? 0 : stream->pos;
|
||||
stream->pos = (stream->pos > stream->length) ? stream->length : stream->pos;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fclose() replacement
|
||||
int S_OggOpus_Callback_close(void *datasource)
|
||||
{
|
||||
// we do nothing here and close all things manually in S_OggOpus_CodecCloseStream()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ftell() replacement
|
||||
opus_int64 S_OggOpus_Callback_tell(void *datasource)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
|
||||
// check if input is valid
|
||||
if(!datasource)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// snd_stream_t in the generic pointer
|
||||
stream = (snd_stream_t *) datasource;
|
||||
|
||||
return (opus_int64) FS_FTell(stream->file);
|
||||
}
|
||||
|
||||
// the callback structure
|
||||
const OpusFileCallbacks S_OggOpus_Callbacks =
|
||||
{
|
||||
&S_OggOpus_Callback_read,
|
||||
&S_OggOpus_Callback_seek,
|
||||
&S_OggOpus_Callback_tell,
|
||||
&S_OggOpus_Callback_close
|
||||
};
|
||||
|
||||
/*
|
||||
=================
|
||||
S_OggOpus_CodecOpenStream
|
||||
=================
|
||||
*/
|
||||
snd_stream_t *S_OggOpus_CodecOpenStream(const char *filename)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
|
||||
// Opus codec control structure
|
||||
OggOpusFile *of;
|
||||
|
||||
// some variables used to get informations about the file
|
||||
const OpusHead *opusInfo;
|
||||
ogg_int64_t numSamples;
|
||||
|
||||
// check if input is valid
|
||||
if(!filename)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Open the stream
|
||||
stream = S_CodecUtilOpen(filename, &opus_codec);
|
||||
if(!stream)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// open the codec with our callbacks and stream as the generic pointer
|
||||
of = op_open_callbacks(stream, &S_OggOpus_Callbacks, NULL, 0, NULL );
|
||||
if (!of)
|
||||
{
|
||||
S_CodecUtilClose(&stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// the stream must be seekable
|
||||
if(!op_seekable(of))
|
||||
{
|
||||
op_free(of);
|
||||
|
||||
S_CodecUtilClose(&stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the info about channels and rate
|
||||
opusInfo = op_head(of, -1);
|
||||
if(!opusInfo)
|
||||
{
|
||||
op_free(of);
|
||||
|
||||
S_CodecUtilClose(&stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(opusInfo->stream_count != 1)
|
||||
{
|
||||
op_free(of);
|
||||
|
||||
S_CodecUtilClose(&stream);
|
||||
|
||||
Com_Printf("Only Ogg Opus files with one stream are support\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(opusInfo->channel_count != 1 && opusInfo->channel_count != 2)
|
||||
{
|
||||
op_free(of);
|
||||
|
||||
S_CodecUtilClose(&stream);
|
||||
|
||||
Com_Printf("Only mono and stereo Ogg Opus files are supported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the number of sample-frames in the file
|
||||
numSamples = op_pcm_total(of, -1);
|
||||
|
||||
// fill in the info-structure in the stream
|
||||
stream->info.rate = 48000;
|
||||
stream->info.width = OPUS_SAMPLEWIDTH;
|
||||
stream->info.channels = opusInfo->channel_count;
|
||||
stream->info.samples = numSamples;
|
||||
stream->info.size = stream->info.samples * stream->info.channels * stream->info.width;
|
||||
stream->info.dataofs = 0;
|
||||
|
||||
// We use stream->pos for the file pointer in the compressed ogg file
|
||||
stream->pos = 0;
|
||||
|
||||
// We use the generic pointer in stream for the opus codec control structure
|
||||
stream->ptr = of;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_OggOpus_CodecCloseStream
|
||||
=================
|
||||
*/
|
||||
void S_OggOpus_CodecCloseStream(snd_stream_t *stream)
|
||||
{
|
||||
// check if input is valid
|
||||
if(!stream)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// let the opus codec cleanup its stuff
|
||||
op_free((OggOpusFile *) stream->ptr);
|
||||
|
||||
// close the stream
|
||||
S_CodecUtilClose(&stream);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_OggOpus_CodecReadStream
|
||||
=================
|
||||
*/
|
||||
int S_OggOpus_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
|
||||
{
|
||||
// buffer handling
|
||||
int samplesRead, samplesLeft, c;
|
||||
opus_int16 *bufPtr;
|
||||
|
||||
// check if input is valid
|
||||
if(!(stream && buffer))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(bytes <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
samplesRead = 0;
|
||||
samplesLeft = bytes / stream->info.channels / stream->info.width;
|
||||
bufPtr = buffer;
|
||||
|
||||
if(samplesLeft <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cycle until we have the requested or all available bytes read
|
||||
while(-1)
|
||||
{
|
||||
// read some samples from the opus codec
|
||||
c = op_read((OggOpusFile *) stream->ptr, bufPtr + samplesRead * stream->info.channels, samplesLeft * stream->info.channels, NULL);
|
||||
|
||||
// no more samples are left
|
||||
if(c <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
samplesRead += c;
|
||||
samplesLeft -= c;
|
||||
|
||||
// we have enough samples
|
||||
if(samplesLeft <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return samplesRead * stream->info.channels * stream->info.width;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================================================
|
||||
S_OggOpus_CodecLoad
|
||||
|
||||
We handle S_OggOpus_CodecLoad as a special case of the streaming functions
|
||||
where we read the whole stream at once.
|
||||
======================================================================
|
||||
*/
|
||||
void *S_OggOpus_CodecLoad(const char *filename, snd_info_t *info)
|
||||
{
|
||||
snd_stream_t *stream;
|
||||
byte *buffer;
|
||||
int bytesRead;
|
||||
|
||||
// check if input is valid
|
||||
if(!(filename && info))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// open the file as a stream
|
||||
stream = S_OggOpus_CodecOpenStream(filename);
|
||||
if(!stream)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// copy over the info
|
||||
info->rate = stream->info.rate;
|
||||
info->width = stream->info.width;
|
||||
info->channels = stream->info.channels;
|
||||
info->samples = stream->info.samples;
|
||||
info->size = stream->info.size;
|
||||
info->dataofs = stream->info.dataofs;
|
||||
|
||||
// allocate a buffer
|
||||
// this buffer must be free-ed by the caller of this function
|
||||
buffer = Hunk_AllocateTempMemory(info->size);
|
||||
if(!buffer)
|
||||
{
|
||||
S_OggOpus_CodecCloseStream(stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// fill the buffer
|
||||
bytesRead = S_OggOpus_CodecReadStream(stream, info->size, buffer);
|
||||
|
||||
// we don't even have read a single byte
|
||||
if(bytesRead <= 0)
|
||||
{
|
||||
Hunk_FreeTempMemory(buffer);
|
||||
S_OggOpus_CodecCloseStream(stream);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
S_OggOpus_CodecCloseStream(stream);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#endif // USE_CODEC_OPUS
|
||||
@@ -1,291 +0,0 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Quake III Arena source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "snd_codec.h"
|
||||
|
||||
/*
|
||||
=================
|
||||
FGetLittleLong
|
||||
=================
|
||||
*/
|
||||
static int FGetLittleLong( fileHandle_t f ) {
|
||||
int v;
|
||||
|
||||
FS_Read( &v, sizeof(v), f );
|
||||
|
||||
return LittleLong( v);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
FGetLittleShort
|
||||
=================
|
||||
*/
|
||||
static short FGetLittleShort( fileHandle_t f ) {
|
||||
short v;
|
||||
|
||||
FS_Read( &v, sizeof(v), f );
|
||||
|
||||
return LittleShort( v);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_ReadChunkInfo
|
||||
=================
|
||||
*/
|
||||
static int S_ReadChunkInfo(fileHandle_t f, char *name)
|
||||
{
|
||||
int len, r;
|
||||
|
||||
name[4] = 0;
|
||||
|
||||
r = FS_Read(name, 4, f);
|
||||
if(r != 4)
|
||||
return -1;
|
||||
|
||||
len = FGetLittleLong(f);
|
||||
if( len < 0 ) {
|
||||
Com_Printf( S_COLOR_YELLOW "WARNING: Negative chunk length\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_FindRIFFChunk
|
||||
|
||||
Returns the length of the data in the chunk, or -1 if not found
|
||||
=================
|
||||
*/
|
||||
static int S_FindRIFFChunk( fileHandle_t f, char *chunk ) {
|
||||
char name[5];
|
||||
int len;
|
||||
|
||||
while( ( len = S_ReadChunkInfo(f, name) ) >= 0 )
|
||||
{
|
||||
// If this is the right chunk, return
|
||||
if( !Q_strncmp( name, chunk, 4 ) )
|
||||
return len;
|
||||
|
||||
len = PAD( len, 2 );
|
||||
|
||||
// Not the right chunk - skip it
|
||||
FS_Seek( f, len, FS_SEEK_CUR );
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_ByteSwapRawSamples
|
||||
=================
|
||||
*/
|
||||
static void S_ByteSwapRawSamples( int samples, int width, int s_channels, const byte *data ) {
|
||||
int i;
|
||||
|
||||
if ( width != 2 ) {
|
||||
return;
|
||||
}
|
||||
if ( LittleShort( 256 ) == 256 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( s_channels == 2 ) {
|
||||
samples <<= 1;
|
||||
}
|
||||
for ( i = 0 ; i < samples ; i++ ) {
|
||||
((short *)data)[i] = LittleShort( ((short *)data)[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_ReadRIFFHeader
|
||||
=================
|
||||
*/
|
||||
static qboolean S_ReadRIFFHeader(fileHandle_t file, snd_info_t *info)
|
||||
{
|
||||
char dump[16];
|
||||
int bits;
|
||||
int fmtlen = 0;
|
||||
|
||||
// skip the riff wav header
|
||||
FS_Read(dump, 12, file);
|
||||
|
||||
// Scan for the format chunk
|
||||
if((fmtlen = S_FindRIFFChunk(file, "fmt ")) < 0)
|
||||
{
|
||||
Com_Printf( S_COLOR_RED "ERROR: Couldn't find \"fmt\" chunk\n");
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// Save the parameters
|
||||
FGetLittleShort(file); // wav_format
|
||||
info->channels = FGetLittleShort(file);
|
||||
info->rate = FGetLittleLong(file);
|
||||
FGetLittleLong(file);
|
||||
FGetLittleShort(file);
|
||||
bits = FGetLittleShort(file);
|
||||
|
||||
if( bits < 8 )
|
||||
{
|
||||
Com_Printf( S_COLOR_RED "ERROR: Less than 8 bit sound is not supported\n");
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
info->width = bits / 8;
|
||||
info->dataofs = 0;
|
||||
|
||||
// Skip the rest of the format chunk if required
|
||||
if(fmtlen > 16)
|
||||
{
|
||||
fmtlen -= 16;
|
||||
FS_Seek( file, fmtlen, FS_SEEK_CUR );
|
||||
}
|
||||
|
||||
// Scan for the data chunk
|
||||
if( (info->size = S_FindRIFFChunk(file, "data")) < 0)
|
||||
{
|
||||
Com_Printf( S_COLOR_RED "ERROR: Couldn't find \"data\" chunk\n");
|
||||
return qfalse;
|
||||
}
|
||||
info->samples = (info->size / info->width) / info->channels;
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
// WAV codec
|
||||
snd_codec_t wav_codec =
|
||||
{
|
||||
"wav",
|
||||
S_WAV_CodecLoad,
|
||||
S_WAV_CodecOpenStream,
|
||||
S_WAV_CodecReadStream,
|
||||
S_WAV_CodecCloseStream,
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
=================
|
||||
S_WAV_CodecLoad
|
||||
=================
|
||||
*/
|
||||
void *S_WAV_CodecLoad(const char *filename, snd_info_t *info)
|
||||
{
|
||||
fileHandle_t file;
|
||||
void *buffer;
|
||||
|
||||
// Try to open the file
|
||||
FS_FOpenFileRead(filename, &file, qtrue, qtrue);
|
||||
if(!file)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read the RIFF header
|
||||
if(!S_ReadRIFFHeader(file, info))
|
||||
{
|
||||
FS_FCloseFile(file);
|
||||
Com_Printf( S_COLOR_RED "ERROR: Incorrect/unsupported format in \"%s\"\n",
|
||||
filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate some memory
|
||||
buffer = Hunk_AllocateTempMemory(info->size);
|
||||
if(!buffer)
|
||||
{
|
||||
FS_FCloseFile(file);
|
||||
Com_Printf( S_COLOR_RED "ERROR: Out of memory reading \"%s\"\n",
|
||||
filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read, byteswap
|
||||
FS_Read(buffer, info->size, file);
|
||||
S_ByteSwapRawSamples(info->samples, info->width, info->channels, (byte *)buffer);
|
||||
|
||||
// Close and return
|
||||
FS_FCloseFile(file);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_WAV_CodecOpenStream
|
||||
=================
|
||||
*/
|
||||
snd_stream_t *S_WAV_CodecOpenStream(const char *filename)
|
||||
{
|
||||
snd_stream_t *rv;
|
||||
|
||||
// Open
|
||||
rv = S_CodecUtilOpen(filename, &wav_codec);
|
||||
if(!rv)
|
||||
return NULL;
|
||||
|
||||
// Read the RIFF header
|
||||
if(!S_ReadRIFFHeader(rv->file, &rv->info))
|
||||
{
|
||||
S_CodecUtilClose(&rv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_WAV_CodecCloseStream
|
||||
=================
|
||||
*/
|
||||
void S_WAV_CodecCloseStream(snd_stream_t *stream)
|
||||
{
|
||||
S_CodecUtilClose(&stream);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_WAV_CodecReadStream
|
||||
=================
|
||||
*/
|
||||
int S_WAV_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
|
||||
{
|
||||
int remaining = stream->info.size - stream->pos;
|
||||
int samples;
|
||||
|
||||
if(remaining <= 0)
|
||||
return 0;
|
||||
if(bytes > remaining)
|
||||
bytes = remaining;
|
||||
stream->pos += bytes;
|
||||
samples = (bytes / stream->info.width) / stream->info.channels;
|
||||
FS_Read(buffer, bytes, stream->file);
|
||||
S_ByteSwapRawSamples(samples, stream->info.width, stream->info.channels, buffer);
|
||||
return bytes;
|
||||
}
|
||||
+789
-438
File diff suppressed because it is too large.
Load diff
+24
-87
@@ -15,14 +15,14 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
along with Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
// snd_local.h -- private sound definations
|
||||
|
||||
|
||||
#include "../qcommon/q_shared.h"
|
||||
#include "q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "snd_public.h"
|
||||
|
||||
@@ -30,9 +30,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
|
||||
#define PAINTBUFFER_SIZE 4096 // this is in samples
|
||||
|
||||
#define SND_CHUNK_SIZE 1024 // samples
|
||||
@@ -63,7 +60,6 @@ typedef struct sfx_s {
|
||||
qboolean soundCompressed; // not in Memory
|
||||
int soundCompressionMethod;
|
||||
int soundLength;
|
||||
int soundChannels;
|
||||
char soundName[MAX_QPATH];
|
||||
int lastTimeUsed;
|
||||
struct sfx_s *next;
|
||||
@@ -72,20 +68,14 @@ typedef struct sfx_s {
|
||||
typedef struct {
|
||||
int channels;
|
||||
int samples; // mono samples in buffer
|
||||
int fullsamples; // samples with all channels in buffer (samples divided by channels)
|
||||
int submission_chunk; // don't mix less than this #
|
||||
int samplebits;
|
||||
int isfloat;
|
||||
int speed;
|
||||
byte *buffer;
|
||||
} dma_t;
|
||||
|
||||
#define START_SAMPLE_IMMEDIATE 0x7fffffff
|
||||
|
||||
#define MAX_DOPPLER_SCALE 50.0f //arbitrary
|
||||
|
||||
#define THIRD_PERSON_THRESHOLD_SQ (48.0f*48.0f)
|
||||
|
||||
typedef struct loopSound_s {
|
||||
vec3_t origin;
|
||||
vec3_t velocity;
|
||||
@@ -114,7 +104,6 @@ typedef struct
|
||||
qboolean fixed_origin; // use origin instead of fetching entnum's origin
|
||||
sfx_t *thesfx; // sfx structure
|
||||
qboolean doppler;
|
||||
qboolean fullVolume;
|
||||
} channel_t;
|
||||
|
||||
|
||||
@@ -130,38 +119,6 @@ typedef struct {
|
||||
int dataofs; // chunk starts this many bytes from file start
|
||||
} wavinfo_t;
|
||||
|
||||
// Interface between Q3 sound "api" and the sound backend
|
||||
typedef struct
|
||||
{
|
||||
void (*Shutdown)(void);
|
||||
void (*StartSound)(const vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx );
|
||||
void (*StartLocalSound)( sfxHandle_t sfx, int channelNum );
|
||||
void (*StartBackgroundTrack)( const char *intro, const char *loop );
|
||||
void (*StopBackgroundTrack)( void );
|
||||
void (*RawSamples)(int stream, int samples, int rate, int width, int channels, const byte *data, float volume, int entityNum);
|
||||
void (*StopAllSounds)( void );
|
||||
void (*ClearLoopingSounds)( qboolean killall );
|
||||
void (*AddLoopingSound)( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
|
||||
void (*AddRealLoopingSound)( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
|
||||
void (*StopLoopingSound)(int entityNum );
|
||||
void (*Respatialize)( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater );
|
||||
void (*UpdateEntityPosition)( int entityNum, const vec3_t origin );
|
||||
void (*Update)( void );
|
||||
void (*DisableSounds)( void );
|
||||
void (*BeginRegistration)( void );
|
||||
sfxHandle_t (*RegisterSound)( const char *sample, qboolean compressed );
|
||||
void (*ClearSoundBuffer)( void );
|
||||
void (*SoundInfo)( void );
|
||||
void (*SoundList)( void );
|
||||
#ifdef USE_VOIP
|
||||
void (*StartCapture)( void );
|
||||
int (*AvailableCaptureSamples)( void );
|
||||
void (*Capture)( int samples, byte *data );
|
||||
void (*StopCapture)( void );
|
||||
void (*MasterGain)( float gain );
|
||||
#endif
|
||||
} soundInterface_t;
|
||||
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
@@ -184,51 +141,43 @@ void SNDDMA_BeginPainting (void);
|
||||
|
||||
void SNDDMA_Submit(void);
|
||||
|
||||
#ifdef USE_VOIP
|
||||
void SNDDMA_StartCapture(void);
|
||||
int SNDDMA_AvailableCaptureSamples(void);
|
||||
void SNDDMA_Capture(int samples, byte *data);
|
||||
void SNDDMA_StopCapture(void);
|
||||
void SNDDMA_MasterGain(float val);
|
||||
#endif
|
||||
|
||||
|
||||
//====================================================================
|
||||
|
||||
#define MAX_SOUNDCHANNELS 96
|
||||
#define MAX_CHANNELS 96
|
||||
|
||||
extern channel_t s_channels[MAX_SOUNDCHANNELS];
|
||||
extern channel_t loop_channels[MAX_SOUNDCHANNELS];
|
||||
extern channel_t s_channels[MAX_CHANNELS];
|
||||
extern channel_t loop_channels[MAX_CHANNELS];
|
||||
extern int numLoopChannels;
|
||||
|
||||
extern int s_paintedtime;
|
||||
extern int s_rawend;
|
||||
extern vec3_t listener_forward;
|
||||
extern vec3_t listener_right;
|
||||
extern vec3_t listener_up;
|
||||
extern dma_t dma;
|
||||
|
||||
#define MAX_RAW_SAMPLES 16384
|
||||
#define MAX_RAW_STREAMS (MAX_CLIENTS * 2 + 1)
|
||||
extern portable_samplepair_t s_rawsamples[MAX_RAW_STREAMS][MAX_RAW_SAMPLES];
|
||||
extern int s_rawend[MAX_RAW_STREAMS];
|
||||
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
|
||||
|
||||
extern cvar_t *s_volume;
|
||||
extern cvar_t *s_musicVolume;
|
||||
extern cvar_t *s_muted;
|
||||
extern cvar_t *s_doppler;
|
||||
extern cvar_t *s_volume;
|
||||
extern cvar_t *s_nosound;
|
||||
extern cvar_t *s_khz;
|
||||
extern cvar_t *s_show;
|
||||
extern cvar_t *s_mixahead;
|
||||
|
||||
extern cvar_t *s_testsound;
|
||||
extern cvar_t *s_testsound;
|
||||
extern cvar_t *s_separation;
|
||||
|
||||
qboolean S_LoadSound( sfx_t *sfx );
|
||||
|
||||
void SND_free(sndBuffer *v);
|
||||
sndBuffer* SND_malloc( void );
|
||||
void SND_setup( void );
|
||||
void SND_shutdown(void);
|
||||
sndBuffer* SND_malloc();
|
||||
void SND_setup();
|
||||
|
||||
void S_PaintChannels(int endtime);
|
||||
|
||||
void S_memoryLoad(sfx_t *sfx);
|
||||
portable_samplepair_t *S_GetRawSamplePointer();
|
||||
|
||||
// spatializes a channel
|
||||
void S_Spatialize(channel_t *ch);
|
||||
@@ -243,7 +192,7 @@ void S_AdpcmGetSamples(sndBuffer *chunk, short *to);
|
||||
#define SENTINEL_MULAW_ZERO_RUN 127
|
||||
#define SENTINEL_MULAW_FOUR_BIT_RUN 126
|
||||
|
||||
void S_FreeOldestSound( void );
|
||||
void S_FreeOldestSound();
|
||||
|
||||
#define NXStream byte
|
||||
|
||||
@@ -257,24 +206,12 @@ extern short *sfxScratchBuffer;
|
||||
extern sfx_t *sfxScratchPointer;
|
||||
extern int sfxScratchIndex;
|
||||
|
||||
qboolean S_Base_Init( soundInterface_t *si );
|
||||
|
||||
// OpenAL stuff
|
||||
typedef enum
|
||||
{
|
||||
SRCPRI_AMBIENT = 0, // Ambient sound effects
|
||||
SRCPRI_ENTITY, // Entity sound effects
|
||||
SRCPRI_ONESHOT, // One-shot sounds
|
||||
SRCPRI_LOCAL, // Local sounds
|
||||
SRCPRI_STREAM // Streams (music, cutscenes)
|
||||
} alSrcPriority_t;
|
||||
|
||||
typedef int srcHandle_t;
|
||||
|
||||
qboolean S_AL_Init( soundInterface_t *si );
|
||||
|
||||
#ifdef idppc_altivec
|
||||
void S_PaintChannelFrom16_altivec( portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE], int snd_vol, channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset );
|
||||
#ifdef __linux__
|
||||
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371
|
||||
// custom Snd_Memset implementation for glibc memset bug workaround
|
||||
void Snd_Memset(void* dest, const int val, const size_t count);
|
||||
#else
|
||||
#define Snd_Memset Com_Memset
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -22,18 +22,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "snd_codec.h"
|
||||
#include "snd_local.h"
|
||||
#include "snd_public.h"
|
||||
|
||||
cvar_t *s_volume;
|
||||
cvar_t *s_muted;
|
||||
cvar_t *s_musicVolume;
|
||||
cvar_t *s_doppler;
|
||||
cvar_t *s_backend;
|
||||
cvar_t *s_muteWhenMinimized;
|
||||
cvar_t *s_muteWhenUnfocused;
|
||||
|
||||
#if 0
|
||||
cvar_t* s_volume;
|
||||
cvar_t* s_musicVolume;
|
||||
cvar_t* s_doppler;
|
||||
|
||||
static soundInterface_t si;
|
||||
|
||||
/*
|
||||
@@ -332,13 +333,11 @@ S_RegisterSound
|
||||
*/
|
||||
sfxHandle_t S_RegisterSound(const char *sample, qboolean compressed, qboolean streamed)
|
||||
{
|
||||
/*
|
||||
if( si.RegisterSound ) {
|
||||
return si.RegisterSound( sample, compressed );
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
// FIXME: infinite loop
|
||||
}
|
||||
|
||||
@@ -889,3 +888,4 @@ void S_FadeSound(float fTime)
|
||||
{
|
||||
// FIXME: stub
|
||||
}
|
||||
#endif
|
||||
+196
-66
@@ -15,7 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
along with Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
@@ -30,7 +30,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*****************************************************************************/
|
||||
|
||||
#include "snd_local.h"
|
||||
#include "snd_codec.h"
|
||||
|
||||
#define DEF_COMSOUNDMEGS "8"
|
||||
|
||||
@@ -57,7 +56,7 @@ void SND_free(sndBuffer *v) {
|
||||
inUse += sizeof(sndBuffer);
|
||||
}
|
||||
|
||||
sndBuffer* SND_malloc(void) {
|
||||
sndBuffer* SND_malloc() {
|
||||
sndBuffer *v;
|
||||
redo:
|
||||
if (freelist == NULL) {
|
||||
@@ -74,7 +73,7 @@ redo:
|
||||
return v;
|
||||
}
|
||||
|
||||
void SND_setup(void) {
|
||||
void SND_setup() {
|
||||
sndBuffer *p, *q;
|
||||
cvar_t *cv;
|
||||
int scs;
|
||||
@@ -100,12 +99,137 @@ void SND_setup(void) {
|
||||
Com_Printf("Sound memory manager started\n");
|
||||
}
|
||||
|
||||
void SND_shutdown(void)
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
WAV loading
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
static byte *data_p;
|
||||
static byte *iff_end;
|
||||
static byte *last_chunk;
|
||||
static byte *iff_data;
|
||||
static int iff_chunk_len;
|
||||
|
||||
static short GetLittleShort(void)
|
||||
{
|
||||
free(sfxScratchBuffer);
|
||||
free(buffer);
|
||||
short val = 0;
|
||||
val = *data_p;
|
||||
val = val + (*(data_p+1)<<8);
|
||||
data_p += 2;
|
||||
return val;
|
||||
}
|
||||
|
||||
static int GetLittleLong(void)
|
||||
{
|
||||
int val = 0;
|
||||
val = *data_p;
|
||||
val = val + (*(data_p+1)<<8);
|
||||
val = val + (*(data_p+2)<<16);
|
||||
val = val + (*(data_p+3)<<24);
|
||||
data_p += 4;
|
||||
return val;
|
||||
}
|
||||
|
||||
static void FindNextChunk(char *name)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
data_p=last_chunk;
|
||||
|
||||
if (data_p >= iff_end)
|
||||
{ // didn't find the chunk
|
||||
data_p = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
data_p += 4;
|
||||
iff_chunk_len = GetLittleLong();
|
||||
if (iff_chunk_len < 0)
|
||||
{
|
||||
data_p = NULL;
|
||||
return;
|
||||
}
|
||||
data_p -= 8;
|
||||
last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
|
||||
if (!strncmp((char *)data_p, name, 4))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void FindChunk(char *name)
|
||||
{
|
||||
last_chunk = iff_data;
|
||||
FindNextChunk (name);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
GetWavinfo
|
||||
============
|
||||
*/
|
||||
static wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
|
||||
{
|
||||
wavinfo_t info;
|
||||
|
||||
Com_Memset (&info, 0, sizeof(info));
|
||||
|
||||
if (!wav)
|
||||
return info;
|
||||
|
||||
iff_data = wav;
|
||||
iff_end = wav + wavlength;
|
||||
|
||||
// find "RIFF" chunk
|
||||
FindChunk("RIFF");
|
||||
if (!(data_p && !strncmp((char *)data_p+8, "WAVE", 4)))
|
||||
{
|
||||
Com_Printf("Missing RIFF/WAVE chunks\n");
|
||||
return info;
|
||||
}
|
||||
|
||||
// get "fmt " chunk
|
||||
iff_data = data_p + 12;
|
||||
// DumpChunks ();
|
||||
|
||||
FindChunk("fmt ");
|
||||
if (!data_p)
|
||||
{
|
||||
Com_Printf("Missing fmt chunk\n");
|
||||
return info;
|
||||
}
|
||||
data_p += 8;
|
||||
info.format = GetLittleShort();
|
||||
info.channels = GetLittleShort();
|
||||
info.rate = GetLittleLong();
|
||||
data_p += 4+2;
|
||||
info.width = GetLittleShort() / 8;
|
||||
|
||||
if (info.format != 1)
|
||||
{
|
||||
Com_Printf("Microsoft PCM format only\n");
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
// find data chunk
|
||||
FindChunk("data");
|
||||
if (!data_p)
|
||||
{
|
||||
Com_Printf("Missing data chunk\n");
|
||||
return info;
|
||||
}
|
||||
|
||||
data_p += 4;
|
||||
info.samples = GetLittleLong () / info.width;
|
||||
info.dataofs = data_p - wav;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
ResampleSfx
|
||||
@@ -113,53 +237,47 @@ ResampleSfx
|
||||
resample / decimate to the current source rate
|
||||
================
|
||||
*/
|
||||
static int ResampleSfx( sfx_t *sfx, int channels, int inrate, int inwidth, int samples, byte *data, qboolean compressed ) {
|
||||
static void ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data, qboolean compressed ) {
|
||||
int outcount;
|
||||
int srcsample;
|
||||
float stepscale;
|
||||
int i, j;
|
||||
int i;
|
||||
int sample, samplefrac, fracstep;
|
||||
int part;
|
||||
sndBuffer *chunk;
|
||||
|
||||
stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2
|
||||
|
||||
outcount = samples / stepscale;
|
||||
outcount = sfx->soundLength / stepscale;
|
||||
sfx->soundLength = outcount;
|
||||
|
||||
srcsample = 0;
|
||||
samplefrac = 0;
|
||||
fracstep = stepscale * 256 * channels;
|
||||
fracstep = stepscale * 256;
|
||||
chunk = sfx->soundData;
|
||||
|
||||
for (i=0 ; i<outcount ; i++)
|
||||
{
|
||||
srcsample += samplefrac >> 8;
|
||||
samplefrac &= 255;
|
||||
srcsample = samplefrac >> 8;
|
||||
samplefrac += fracstep;
|
||||
for (j=0 ; j<channels ; j++)
|
||||
{
|
||||
if( inwidth == 2 ) {
|
||||
sample = ( ((short *)data)[srcsample+j] );
|
||||
if( inwidth == 2 ) {
|
||||
sample = LittleShort ( ((short *)data)[srcsample] );
|
||||
} else {
|
||||
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
|
||||
}
|
||||
part = (i&(SND_CHUNK_SIZE-1));
|
||||
if (part == 0) {
|
||||
sndBuffer *newchunk;
|
||||
newchunk = SND_malloc();
|
||||
if (chunk == NULL) {
|
||||
sfx->soundData = newchunk;
|
||||
} else {
|
||||
sample = (unsigned int)( (unsigned char)(data[srcsample+j]) - 128) << 8;
|
||||
chunk->next = newchunk;
|
||||
}
|
||||
part = (i*channels+j)&(SND_CHUNK_SIZE-1);
|
||||
if (part == 0) {
|
||||
sndBuffer *newchunk;
|
||||
newchunk = SND_malloc();
|
||||
if (chunk == NULL) {
|
||||
sfx->soundData = newchunk;
|
||||
} else {
|
||||
chunk->next = newchunk;
|
||||
}
|
||||
chunk = newchunk;
|
||||
}
|
||||
|
||||
chunk->sndChunk[part] = sample;
|
||||
chunk = newchunk;
|
||||
}
|
||||
}
|
||||
|
||||
return outcount;
|
||||
chunk->sndChunk[part] = sample;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -169,39 +287,35 @@ ResampleSfx
|
||||
resample / decimate to the current source rate
|
||||
================
|
||||
*/
|
||||
static int ResampleSfxRaw( short *sfx, int channels, int inrate, int inwidth, int samples, byte *data ) {
|
||||
static int ResampleSfxRaw( short *sfx, int inrate, int inwidth, int samples, byte *data ) {
|
||||
int outcount;
|
||||
int srcsample;
|
||||
float stepscale;
|
||||
int i, j;
|
||||
int i;
|
||||
int sample, samplefrac, fracstep;
|
||||
|
||||
stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2
|
||||
|
||||
outcount = samples / stepscale;
|
||||
|
||||
srcsample = 0;
|
||||
samplefrac = 0;
|
||||
fracstep = stepscale * 256 * channels;
|
||||
fracstep = stepscale * 256;
|
||||
|
||||
for (i=0 ; i<outcount ; i++)
|
||||
{
|
||||
srcsample += samplefrac >> 8;
|
||||
samplefrac &= 255;
|
||||
srcsample = samplefrac >> 8;
|
||||
samplefrac += fracstep;
|
||||
for (j=0 ; j<channels ; j++)
|
||||
{
|
||||
if( inwidth == 2 ) {
|
||||
sample = LittleShort ( ((short *)data)[srcsample+j] );
|
||||
} else {
|
||||
sample = (int)( (unsigned char)(data[srcsample+j]) - 128) << 8;
|
||||
}
|
||||
sfx[i*channels+j] = sample;
|
||||
if( inwidth == 2 ) {
|
||||
sample = LittleShort ( ((short *)data)[srcsample] );
|
||||
} else {
|
||||
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
|
||||
}
|
||||
sfx[i] = sample;
|
||||
}
|
||||
return outcount;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
@@ -216,23 +330,40 @@ qboolean S_LoadSound( sfx_t *sfx )
|
||||
{
|
||||
byte *data;
|
||||
short *samples;
|
||||
snd_info_t info;
|
||||
// int size;
|
||||
wavinfo_t info;
|
||||
int size;
|
||||
|
||||
// player specific sounds are never directly loaded
|
||||
if ( sfx->soundName[0] == '*') {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// load it in
|
||||
data = S_CodecLoad(sfx->soundName, &info);
|
||||
if(!data)
|
||||
size = FS_ReadFile( sfx->soundName, (void **)&data );
|
||||
if ( !data ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
info = GetWavinfo( sfx->soundName, data, size );
|
||||
if ( info.channels != 1 ) {
|
||||
Com_Printf ("%s is a stereo wav file\n", sfx->soundName);
|
||||
FS_FreeFile (data);
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
if ( info.width == 1 ) {
|
||||
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is a 8 bit audio file\n", sfx->soundName);
|
||||
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is a 8 bit wav file\n", sfx->soundName);
|
||||
}
|
||||
|
||||
if ( info.rate != 22050 ) {
|
||||
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is not a 22kHz audio file\n", sfx->soundName);
|
||||
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is not a 22kHz wav file\n", sfx->soundName);
|
||||
}
|
||||
|
||||
samples = Hunk_AllocateTempMemory(info.channels * info.samples * sizeof(short) * 2);
|
||||
if (!info.samples) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
samples = Hunk_AllocateTempMemory(info.samples * sizeof(short) * 2);
|
||||
|
||||
sfx->lastTimeUsed = Com_Milliseconds()+1;
|
||||
|
||||
@@ -242,37 +373,36 @@ qboolean S_LoadSound( sfx_t *sfx )
|
||||
// manager to do the right thing for us and page
|
||||
// sound in as needed
|
||||
|
||||
if( info.channels == 1 && sfx->soundCompressed == qtrue) {
|
||||
if( sfx->soundCompressed == qtrue) {
|
||||
sfx->soundCompressionMethod = 1;
|
||||
sfx->soundData = NULL;
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, data + info.dataofs );
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
|
||||
S_AdpcmEncodeSound(sfx, samples);
|
||||
#if 0
|
||||
} else if (info.channels == 1 && info.samples>(SND_CHUNK_SIZE*16) && info.width >1) {
|
||||
} else if (info.samples>(SND_CHUNK_SIZE*16) && info.width >1) {
|
||||
sfx->soundCompressionMethod = 3;
|
||||
sfx->soundData = NULL;
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, (data + info.dataofs) );
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
|
||||
encodeMuLaw( sfx, samples);
|
||||
} else if (info.channels == 1 && info.samples>(SND_CHUNK_SIZE*6400) && info.width >1) {
|
||||
} else if (info.samples>(SND_CHUNK_SIZE*6400) && info.width >1) {
|
||||
sfx->soundCompressionMethod = 2;
|
||||
sfx->soundData = NULL;
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, (data + info.dataofs) );
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
|
||||
encodeWavelet( sfx, samples);
|
||||
#endif
|
||||
} else {
|
||||
sfx->soundCompressionMethod = 0;
|
||||
sfx->soundLength = info.samples;
|
||||
sfx->soundData = NULL;
|
||||
sfx->soundLength = ResampleSfx( sfx, info.channels, info.rate, info.width, info.samples, data + info.dataofs, qfalse );
|
||||
ResampleSfx( sfx, info.rate, info.width, data + info.dataofs, qfalse );
|
||||
}
|
||||
|
||||
sfx->soundChannels = info.channels;
|
||||
|
||||
Hunk_FreeTempMemory(samples);
|
||||
Hunk_FreeTempMemory(data);
|
||||
FS_FreeFile( data );
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
void S_DisplayFreeMemory(void) {
|
||||
void S_DisplayFreeMemory() {
|
||||
Com_Printf("%d bytes free sound buffer memory, %d total used\n", inUse, totalInUse);
|
||||
}
|
||||
+182
-128
@@ -15,23 +15,24 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
along with Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
// snd_mix.c -- portable code to mix sounds for snd_dma.c
|
||||
|
||||
#include "client.h"
|
||||
#include "snd_local.h"
|
||||
|
||||
static portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
|
||||
static int snd_vol;
|
||||
|
||||
// bk001119 - these not static, required by unix/snd_mixa.s
|
||||
int* snd_p;
|
||||
int snd_linear_count;
|
||||
short* snd_out;
|
||||
|
||||
#if !id386 // if configured not to use asm
|
||||
#if !( (defined __linux__ || defined __FreeBSD__ ) && (defined __i386__) ) // rb010123
|
||||
#if !id386
|
||||
|
||||
void S_WriteLinearBlastStereo16 (void)
|
||||
{
|
||||
@@ -57,9 +58,6 @@ void S_WriteLinearBlastStereo16 (void)
|
||||
snd_out[i+1] = val;
|
||||
}
|
||||
}
|
||||
#elif defined(__GNUC__)
|
||||
// uses snd_mixa.s
|
||||
void S_WriteLinearBlastStereo16 (void);
|
||||
#else
|
||||
|
||||
__declspec( naked ) void S_WriteLinearBlastStereo16 (void)
|
||||
@@ -106,6 +104,10 @@ LClampDone2:
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#else
|
||||
// forward declare, implementation somewhere else
|
||||
void S_WriteLinearBlastStereo16 (void);
|
||||
#endif
|
||||
|
||||
void S_TransferStereo16 (unsigned long *pbuf, int endtime)
|
||||
@@ -119,24 +121,21 @@ void S_TransferStereo16 (unsigned long *pbuf, int endtime)
|
||||
while (ls_paintedtime < endtime)
|
||||
{
|
||||
// handle recirculating buffer issues
|
||||
lpos = ls_paintedtime % dma.fullsamples;
|
||||
lpos = ls_paintedtime & ((dma.samples>>1)-1);
|
||||
|
||||
snd_out = (short *) pbuf + (lpos<<1); // lpos * dma.channels
|
||||
snd_out = (short *) pbuf + (lpos<<1);
|
||||
|
||||
snd_linear_count = dma.fullsamples - lpos;
|
||||
snd_linear_count = (dma.samples>>1) - lpos;
|
||||
if (ls_paintedtime + snd_linear_count > endtime)
|
||||
snd_linear_count = endtime - ls_paintedtime;
|
||||
|
||||
snd_linear_count <<= 1; // snd_linear_count *= dma.channels
|
||||
snd_linear_count <<= 1;
|
||||
|
||||
// write a linear blast of samples
|
||||
S_WriteLinearBlastStereo16 ();
|
||||
|
||||
snd_p += snd_linear_count;
|
||||
ls_paintedtime += (snd_linear_count>>1); // snd_linear_count / dma.channels
|
||||
|
||||
if( CL_VideoRecording( ) )
|
||||
CL_WriteAVIAudioFrame( (byte *)snd_out, snd_linear_count << 1 ); // snd_linear_count * (dma.samplebits/8)
|
||||
ls_paintedtime += (snd_linear_count>>1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,16 +149,19 @@ void S_TransferPaintBuffer(int endtime)
|
||||
{
|
||||
int out_idx;
|
||||
int count;
|
||||
int out_mask;
|
||||
int *p;
|
||||
int step;
|
||||
int val;
|
||||
int i;
|
||||
unsigned long *pbuf;
|
||||
|
||||
pbuf = (unsigned long *)dma.buffer;
|
||||
|
||||
|
||||
if ( s_testsound->integer ) {
|
||||
int i;
|
||||
int count;
|
||||
|
||||
// write a fixed sine wave
|
||||
count = (endtime - s_paintedtime);
|
||||
for (i=0 ; i<count ; i++)
|
||||
@@ -175,73 +177,38 @@ void S_TransferPaintBuffer(int endtime)
|
||||
{ // general case
|
||||
p = (int *) paintbuffer;
|
||||
count = (endtime - s_paintedtime) * dma.channels;
|
||||
out_idx = ((unsigned int)s_paintedtime * dma.channels) % dma.samples;
|
||||
step = 3 - MIN(dma.channels, 2);
|
||||
out_mask = dma.samples - 1;
|
||||
out_idx = s_paintedtime * dma.channels & out_mask;
|
||||
step = 3 - dma.channels;
|
||||
|
||||
if ((dma.isfloat) && (dma.samplebits == 32))
|
||||
{
|
||||
float *out = (float *) pbuf;
|
||||
for (i=0 ; i<count ; i++)
|
||||
{
|
||||
if ((i % dma.channels) >= 2)
|
||||
{
|
||||
val = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = *p >> 8;
|
||||
p+= step;
|
||||
}
|
||||
if (val > 0x7fff)
|
||||
val = 0x7fff;
|
||||
else if (val < -32767) /* clamp to one less than max to make division max out at -1.0f. */
|
||||
val = -32767;
|
||||
out[out_idx] = ((float) val) / 32767.0f;
|
||||
out_idx = (out_idx + 1) % dma.samples;
|
||||
}
|
||||
}
|
||||
else if (dma.samplebits == 16)
|
||||
if (dma.samplebits == 16)
|
||||
{
|
||||
short *out = (short *) pbuf;
|
||||
for (i=0 ; i<count ; i++)
|
||||
while (count--)
|
||||
{
|
||||
if ((i % dma.channels) >= 2)
|
||||
{
|
||||
val = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = *p >> 8;
|
||||
p+= step;
|
||||
}
|
||||
val = *p >> 8;
|
||||
p+= step;
|
||||
if (val > 0x7fff)
|
||||
val = 0x7fff;
|
||||
else if (val < -32768)
|
||||
val = -32768;
|
||||
out[out_idx] = val;
|
||||
out_idx = (out_idx + 1) % dma.samples;
|
||||
out_idx = (out_idx + 1) & out_mask;
|
||||
}
|
||||
}
|
||||
else if (dma.samplebits == 8)
|
||||
{
|
||||
unsigned char *out = (unsigned char *) pbuf;
|
||||
for (i=0 ; i<count ; i++)
|
||||
while (count--)
|
||||
{
|
||||
if ((i % dma.channels) >= 2)
|
||||
{
|
||||
val = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = *p >> 8;
|
||||
p+= step;
|
||||
}
|
||||
val = *p >> 8;
|
||||
p+= step;
|
||||
if (val > 0x7fff)
|
||||
val = 0x7fff;
|
||||
else if (val < -32768)
|
||||
val = -32768;
|
||||
out[out_idx] = (val>>8) + 128;
|
||||
out_idx = (out_idx + 1) % dma.samples;
|
||||
out_idx = (out_idx + 1) & out_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,18 +223,14 @@ CHANNEL MIXING
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
|
||||
static void S_PaintChannelFrom16( channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
|
||||
int data, aoff, boff;
|
||||
int leftvol, rightvol;
|
||||
int i, j;
|
||||
portable_samplepair_t *samp;
|
||||
sndBuffer *chunk;
|
||||
short *samples;
|
||||
float ooff, fdata[2], fdiv, fleftvol, frightvol;
|
||||
|
||||
if (sc->soundChannels <= 0) {
|
||||
return;
|
||||
}
|
||||
float ooff, fdata, fdiv, fleftvol, frightvol;
|
||||
|
||||
samp = &paintbuffer[ bufferOffset ];
|
||||
|
||||
@@ -275,14 +238,6 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
|
||||
sampleOffset = sampleOffset*ch->oldDopplerScale;
|
||||
}
|
||||
|
||||
if ( sc->soundChannels == 2 ) {
|
||||
sampleOffset *= sc->soundChannels;
|
||||
|
||||
if ( sampleOffset & 1 ) {
|
||||
sampleOffset &= ~1;
|
||||
}
|
||||
}
|
||||
|
||||
chunk = sc->soundData;
|
||||
while (sampleOffset>=SND_CHUNK_SIZE) {
|
||||
chunk = chunk->next;
|
||||
@@ -293,16 +248,126 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
|
||||
}
|
||||
|
||||
if (!ch->doppler || ch->dopplerScale==1.0f) {
|
||||
#if idppc_altivec
|
||||
vector signed short volume_vec;
|
||||
vector unsigned int volume_shift;
|
||||
int vectorCount, samplesLeft, chunkSamplesLeft;
|
||||
#endif
|
||||
leftvol = ch->leftvol*snd_vol;
|
||||
rightvol = ch->rightvol*snd_vol;
|
||||
samples = chunk->sndChunk;
|
||||
#if idppc_altivec
|
||||
((short *)&volume_vec)[0] = leftvol;
|
||||
((short *)&volume_vec)[1] = leftvol;
|
||||
((short *)&volume_vec)[4] = leftvol;
|
||||
((short *)&volume_vec)[5] = leftvol;
|
||||
((short *)&volume_vec)[2] = rightvol;
|
||||
((short *)&volume_vec)[3] = rightvol;
|
||||
((short *)&volume_vec)[6] = rightvol;
|
||||
((short *)&volume_vec)[7] = rightvol;
|
||||
volume_shift = vec_splat_u32(8);
|
||||
i = 0;
|
||||
|
||||
while(i < count) {
|
||||
/* Try to align destination to 16-byte boundary */
|
||||
while(i < count && (((unsigned long)&samp[i] & 0x1f) || ((count-i) < 8) || ((SND_CHUNK_SIZE - sampleOffset) < 8))) {
|
||||
data = samples[sampleOffset++];
|
||||
samp[i].left += (data * leftvol)>>8;
|
||||
samp[i].right += (data * rightvol)>>8;
|
||||
|
||||
if (sampleOffset == SND_CHUNK_SIZE) {
|
||||
chunk = chunk->next;
|
||||
samples = chunk->sndChunk;
|
||||
sampleOffset = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
/* Destination is now aligned. Process as many 8-sample
|
||||
chunks as we can before we run out of room from the current
|
||||
sound chunk. We do 8 per loop to avoid extra source data reads. */
|
||||
samplesLeft = count - i;
|
||||
chunkSamplesLeft = SND_CHUNK_SIZE - sampleOffset;
|
||||
if(samplesLeft > chunkSamplesLeft)
|
||||
samplesLeft = chunkSamplesLeft;
|
||||
|
||||
vectorCount = samplesLeft / 8;
|
||||
|
||||
if(vectorCount)
|
||||
{
|
||||
vector unsigned char tmp;
|
||||
vector short s0, s1, sampleData0, sampleData1;
|
||||
vector short samples0, samples1;
|
||||
vector signed int left0, right0;
|
||||
vector signed int merge0, merge1;
|
||||
vector signed int d0, d1, d2, d3;
|
||||
vector unsigned char samplePermute0 =
|
||||
(vector unsigned char)(0, 1, 4, 5, 0, 1, 4, 5, 2, 3, 6, 7, 2, 3, 6, 7);
|
||||
vector unsigned char samplePermute1 =
|
||||
(vector unsigned char)(8, 9, 12, 13, 8, 9, 12, 13, 10, 11, 14, 15, 10, 11, 14, 15);
|
||||
vector unsigned char loadPermute0, loadPermute1;
|
||||
|
||||
// Rather than permute the vectors after we load them to do the sample
|
||||
// replication and rearrangement, we permute the alignment vector so
|
||||
// we do everything in one step below and avoid data shuffling.
|
||||
tmp = vec_lvsl(0,&samples[sampleOffset]);
|
||||
loadPermute0 = vec_perm(tmp,tmp,samplePermute0);
|
||||
loadPermute1 = vec_perm(tmp,tmp,samplePermute1);
|
||||
|
||||
s0 = *(vector short *)&samples[sampleOffset];
|
||||
while(vectorCount)
|
||||
{
|
||||
/* Load up source (16-bit) sample data */
|
||||
s1 = *(vector short *)&samples[sampleOffset+7];
|
||||
|
||||
/* Load up destination sample data */
|
||||
d0 = *(vector signed int *)&samp[i];
|
||||
d1 = *(vector signed int *)&samp[i+2];
|
||||
d2 = *(vector signed int *)&samp[i+4];
|
||||
d3 = *(vector signed int *)&samp[i+6];
|
||||
|
||||
sampleData0 = vec_perm(s0,s1,loadPermute0);
|
||||
sampleData1 = vec_perm(s0,s1,loadPermute1);
|
||||
|
||||
merge0 = vec_mule(sampleData0,volume_vec);
|
||||
merge0 = vec_sra(merge0,volume_shift); /* Shift down to proper range */
|
||||
|
||||
merge1 = vec_mulo(sampleData0,volume_vec);
|
||||
merge1 = vec_sra(merge1,volume_shift);
|
||||
|
||||
d0 = vec_add(merge0,d0);
|
||||
d1 = vec_add(merge1,d1);
|
||||
|
||||
merge0 = vec_mule(sampleData1,volume_vec);
|
||||
merge0 = vec_sra(merge0,volume_shift); /* Shift down to proper range */
|
||||
|
||||
merge1 = vec_mulo(sampleData1,volume_vec);
|
||||
merge1 = vec_sra(merge1,volume_shift);
|
||||
|
||||
d2 = vec_add(merge0,d2);
|
||||
d3 = vec_add(merge1,d3);
|
||||
|
||||
/* Store destination sample data */
|
||||
*(vector signed int *)&samp[i] = d0;
|
||||
*(vector signed int *)&samp[i+2] = d1;
|
||||
*(vector signed int *)&samp[i+4] = d2;
|
||||
*(vector signed int *)&samp[i+6] = d3;
|
||||
|
||||
i += 8;
|
||||
vectorCount--;
|
||||
s0 = s1;
|
||||
sampleOffset += 8;
|
||||
}
|
||||
if (sampleOffset == SND_CHUNK_SIZE) {
|
||||
chunk = chunk->next;
|
||||
samples = chunk->sndChunk;
|
||||
sampleOffset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
for ( i=0 ; i<count ; i++ ) {
|
||||
data = samples[sampleOffset++];
|
||||
samp[i].left += (data * leftvol)>>8;
|
||||
|
||||
if ( sc->soundChannels == 2 ) {
|
||||
data = samples[sampleOffset++];
|
||||
}
|
||||
samp[i].right += (data * rightvol)>>8;
|
||||
|
||||
if (sampleOffset == SND_CHUNK_SIZE) {
|
||||
@@ -311,6 +376,7 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
|
||||
sampleOffset = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
fleftvol = ch->leftvol*snd_vol;
|
||||
frightvol = ch->rightvol*snd_vol;
|
||||
@@ -324,10 +390,10 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
|
||||
for ( i=0 ; i<count ; i++ ) {
|
||||
|
||||
aoff = ooff;
|
||||
ooff = ooff + ch->dopplerScale * sc->soundChannels;
|
||||
ooff = ooff + ch->dopplerScale;
|
||||
boff = ooff;
|
||||
fdata[0] = fdata[1] = 0;
|
||||
for (j=aoff; j<boff; j += sc->soundChannels) {
|
||||
fdata = 0;
|
||||
for (j=aoff; j<boff; j++) {
|
||||
if (j == SND_CHUNK_SIZE) {
|
||||
chunk = chunk->next;
|
||||
if (!chunk) {
|
||||
@@ -336,32 +402,15 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
|
||||
samples = chunk->sndChunk;
|
||||
ooff -= SND_CHUNK_SIZE;
|
||||
}
|
||||
if ( sc->soundChannels == 2 ) {
|
||||
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
|
||||
fdata[1] += samples[(j+1)&(SND_CHUNK_SIZE-1)];
|
||||
} else {
|
||||
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
|
||||
fdata[1] += samples[j&(SND_CHUNK_SIZE-1)];
|
||||
}
|
||||
fdata += samples[j&(SND_CHUNK_SIZE-1)];
|
||||
}
|
||||
fdiv = 256 * (boff-aoff) / sc->soundChannels;
|
||||
samp[i].left += (fdata[0] * fleftvol)/fdiv;
|
||||
samp[i].right += (fdata[1] * frightvol)/fdiv;
|
||||
fdiv = 256 * (boff-aoff);
|
||||
samp[i].left += (fdata * fleftvol)/fdiv;
|
||||
samp[i].right += (fdata * frightvol)/fdiv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void S_PaintChannelFrom16( channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
|
||||
#if idppc_altivec
|
||||
if (com_altivec->integer) {
|
||||
// must be in a separate translation unit or G3 systems will crash.
|
||||
S_PaintChannelFrom16_altivec( paintbuffer, snd_vol, ch, sc, count, sampleOffset, bufferOffset );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
S_PaintChannelFrom16_scalar( ch, sc, count, sampleOffset, bufferOffset );
|
||||
}
|
||||
|
||||
void S_PaintChannelFromWavelet( channel_t *ch, sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
|
||||
int data;
|
||||
int leftvol, rightvol;
|
||||
@@ -383,7 +432,7 @@ void S_PaintChannelFromWavelet( channel_t *ch, sfx_t *sc, int count, int sampleO
|
||||
}
|
||||
|
||||
if (i!=sfxScratchIndex || sfxScratchPointer != sc) {
|
||||
decodeWavelet(chunk, sfxScratchBuffer);
|
||||
S_AdpcmGetSamples( chunk, sfxScratchBuffer );
|
||||
sfxScratchIndex = i;
|
||||
sfxScratchPointer = sc;
|
||||
}
|
||||
@@ -480,7 +529,7 @@ void S_PaintChannelFromMuLaw( channel_t *ch, sfx_t *sc, int count, int sampleOff
|
||||
samp[i].left += (data * leftvol)>>8;
|
||||
samp[i].right += (data * rightvol)>>8;
|
||||
samples++;
|
||||
if (chunk != NULL && samples == (byte *)chunk->sndChunk+(SND_CHUNK_SIZE*2)) {
|
||||
if (samples == (byte *)chunk->sndChunk+(SND_CHUNK_SIZE*2)) {
|
||||
chunk = chunk->next;
|
||||
samples = (byte *)chunk->sndChunk;
|
||||
}
|
||||
@@ -513,16 +562,13 @@ S_PaintChannels
|
||||
void S_PaintChannels( int endtime ) {
|
||||
int i;
|
||||
int end;
|
||||
int stream;
|
||||
channel_t *ch;
|
||||
sfx_t *sc;
|
||||
int ltime, count;
|
||||
int sampleOffset;
|
||||
|
||||
if(s_muted->integer)
|
||||
snd_vol = 0;
|
||||
else
|
||||
snd_vol = s_volume->value*255;
|
||||
|
||||
snd_vol = s_volume->value*255;
|
||||
|
||||
//Com_Printf ("%i to %i\n", s_paintedtime, endtime);
|
||||
while ( s_paintedtime < endtime ) {
|
||||
@@ -533,24 +579,36 @@ void S_PaintChannels( int endtime ) {
|
||||
end = s_paintedtime + PAINTBUFFER_SIZE;
|
||||
}
|
||||
|
||||
// clear the paint buffer and mix any raw samples...
|
||||
Com_Memset(paintbuffer, 0, sizeof (paintbuffer));
|
||||
for (stream = 0; stream < MAX_RAW_STREAMS; stream++) {
|
||||
if ( s_rawend[stream] >= s_paintedtime ) {
|
||||
// copy from the streaming sound source
|
||||
const portable_samplepair_t *rawsamples = s_rawsamples[stream];
|
||||
const int stop = (end < s_rawend[stream]) ? end : s_rawend[stream];
|
||||
for ( i = s_paintedtime ; i < stop ; i++ ) {
|
||||
const int s = i&(MAX_RAW_SAMPLES-1);
|
||||
paintbuffer[i-s_paintedtime].left += rawsamples[s].left;
|
||||
paintbuffer[i-s_paintedtime].right += rawsamples[s].right;
|
||||
}
|
||||
// clear the paint buffer to either music or zeros
|
||||
if ( s_rawend < s_paintedtime ) {
|
||||
if ( s_rawend ) {
|
||||
//Com_DPrintf ("background sound underrun\n");
|
||||
}
|
||||
Com_Memset(paintbuffer, 0, (end - s_paintedtime) * sizeof(portable_samplepair_t));
|
||||
} else {
|
||||
// copy from the streaming sound source
|
||||
int s;
|
||||
int stop;
|
||||
|
||||
stop = (end < s_rawend) ? end : s_rawend;
|
||||
|
||||
for ( i = s_paintedtime ; i < stop ; i++ ) {
|
||||
s = i&(MAX_RAW_SAMPLES-1);
|
||||
paintbuffer[i-s_paintedtime] = s_rawsamples[s];
|
||||
}
|
||||
// if (i != end)
|
||||
// Com_Printf ("partial stream\n");
|
||||
// else
|
||||
// Com_Printf ("full stream\n");
|
||||
for ( ; i < end ; i++ ) {
|
||||
paintbuffer[i-s_paintedtime].left =
|
||||
paintbuffer[i-s_paintedtime].right = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// paint in the channels.
|
||||
ch = s_channels;
|
||||
for ( i = 0; i < MAX_SOUNDCHANNELS ; i++, ch++ ) {
|
||||
for ( i = 0; i < MAX_CHANNELS ; i++, ch++ ) {
|
||||
if ( !ch->thesfx || (ch->leftvol<0.25 && ch->rightvol<0.25 )) {
|
||||
continue;
|
||||
}
|
||||
@@ -558,10 +616,6 @@ void S_PaintChannels( int endtime ) {
|
||||
ltime = s_paintedtime;
|
||||
sc = ch->thesfx;
|
||||
|
||||
if (sc->soundData==NULL || sc->soundLength==0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sampleOffset = ltime - ch->startSample;
|
||||
count = end - ltime;
|
||||
if ( sampleOffset + count > sc->soundLength ) {
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -15,7 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
along with Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
@@ -38,8 +38,8 @@ void S_StopBackgroundTrack( void );
|
||||
|
||||
// cinematics and voice-over-network will send raw samples
|
||||
// 1.0 volume will be direct output of source samples
|
||||
void S_RawSamples(int stream, int samples, int rate, int width, int channels,
|
||||
const byte *data, float volume, int entityNum);
|
||||
void S_RawSamples (int samples, int rate, int width, int channels,
|
||||
const byte *data, float volume);
|
||||
|
||||
// stop all sounds and the background track
|
||||
void S_StopAllSounds(qboolean stop_music);
|
||||
@@ -51,21 +51,20 @@ void S_AddLoopingSound(const vec3_t origin, const vec3_t velocity, sfxHandle_t s
|
||||
void S_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
|
||||
void S_StopLoopingSound(int entityNum );
|
||||
|
||||
// recompute the relative volumes for all running sounds
|
||||
// relative to the given entityNum / orientation
|
||||
void S_Respatialize(int entityNum, const vec3_t origin, vec3_t axis[3], int inwater);
|
||||
// recompute the reletive volumes for all running sounds
|
||||
// reletive to the given entityNum / orientation
|
||||
void S_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater );
|
||||
|
||||
// let the sound system know where an entity currently is
|
||||
void S_UpdateEntityPosition(int entityNum, const vec3_t origin);
|
||||
void S_UpdateEntityPosition( int entityNum, const vec3_t origin );
|
||||
|
||||
void S_Update( void );
|
||||
|
||||
void S_DisableSounds( void );
|
||||
|
||||
void S_BeginRegistration(void);
|
||||
void S_BeginRegistration( void );
|
||||
void S_EndRegistration(void);
|
||||
qboolean S_IsSoundRegistered(const char* name);
|
||||
|
||||
// RegisterSound will allways return a valid sample, even if it
|
||||
// has to create a placeholder. This prevents continuous filesystem
|
||||
// checks for missing files
|
||||
@@ -110,15 +109,6 @@ void S_RespatializeOld(int entityNum, const vec3_t origin, vec3_t axis[3]);
|
||||
void S_UpdateEntity(int entityNum, const vec3_t origin, const vec3_t velocity, qboolean use_listener);
|
||||
void S_FadeSound(float fTime);
|
||||
|
||||
#ifdef USE_VOIP
|
||||
void S_StartCapture( void );
|
||||
int S_AvailableCaptureSamples( void );
|
||||
void S_Capture( int samples, byte *data );
|
||||
void S_StopCapture( void );
|
||||
void S_MasterGain( float gain );
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+18
-17
@@ -15,13 +15,15 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Quake III Arena source code; if not, write to the Free Software
|
||||
along with Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "snd_local.h"
|
||||
|
||||
long myftol( float f );
|
||||
|
||||
#define C0 0.4829629131445341
|
||||
#define C1 0.8365163037378079
|
||||
#define C2 0.2241438680420134
|
||||
@@ -29,8 +31,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
void daub4(float b[], unsigned long n, int isign)
|
||||
{
|
||||
float wksp[4097] = { 0.0f };
|
||||
#define a(x) b[(x)-1] // numerical recipies so a[1] = b[0]
|
||||
float wksp[4097];
|
||||
float *a=b-1; // numerical recipies so a[1] = b[0]
|
||||
|
||||
unsigned long nh,nh1,i,j;
|
||||
|
||||
@@ -39,23 +41,22 @@ void daub4(float b[], unsigned long n, int isign)
|
||||
nh1=(nh=n >> 1)+1;
|
||||
if (isign >= 0) {
|
||||
for (i=1,j=1;j<=n-3;j+=2,i++) {
|
||||
wksp[i] = C0*a(j)+C1*a(j+1)+C2*a(j+2)+C3*a(j+3);
|
||||
wksp[i+nh] = C3*a(j)-C2*a(j+1)+C1*a(j+2)-C0*a(j+3);
|
||||
wksp[i] = C0*a[j]+C1*a[j+1]+C2*a[j+2]+C3*a[j+3];
|
||||
wksp[i+nh] = C3*a[j]-C2*a[j+1]+C1*a[j+2]-C0*a[j+3];
|
||||
}
|
||||
wksp[i ] = C0*a(n-1)+C1*a(n)+C2*a(1)+C3*a(2);
|
||||
wksp[i+nh] = C3*a(n-1)-C2*a(n)+C1*a(1)-C0*a(2);
|
||||
wksp[i ] = C0*a[n-1]+C1*a[n]+C2*a[1]+C3*a[2];
|
||||
wksp[i+nh] = C3*a[n-1]-C2*a[n]+C1*a[1]-C0*a[2];
|
||||
} else {
|
||||
wksp[1] = C2*a(nh)+C1*a(n)+C0*a(1)+C3*a(nh1);
|
||||
wksp[2] = C3*a(nh)-C0*a(n)+C1*a(1)-C2*a(nh1);
|
||||
wksp[1] = C2*a[nh]+C1*a[n]+C0*a[1]+C3*a[nh1];
|
||||
wksp[2] = C3*a[nh]-C0*a[n]+C1*a[1]-C2*a[nh1];
|
||||
for (i=1,j=3;i<nh;i++) {
|
||||
wksp[j++] = C2*a(i)+C1*a(i+nh)+C0*a(i+1)+C3*a(i+nh1);
|
||||
wksp[j++] = C3*a(i)-C0*a(i+nh)+C1*a(i+1)-C2*a(i+nh1);
|
||||
wksp[j++] = C2*a[i]+C1*a[i+nh]+C0*a[i+1]+C3*a[i+nh1];
|
||||
wksp[j++] = C3*a[i]-C0*a[i+nh]+C1*a[i+1]-C2*a[i+nh1];
|
||||
}
|
||||
}
|
||||
for (i=1;i<=n;i++) {
|
||||
a(i)=wksp[i];
|
||||
a[i]=wksp[i];
|
||||
}
|
||||
#undef a
|
||||
}
|
||||
|
||||
void wt1(float a[], unsigned long n, int isign)
|
||||
@@ -120,7 +121,7 @@ void NXPutc(NXStream *stream, char out) {
|
||||
|
||||
|
||||
void encodeWavelet( sfx_t *sfx, short *packets) {
|
||||
float wksp[4097] = {0}, temp;
|
||||
float wksp[4097], temp;
|
||||
int i, samples, size;
|
||||
sndBuffer *newchunk, *chunk;
|
||||
byte *out;
|
||||
@@ -147,7 +148,7 @@ void encodeWavelet( sfx_t *sfx, short *packets) {
|
||||
newchunk = SND_malloc();
|
||||
if (sfx->soundData == NULL) {
|
||||
sfx->soundData = newchunk;
|
||||
} else if (chunk != NULL) {
|
||||
} else {
|
||||
chunk->next = newchunk;
|
||||
}
|
||||
chunk = newchunk;
|
||||
@@ -170,7 +171,7 @@ void encodeWavelet( sfx_t *sfx, short *packets) {
|
||||
}
|
||||
|
||||
void decodeWavelet(sndBuffer *chunk, short *to) {
|
||||
float wksp[4097] = {0};
|
||||
float wksp[4097];
|
||||
int i;
|
||||
byte *out;
|
||||
|
||||
@@ -216,7 +217,7 @@ void encodeMuLaw( sfx_t *sfx, short *packets) {
|
||||
newchunk = SND_malloc();
|
||||
if (sfx->soundData == NULL) {
|
||||
sfx->soundData = newchunk;
|
||||
} else if (chunk != NULL) {
|
||||
} else {
|
||||
chunk->next = newchunk;
|
||||
}
|
||||
chunk = newchunk;
|
||||
|
||||
@@ -25,15 +25,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "../qcommon/q_shared.h"
|
||||
#include "bg_public.h"
|
||||
|
||||
/*
|
||||
================
|
||||
BG_EvaluateTrajectory
|
||||
================
|
||||
*/
|
||||
void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result ) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
BG_EvaluateTrajectoryDelta
|
||||
|
||||
@@ -1423,7 +1423,7 @@ void PmoveSingle( pmove_t *pmove )
|
||||
if( pm->ps->pm_type == PM_CLIMBWALL )
|
||||
{
|
||||
pm->ps->fLeanAngle = 0.0f;
|
||||
pm->cmd.buttons &= ~( BUTTON_LEANLEFT | BUTTON_LEANRIGHT );
|
||||
pm->cmd.buttons &= ~( BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT );
|
||||
}
|
||||
|
||||
// clear all pmove local vars
|
||||
@@ -1447,10 +1447,10 @@ void PmoveSingle( pmove_t *pmove )
|
||||
|
||||
pml.frametime = pml.msec * 0.001;
|
||||
|
||||
if( ( pm->cmd.buttons & ( BUTTON_LEANLEFT | BUTTON_LEANRIGHT ) &&
|
||||
( pm->cmd.buttons & ( BUTTON_LEANLEFT | BUTTON_LEANRIGHT ) ) != ( BUTTON_LEANLEFT | BUTTON_LEANRIGHT ) ) )
|
||||
if( ( pm->cmd.buttons & ( BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT ) &&
|
||||
( pm->cmd.buttons & ( BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT ) ) != ( BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT ) ) )
|
||||
{
|
||||
if( pm->cmd.buttons & BUTTON_LEANLEFT )
|
||||
if( pm->cmd.buttons & BUTTON_LEAN_LEFT )
|
||||
{
|
||||
if( pm->ps->fLeanAngle <= -40.0f )
|
||||
{
|
||||
|
||||
+87
-9
@@ -66,6 +66,34 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#define CS_MOTD 4 // g_motd string for server message of the day
|
||||
#define CS_WARMUP 5 // server time when the match will be restarted
|
||||
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
#define CS_MUSIC 6 // MUSIC_NewSoundtrack(cs)
|
||||
#define CS_FOGINFO 7 // cg.farplane_cull cg.farplane_distance cg.farplane_color[3]
|
||||
#define CS_SKYINFO 8 // cg.sky_alpha cg.sky_portal
|
||||
|
||||
#define CS_GAME_VERSION 9
|
||||
#define CS_LEVEL_START_TIME 10 // so the timer only shows the current level cgs.levelStartTime
|
||||
|
||||
#define CS_CURRENT_OBJECTIVE 11
|
||||
|
||||
#define CS_RAIN_DENSITY 12 // cg.rain
|
||||
#define CS_RAIN_SPEED 13
|
||||
#define CS_RAIN_SPEEDVARY 14
|
||||
#define CS_RAIN_SLANT 15
|
||||
#define CS_RAIN_LENGTH 16
|
||||
#define CS_RAIN_MINDIST 17
|
||||
#define CS_RAIN_WIDTH 18
|
||||
#define CS_RAIN_SHADER 19
|
||||
#define CS_RAIN_NUMSHADERS 20
|
||||
|
||||
#define CS_VOTE_TIME 21
|
||||
#define CS_VOTE_STRING 22
|
||||
#define CS_VOTE_YES 23
|
||||
#define CS_VOTE_NO 24
|
||||
#define CS_VOTE_UNDECIDED 25
|
||||
|
||||
#else
|
||||
|
||||
#define CS_MUSIC 8 // MUSIC_NewSoundtrack(cs)
|
||||
#define CS_FOGINFO 9 // cg.farplane_cull cg.farplane_distance cg.farplane_color[3]
|
||||
#define CS_SKYINFO 10 // cg.sky_alpha cg.sky_portal
|
||||
@@ -85,6 +113,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#define CS_RAIN_SHADER 21
|
||||
#define CS_RAIN_NUMSHADERS 22
|
||||
|
||||
#endif
|
||||
|
||||
#define CS_MATCHEND 26 // cgs.matchEndTime
|
||||
|
||||
#define CS_MODELS 32
|
||||
@@ -98,11 +128,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#define CS_PLAYERS (CS_LIGHTSTYLES+MAX_LIGHTSTYLES) // 1684
|
||||
|
||||
#define CS_WEAPONS (CS_PLAYERS+MAX_CLIENTS) // su44 was here
|
||||
#define CS_TEAMS 1876
|
||||
#define CS_GENERAL_STRINGS 1877
|
||||
#define CS_SPECTATORS 1878
|
||||
#define CS_ALLIES 1879
|
||||
#define CS_AXIS 1880
|
||||
#define CS_TEAMS 1892
|
||||
#define CS_GENERAL_STRINGS 1893
|
||||
#define CS_SPECTATORS 1894
|
||||
#define CS_ALLIES 1895
|
||||
#define CS_AXIS 1896
|
||||
#define CS_SOUNDTRACK 1881
|
||||
|
||||
#define CS_TEAMINFO 1
|
||||
@@ -528,6 +558,15 @@ extern const char *means_of_death_strings[];
|
||||
#define DF_NO_DROP_WEAPONS (1<<16)
|
||||
#define DF_NO_FOOTSTEPS (1<<17)
|
||||
|
||||
#define DF_WEAPON_LANDMINE_ALWAYS (1<<21)
|
||||
#define DF_WEAPON_NO_RIFLE (1<<22)
|
||||
#define DF_WEAPON_NO_SNIPER (1<<23)
|
||||
#define DF_WEAPON_NO_SMG (1<<24)
|
||||
#define DF_WEAPON_NO_MG (1<<25)
|
||||
#define DF_WEAPON_NO_ROCKET (1<<26)
|
||||
#define DF_WEAPON_NO_SHOTGUN (1<<27)
|
||||
#define DF_WEAPON_NO_LANDMINE (1<<28)
|
||||
|
||||
#define DM_FLAG( flag ) ( g_gametype->integer && ( ( int )dmflags->integer & ( flag ) ) )
|
||||
|
||||
// content masks
|
||||
@@ -609,13 +648,52 @@ typedef enum {
|
||||
ET_EXEC_COMMANDS
|
||||
} entityType_t;
|
||||
|
||||
// su44; yes, I know there is no q3 trajectory_t in MoHAA,
|
||||
// but I need it for fgame rotating doors code.
|
||||
void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result );
|
||||
void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result );
|
||||
|
||||
void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap );
|
||||
void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap );
|
||||
void BG_PlayerStateToEntityStateExtraPolate(playerState_t* ps, entityState_t* s, int time, qboolean snap);
|
||||
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
|
||||
enum vmAnim_e {
|
||||
VM_ANIM_DISABLED,
|
||||
VM_ANIM_IDLE,
|
||||
VM_ANIM_CHARGE,
|
||||
VM_ANIM_FIRE,
|
||||
VM_ANIM_FIRE_SECONDARY,
|
||||
VM_ANIM_RECHAMBER,
|
||||
VM_ANIM_RELOAD,
|
||||
VM_ANIM_RELOAD_SINGLE,
|
||||
VM_ANIM_RELOAD_END,
|
||||
VM_ANIM_PULLOUT,
|
||||
VM_ANIM_PUTAWAY,
|
||||
VM_ANIM_LADDERSTEP,
|
||||
VM_ANIM_IDLE_0,
|
||||
VM_ANIM_IDLE_1,
|
||||
VM_ANIM_IDLE_2,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
enum vmAnim_e {
|
||||
VM_ANIM_IDLE,
|
||||
VM_ANIM_CHARGE,
|
||||
VM_ANIM_FIRE,
|
||||
VM_ANIM_FIRE_SECONDARY,
|
||||
VM_ANIM_RECHAMBER,
|
||||
VM_ANIM_RELOAD,
|
||||
VM_ANIM_RELOAD_SINGLE,
|
||||
VM_ANIM_RELOAD_END,
|
||||
VM_ANIM_PULLOUT,
|
||||
VM_ANIM_PUTAWAY,
|
||||
VM_ANIM_LADDERSTEP,
|
||||
VM_ANIM_IDLE_0,
|
||||
VM_ANIM_IDLE_1,
|
||||
VM_ANIM_IDLE_2,
|
||||
VM_ANIM_DISABLED,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -422,7 +422,7 @@ void State::ParseAndProcessCommand
|
||||
{
|
||||
int argc;
|
||||
const char *argv[ MAX_COMMANDS ];
|
||||
char args[ MAX_COMMANDS ][ MAXTOKEN ];
|
||||
char args[ MAX_COMMANDS ][ SCRIPT_MAXTOKEN ];
|
||||
Script script;
|
||||
Event *event;
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ typedef struct gameImport_s
|
||||
void ( *AddCommand )( const char *cmdName, xcommand_t cmdFunction );
|
||||
int ( *FS_ReadFile )( const char *qpath, void **buffer, qboolean quiet );
|
||||
void ( *FS_FreeFile )( void *buffer );
|
||||
size_t( *FS_WriteFile )( const char *qpath, const void *buffer, size_t size );
|
||||
int ( *FS_WriteFile )( const char *qpath, const void *buffer, int size );
|
||||
fileHandle_t ( *FS_FOpenFileWrite )( const char *fileName );
|
||||
fileHandle_t ( *FS_FOpenFileAppend )( const char *fileName );
|
||||
const char *( *FS_PrepFileWrite )( const char *fileName );
|
||||
|
||||
+66
-16
@@ -1907,11 +1907,11 @@ qboolean Player::checkattackleft
|
||||
return false;
|
||||
}
|
||||
|
||||
if( last_ucmd.buttons & BUTTON_ATTACK )
|
||||
if( last_ucmd.buttons & BUTTON_ATTACKLEFT )
|
||||
{
|
||||
Weapon *weapon;
|
||||
|
||||
last_attack_button = BUTTON_ATTACK;
|
||||
last_attack_button = BUTTON_ATTACKLEFT;
|
||||
|
||||
weapon = GetActiveWeapon( WEAPON_MAIN );
|
||||
if( weapon )
|
||||
@@ -1939,7 +1939,7 @@ qboolean Player::checkattackbuttonleft
|
||||
return false;
|
||||
}
|
||||
|
||||
return ( last_ucmd.buttons & BUTTON_ATTACK );
|
||||
return ( last_ucmd.buttons & BUTTON_ATTACKLEFT );
|
||||
}
|
||||
|
||||
|
||||
@@ -1954,11 +1954,11 @@ qboolean Player::checkattackright
|
||||
return false;
|
||||
}
|
||||
|
||||
if( last_ucmd.buttons & BUTTON_ATTACK2 )
|
||||
if( last_ucmd.buttons & BUTTON_ATTACKRIGHT )
|
||||
{
|
||||
Weapon *weapon;
|
||||
|
||||
last_attack_button = BUTTON_ATTACK2;
|
||||
last_attack_button = BUTTON_ATTACKRIGHT;
|
||||
|
||||
weapon = GetActiveWeapon( WEAPON_MAIN );
|
||||
if( weapon )
|
||||
@@ -1986,7 +1986,7 @@ qboolean Player::checkattackbuttonright
|
||||
return false;
|
||||
}
|
||||
|
||||
return ( last_ucmd.buttons & BUTTON_ATTACK2 );
|
||||
return ( last_ucmd.buttons & BUTTON_ATTACKRIGHT );
|
||||
}
|
||||
|
||||
qboolean Player::checksneak
|
||||
@@ -3666,6 +3666,49 @@ qboolean Player::checkimmediateswitch( Conditional &condition )
|
||||
return ( g_gametype->integer && g_immediateswitch->integer );
|
||||
}
|
||||
|
||||
|
||||
qboolean Player::checkmovementspeed(Conditional& condition)
|
||||
{
|
||||
int speed = atoi(condition.getParm(1));
|
||||
return client->ps.speed >= speed;
|
||||
}
|
||||
|
||||
qboolean Player::checkabletodefuse(Conditional& condition)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean Player::checkonlandmine(Conditional& condition)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean Player::checknearlandmine(Conditional& condition)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean Player::CondCanPlaceLandmine(Conditional& condition)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean Player::CondWeaponCurrentFireAnim(Conditional& condition)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean Player::CondVehicleType(Conditional& condition)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean Player::CondAnimDoneVM( Conditional &condition )
|
||||
{
|
||||
return animDoneVM;
|
||||
@@ -4024,6 +4067,13 @@ Condition<Player> Player::Conditions[] =
|
||||
{ "MIN_CHARGE_TIME_MET", &Player::checkminchargetimemet },
|
||||
{ "MAX_CHARGE_TIME_MET", &Player::checkmaxchargetimemet },
|
||||
{ "IMMEDIATE_SWITCH", &Player::checkimmediateswitch },
|
||||
{ "CHECK_MOVEMENT_SPEED", &Player::checkmovementspeed },
|
||||
{ "ABLE_TO_DEFUSE", &Player::checkabletodefuse },
|
||||
{ "ON_LANDMINE", &Player::checkonlandmine },
|
||||
{ "NEAR_LANDMINE", &Player::checknearlandmine },
|
||||
{ "CAN_PLACE_LANDMINE", &Player::CondCanPlaceLandmine },
|
||||
{ "WEAPON_CURRENT_FIRE_ANIM", &Player::CondWeaponCurrentFireAnim },
|
||||
{ "VEHICLE_TYPE", &Player::CondVehicleType },
|
||||
{ "ANIMDONE_VM", &Player::CondAnimDoneVM },
|
||||
{ "CLIENT_COMMAND", &Player::CondClientCommand },
|
||||
{ "IS_VM_ANIM", &Player::CondVMAnim },
|
||||
@@ -6957,7 +7007,7 @@ void Player::ClientThink
|
||||
client->ps.pm_flags |= PMF_FROZEN;
|
||||
client->ps.pm_flags |= PMF_INTERMISSION;
|
||||
|
||||
if( level.time - level.intermissiontime > 5.0f && ( new_buttons & ( BUTTON_ATTACK | BUTTON_ATTACK2 ) ) )
|
||||
if( level.time - level.intermissiontime > 5.0f && ( new_buttons & ( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT ) ) )
|
||||
{
|
||||
level.exitintermission = true;
|
||||
}
|
||||
@@ -6998,7 +7048,7 @@ void Player::ClientThink
|
||||
{
|
||||
if( level.intermissiontype )
|
||||
{
|
||||
if( ( new_buttons & BUTTON_ATTACK ) || ( new_buttons & BUTTON_ATTACK2 ) )
|
||||
if( ( new_buttons & BUTTON_ATTACKLEFT ) || ( new_buttons & BUTTON_ATTACKRIGHT ) )
|
||||
{
|
||||
if( level.intermissiontype == TRANS_MISSION_FAILED )
|
||||
{
|
||||
@@ -7044,7 +7094,7 @@ void Player::ClientThink
|
||||
return;
|
||||
}
|
||||
|
||||
if( new_buttons & BUTTON_ATTACK2 )
|
||||
if( new_buttons & BUTTON_ATTACKRIGHT )
|
||||
{
|
||||
Weapon *weapon = GetActiveWeapon( WEAPON_MAIN );
|
||||
|
||||
@@ -7252,7 +7302,7 @@ void Player::Think
|
||||
if (g_gametype->integer == GT_SINGLE_PLAYER)
|
||||
{
|
||||
|
||||
if (((server_new_buttons & BUTTON_ATTACK) || (server_new_buttons & BUTTON_ATTACK2)) &&
|
||||
if (((server_new_buttons & BUTTON_ATTACKLEFT) || (server_new_buttons & BUTTON_ATTACKRIGHT)) &&
|
||||
(!GetActiveWeapon(WEAPON_MAIN)) &&
|
||||
(!IsDead()) &&
|
||||
(!IsNewActiveWeapon()) &&
|
||||
@@ -7270,7 +7320,7 @@ void Player::Think
|
||||
{
|
||||
if (dmManager.AllowRespawn())
|
||||
{
|
||||
if (((server_new_buttons & BUTTON_ATTACK) || (server_new_buttons & BUTTON_ATTACK2)) ||
|
||||
if (((server_new_buttons & BUTTON_ATTACKLEFT) || (server_new_buttons & BUTTON_ATTACKRIGHT)) ||
|
||||
(g_forcerespawn->integer > 0 && level.time > g_forcerespawn->integer + respawn_time))
|
||||
{
|
||||
m_bSpectator = false;
|
||||
@@ -7288,7 +7338,7 @@ void Player::Think
|
||||
|
||||
if (IsSpectator() && !m_bTempSpectator)
|
||||
{
|
||||
if (level.time <= respawn_time || !((server_new_buttons & BUTTON_ATTACK) || (server_new_buttons & BUTTON_ATTACK2)))
|
||||
if (level.time <= respawn_time || !((server_new_buttons & BUTTON_ATTACKLEFT) || (server_new_buttons & BUTTON_ATTACKRIGHT)))
|
||||
{
|
||||
if (level.time - 10.0f > m_fWeapSelectTime)
|
||||
{
|
||||
@@ -11544,7 +11594,7 @@ void Player::EventGetFireHeld
|
||||
)
|
||||
|
||||
{
|
||||
ev->AddInteger( buttons & ( BUTTON_ATTACK | BUTTON_ATTACK2 ) ? qtrue : qfalse );
|
||||
ev->AddInteger( buttons & ( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT ) ? qtrue : qfalse );
|
||||
}
|
||||
|
||||
void Player::Score
|
||||
@@ -14202,7 +14252,7 @@ void Player::LeanLeftHeld
|
||||
|
||||
player = ( Player * )this;
|
||||
|
||||
buttonheld = !!( player->buttons & BUTTON_LEANLEFT );
|
||||
buttonheld = !!( player->buttons & BUTTON_LEAN_LEFT );
|
||||
|
||||
ev->AddInteger( buttonheld );
|
||||
}
|
||||
@@ -14218,7 +14268,7 @@ void Player::LeanRightHeld
|
||||
|
||||
player = ( Player * )this;
|
||||
|
||||
buttonheld = !!( player->buttons & BUTTON_LEANRIGHT );
|
||||
buttonheld = !!( player->buttons & BUTTON_LEAN_RIGHT );
|
||||
|
||||
ev->AddInteger( buttonheld );
|
||||
}
|
||||
@@ -14362,7 +14412,7 @@ void Player::SecFireHeld
|
||||
|
||||
player = ( Player * )this;
|
||||
|
||||
buttonheld = !!( player->buttons & BUTTON_ATTACK2 );
|
||||
buttonheld = !!( player->buttons & BUTTON_ATTACKRIGHT );
|
||||
|
||||
ev->AddInteger( buttonheld );
|
||||
}
|
||||
|
||||
@@ -443,6 +443,13 @@ public:
|
||||
qboolean checkminchargetimemet( Conditional &condition );
|
||||
qboolean checkmaxchargetimemet( Conditional &condition );
|
||||
qboolean checkimmediateswitch( Conditional &condition );
|
||||
qboolean checkmovementspeed( Conditional &condition );
|
||||
qboolean checkabletodefuse( Conditional &condition );
|
||||
qboolean checkonlandmine( Conditional &condition );
|
||||
qboolean checknearlandmine( Conditional &condition );
|
||||
qboolean CondCanPlaceLandmine( Conditional &condition );
|
||||
qboolean CondWeaponCurrentFireAnim( Conditional &condition );
|
||||
qboolean CondVehicleType( Conditional &condition );
|
||||
qboolean CondAnimDoneVM( Conditional &condition );
|
||||
qboolean CondClientCommand( Conditional &condition );
|
||||
qboolean CondVMAnim( Conditional &condition );
|
||||
|
||||
+12
-12
@@ -503,7 +503,7 @@ void PlayerBot::UpdateBotStates
|
||||
if( IsDead() )
|
||||
{
|
||||
// The bot should respawn
|
||||
m_botCmd.buttons ^= BUTTON_ATTACK;
|
||||
m_botCmd.buttons ^= BUTTON_ATTACKLEFT;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1419,7 +1419,7 @@ void PlayerBot::State_EndAttack
|
||||
)
|
||||
|
||||
{
|
||||
m_botCmd.buttons &= ~( BUTTON_ATTACK | BUTTON_ATTACK2 );
|
||||
m_botCmd.buttons &= ~( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT );
|
||||
}
|
||||
|
||||
void PlayerBot::State_Attack
|
||||
@@ -1470,16 +1470,16 @@ void PlayerBot::State_Attack
|
||||
{
|
||||
if( pWeap->IsSemiAuto() )
|
||||
{
|
||||
m_botCmd.buttons ^= BUTTON_ATTACK;
|
||||
m_botCmd.buttons ^= BUTTON_ATTACKLEFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_botCmd.buttons |= BUTTON_ATTACK;
|
||||
m_botCmd.buttons |= BUTTON_ATTACKLEFT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_botCmd.buttons &= ~BUTTON_ATTACK;
|
||||
m_botCmd.buttons &= ~BUTTON_ATTACKLEFT;
|
||||
}
|
||||
}
|
||||
else if( pWeap->GetFireType( FIRE_SECONDARY ) == FT_MELEE )
|
||||
@@ -1488,21 +1488,21 @@ void PlayerBot::State_Attack
|
||||
|
||||
if( fDistanceSquared <= fSecondaryBulletRangeSquared )
|
||||
{
|
||||
m_botCmd.buttons ^= BUTTON_ATTACK2;
|
||||
m_botCmd.buttons ^= BUTTON_ATTACKRIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_botCmd.buttons &= ~BUTTON_ATTACK2;
|
||||
m_botCmd.buttons &= ~BUTTON_ATTACKRIGHT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_botCmd.buttons &= ~( BUTTON_ATTACK | BUTTON_ATTACK2 );
|
||||
m_botCmd.buttons &= ~( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_botCmd.buttons &= ~( BUTTON_ATTACK | BUTTON_ATTACK2 );
|
||||
m_botCmd.buttons &= ~( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT );
|
||||
fMinDistanceSquared = 0;
|
||||
}
|
||||
|
||||
@@ -1634,10 +1634,10 @@ void PlayerBot::Killed
|
||||
Player::Killed( ev );
|
||||
|
||||
// send the respawn buttons
|
||||
if( !( m_botCmd.buttons & BUTTON_ATTACK ) )
|
||||
m_botCmd.buttons |= BUTTON_ATTACK;
|
||||
if( !( m_botCmd.buttons & BUTTON_ATTACKLEFT ) )
|
||||
m_botCmd.buttons |= BUTTON_ATTACKLEFT;
|
||||
else
|
||||
m_botCmd.buttons &= ~BUTTON_ATTACK;
|
||||
m_botCmd.buttons &= ~BUTTON_ATTACKLEFT;
|
||||
|
||||
m_botEyes.ofs[ 0 ] = 0;
|
||||
m_botEyes.ofs[ 1 ] = 0;
|
||||
|
||||
@@ -772,7 +772,7 @@ qboolean TurretGun::UserAim
|
||||
|
||||
m_vUserLastCmdAng = vNewCmdAng;
|
||||
|
||||
if( ( ucmd->buttons & BUTTON_ATTACK ) || ( ucmd->buttons & BUTTON_ATTACK2 ) )
|
||||
if( ( ucmd->buttons & BUTTON_ATTACKLEFT ) || ( ucmd->buttons & BUTTON_ATTACKRIGHT ) )
|
||||
{
|
||||
if( !m_iFiring ) {
|
||||
m_iFiring = 1;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(gcd)
|
||||
|
||||
set(CURRENT_DIR "code/gamespy")
|
||||
|
||||
include_directories("${CURRENT_DIR}/common")
|
||||
|
||||
+100
-162
@@ -200,168 +200,109 @@ void Alias_ListAddParms(AliasListNode_t* node, const char* parameters)
|
||||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
for (;;)
|
||||
{
|
||||
while (1)
|
||||
token = nptr = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !token[0])
|
||||
{
|
||||
while (1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Q_stricmp(token, "stop"))
|
||||
{
|
||||
node->stop_flag = 1;
|
||||
}
|
||||
else if (!Q_stricmp(token, "soundparms"))
|
||||
{
|
||||
node->volume = getTokenFloat(¶meters, "volume", node);
|
||||
node->volumeMod = getTokenFloat(¶meters, "volumeMod", node);
|
||||
node->pitch = getTokenFloat(¶meters, "pitch", node);
|
||||
node->pitchMod = getTokenFloat(¶meters, "pitchMod", node);
|
||||
node->dist = getTokenFloat(¶meters, "dist", node);
|
||||
node->maxDist = getTokenFloat(¶meters, "maxDist", node);
|
||||
|
||||
token = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
token = nptr = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_stricmp(nptr, "weight"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
node->stop_flag = 1;
|
||||
}
|
||||
|
||||
if (Q_stricmp(nptr, "weight"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
token = COM_GetToken((char**)¶meters, 1);
|
||||
if (!token || !*token)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
temp_float = atof(token);
|
||||
|
||||
if (temp_float < 0.0f)
|
||||
{
|
||||
Com_Printf("Weight value out of range in %s alias\n", node->alias_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
node->weight = temp_float;
|
||||
}
|
||||
|
||||
if (Q_stricmp(nptr, "soundparms"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
node->volume = getTokenFloat(¶meters, "volume", node);
|
||||
node->volumeMod = getTokenFloat(¶meters, "volumeMod", node);
|
||||
node->pitch = getTokenFloat(¶meters, "pitch", node);
|
||||
node->pitchMod = getTokenFloat(¶meters, "pitchMod", node);
|
||||
node->dist = getTokenFloat(¶meters, "dist", node);
|
||||
node->maxDist = getTokenFloat(¶meters, "maxDist", node);
|
||||
|
||||
token = COM_GetToken((char**)¶meters, 1);
|
||||
if (!token || !*token)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
node->channel = S_ChannelNameToNum(token);
|
||||
if (node->channel == -1)
|
||||
{
|
||||
Com_Printf("%s is not avalid channel on %s alias.\n", token, node->alias_name);
|
||||
node->channel = 0;
|
||||
}
|
||||
|
||||
token = COM_GetToken((char**)¶meters, 1);
|
||||
if (!token || !*token)
|
||||
{
|
||||
Com_Printf("ERROR: defaulting %s to not streamed - please setup alias properly.\n", node->alias_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Q_stricmp(token, "streamed"))
|
||||
{
|
||||
node->streamed = 1;
|
||||
}
|
||||
else if (!Q_stricmp(token, "loaded"))
|
||||
{
|
||||
node->streamed = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf("ERROR: Expecting streamed or loaded in ubersound and got %s on alias %s\n", token, node->alias_name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (Q_stricmp(nptr, "subtitle"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
token = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
{
|
||||
Com_Printf("NULL subtitle on %s alias.\n", node->alias_name);
|
||||
return;
|
||||
}
|
||||
|
||||
node->subtitle = Z_TagMalloc(strlen(token) + 1, TAG_TIKI);
|
||||
strcpy(node->subtitle, token);
|
||||
}
|
||||
|
||||
if (Q_stricmp(nptr, "pitch"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
token = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
temp_float = atof(token);
|
||||
if (temp_float < 0.0f)
|
||||
{
|
||||
Com_Printf("Pitch value out of range in %s alias\n", node->alias_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
node->pitch = temp_float;
|
||||
}
|
||||
|
||||
if (Q_stricmp(nptr, "pitchmod"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
token = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
temp_float = atof(token);
|
||||
if (temp_float < 0.0f)
|
||||
{
|
||||
Com_Printf("PitchMod value out of range in %s alias\n", node->alias_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
node->pitchMod = temp_float;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_stricmp(nptr, "volumemod"))
|
||||
node->channel = S_ChannelNameToNum(token);
|
||||
if (node->channel == -1)
|
||||
{
|
||||
break;
|
||||
Com_Printf("%s is not avalid channel on %s alias.\n", token, node->alias_name);
|
||||
node->channel = 0;
|
||||
}
|
||||
|
||||
token = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
{
|
||||
Com_Printf("ERROR: defaulting %s to not streamed - please setup alias properly.\n", node->alias_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Q_stricmp(token, "streamed"))
|
||||
{
|
||||
node->streamed = qtrue;
|
||||
}
|
||||
else if (!Q_stricmp(token, "loaded"))
|
||||
{
|
||||
node->streamed = qfalse;
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf("ERROR: Expecting streamed or loaded in ubersound and got %s on alias %s\n", token, node->alias_name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!Q_stricmp(token, "subtitle"))
|
||||
{
|
||||
token = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
{
|
||||
Com_Printf("NULL subtitle on %s alias.\n", node->alias_name);
|
||||
return;
|
||||
}
|
||||
|
||||
node->subtitle = Z_TagMalloc(strlen(token) + 1, TAG_TIKI);
|
||||
strcpy(node->subtitle, token);
|
||||
}
|
||||
else if (!Q_stricmp(token, "pitch"))
|
||||
{
|
||||
token = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
temp_float = atof(token);
|
||||
if (temp_float < 0.0f)
|
||||
{
|
||||
Com_Printf("Pitch value out of range in %s alias\n", node->alias_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
node->pitch = temp_float;
|
||||
}
|
||||
else if (!Q_stricmp(token, "pitchmod"))
|
||||
{
|
||||
token = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
temp_float = atof(token);
|
||||
if (temp_float < 0.0f)
|
||||
{
|
||||
Com_Printf("PitchMod value out of range in %s alias\n", node->alias_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
node->pitchMod = temp_float;
|
||||
}
|
||||
else if (!Q_stricmp(token, "volumemod"))
|
||||
{
|
||||
token = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
{
|
||||
@@ -377,8 +318,7 @@ void Alias_ListAddParms(AliasListNode_t* node, const char* parameters)
|
||||
|
||||
node->volumeMod = temp_float;
|
||||
}
|
||||
|
||||
if (!Q_stricmp(nptr, "dist"))
|
||||
else if (!Q_stricmp(token, "dist"))
|
||||
{
|
||||
token = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
@@ -396,7 +336,7 @@ void Alias_ListAddParms(AliasListNode_t* node, const char* parameters)
|
||||
|
||||
node->dist = temp_float;
|
||||
}
|
||||
else if (!Q_stricmp(nptr, "channel"))
|
||||
else if (!Q_stricmp(token, "channel"))
|
||||
{
|
||||
token = COM_GetToken((char**)¶meters, qtrue);
|
||||
if (!token || !*token)
|
||||
@@ -418,8 +358,6 @@ void Alias_ListAddParms(AliasListNode_t* node, const char* parameters)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: stub
|
||||
}
|
||||
|
||||
qboolean Alias_ListAdd(AliasList_t* list, const char* alias, const char* name, const char* parameters)
|
||||
@@ -728,7 +666,7 @@ void Alias_ListFindRandomRange(AliasList_t* list, const char* alias, int* min_in
|
||||
}
|
||||
} while (r >= l);
|
||||
|
||||
if (l >= r)
|
||||
if (r >= l)
|
||||
{
|
||||
numfound = 0;
|
||||
*min_index = index;
|
||||
@@ -736,7 +674,7 @@ void Alias_ListFindRandomRange(AliasList_t* list, const char* alias, int* min_in
|
||||
totalfoundweight = 0.f;
|
||||
|
||||
ptr = &list->sorted_list[index];
|
||||
for (i = 0; i < index; i++, ptr--)
|
||||
for (i = index + 1; i > 0; i--, ptr--)
|
||||
{
|
||||
if (strncmp(convalias, (*ptr)->alias_name, length)) {
|
||||
break;
|
||||
@@ -746,7 +684,7 @@ void Alias_ListFindRandomRange(AliasList_t* list, const char* alias, int* min_in
|
||||
{
|
||||
foundlist[numfound++] = *ptr;
|
||||
totalfoundweight += (*ptr)->weight;
|
||||
*min_index = i;
|
||||
*min_index = i - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -609,6 +609,7 @@ void CMod_LoadPatches( gamelump_t *surfs, gamelump_t *verts, int *shaderSubdivis
|
||||
vec3_t points[MAX_PATCH_VERTS];
|
||||
int width, height;
|
||||
int shaderNum;
|
||||
char tempName[MAX_QPATH + 1];
|
||||
|
||||
in = ( dsurface_t * )surfs->buffer;
|
||||
if( surfs->length % sizeof( *in ) )
|
||||
@@ -668,6 +669,9 @@ void CMod_LoadPatches( gamelump_t *surfs, gamelump_t *verts, int *shaderSubdivis
|
||||
|
||||
// create the internal facet structure
|
||||
patch->pc = CM_GeneratePatchCollide( width, height, points, patch->subdivisions );
|
||||
|
||||
sprintf(tempName, "s%d", i);
|
||||
UI_LoadResource(tempName);
|
||||
}
|
||||
|
||||
Hunk_FreeTempMemory( shaderSubdivisions );
|
||||
@@ -878,9 +882,9 @@ void CM_LoadMap( const char *name, qboolean clientload, int *checksum ) {
|
||||
((int *)&header)[i] = LittleLong ( ((int *)&header)[i]);
|
||||
}
|
||||
|
||||
if ( header.version != BSP_VERSION ) {
|
||||
Com_Error (ERR_DROP, "CM_LoadMap: %s has wrong version number (%i should be %i)"
|
||||
, name, header.version, BSP_VERSION );
|
||||
if ( header.version < BSP_MIN_VERSION || header.version > BSP_MAX_VERSION ) {
|
||||
Com_Error (ERR_DROP, "CM_LoadMap: %s has wrong version number (%i should be between %i and %i)"
|
||||
, name, header.version, BSP_MIN_VERSION, BSP_MAX_VERSION );
|
||||
}
|
||||
|
||||
cmod_base = ( byte * )&header;
|
||||
|
||||
+31
-210
@@ -31,6 +31,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
// FPS
|
||||
#include <chrono>
|
||||
|
||||
#include <tiki.h>
|
||||
|
||||
qboolean CL_FinishedIntro(void);
|
||||
@@ -72,7 +75,6 @@ fileHandle_t com_journalDataFile; // config files are written here
|
||||
cvar_t *paused;
|
||||
cvar_t *config;
|
||||
cvar_t *fps;
|
||||
float currentfps;
|
||||
cvar_t *com_speeds;
|
||||
cvar_t *developer;
|
||||
cvar_t *com_dedicated;
|
||||
@@ -126,6 +128,18 @@ static char *rd_buffer;
|
||||
static int rd_buffersize;
|
||||
static void (*rd_flush)( char *buffer );
|
||||
|
||||
#define MAX_FPS_TIMES 16
|
||||
|
||||
using fps_clock_t = std::chrono::high_resolution_clock;
|
||||
using fps_time_t = fps_clock_t::time_point;
|
||||
using fps_delta_t = fps_clock_t::duration;
|
||||
|
||||
static int fpsindex;
|
||||
static fps_delta_t fpstimes[MAX_FPS_TIMES];
|
||||
static fps_delta_t fpstotal;
|
||||
static fps_time_t fpslasttime;
|
||||
float currentfps;
|
||||
|
||||
void Com_BeginRedirect (char *buffer, int buffersize, void (*flush)( char *) )
|
||||
{
|
||||
if (!buffer || !buffersize || !flush)
|
||||
@@ -1752,6 +1766,22 @@ void Com_Frame( void ) {
|
||||
com_frameNumber, all, sv, ev, cl, time_game, time_frontend, time_backend );
|
||||
}
|
||||
|
||||
if (fps->integer) {
|
||||
fps_time_t fpstime = fps_clock_t::now();
|
||||
fps_delta_t delta = fpstime - fpslasttime;
|
||||
|
||||
fpstotal = (fpstime - fpslasttime) + (fpstotal - fpstimes[fpsindex]);
|
||||
fpstimes[fpsindex] = fpstime - fpslasttime;
|
||||
fpsindex = (fpsindex + 1) % MAX_FPS_TIMES;
|
||||
fpslasttime = fpstime;
|
||||
|
||||
if (fpstotal.count()) {
|
||||
currentfps = 16.0 / std::chrono::duration<long double>(fpstotal).count();
|
||||
} else {
|
||||
currentfps = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// trace optimization tracking
|
||||
//
|
||||
@@ -1893,23 +1923,10 @@ command line completion
|
||||
===========================================
|
||||
*/
|
||||
|
||||
/*
|
||||
==================
|
||||
Field_Clear
|
||||
==================
|
||||
*/
|
||||
void Field_Clear( field_t *edit ) {
|
||||
memset(edit->buffer, 0, MAX_EDIT_LINE);
|
||||
edit->cursor = 0;
|
||||
edit->scroll = 0;
|
||||
}
|
||||
|
||||
static const char *completionString;
|
||||
static char shortestMatch[MAX_TOKEN_CHARS];
|
||||
static int matchCount;
|
||||
// field we are working on, passed to Field_AutoComplete(&g_consoleCommand for instance)
|
||||
static field_t *completionField;
|
||||
|
||||
/*
|
||||
===============
|
||||
FindMatches
|
||||
@@ -1968,200 +1985,4 @@ static void PrintCvarMatches( const char *s ) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Field_FindFirstSeparator
|
||||
===============
|
||||
*/
|
||||
static char *Field_FindFirstSeparator( char *s )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < strlen( s ); i++ )
|
||||
{
|
||||
if( s[ i ] == ';' )
|
||||
return &s[ i ];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef DEDICATED
|
||||
/*
|
||||
===============
|
||||
Field_CompleteKeyname
|
||||
===============
|
||||
*/
|
||||
static void Field_CompleteKeyname( void )
|
||||
{
|
||||
matchCount = 0;
|
||||
shortestMatch[ 0 ] = 0;
|
||||
|
||||
Key_KeynameCompletion( FindMatches );
|
||||
|
||||
if( matchCount == 0 )
|
||||
return;
|
||||
|
||||
Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) -
|
||||
strlen( completionString ) ], shortestMatch,
|
||||
sizeof( completionField->buffer ) );
|
||||
completionField->cursor = ( int )strlen( completionField->buffer );
|
||||
|
||||
if( matchCount == 1 )
|
||||
{
|
||||
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
|
||||
completionField->cursor++;
|
||||
return;
|
||||
}
|
||||
|
||||
Com_Printf( "]%s\n", completionField->buffer );
|
||||
|
||||
Key_KeynameCompletion( PrintMatches );
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
===============
|
||||
Field_CompleteFilename
|
||||
===============
|
||||
*/
|
||||
static void Field_CompleteFilename( const char *dir,
|
||||
const char *ext, qboolean stripExt )
|
||||
{
|
||||
size_t pos;
|
||||
|
||||
matchCount = 0;
|
||||
shortestMatch[ 0 ] = 0;
|
||||
|
||||
FS_FilenameCompletion( dir, ext, stripExt, FindMatches );
|
||||
|
||||
if( matchCount == 0 )
|
||||
return;
|
||||
|
||||
pos = strlen( completionField->buffer ) - strlen( completionString );
|
||||
Q_strncpyz( &completionField->buffer[ pos ], shortestMatch,
|
||||
sizeof( completionField->buffer ) - pos );
|
||||
completionField->cursor = ( int )strlen( completionField->buffer );
|
||||
|
||||
if( matchCount == 1 )
|
||||
{
|
||||
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
|
||||
completionField->cursor++;
|
||||
return;
|
||||
}
|
||||
|
||||
Com_Printf( "]%s\n", completionField->buffer );
|
||||
|
||||
FS_FilenameCompletion( dir, ext, stripExt, PrintMatches );
|
||||
}
|
||||
|
||||
static void keyConcatArgs(void) {
|
||||
int i;
|
||||
char* arg;
|
||||
|
||||
for (i = 1; i < Cmd_Argc(); i++) {
|
||||
Q_strcat(completionField->buffer, sizeof(completionField->buffer), " ");
|
||||
arg = Cmd_Argv(i);
|
||||
while (*arg) {
|
||||
if (*arg == ' ') {
|
||||
Q_strcat(completionField->buffer, sizeof(completionField->buffer), "\"");
|
||||
break;
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
Q_strcat(completionField->buffer, sizeof(completionField->buffer), Cmd_Argv(i));
|
||||
if (*arg == ' ') {
|
||||
Q_strcat(completionField->buffer, sizeof(completionField->buffer), "\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ConcatRemaining(const char* src, const char* start) {
|
||||
const char* str;
|
||||
|
||||
str = strstr(src, start);
|
||||
if (!str) {
|
||||
keyConcatArgs();
|
||||
return;
|
||||
}
|
||||
|
||||
str += strlen(start);
|
||||
Q_strcat(completionField->buffer, sizeof(completionField->buffer), str);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Field_CompleteCommand
|
||||
|
||||
perform Tab expansion
|
||||
NOTE TTimo this was originally client code only
|
||||
moved to common code when writing tty console for *nix dedicated server
|
||||
===============
|
||||
*/
|
||||
void Field_CompleteCommand(field_t* field) {
|
||||
field_t temp;
|
||||
|
||||
completionField = field;
|
||||
|
||||
// only look at the first token for completion purposes
|
||||
Cmd_TokenizeString(completionField->buffer);
|
||||
|
||||
completionString = Cmd_Argv(0);
|
||||
if (completionString[0] == '\\' || completionString[0] == '/') {
|
||||
completionString++;
|
||||
}
|
||||
matchCount = 0;
|
||||
shortestMatch[0] = 0;
|
||||
|
||||
if (strlen(completionString) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cmd_CommandCompletion(FindMatches);
|
||||
Cvar_CommandCompletion(FindMatches);
|
||||
|
||||
if (matchCount == 0) {
|
||||
return; // no matches
|
||||
}
|
||||
|
||||
Com_Memcpy(&temp, completionField, sizeof(field_t));
|
||||
|
||||
if (matchCount == 1) {
|
||||
Com_sprintf(completionField->buffer, sizeof(completionField->buffer), "\\%s", shortestMatch);
|
||||
if (Cmd_Argc() == 1) {
|
||||
Q_strcat(completionField->buffer, sizeof(completionField->buffer), " ");
|
||||
}
|
||||
else {
|
||||
ConcatRemaining(temp.buffer, completionString);
|
||||
}
|
||||
completionField->cursor = strlen(completionField->buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
// multiple matches, complete to shortest
|
||||
Com_sprintf(completionField->buffer, sizeof(completionField->buffer), "\\%s", shortestMatch);
|
||||
completionField->cursor = strlen(completionField->buffer);
|
||||
ConcatRemaining(temp.buffer, completionString);
|
||||
|
||||
Com_Printf("]%s\n", completionField->buffer);
|
||||
|
||||
// run through again, printing matches
|
||||
Cmd_CommandCompletion(PrintMatches);
|
||||
Cvar_CommandCompletion(PrintMatches);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Field_AutoComplete
|
||||
|
||||
Perform Tab expansion
|
||||
===============
|
||||
*/
|
||||
void Field_AutoComplete( field_t *field )
|
||||
{
|
||||
completionField = field;
|
||||
|
||||
Field_CompleteCommand(field);
|
||||
}
|
||||
|
||||
}
|
||||
+12
-6
@@ -3068,7 +3068,7 @@ static void FS_ReorderPurePaks( void )
|
||||
FS_Startup
|
||||
================
|
||||
*/
|
||||
static void FS_Startup( const char *gameName )
|
||||
static void FS_Startup(const char* gameName, const char* extensionName)
|
||||
{
|
||||
const char* homePath;
|
||||
|
||||
@@ -3087,10 +3087,16 @@ static void FS_Startup( const char *gameName )
|
||||
fs_gamedirvar = Cvar_Get( "fs_game", "", CVAR_INIT | CVAR_SYSTEMINFO );
|
||||
fs_restrict = Cvar_Get( "fs_restrict", "", CVAR_INIT );
|
||||
|
||||
FS_AddGameDirectory( fs_basepath->string, gameName );
|
||||
if (gameName) {
|
||||
FS_AddGameDirectory(fs_basepath->string, gameName);
|
||||
}
|
||||
|
||||
if( *fs_gamedirvar->string && !Q_stricmp( gameName, "main" ) && Q_stricmp( fs_gamedirvar->string, gameName ) ) {
|
||||
FS_AddGameDirectory( fs_basepath->string, fs_gamedirvar->string );
|
||||
if (Q_stricmp(gameName, extensionName)) {
|
||||
FS_AddGameDirectory(fs_basepath->string, extensionName);
|
||||
}
|
||||
|
||||
if (*fs_gamedirvar->string && !Q_stricmp(gameName, GAME_EXTENSION_BASE) && Q_stricmp(fs_gamedirvar->string, gameName)) {
|
||||
FS_AddGameDirectory(fs_basepath->string, fs_gamedirvar->string);
|
||||
}
|
||||
|
||||
fs_mapdir = Cvar_Get( "mapdir", "", 0 );
|
||||
@@ -3594,7 +3600,7 @@ void FS_InitFilesystem( void ) {
|
||||
Com_StartupVariable( "fs_homepath" );
|
||||
|
||||
// try to start up normally
|
||||
FS_Startup( BASEGAME );
|
||||
FS_Startup( BASEGAME, GAME_EXTENSION_BASE);
|
||||
FS_SetRestrictions();
|
||||
|
||||
if( !silentStart ) {
|
||||
@@ -3640,7 +3646,7 @@ void FS_Restart( int checksumFeed ) {
|
||||
FS_ClearPakReferences(0);
|
||||
|
||||
// try to start up normally
|
||||
FS_Startup( BASEGAME );
|
||||
FS_Startup(BASEGAME, GAME_EXTENSION_BASE);
|
||||
|
||||
FS_CheckPak0( );
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ void* MEM_TempAlloc::CreateBlock(size_t len)
|
||||
// allocate a new block
|
||||
tempBlock_t* prev_block = m_CurrentMemoryBlock;
|
||||
m_CurrentMemoryBlock = (tempBlock_t*)MEM_TempAllocate(
|
||||
sizeof(tempBlock_t) + max(m_BlockSize, len));
|
||||
sizeof(tempBlock_t) + Q_max(m_BlockSize, len));
|
||||
m_CurrentMemoryBlock->prev = prev_block;
|
||||
return m_CurrentMemoryBlock->GetData();
|
||||
}
|
||||
|
||||
+542
-183
@@ -32,10 +32,10 @@ int oldsize = 0;
|
||||
// TA stuff
|
||||
//===================
|
||||
|
||||
static constexpr unsigned int MAX_PACKED_COORD = 65536;
|
||||
static constexpr unsigned int MAX_PACKED_COORD_HALF = MAX_PACKED_COORD / 2;
|
||||
static constexpr unsigned int MAX_PACKED_COORD_EXTRA = 262144;
|
||||
static constexpr unsigned int MAX_PACKED_COORD_EXTRA_HALF = MAX_PACKED_COORD_EXTRA / 2;
|
||||
static constexpr int MAX_PACKED_COORD = 65536;
|
||||
static constexpr int MAX_PACKED_COORD_HALF = MAX_PACKED_COORD / 2;
|
||||
static constexpr int MAX_PACKED_COORD_EXTRA = 262144;
|
||||
static constexpr int MAX_PACKED_COORD_EXTRA_HALF = MAX_PACKED_COORD_EXTRA / 2;
|
||||
|
||||
//===
|
||||
// Statistics for changes reporting
|
||||
@@ -326,11 +326,21 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
|
||||
}
|
||||
msg->readcount = (msg->bit>>3)+1;
|
||||
}
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
if (sgn) {
|
||||
if (value & 1) {
|
||||
value = ~(value >> 1);
|
||||
} else {
|
||||
value >>= 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (sgn) {
|
||||
if (value & (1 << (bits - 1))) {
|
||||
value |= -1 ^ ((1 << bits) - 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -417,6 +427,32 @@ void MSG_WriteString( msg_t *sb, const char *s ) {
|
||||
}
|
||||
}
|
||||
|
||||
void MSG_WriteBigString( msg_t *sb, const char *s ) {
|
||||
if ( !s ) {
|
||||
MSG_WriteByte(sb, 0);
|
||||
} else {
|
||||
size_t l;
|
||||
int i;
|
||||
char string[BIG_INFO_STRING];
|
||||
|
||||
l = strlen( s );
|
||||
if ( l >= BIG_INFO_STRING ) {
|
||||
Com_Printf("MSG_WriteString: BIG_INFO_STRING");
|
||||
MSG_WriteByte(sb, 0);
|
||||
return;
|
||||
}
|
||||
Q_strncpyz( string, s, sizeof( string ) );
|
||||
|
||||
for ( i = 0 ; i <= l ; i++ ) {
|
||||
MSG_WriteByte(sb, string[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
|
||||
void MSG_WriteScrambledString(msg_t* sb, const char* s) {
|
||||
if (!s) {
|
||||
strstats[0]++;
|
||||
@@ -444,28 +480,6 @@ void MSG_WriteScrambledString(msg_t* sb, const char* s) {
|
||||
}
|
||||
}
|
||||
|
||||
void MSG_WriteBigString( msg_t *sb, const char *s ) {
|
||||
if ( !s ) {
|
||||
MSG_WriteByte(sb, 0);
|
||||
} else {
|
||||
size_t l;
|
||||
int i;
|
||||
char string[BIG_INFO_STRING];
|
||||
|
||||
l = strlen( s );
|
||||
if ( l >= BIG_INFO_STRING ) {
|
||||
Com_Printf("MSG_WriteString: BIG_INFO_STRING");
|
||||
MSG_WriteByte(sb, 0);
|
||||
return;
|
||||
}
|
||||
Q_strncpyz( string, s, sizeof( string ) );
|
||||
|
||||
for ( i = 0 ; i <= l ; i++ ) {
|
||||
MSG_WriteByte(sb, string[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MSG_WriteScrambledBigString(msg_t* sb, const char* s) {
|
||||
if (!s) {
|
||||
strstats[0]++;
|
||||
@@ -493,6 +507,18 @@ void MSG_WriteScrambledBigString(msg_t* sb, const char* s) {
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void MSG_WriteScrambledString(msg_t* sb, const char* s) {
|
||||
return MSG_WriteString(sb, s);
|
||||
}
|
||||
|
||||
void MSG_WriteScrambledBigString(msg_t* sb, const char* s) {
|
||||
return MSG_WriteBigString(sb, s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void MSG_WriteAngle( msg_t *sb, float f ) {
|
||||
MSG_WriteByte (sb, (int)(f*256/360) & 255);
|
||||
}
|
||||
@@ -598,6 +624,8 @@ float MSG_ReadFloat( msg_t *msg ) {
|
||||
return dat.f;
|
||||
}
|
||||
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
|
||||
char* MSG_ReadScrambledString(msg_t* msg) {
|
||||
static char string[MAX_STRING_CHARS];
|
||||
int l, c;
|
||||
@@ -610,6 +638,9 @@ char* MSG_ReadScrambledString(msg_t* msg) {
|
||||
}
|
||||
|
||||
c = NetByteToStrChar[c];
|
||||
if (!c) {
|
||||
break;
|
||||
}
|
||||
// translate all fmt spec to avoid crash bugs
|
||||
if (c == '%') {
|
||||
c = '.';
|
||||
@@ -629,6 +660,52 @@ char* MSG_ReadScrambledString(msg_t* msg) {
|
||||
return string;
|
||||
}
|
||||
|
||||
char* MSG_ReadScrambledBigString(msg_t* msg) {
|
||||
static char string[BIG_INFO_STRING];
|
||||
int l, c;
|
||||
|
||||
l = 0;
|
||||
do {
|
||||
c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
c = NetByteToStrChar[c];
|
||||
if (!c) {
|
||||
break;
|
||||
}
|
||||
// translate all fmt spec to avoid crash bugs
|
||||
if (c == '%') {
|
||||
c = '.';
|
||||
}
|
||||
// don't allow higher ascii values
|
||||
// (su44: this check is missing in MoHAA)
|
||||
if (c > 127) {
|
||||
c = '.';
|
||||
}
|
||||
|
||||
string[l] = c;
|
||||
l++;
|
||||
} while (l < sizeof(string) - 1);
|
||||
|
||||
string[l] = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
char* MSG_ReadScrambledString(msg_t* msg) {
|
||||
return MSG_ReadString(msg);
|
||||
}
|
||||
|
||||
char* MSG_ReadScrambledBigString(msg_t* msg) {
|
||||
return MSG_ReadBigString(msg);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
char *MSG_ReadString( msg_t *msg ) {
|
||||
static char string[MAX_STRING_CHARS];
|
||||
int l,c;
|
||||
@@ -721,7 +798,6 @@ void MSG_GetNullEntityState(entityState_t *nullState) {
|
||||
nullState->alpha = 1.0f;
|
||||
nullState->scale = 1.0f;
|
||||
nullState->parent = ENTITYNUM_NONE;
|
||||
nullState->tag_num = -1; // su44
|
||||
nullState->constantLight = 0xffffff;
|
||||
nullState->renderfx = 16;
|
||||
nullState->bone_tag[4] = -1;
|
||||
@@ -1171,6 +1247,157 @@ typedef struct {
|
||||
// using the stringizing operator to save typing...
|
||||
#define NETF(x) #x,(size_t)&((entityState_t*)0)->x
|
||||
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
netField_t entityStateFields[] =
|
||||
{
|
||||
{ NETF(netorigin[0]), 0, netFieldType_t::coord },
|
||||
{ NETF(netorigin[1]), 0, netFieldType_t::coord },
|
||||
{ NETF(netangles[1]), 12, netFieldType_t::angle },
|
||||
{ NETF(frameInfo[0].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[1].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(bone_angles[0][0]), -13, netFieldType_t::angle },
|
||||
{ NETF(bone_angles[3][0]), -13, netFieldType_t::angle },
|
||||
{ NETF(bone_angles[1][0]), -13, netFieldType_t::angle },
|
||||
{ NETF(bone_angles[2][0]), -13, netFieldType_t::angle },
|
||||
{ NETF(netorigin[2]), 0, netFieldType_t::coord },
|
||||
{ NETF(frameInfo[0].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[1].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[2].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[3].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[0].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[1].index), 12, netFieldType_t::regular },
|
||||
{ NETF(actionWeight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[2].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[3].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[2].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[3].index), 12, netFieldType_t::regular },
|
||||
{ NETF(eType), 8, netFieldType_t::regular },
|
||||
{ NETF(modelindex), 16, netFieldType_t::regular },
|
||||
{ NETF(parent), 16, netFieldType_t::regular },
|
||||
{ NETF(constantLight), 32, netFieldType_t::regular },
|
||||
{ NETF(renderfx), 32, netFieldType_t::regular },
|
||||
{ NETF(bone_tag[0]), -8, netFieldType_t::regular },
|
||||
{ NETF(bone_tag[1]), -8, netFieldType_t::regular },
|
||||
{ NETF(bone_tag[2]), -8, netFieldType_t::regular },
|
||||
{ NETF(bone_tag[3]), -8, netFieldType_t::regular },
|
||||
{ NETF(bone_tag[4]), -8, netFieldType_t::regular },
|
||||
{ NETF(scale), 10, netFieldType_t::scale },
|
||||
{ NETF(alpha), 8, netFieldType_t::alpha },
|
||||
{ NETF(usageIndex), 16, netFieldType_t::regular },
|
||||
{ NETF(eFlags), 16, netFieldType_t::regular },
|
||||
{ NETF(solid), 32, netFieldType_t::regular },
|
||||
{ NETF(netangles[2]), 12, netFieldType_t::angle },
|
||||
{ NETF(netangles[0]), 12, netFieldType_t::angle },
|
||||
{ NETF(tag_num), 10, netFieldType_t::regular },
|
||||
{ NETF(bone_angles[1][2]), -13, netFieldType_t::angle },
|
||||
{ NETF(attach_use_angles), 1, netFieldType_t::regular },
|
||||
{ NETF(origin2[1]), 0, netFieldType_t::coord },
|
||||
{ NETF(origin2[0]), 0, netFieldType_t::coord },
|
||||
{ NETF(origin2[2]), 0, netFieldType_t::coord },
|
||||
{ NETF(bone_angles[0][2]), -13, netFieldType_t::angle },
|
||||
{ NETF(bone_angles[2][2]), -13, netFieldType_t::angle },
|
||||
{ NETF(bone_angles[3][2]), -13, netFieldType_t::angle },
|
||||
{ NETF(surfaces[0]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[1]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[2]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[3]), 8, netFieldType_t::regular },
|
||||
{ NETF(bone_angles[0][1]), -13, netFieldType_t::angle },
|
||||
{ NETF(surfaces[4]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[5]), 8, netFieldType_t::regular },
|
||||
{ NETF(pos.trTime), 32, netFieldType_t::regular },
|
||||
{ NETF(pos.trDelta[0]), 0, netFieldType_t::velocity },
|
||||
{ NETF(pos.trDelta[1]), 0, netFieldType_t::velocity },
|
||||
{ NETF(pos.trDelta[2]), 0, netFieldType_t::velocity },
|
||||
{ NETF(loopSound), 16, netFieldType_t::regular },
|
||||
{ NETF(loopSoundVolume), 0, netFieldType_t::regular },
|
||||
{ NETF(loopSoundMinDist), 0, netFieldType_t::regular },
|
||||
{ NETF(loopSoundMaxDist), 0, netFieldType_t::regular },
|
||||
{ NETF(loopSoundPitch), 0, netFieldType_t::regular },
|
||||
{ NETF(loopSoundFlags), 8, netFieldType_t::regular },
|
||||
{ NETF(attach_offset[0]), 0, netFieldType_t::regular },
|
||||
{ NETF(attach_offset[1]), 0, netFieldType_t::regular },
|
||||
{ NETF(attach_offset[2]), 0, netFieldType_t::regular },
|
||||
{ NETF(beam_entnum), 16, netFieldType_t::regular },
|
||||
{ NETF(skinNum), 16, netFieldType_t::regular },
|
||||
{ NETF(wasframe), 10, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[4].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[5].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[6].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[7].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[8].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[9].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[10].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[11].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[12].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[13].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[14].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[15].index), 12, netFieldType_t::regular },
|
||||
{ NETF(frameInfo[4].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[5].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[6].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[7].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[8].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[9].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[10].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[11].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[12].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[13].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[14].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[15].time), 15, netFieldType_t::animTime },
|
||||
{ NETF(frameInfo[4].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[5].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[6].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[7].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[8].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[9].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[10].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[11].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[12].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[13].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[14].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(frameInfo[15].weight), 8, netFieldType_t::animWeight },
|
||||
{ NETF(bone_angles[1][1]), -13, netFieldType_t::angle },
|
||||
{ NETF(bone_angles[2][1]), -13, netFieldType_t::angle },
|
||||
{ NETF(bone_angles[3][1]), -13, netFieldType_t::angle },
|
||||
{ NETF(bone_angles[4][0]), -13, netFieldType_t::angle },
|
||||
{ NETF(bone_angles[4][1]), -13, netFieldType_t::angle },
|
||||
{ NETF(bone_angles[4][2]), -13, netFieldType_t::angle },
|
||||
{ NETF(clientNum), 8, netFieldType_t::regular },
|
||||
{ NETF(groundEntityNum), GENTITYNUM_BITS, netFieldType_t::regular },
|
||||
{ NETF(shader_data[0]), 0, netFieldType_t::regular },
|
||||
{ NETF(shader_data[1]), 0, netFieldType_t::regular },
|
||||
{ NETF(shader_time), 0, netFieldType_t::regular },
|
||||
{ NETF(eyeVector[0]), 0, netFieldType_t::regular },
|
||||
{ NETF(eyeVector[1]), 0, netFieldType_t::regular },
|
||||
{ NETF(eyeVector[2]), 0, netFieldType_t::regular },
|
||||
{ NETF(surfaces[6]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[7]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[8]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[9]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[10]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[11]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[12]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[13]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[14]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[15]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[16]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[17]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[18]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[19]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[20]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[21]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[22]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[23]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[24]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[25]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[26]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[27]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[28]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[29]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[30]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[31]), 8, netFieldType_t::regular }
|
||||
};
|
||||
#else
|
||||
netField_t entityStateFields[] =
|
||||
{
|
||||
{ NETF(netorigin[0]), 0, netFieldType_t::coord },
|
||||
@@ -1320,6 +1547,7 @@ netField_t entityStateFields[] =
|
||||
{ NETF(surfaces[30]), 8, netFieldType_t::regular },
|
||||
{ NETF(surfaces[31]), 8, netFieldType_t::regular }
|
||||
};
|
||||
#endif
|
||||
static constexpr unsigned long numEntityFields = sizeof(entityStateFields) / sizeof(entityStateFields[0]);
|
||||
|
||||
// if (int)f == f and (int)f + ( 1<<(FLOAT_INT_BITS-1) ) < ( 1 << FLOAT_INT_BITS )
|
||||
@@ -1343,22 +1571,25 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
|
||||
if (!MSG_ReadBits(sb, 1))
|
||||
{
|
||||
// integral float
|
||||
int32_t truncFloat = MSG_ReadBits(sb, -FLOAT_INT_BITS);
|
||||
// bias to allow equal parts positive and negative
|
||||
truncFloat -= FLOAT_INT_BIAS;
|
||||
*(float*)toF = (float)truncFloat;
|
||||
*(float*)toF = MSG_ReadBits(sb, -FLOAT_INT_BITS);
|
||||
}
|
||||
else
|
||||
{
|
||||
// full floating point value
|
||||
*(float*)toF = MSG_ReadFloat(sb);
|
||||
unsigned int v = MSG_ReadBits(sb, 32);
|
||||
if (v & 1) {
|
||||
*(int*)toF = ((v + 0x7A000000) >> 1) | 0x80000000;
|
||||
}
|
||||
else {
|
||||
*(int*)toF = (v + 0x7A000000) >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MSG_ReadBits(msg, 1)) {
|
||||
*(int*)toF = MSG_ReadBits(msg, bits);
|
||||
if (MSG_ReadBits(sb, 1)) {
|
||||
*(int*)toF = MSG_ReadBits(sb, bits);
|
||||
}
|
||||
else {
|
||||
*(int*)toF = 0;
|
||||
@@ -1366,6 +1597,11 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
|
||||
}
|
||||
}
|
||||
|
||||
void MSG_ReadRegularSimple(msg_t* sb, int bits, void* toF)
|
||||
{
|
||||
MSG_ReadRegular(sb, bits, toF);
|
||||
}
|
||||
|
||||
void MSG_WriteRegular(msg_t* sb, int bits, const void* toF)
|
||||
{
|
||||
float fullFloat;
|
||||
@@ -1382,16 +1618,19 @@ void MSG_WriteRegular(msg_t* sb, int bits, const void* toF)
|
||||
}
|
||||
else {
|
||||
MSG_WriteBits(sb, 1, 1);
|
||||
if (trunc == fullFloat && trunc + FLOAT_INT_BIAS >= 0 &&
|
||||
trunc + FLOAT_INT_BIAS < (1 << FLOAT_INT_BITS)) {
|
||||
if (trunc == fullFloat && trunc >= -4096 && trunc < 4096) {
|
||||
// send as small integer
|
||||
MSG_WriteBits(sb, 0, 1);
|
||||
MSG_WriteBits(sb, trunc + FLOAT_INT_BIAS, FLOAT_INT_BITS);
|
||||
MSG_WriteBits(sb, trunc, -FLOAT_INT_BITS);
|
||||
}
|
||||
else {
|
||||
// send as full floating point value
|
||||
int newvalue = *(int*)toF * 2 - 0x7A000000;
|
||||
if (*(int*)toF < 0) {
|
||||
newvalue |= 1;
|
||||
}
|
||||
MSG_WriteBits(sb, 1, 1);
|
||||
MSG_WriteBits(sb, *(int*)toF, 32);
|
||||
// send as full floating point value
|
||||
MSG_WriteBits(sb, newvalue, 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1418,9 +1657,9 @@ void MSG_WriteEntityNum(msg_t* sb, short number)
|
||||
MSG_WriteBits(sb, (number + 1) % MAX_GENTITIES, GENTITYNUM_BITS);
|
||||
}
|
||||
|
||||
short MSG_ReadEntityNum(msg_t* sb)
|
||||
unsigned short MSG_ReadEntityNum(msg_t* sb)
|
||||
{
|
||||
return (MSG_ReadBits(sb, GENTITYNUM_BITS) - 1) % MAX_GENTITIES;
|
||||
return (unsigned short)(MSG_ReadBits(sb, GENTITYNUM_BITS) - 1) % MAX_GENTITIES;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -1436,7 +1675,7 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
|
||||
else
|
||||
{
|
||||
if (!MSG_ReadBits(sb, 1)) {
|
||||
*(float*)toF = (float)MSG_ReadBits(sb, FLOAT_INT_BITS);
|
||||
*(float*)toF = (int)MSG_ReadBits(sb, FLOAT_INT_BITS) - FLOAT_INT_BIAS;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1456,6 +1695,28 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
|
||||
}
|
||||
}
|
||||
|
||||
void MSG_ReadRegularSimple(msg_t* sb, int bits, void* toF)
|
||||
{
|
||||
if (bits == 0) {
|
||||
// float
|
||||
if (MSG_ReadBits(sb, 1) == 0) {
|
||||
// integral float
|
||||
int trunc = MSG_ReadBits(sb, FLOAT_INT_BITS);
|
||||
// bias to allow equal parts positive and negative
|
||||
trunc -= FLOAT_INT_BIAS;
|
||||
*(float*)toF = trunc;
|
||||
}
|
||||
else {
|
||||
// full floating point value
|
||||
*(int*)toF = MSG_ReadBits(sb, 32);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// integer
|
||||
*(int*)toF = MSG_ReadBits(sb, bits);
|
||||
}
|
||||
}
|
||||
|
||||
void MSG_WriteRegular(msg_t* sb, int bits, const void* toF)
|
||||
{
|
||||
float fullFloat;
|
||||
@@ -1530,7 +1791,7 @@ void MSG_WriteEntityNum(msg_t* sb, short number)
|
||||
MSG_WriteBits(sb, number % MAX_GENTITIES, GENTITYNUM_BITS);
|
||||
}
|
||||
|
||||
short MSG_ReadEntityNum(msg_t* sb)
|
||||
unsigned short MSG_ReadEntityNum(msg_t* sb)
|
||||
{
|
||||
return MSG_ReadBits(sb, GENTITYNUM_BITS) % MAX_GENTITIES;
|
||||
}
|
||||
@@ -1568,7 +1829,7 @@ void MSG_WriteDeltaEntity( msg_t *msg, struct entityState_s *from, struct entity
|
||||
if ( from == NULL ) {
|
||||
return;
|
||||
}
|
||||
MSG_WriteBits( msg, from->number, GENTITYNUM_BITS );
|
||||
MSG_WriteEntityNum(msg, from->number);
|
||||
MSG_WriteBits( msg, 1, 1 );
|
||||
return;
|
||||
}
|
||||
@@ -1813,6 +2074,55 @@ int MSG_PackCoordExtra(float coord)
|
||||
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
|
||||
float MSG_ReadPackedAngle(msg_t* msg, int bits)
|
||||
{
|
||||
int packed = MSG_ReadBits(msg, abs(bits));
|
||||
return MSG_UnpackAngle(packed, bits);
|
||||
}
|
||||
|
||||
float MSG_ReadPackedAnimTime(msg_t* msg, int bits, float fromValue, float frameTime)
|
||||
{
|
||||
int packed;
|
||||
if (!MSG_ReadBits(msg, 1)) {
|
||||
return fromValue + frameTime;
|
||||
}
|
||||
|
||||
packed = MSG_ReadBits(msg, bits);
|
||||
return MSG_UnpackAnimTime(packed);
|
||||
}
|
||||
|
||||
float MSG_ReadPackedAnimWeight(msg_t* msg, int bits)
|
||||
{
|
||||
int packed = MSG_ReadBits(msg, bits);
|
||||
return MSG_UnpackAnimWeight(packed, bits);
|
||||
}
|
||||
|
||||
float MSG_ReadPackedScale(msg_t* msg, int bits)
|
||||
{
|
||||
int packed = MSG_ReadBits(msg, bits);
|
||||
return MSG_UnpackScale(packed);
|
||||
}
|
||||
|
||||
float MSG_ReadPackedAlpha(msg_t* msg, int bits)
|
||||
{
|
||||
int packed = MSG_ReadBits(msg, bits);
|
||||
return MSG_UnpackAlpha(packed, bits);
|
||||
}
|
||||
|
||||
float MSG_ReadPackedCoord(msg_t* msg, float fromValue, int bits)
|
||||
{
|
||||
int packedFrom = MSG_PackCoord(fromValue);
|
||||
int packedTo = MSG_ReadDeltaCoord(msg, packedFrom);
|
||||
return MSG_UnpackCoord(packedTo, bits);
|
||||
}
|
||||
|
||||
float MSG_ReadPackedCoordExtra(msg_t* msg, float fromValue, int bits)
|
||||
{
|
||||
int packedFrom = MSG_PackCoordExtra(fromValue);
|
||||
int packedTo = MSG_ReadDeltaCoordExtra(msg, packedFrom);
|
||||
return MSG_UnpackCoordExtra(packedTo, bits);
|
||||
}
|
||||
|
||||
void MSG_WritePackedAngle(msg_t* msg, float value, int bits)
|
||||
{
|
||||
int packed = MSG_PackAngle(value, bits);
|
||||
@@ -1823,9 +2133,10 @@ void MSG_WritePackedAnimTime(msg_t* msg, float fromValue, float toValue, float f
|
||||
{
|
||||
int packed;
|
||||
|
||||
if (abs(fromValue - toValue) < frameTime) {
|
||||
if (fabs(fromValue - toValue) < frameTime) {
|
||||
// below the frame time, don't send
|
||||
MSG_WriteBits(msg, 0, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
MSG_WriteBits(msg, 1, 1);
|
||||
@@ -1923,6 +2234,80 @@ qboolean MSG_DeltaNeeded(const void* fromField, const void* toField, int fieldTy
|
||||
|
||||
#else
|
||||
|
||||
float MSG_ReadPackedAngle(msg_t* msg, int bits)
|
||||
{
|
||||
int result;
|
||||
float tmp = 1.0f;
|
||||
if (bits < 0) {
|
||||
if (MSG_ReadBits(msg, 1))
|
||||
tmp = -1.0f;
|
||||
bits = ~bits;
|
||||
}
|
||||
|
||||
result = MSG_ReadBits(msg, bits);
|
||||
switch (bits)
|
||||
{
|
||||
case 8:
|
||||
return tmp * 360.f / 256.f;
|
||||
case 12:
|
||||
return tmp * result * 360.f / 4096.f;
|
||||
case 16:
|
||||
return tmp * result * 360.f / 65536.f;
|
||||
default:
|
||||
return tmp * 360.f / (1 << bits) * result;
|
||||
}
|
||||
}
|
||||
|
||||
float MSG_ReadPackedAnimTime(msg_t* msg, int bits, float fromValue, float frameTime)
|
||||
{
|
||||
return MSG_ReadBits(msg, 15) / 100.0f;
|
||||
}
|
||||
|
||||
float MSG_ReadPackedAnimWeight(msg_t* msg, int bits)
|
||||
{
|
||||
float tmp = MSG_ReadBits(msg, 8) / 255.0f;
|
||||
if (tmp < 0.0f)
|
||||
return 0.0f;
|
||||
else if (tmp > 1.0f)
|
||||
return 1.0f;
|
||||
else
|
||||
return tmp;
|
||||
}
|
||||
|
||||
float MSG_ReadPackedScale(msg_t* msg, int bits)
|
||||
{
|
||||
return MSG_ReadBits(msg, 10) / 100.0f;
|
||||
}
|
||||
|
||||
float MSG_ReadPackedAlpha(msg_t* msg, int bits)
|
||||
{
|
||||
float tmp = MSG_ReadBits(msg, 8) / 255.0f;
|
||||
if (tmp < 0.0f)
|
||||
return 0.0f;
|
||||
else if (tmp > 1.0f)
|
||||
return 1.0f;
|
||||
else
|
||||
return tmp;
|
||||
}
|
||||
|
||||
float MSG_ReadPackedCoord(msg_t* msg, float fromValue, int bits)
|
||||
{
|
||||
float tmp = 1.0f;
|
||||
int value = MSG_ReadBits(msg, 19);
|
||||
if (value & 262144) // test for 19th bit
|
||||
tmp = -1.0f;
|
||||
value &= ~262144; // remove that bit
|
||||
return tmp * value / 16.0f;
|
||||
}
|
||||
|
||||
float MSG_ReadPackedCoordExtra(msg_t* msg, float fromValue, int bits)
|
||||
{
|
||||
int packedFrom = MSG_PackCoordExtra(fromValue);
|
||||
int packedTo = MSG_ReadDeltaCoordExtra(msg, packedFrom);
|
||||
return MSG_UnpackCoordExtra(packedTo, bits);
|
||||
}
|
||||
|
||||
|
||||
void MSG_WritePackedAngle(msg_t* msg, float value, int bits)
|
||||
{
|
||||
// angles, what a mess! it wouldnt surprise me if something goes wrong here ;)
|
||||
@@ -2044,6 +2429,25 @@ qboolean MSG_DeltaNeeded(const void* fromField, const void* toField, int fieldTy
|
||||
|
||||
#endif
|
||||
|
||||
float MSG_ReadPackedVelocity(msg_t* msg, int bits)
|
||||
{
|
||||
float tmp = 1.0f;
|
||||
int value = MSG_ReadBits(msg, 17);
|
||||
if (value & 65536) // test for 17th bit
|
||||
tmp = -1.0f;
|
||||
value &= ~65536; // remove that bit
|
||||
return tmp * value / 8.0f;
|
||||
}
|
||||
|
||||
int MSG_ReadPackedSimple(msg_t* msg, int fromValue, int bits)
|
||||
{
|
||||
if (!MSG_ReadBits(msg, 1)) {
|
||||
return fromValue;
|
||||
}
|
||||
|
||||
return MSG_ReadBits(msg, bits);
|
||||
}
|
||||
|
||||
void MSG_WritePackedVelocity(msg_t* msg, float value, int bits)
|
||||
{
|
||||
int32_t packed = (uint32_t)(value * 8.0f);
|
||||
@@ -2159,99 +2563,34 @@ void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to,
|
||||
} else {
|
||||
switch (field->type) {
|
||||
case netFieldType_e::regular:
|
||||
if ( field->bits == 0 ) {
|
||||
// float
|
||||
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
|
||||
*(float *)toF = 0.0f;
|
||||
} else {
|
||||
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
|
||||
// integral float
|
||||
trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
|
||||
// bias to allow equal parts positive and negative
|
||||
trunc -= FLOAT_INT_BIAS;
|
||||
*(float *)toF = trunc;
|
||||
if ( print ) {
|
||||
Com_Printf( "%s:%i ", field->name, trunc );
|
||||
}
|
||||
} else {
|
||||
// full floating point value
|
||||
*toF = MSG_ReadBits( msg, 32 );
|
||||
if ( print ) {
|
||||
Com_Printf( "%s:%f ", field->name, *(float *)toF );
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
|
||||
*toF = 0;
|
||||
} else {
|
||||
// integer
|
||||
*toF = MSG_ReadBits( msg, field->bits );
|
||||
if ( print ) {
|
||||
Com_Printf( "%s:%i ", field->name, *toF );
|
||||
}
|
||||
}
|
||||
}
|
||||
MSG_ReadRegular(msg, field->bits, toF);
|
||||
break;
|
||||
case netFieldType_e::angle: // angles, what a mess! it wouldnt surprise me if something goes wrong here ;)
|
||||
tmp = 1.0f;
|
||||
if ( field->bits < 0 ) {
|
||||
if ( MSG_ReadBits( msg, 1 ) )
|
||||
tmp = -1.0f;
|
||||
bits = ~field->bits;
|
||||
}
|
||||
else bits = field->bits;
|
||||
|
||||
result = MSG_ReadBits( msg, bits );
|
||||
if ( bits == 12 )
|
||||
*(float *)toF = result * 0.087890625f * tmp;
|
||||
else if ( bits == 8 )
|
||||
*(float *)toF = result * 1.411764705882353f * tmp;
|
||||
else if ( bits == 16 )
|
||||
*(float *)toF = result * 0.0054931640625f * tmp;
|
||||
else
|
||||
*(float *)toF = result * (1 << bits) * tmp / 360.0f;
|
||||
*(float*)toF = MSG_ReadPackedAngle(msg, field->bits);
|
||||
break;
|
||||
case netFieldType_e::animTime: // time
|
||||
*(float *)toF = MSG_ReadBits( msg, 15 ) * 0.0099999998f;
|
||||
*(float*)toF = MSG_ReadPackedAnimTime(msg, field->bits, *(float*)fromF, frameTime);
|
||||
break;
|
||||
case netFieldType_e::animWeight: // nasty!
|
||||
tmp = MSG_ReadBits( msg, 8 ) / 255.0f;
|
||||
if ( tmp < 0.0f )
|
||||
*(float *)toF = 0.0f;
|
||||
else if ( tmp > 1.0f )
|
||||
*(float *)toF = 1.0f;
|
||||
else
|
||||
*(float *)toF = tmp;
|
||||
// FPU instructions yay
|
||||
*(float*)toF = MSG_ReadPackedAnimWeight(msg, field->bits);
|
||||
break;
|
||||
case netFieldType_e::scale:
|
||||
*(float *)toF = MSG_ReadBits( msg, 10 ) *0.0099999998f;
|
||||
*(float*)toF = MSG_ReadPackedScale(msg, field->bits);
|
||||
break;
|
||||
case netFieldType_e::alpha:
|
||||
tmp = MSG_ReadBits( msg, 8 ) / 255.0f;
|
||||
if ( tmp < 0.0f )
|
||||
*(float *)toF = 0.0f;
|
||||
else if ( tmp > 1.0f )
|
||||
*(float *)toF = 1.0f;
|
||||
else
|
||||
*(float *)toF = tmp;
|
||||
*(float*)toF = MSG_ReadPackedAlpha(msg, field->bits);
|
||||
break;
|
||||
case netFieldType_e::coord:
|
||||
tmp = 1.0f;
|
||||
bits = MSG_ReadBits( msg, 19 );
|
||||
if ( bits & 262144 ) // test for 19th bit
|
||||
tmp = -1.0f;
|
||||
bits &= ~262144; // remove that bit
|
||||
*(float *)toF = tmp * bits / 16.0f;
|
||||
*(float*)toF = MSG_ReadPackedCoord(msg, *(float*)fromF, field->bits);
|
||||
break;
|
||||
case netFieldType_e::coordExtra:
|
||||
*(float*)toF = MSG_ReadPackedCoordExtra(msg, *(float*)fromF, field->bits);
|
||||
break;
|
||||
case netFieldType_e::velocity:
|
||||
tmp = 1.0f;
|
||||
bits = MSG_ReadBits( msg, 17 );
|
||||
if ( bits & 65536 ) // test for 17th bit
|
||||
tmp = -1.0f;
|
||||
bits &= ~65536; // remove that bit
|
||||
*(float *)toF = tmp * bits / 8.0f;
|
||||
*(float*)toF = MSG_ReadPackedVelocity(msg, field->bits);
|
||||
break;
|
||||
case netFieldType_e::simple:
|
||||
*(int*)toF = MSG_ReadPackedSimple(msg, *(int*)fromF, field->bits);
|
||||
break;
|
||||
default:
|
||||
Com_Error( ERR_DROP, "MSG_ReadDeltaEntity: unrecognized entity field type %i for field\n", i );
|
||||
@@ -2329,6 +2668,16 @@ float MSG_UnpackAnimTime(int packed)
|
||||
return packed / 100.f;
|
||||
}
|
||||
|
||||
float MSG_UnpackAnimWeight(int result, int bits)
|
||||
{
|
||||
const int32_t max = (1 << bits) - 1;
|
||||
const float tmp = (float)result / (float)max;
|
||||
|
||||
if (tmp < 0.0f) return 0.f;
|
||||
else if (tmp > 1.0f) return 1.f;
|
||||
else return tmp;
|
||||
}
|
||||
|
||||
float MSG_UnpackScale(int packed)
|
||||
{
|
||||
return packed / 100.f;
|
||||
@@ -2501,6 +2850,66 @@ plyer_state_t communication
|
||||
// using the stringizing operator to save typing...
|
||||
#define PSF(x) #x,(size_t)&((playerState_t*)0)->x
|
||||
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
netField_t playerStateFields[] =
|
||||
{
|
||||
{ PSF(commandTime), 32, netFieldType_t::regular },
|
||||
{ PSF(origin[0]), 0, netFieldType_t::coordExtra },
|
||||
{ PSF(origin[1]), 0, netFieldType_t::coordExtra },
|
||||
{ PSF(viewangles[1]), 0, netFieldType_t::regular },
|
||||
{ PSF(velocity[1]), 0, netFieldType_t::velocity },
|
||||
{ PSF(velocity[0]), 0, netFieldType_t::velocity },
|
||||
{ PSF(viewangles[0]), 0, netFieldType_t::regular },
|
||||
{ PSF(origin[2]), 0, netFieldType_t::coordExtra },
|
||||
{ PSF(velocity[2]), 0, netFieldType_t::velocity },
|
||||
{ PSF(iViewModelAnimChanged), 2, netFieldType_t::regular },
|
||||
{ PSF(damage_angles[0]), -13, netFieldType_t::angle },
|
||||
{ PSF(damage_angles[1]), -13, netFieldType_t::angle },
|
||||
{ PSF(damage_angles[2]), -13, netFieldType_t::angle },
|
||||
{ PSF(speed), 16, netFieldType_t::regular },
|
||||
{ PSF(delta_angles[1]), 16, netFieldType_t::regular },
|
||||
{ PSF(viewheight), -8, netFieldType_t::regular },
|
||||
{ PSF(groundEntityNum), GENTITYNUM_BITS, netFieldType_t::regular },
|
||||
{ PSF(delta_angles[0]), 16, netFieldType_t::regular },
|
||||
{ PSF(iViewModelAnim), 4, netFieldType_t::regular },
|
||||
{ PSF(fov), 0, netFieldType_t::regular },
|
||||
{ PSF(current_music_mood), 8, netFieldType_t::regular },
|
||||
{ PSF(gravity), 16, netFieldType_t::regular },
|
||||
{ PSF(fallback_music_mood), 8, netFieldType_t::regular },
|
||||
{ PSF(music_volume), 0, netFieldType_t::regular },
|
||||
{ PSF(pm_flags), 16, netFieldType_t::regular },
|
||||
{ PSF(clientNum), 8, netFieldType_t::regular },
|
||||
{ PSF(fLeanAngle), 0, netFieldType_t::regular },
|
||||
{ PSF(blend[3]), 0, netFieldType_t::regular },
|
||||
{ PSF(blend[0]), 0, netFieldType_t::regular },
|
||||
{ PSF(pm_type), 8, netFieldType_t::regular },
|
||||
{ PSF(feetfalling), 8, netFieldType_t::regular },
|
||||
{ PSF(radarInfo), 26, netFieldType_t::regular },
|
||||
{ PSF(camera_angles[0]), 16, netFieldType_t::angle },
|
||||
{ PSF(camera_angles[1]), 16, netFieldType_t::angle },
|
||||
{ PSF(camera_angles[2]), 16, netFieldType_t::angle },
|
||||
{ PSF(camera_origin[0]), 0, netFieldType_t::coordExtra },
|
||||
{ PSF(camera_origin[1]), 0, netFieldType_t::coordExtra },
|
||||
{ PSF(camera_origin[2]), 0, netFieldType_t::coordExtra },
|
||||
{ PSF(camera_posofs[0]), 0, netFieldType_t::coordExtra },
|
||||
{ PSF(camera_posofs[2]), 0, netFieldType_t::coordExtra },
|
||||
{ PSF(camera_time), 0, netFieldType_t::regular },
|
||||
{ PSF(voted), 1, netFieldType_t::regular },
|
||||
{ PSF(bobCycle), 8, netFieldType_t::regular },
|
||||
{ PSF(delta_angles[2]), 16, netFieldType_t::regular },
|
||||
{ PSF(viewangles[2]), 0, netFieldType_t::regular },
|
||||
{ PSF(music_volume_fade_time), 0, netFieldType_t::regular },
|
||||
{ PSF(reverb_type), 6, netFieldType_t::regular },
|
||||
{ PSF(reverb_level), 0, netFieldType_t::regular },
|
||||
{ PSF(blend[1]), 0, netFieldType_t::regular },
|
||||
{ PSF(blend[2]), 0, netFieldType_t::regular },
|
||||
{ PSF(camera_offset[0]), 0, netFieldType_t::regular },
|
||||
{ PSF(camera_offset[1]), 0, netFieldType_t::regular },
|
||||
{ PSF(camera_offset[2]), 0, netFieldType_t::regular },
|
||||
{ PSF(camera_posofs[1]), 0, netFieldType_t::coordExtra },
|
||||
{ PSF(camera_flags), 16, netFieldType_t::regular }
|
||||
};
|
||||
#else
|
||||
netField_t playerStateFields[] =
|
||||
{
|
||||
{ PSF(commandTime), 32, netFieldType_t::regular },
|
||||
@@ -2559,6 +2968,7 @@ netField_t playerStateFields[] =
|
||||
{ PSF(camera_posofs[1]), 0, netFieldType_t::coord },
|
||||
{ PSF(camera_flags), 16, netFieldType_t::regular }
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
=============
|
||||
@@ -2793,80 +3203,29 @@ void MSG_ReadDeltaPlayerstate(msg_t *msg, playerState_t *from, playerState_t *to
|
||||
|
||||
numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] );
|
||||
lc = MSG_ReadByte(msg);
|
||||
//Com_DPrintf( "===\nMSG_ReadDeltaPlayerstate: count %i\n===\n", lc );
|
||||
assert(lc <= numFields);
|
||||
for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) {
|
||||
fromF = (int *)( (byte *)from + field->offset );
|
||||
toF = (int *)( (byte *)to + field->offset );
|
||||
//Com_DPrintf( "field %s ", field->name );
|
||||
if ( ! MSG_ReadBits( msg, 1 ) ) {
|
||||
// no change
|
||||
*toF = *fromF;
|
||||
//Com_DPrintf( "NO CHANGE " );
|
||||
//Com_DPrintf( "value int %i, float %f\n", *toF, *(float *)toF );
|
||||
} else {
|
||||
//Com_DPrintf( "type %i, ", field->type );
|
||||
switch ( field->type ) {
|
||||
case netFieldType_e::regular:
|
||||
if ( field->bits == 0 ) {
|
||||
// float
|
||||
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
|
||||
// integral float
|
||||
trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
|
||||
// bias to allow equal parts positive and negative
|
||||
trunc -= FLOAT_INT_BIAS;
|
||||
*(float *)toF = trunc;
|
||||
if ( print ) {
|
||||
Com_Printf( "%s:%i ", field->name, trunc );
|
||||
}
|
||||
} else {
|
||||
// full floating point value
|
||||
*toF = MSG_ReadBits( msg, 32 );
|
||||
if ( print ) {
|
||||
Com_Printf( "%s:%f ", field->name, *(float *)toF );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// integer
|
||||
*toF = MSG_ReadBits( msg, field->bits );
|
||||
if ( print ) {
|
||||
Com_Printf( "%s:%i ", field->name, *toF );
|
||||
}
|
||||
}
|
||||
MSG_ReadRegularSimple(msg, field->bits, toF);
|
||||
break;
|
||||
case netFieldType_e::angle:
|
||||
tmp = 1.0f;
|
||||
if ( field->bits < 0 ) {
|
||||
if ( MSG_ReadBits( msg, 1 ) )
|
||||
tmp = -1.0f;
|
||||
bits = - field->bits -1;
|
||||
}
|
||||
else bits = field->bits;
|
||||
|
||||
result = MSG_ReadBits( msg, bits );
|
||||
if ( field->bits == 12 )
|
||||
*(float *)toF = result * 0.087890625f * tmp;
|
||||
else if ( field->bits == 8 )
|
||||
*(float *)toF = result * 1.411764705882353f * tmp;
|
||||
else if ( field->bits == 16 )
|
||||
*(float *)toF = result * 0.0054931640625f * tmp;
|
||||
else
|
||||
*(float *)toF = result * (1 << bits) * tmp / 360.0f;
|
||||
*(float*)toF = MSG_ReadPackedAngle(msg, field->bits);
|
||||
break;
|
||||
case netFieldType_e::coord:
|
||||
tmp = 1.0f;
|
||||
bits = MSG_ReadBits( msg, 19 );
|
||||
if ( bits & 262144 ) // test for 19th bit
|
||||
tmp = -1.0f;
|
||||
bits &= ~262144; // 4294705151; // remove that bit
|
||||
*(float *)toF = tmp * bits / 16.0f;
|
||||
*(float*)toF = MSG_ReadPackedCoord(msg, *(float*)fromF, field->bits);
|
||||
break;
|
||||
case netFieldType_e::coordExtra:
|
||||
*(float*)toF = MSG_ReadPackedCoordExtra(msg, *(float*)fromF, field->bits);
|
||||
break;
|
||||
case netFieldType_e::velocity:
|
||||
tmp = 1.0f;
|
||||
bits = MSG_ReadBits( msg, 17 );
|
||||
if ( bits & 65536 ) // test for 17th bit
|
||||
tmp = -1.0f;
|
||||
bits &= ~65536; // 4294901759; // remove that bit
|
||||
*(float *)toF = tmp * bits / 8.0f;
|
||||
*(float*)toF = MSG_ReadPackedVelocity(msg, field->bits);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
+79
-71
@@ -29,14 +29,38 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PRODUCT_NAME "OpenMoHAA"
|
||||
#define PRODUCT_VERSION "0.49-alpha"
|
||||
#define PRODUCT_DATE __DATE__
|
||||
#define PRODUCT_NAME "OpenMoHAA"
|
||||
|
||||
//
|
||||
// Version
|
||||
//
|
||||
// These values are the only one that must be set for the version
|
||||
#define PRODUCT_VERSION_MAJOR 0
|
||||
#define PRODUCT_VERSION_MINOR 53
|
||||
#define PRODUCT_VERSION_PATCH 0
|
||||
#define PRODUCT_VERSION_STAGE "alpha"
|
||||
|
||||
//
|
||||
// Version display
|
||||
//
|
||||
#define PRODUCT_VERSION_NUMBER_STRING XSTRING(PRODUCT_VERSION_MAJOR) "." XSTRING(PRODUCT_VERSION_MINOR) "." XSTRING(PRODUCT_VERSION_PATCH)
|
||||
#define PRODUCT_VERSION PRODUCT_VERSION_NUMBER_STRING "-" PRODUCT_VERSION_STAGE
|
||||
#define PRODUCT_DATE __DATE__
|
||||
|
||||
#define BASEGAME "main"
|
||||
|
||||
//
|
||||
// The target type specifies which content pack the engine targets.
|
||||
//
|
||||
// Note: An universal client is not currently possible without refactoring the network and the file system.
|
||||
// Pak files must be reloaded on-the-fly depending on the server the client is connecting to.
|
||||
//
|
||||
#if TARGET_GAME_TYPE == 1
|
||||
//
|
||||
// Team Assault
|
||||
#define BASEGAME "mainta"
|
||||
#define PRODUCT_EXTENSION "Spearhead"
|
||||
//
|
||||
#define GAME_EXTENSION_BASE "mainta"
|
||||
#define PRODUCT_EXTENSION "spearhead"
|
||||
// The version string must be equal or above 2.0 to be able to connect to spearhead servers
|
||||
#define TARGET_GAME_VERSION "2.16"
|
||||
#define TARGET_GAME_PROTOCOL 17
|
||||
@@ -46,10 +70,12 @@ extern "C" {
|
||||
#define HOMEPATH_NAME_WIN "mohta"
|
||||
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
|
||||
#elif TARGET_GAME_TYPE == 2
|
||||
//
|
||||
// Team Tactics
|
||||
#define BASEGAME "maintt"
|
||||
#define PRODUCT_EXTENSION "Breakthrough"
|
||||
// The version string must be equal or above 2.0 to be able to connect to breakthrough servers
|
||||
//
|
||||
#define GAME_EXTENSION_BASE "maintt"
|
||||
#define PRODUCT_EXTENSION "breakthrough"
|
||||
// The version string must be equal or above 2.0 to be able to connect to breakthrough servers
|
||||
#define TARGET_GAME_VERSION "2.41"
|
||||
#define TARGET_GAME_PROTOCOL 17
|
||||
#define TARGET_GAME_NAME "mohaab"
|
||||
@@ -58,11 +84,13 @@ extern "C" {
|
||||
#define HOMEPATH_NAME_WIN "mohtt"
|
||||
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
|
||||
#else
|
||||
// The default: the base game (no expansion)
|
||||
|
||||
#define BASEGAME "main"
|
||||
#define PRODUCT_EXTENSION "Base"
|
||||
// The version string must be below 1.12, otherwise it's not possible to connect
|
||||
//
|
||||
// Base game
|
||||
//
|
||||
|
||||
#define GAME_EXTENSION_BASE "main"
|
||||
#define PRODUCT_EXTENSION "base"
|
||||
// The version string must be 1.1x or below, otherwise it's not possible to connect
|
||||
#define TARGET_GAME_VERSION "1.12"
|
||||
#define TARGET_GAME_PROTOCOL 8
|
||||
#define TARGET_GAME_NAME "mohaa"
|
||||
@@ -72,11 +100,11 @@ extern "C" {
|
||||
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
|
||||
#endif
|
||||
|
||||
#define PRODUCT_NAME_FULL PRODUCT_NAME ": " PRODUCT_EXTENSION
|
||||
#define PRODUCT_VERSION_FULL PRODUCT_VERSION " (for " TARGET_GAME_VERSION ")"
|
||||
#define PRODUCT_NAME_FULL PRODUCT_NAME " - v" PRODUCT_VERSION " - ext-" PRODUCT_EXTENSION
|
||||
#define PRODUCT_VERSION_FULL PRODUCT_NAME_FULL
|
||||
|
||||
#define CLIENT_WINDOW_TITLE "OpenMoHAA"
|
||||
#define CLIENT_WINDOW_MIN_TITLE "OpenMoHAA"
|
||||
#define CLIENT_WINDOW_TITLE PRODUCT_NAME
|
||||
#define CLIENT_WINDOW_MIN_TITLE PRODUCT_NAME
|
||||
|
||||
#define MAX_TEAMNAME 32
|
||||
|
||||
@@ -501,11 +529,11 @@ extern vec4_t g_color_table[8];
|
||||
#define LERP( a, b, w ) ( ( a ) * ( 1.0f - ( w ) ) + ( b ) * ( w ) )
|
||||
#define LUMA( red, green, blue ) ( 0.2126f * ( red ) + 0.7152f * ( green ) + 0.0722f * ( blue ) )
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#ifndef Q_min
|
||||
#define Q_min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef max
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#ifndef Q_max
|
||||
#define Q_max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define bound(a,minval,maxval) ( ((a) > (minval)) ? ( ((a) < (maxval)) ? (a) : (maxval) ) : (minval) )
|
||||
@@ -1608,7 +1636,7 @@ typedef struct {
|
||||
|
||||
// maybe this is better put somewhere else...
|
||||
typedef struct server_sound_s {
|
||||
float origin[3];
|
||||
vec3_t origin;
|
||||
int entity_number;
|
||||
int channel;
|
||||
short int sound_index;
|
||||
@@ -1703,6 +1731,11 @@ typedef struct playerState_s {
|
||||
float camera_posofs[3];
|
||||
int camera_flags;
|
||||
float damage_angles[3];
|
||||
// --
|
||||
// Team Assault
|
||||
int radarInfo;
|
||||
qboolean voted;
|
||||
// --
|
||||
|
||||
// not communicated over the net at all
|
||||
int ping; // server to game info for scoreboard
|
||||
@@ -1712,44 +1745,33 @@ typedef struct playerState_s {
|
||||
|
||||
//====================================================================
|
||||
|
||||
#define BUTTON_ATTACKRIGHT_BITINDEX 0
|
||||
#define BUTTON_ATTACKLEFT_BITINDEX 1
|
||||
#define BUTTON_SNEAK_BITINDEX 2
|
||||
#define BUTTON_RUN_BITINDEX 3
|
||||
#define BUTTON_HOLSTERWEAPON_BITINDEX 4
|
||||
#define BUTTON_USE_BITINDEX 5
|
||||
#define BUTTON_TALK_BITINDEX 6 // displays talk balloon and disables actions
|
||||
#define BUTTON_ANY_BITINDEX 11 // any key whatsoever
|
||||
#define BUTTON_MOUSE_BITINDEX 14 // mouse move
|
||||
|
||||
//
|
||||
// usercmd_t->button bits, many of which are generated by the client system,
|
||||
// so they aren't game/cgame only definitions
|
||||
// so they aren't game-only definitions
|
||||
//
|
||||
#define BUTTON_ATTACK 1 // +/-attackprimary
|
||||
#define BUTTON_ATTACK2 2 // +/-attacksecondary
|
||||
#define BUTTON_RUN 4 // +/-speed
|
||||
// walking can't just be infered from MOVE_RUN
|
||||
// because a key pressed late in the frame will
|
||||
// only generate a small move value for that frame
|
||||
// walking will use different animations and
|
||||
// won't generate footsteps
|
||||
#define BUTTON_ATTACKLEFT_BITINDEX 0
|
||||
#define BUTTON_ATTACKRIGHT_BITINDEX 1
|
||||
#define BUTTON_RUN_BITINDEX 2
|
||||
#define BUTTON_USE_BITINDEX 3
|
||||
#define BUTTON_LEAN_LEFT_BITINDEX 4
|
||||
#define BUTTON_LEAN_RIGHT_BITINDEX 5
|
||||
#define BUTTON_TALK_BITINDEX 6 // displays talk balloon and disables actions
|
||||
#define BUTTON_ANY_BITINDEX 10 // any key whatsoever
|
||||
#define BUTTON_ANY2_BITINDEX 11 // any key whatsoever (regardless of keycatcher)
|
||||
#define BUTTON_MOUSE_BITINDEX 14 // mouse move
|
||||
#define BUTTON_HOLSTER_BITINDEX 15
|
||||
|
||||
#define BUTTON_USE 8
|
||||
#define BUTTON_LEANLEFT 16 // +/-leanleft
|
||||
#define BUTTON_LEANRIGHT 32 // +/-leanright
|
||||
#define BUTTON_NEGATIVE 64
|
||||
|
||||
#define BUTTON_GETFLAG 128
|
||||
#define BUTTON_GUARDBASE 256
|
||||
#define BUTTON_PATROL 512
|
||||
#define BUTTON_FOLLOWME 1024
|
||||
|
||||
#define BUTTON_HOLSTER 32768
|
||||
|
||||
#define BUTTON_TALK ( 1 << BUTTON_TALK_BITINDEX ) // displays talk balloon and disables actions
|
||||
#define BUTTON_ANY ( 1 << BUTTON_ANY_BITINDEX ) // any key whatsoever
|
||||
#define BUTTON_MOUSE ( 1 << BUTTON_MOUSE_BITINDEX )
|
||||
#define BUTTON_ATTACKLEFT (1 << BUTTON_ATTACKLEFT_BITINDEX)
|
||||
#define BUTTON_ATTACKRIGHT (1 << BUTTON_ATTACKRIGHT_BITINDEX)
|
||||
#define BUTTON_RUN (1 << BUTTON_RUN_BITINDEX)
|
||||
#define BUTTON_USE (1 << BUTTON_USE_BITINDEX)
|
||||
#define BUTTON_LEAN_LEFT (1 << BUTTON_LEAN_LEFT_BITINDEX)
|
||||
#define BUTTON_LEAN_RIGHT (1 << BUTTON_LEAN_RIGHT_BITINDEX)
|
||||
#define BUTTON_TALK (1 << BUTTON_TALK_BITINDEX) // displays talk balloon and disables actions
|
||||
#define BUTTON_ANY (1 << BUTTON_ANY_BITINDEX) // any key whatsoever
|
||||
#define BUTTON_ANY2 (1 << BUTTON_ANY_BITINDEX) // any key whatsoever (regardless of keycatcher)
|
||||
#define BUTTON_MOUSE (1 << BUTTON_MOUSE_BITINDEX)
|
||||
#define BUTTON_HOLSTER (1 << BUTTON_HOLSTER_BITINDEX)
|
||||
|
||||
#define WEAPON_COMMAND_USE_PISTOL 1
|
||||
#define WEAPON_COMMAND_USE_RIFLE 2
|
||||
@@ -1767,7 +1789,7 @@ typedef struct playerState_s {
|
||||
#define WEAPON_COMMAND_HOLSTER 14
|
||||
#define WEAPON_COMMAND_DROP 15
|
||||
#define WEAPON_COMMAND_MAX 15
|
||||
#define WEAPON_COMMAND_MASK WEAPON_COMMAND_MAX << 7
|
||||
#define WEAPON_COMMAND_MASK (WEAPON_COMMAND_MAX << 7)
|
||||
|
||||
|
||||
#define MOVE_RUN 120 // if forwardmove or rightmove are >= MOVE_RUN,
|
||||
@@ -2041,20 +2063,6 @@ typedef struct hdelement_s {
|
||||
struct fontheader_s *pFont;
|
||||
} hdelement_t;
|
||||
|
||||
enum vmAnim_e {
|
||||
VM_ANIM_IDLE,
|
||||
VM_ANIM_CHARGE,
|
||||
VM_ANIM_FIRE,
|
||||
VM_ANIM_FIRE_SECONDARY,
|
||||
VM_ANIM_RECHAMBER,
|
||||
VM_ANIM_RELOAD,
|
||||
VM_ANIM_RELOAD_SINGLE,
|
||||
VM_ANIM_RELOAD_END,
|
||||
VM_ANIM_PULLOUT,
|
||||
VM_ANIM_PUTAWAY,
|
||||
VM_ANIM_LADDERSTEP
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
frameInfo_t g_VMFrameInfo[MAX_FRAMEINFOS];
|
||||
|
||||
|
||||
+15
-21
@@ -83,7 +83,10 @@ void MSG_WriteLong (msg_t *sb, int c);
|
||||
void MSG_WriteFloat (msg_t *sb, float f);
|
||||
void MSG_WriteString (msg_t *sb, const char *s);
|
||||
void MSG_WriteBigString (msg_t *sb, const char *s);
|
||||
void MSG_WriteScrambledString(msg_t* sb, const char* s);
|
||||
void MSG_WriteScrambledBigString(msg_t* sb, const char* s);
|
||||
void MSG_WriteAngle16 (msg_t *sb, float f);
|
||||
void MSG_WriteEntityNum(msg_t* sb, short number);
|
||||
|
||||
void MSG_BeginReading (msg_t *sb);
|
||||
void MSG_BeginReadingOOB(msg_t *sb);
|
||||
@@ -104,9 +107,12 @@ float MSG_ReadFloat (msg_t *sb);
|
||||
char *MSG_ReadString (msg_t *sb);
|
||||
char *MSG_ReadBigString (msg_t *sb);
|
||||
char *MSG_ReadStringLine( msg_t *sb );
|
||||
char* MSG_ReadScrambledString(msg_t* msg);
|
||||
char* MSG_ReadScrambledBigString(msg_t* msg);
|
||||
float MSG_ReadAngle8( msg_t *sb );
|
||||
float MSG_ReadAngle16 (msg_t *sb);
|
||||
void MSG_ReadData (msg_t *sb, void *buffer, int size);
|
||||
unsigned short MSG_ReadEntityNum(msg_t* sb);
|
||||
|
||||
|
||||
void MSG_WriteDeltaUsercmd( msg_t *msg, struct usercmd_s *from, struct usercmd_s *to );
|
||||
@@ -158,6 +164,7 @@ void MSG_WritePackedSimple(msg_t* msg, int value, int bits);
|
||||
|
||||
float MSG_UnpackAngle(int value, int bits);
|
||||
float MSG_UnpackAnimTime(int packed);
|
||||
float MSG_UnpackAnimWeight(int result, int bits);
|
||||
float MSG_UnpackScale(int packed);
|
||||
float MSG_UnpackAlpha(int packed, int bits);
|
||||
float MSG_UnpackCoord(int packed, int bits);
|
||||
@@ -798,26 +805,6 @@ MISC
|
||||
/*
|
||||
==============================================================
|
||||
|
||||
Edit fields and command line history/completion
|
||||
|
||||
==============================================================
|
||||
*/
|
||||
|
||||
#define MAX_EDIT_LINE 256
|
||||
typedef struct {
|
||||
int cursor;
|
||||
int scroll;
|
||||
int widthInChars;
|
||||
char buffer[MAX_EDIT_LINE];
|
||||
} field_t;
|
||||
|
||||
void Field_Clear( field_t *edit );
|
||||
void Field_CompleteCommand( field_t *edit );
|
||||
void Field_AutoComplete( field_t *edit );
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
||||
MISC
|
||||
|
||||
==============================================================
|
||||
@@ -882,10 +869,10 @@ void Com_StartupVariable( const char *match );
|
||||
// only a set with the exact name. Only used during startup.
|
||||
|
||||
|
||||
extern float currentfps;
|
||||
extern cvar_t *paused;
|
||||
extern cvar_t *config;
|
||||
extern cvar_t *fps;
|
||||
extern float currentfps;
|
||||
extern cvar_t *developer;
|
||||
extern cvar_t *com_dedicated;
|
||||
extern cvar_t *com_speeds;
|
||||
@@ -1237,6 +1224,13 @@ char **Sys_ListFiles( const char *directory, const char *extension, const char *
|
||||
void Sys_FreeFileList( char **list );
|
||||
void Sys_Sleep(int msec);
|
||||
|
||||
void Sys_InitStreamThread(void);
|
||||
void Sys_ShutdownStreamThread(void);
|
||||
void Sys_BeginStreamedFile(fileHandle_t f, int readAhead);
|
||||
void Sys_EndStreamedFile(fileHandle_t f);
|
||||
int Sys_StreamedRead(void* buffer, int size, int count, fileHandle_t f);
|
||||
void Sys_StreamSeek(fileHandle_t f, int offset, int origin);
|
||||
|
||||
qboolean Sys_LowPhysicalMemory( void );
|
||||
|
||||
void SetNormalThreadPriority( void );
|
||||
|
||||
@@ -468,8 +468,8 @@ typedef struct {
|
||||
// little-endian "2015"
|
||||
|
||||
#define BSP_BETA_VERSION 18 // Beta Allied Assault
|
||||
#define BSP_BASE_VERSION 19 // vanilla Allied Assault
|
||||
#define BSP_VERSION 19 // current Allied Assault
|
||||
#define BSP_MIN_VERSION 18 // Beta Allied Assault
|
||||
#define BSP_MAX_VERSION 21 // Breakthrough
|
||||
|
||||
|
||||
// there shouldn't be any problem with increasing these values at the
|
||||
@@ -535,7 +535,7 @@ typedef struct cTerraPatch_s {
|
||||
byte s;
|
||||
byte t;
|
||||
|
||||
float texCoord[ 2 ][ 2 ][ 2 ];
|
||||
vec2_t texCoord[ 2 ][ 2 ];
|
||||
|
||||
char x;
|
||||
char y;
|
||||
@@ -555,9 +555,9 @@ typedef struct cTerraPatch_s {
|
||||
} cTerraPatch_t;
|
||||
|
||||
typedef struct cStaticModel_s {
|
||||
char model[ 128 ];
|
||||
float origin[ 3 ];
|
||||
float angles[ 3 ];
|
||||
char model[128];
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
float scale;
|
||||
int firstVertexData;
|
||||
int numVertexData;
|
||||
|
||||
@@ -582,7 +582,7 @@ const char* Script::GrabNextToken(qboolean crossline)
|
||||
*token_p++ = *script_p++;
|
||||
}
|
||||
|
||||
if (token_p == &token[MAXTOKEN]) {
|
||||
if (token_p == &token[SCRIPT_MAXTOKEN]) {
|
||||
FILE_Error(ERR_DROP, "Token too large on line %i in file %s\n",
|
||||
line, filename.c_str());
|
||||
}
|
||||
@@ -824,7 +824,7 @@ const char* Script::GetLine(qboolean crossline)
|
||||
start = script_p;
|
||||
SkipToEOL();
|
||||
size = script_p - start;
|
||||
if (size < (MAXTOKEN - 1)) {
|
||||
if (size < (SCRIPT_MAXTOKEN - 1)) {
|
||||
memcpy(token, start, size);
|
||||
token[size] = '\0';
|
||||
} else {
|
||||
@@ -859,7 +859,7 @@ const char* Script::GetRaw(void)
|
||||
start = script_p;
|
||||
SkipToEOL();
|
||||
size = script_p - start;
|
||||
if (size < (MAXTOKEN - 1)) {
|
||||
if (size < (SCRIPT_MAXTOKEN - 1)) {
|
||||
memset(token, 0, sizeof(token));
|
||||
memcpy(token, start, size);
|
||||
} else {
|
||||
@@ -946,7 +946,7 @@ const char* Script::GetString(qboolean crossline)
|
||||
startline, filename.c_str());
|
||||
}
|
||||
|
||||
if (token_p == &token[MAXTOKEN]) {
|
||||
if (token_p == &token[SCRIPT_MAXTOKEN]) {
|
||||
FILE_Error(ERR_DROP, "String too large on line %i in file %s\n",
|
||||
line, filename.c_str());
|
||||
}
|
||||
@@ -1075,7 +1075,7 @@ int Script::LinesInFile(void)
|
||||
qboolean temp_tokenready;
|
||||
const char* temp_script_p;
|
||||
int temp_line;
|
||||
char temp_token[MAXTOKEN];
|
||||
char temp_token[SCRIPT_MAXTOKEN];
|
||||
int numentries;
|
||||
|
||||
temp_tokenready = tokenready;
|
||||
|
||||
@@ -40,13 +40,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#define TOKENSPACE (' ')
|
||||
#define TOKENSPECIAL ('$')
|
||||
|
||||
#define MAXTOKEN 512
|
||||
#define SCRIPT_MAXTOKEN 512
|
||||
|
||||
typedef struct {
|
||||
qboolean tokenready;
|
||||
int offset;
|
||||
int line;
|
||||
char token[MAXTOKEN];
|
||||
char token[SCRIPT_MAXTOKEN];
|
||||
} scriptmarker_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -67,7 +67,7 @@ protected:
|
||||
Container<macro*> macrolist;
|
||||
|
||||
int line;
|
||||
char token[MAXTOKEN];
|
||||
char token[SCRIPT_MAXTOKEN];
|
||||
|
||||
qboolean releaseBuffer;
|
||||
qboolean hasError;
|
||||
|
||||
@@ -87,7 +87,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#define SURF_NOMARKS 0x20 // don't leave missile marks
|
||||
#define SURF_CASTSHADOW 0x40
|
||||
#define SURF_NODRAW 0x80 // don't generate a drawsurface at all
|
||||
#define SURF_HINT 0x100 // make a primary bsp splitter
|
||||
#define SURF_NOLIGHTMAP 0x100 // surface doesn't need a lightmap
|
||||
#define SURF_ALPHASHADOW 0x200 // do per-pixel light shadow casting in q3map
|
||||
#define SURF_NOSTEPS 0x400 // no footstep sounds
|
||||
#define SURF_NONSOLID 0x800 // don't collide against curves with this set
|
||||
@@ -109,7 +109,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#define SURF_CARPET 0x8000000 // carpet effects
|
||||
#define SURF_BACKSIDE 0x10000000 // su44: backside
|
||||
#define SURF_NODLIGHT 0x20000000 // don't dlight even if solid (solid lava, skies)
|
||||
#define SURF_NOLIGHTMAP 0x40000000 // surface doesn't need a lightmap
|
||||
#define SURF_HINT 0x40000000 // make a primary bsp splitter
|
||||
#define SURF_UNKNOWN3 0x80000000 // IneQuation: WTF?
|
||||
|
||||
#define SURF_FLESH 0x40 // make flesh sounds and effects
|
||||
|
||||
@@ -388,7 +388,7 @@ void TikiScript::AddMacro( const char *name, const char *expansion )
|
||||
return;
|
||||
}
|
||||
|
||||
if( nummacros >= MAXMACROS )
|
||||
if( nummacros >= TIKI_MAXMACROS )
|
||||
{
|
||||
TIKI_DPrintf( "Too many %cdefine in file %s\n", TOKENSPECIAL, Filename() );
|
||||
}
|
||||
@@ -420,7 +420,7 @@ qboolean TikiScript::ProcessCommand( qboolean crossline )
|
||||
char argument1[ 256 ];
|
||||
char argument2[ 256 ];
|
||||
|
||||
sscanf( script_p, "%c%s %s %s\n", &dummy, &command, &argument1, &argument2 );
|
||||
sscanf( script_p, "%c%s %s %s\n", &dummy, command, argument1, argument2 );
|
||||
|
||||
if( !stricmp( command, "define" ) )
|
||||
{
|
||||
@@ -760,7 +760,7 @@ const char *TikiScript::GetToken( qboolean crossline )
|
||||
*token_p++ = *i->script_p++;
|
||||
}
|
||||
|
||||
if( token_p == &i->token[ MAXTOKEN ] )
|
||||
if( token_p == &i->token[ TIKI_MAXTOKEN ] )
|
||||
{
|
||||
TIKI_DPrintf( "Token too large on line %i in file %s\n", i->line, i->Filename() );
|
||||
break;
|
||||
@@ -869,7 +869,7 @@ const char *TikiScript::GetLine( qboolean crossline )
|
||||
start = i->script_p;
|
||||
SkipToEOL();
|
||||
size = i->script_p - start;
|
||||
if( size < ( MAXTOKEN - 1 ) )
|
||||
if( size < ( TIKI_MAXTOKEN - 1 ) )
|
||||
{
|
||||
memcpy( i->token, start, size );
|
||||
i->token[ size ] = '\0';
|
||||
@@ -928,7 +928,7 @@ const char *TikiScript::GetAndIgnoreLine( qboolean crossline )
|
||||
start = script_p;
|
||||
SkipToEOL();
|
||||
size = script_p - start;
|
||||
if( size < ( MAXTOKEN - 1 ) )
|
||||
if( size < ( TIKI_MAXTOKEN - 1 ) )
|
||||
{
|
||||
memcpy( token, start, size );
|
||||
token[ size ] = '\0';
|
||||
@@ -981,7 +981,7 @@ const char *TikiScript::GetRaw( void )
|
||||
start = script_p;
|
||||
SkipToEOL();
|
||||
size = script_p - start;
|
||||
if( size < ( MAXTOKEN - 1 ) )
|
||||
if( size < ( TIKI_MAXTOKEN - 1 ) )
|
||||
{
|
||||
memset( token, 0, sizeof( token ) );
|
||||
memcpy( token, start, size );
|
||||
@@ -1086,7 +1086,7 @@ const char *TikiScript::GetString( qboolean crossline )
|
||||
"line %d in file %s\n", startline, i->filename );
|
||||
}
|
||||
|
||||
if( token_p == &i->token[ MAXTOKEN ] )
|
||||
if( token_p == &i->token[ TIKI_MAXTOKEN ] )
|
||||
{
|
||||
TIKI_DPrintf( "String too large on line %i in file %s\n", i->line, i->filename );
|
||||
}
|
||||
@@ -1192,7 +1192,7 @@ int TikiScript::LinesInFile( void )
|
||||
qboolean temp_tokenready;
|
||||
const char *temp_script_p;
|
||||
int temp_line;
|
||||
char temp_token[ MAXTOKEN ];
|
||||
char temp_token[ TIKI_MAXTOKEN ];
|
||||
int numentries;
|
||||
|
||||
temp_tokenready = tokenready;
|
||||
@@ -1232,7 +1232,7 @@ void TikiScript::Parse( char *data, int length, const char *name )
|
||||
Reset();
|
||||
this->length = length;
|
||||
end_p = script_p + length;
|
||||
strncpy( filename, name, MAXTOKEN );
|
||||
strncpy( filename, name, TIKI_MAXTOKEN );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -32,21 +32,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#define TOKENSPACE (' ')
|
||||
#define TOKENSPECIAL ('$')
|
||||
|
||||
#ifndef MAXTOKEN
|
||||
#define MAXTOKEN 256
|
||||
#endif
|
||||
#define TIKI_MAXTOKEN 256
|
||||
|
||||
#define MAXMACROS 48
|
||||
#define TIKI_MAXMACROS 48
|
||||
|
||||
typedef struct {
|
||||
char name[ MAXTOKEN ];
|
||||
char macro[ MAXTOKEN ];
|
||||
char name[TIKI_MAXTOKEN];
|
||||
char macro[TIKI_MAXTOKEN];
|
||||
} tiki_macro_t;
|
||||
|
||||
typedef struct {
|
||||
const char *mark_script_p;
|
||||
qboolean mark_tokenready;
|
||||
char mark_token[ MAXTOKEN ];
|
||||
char mark_token[TIKI_MAXTOKEN];
|
||||
} tiki_mark_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -57,13 +55,13 @@ protected:
|
||||
qboolean tokenready;
|
||||
class TikiScript *include;
|
||||
class TikiScript *parent;
|
||||
char filename[ MAXTOKEN ];
|
||||
char filename[TIKI_MAXTOKEN];
|
||||
const char *script_p;
|
||||
const char *end_p;
|
||||
tiki_macro_t macros[ MAXMACROS ];
|
||||
tiki_macro_t macros[TIKI_MAXMACROS];
|
||||
int nummacros;
|
||||
int line;
|
||||
char token[ MAXTOKEN ];
|
||||
char token[TIKI_MAXTOKEN];
|
||||
qboolean releaseBuffer;
|
||||
tiki_mark_t mark[ 64 ];
|
||||
int mark_pos;
|
||||
|
||||
@@ -90,6 +90,28 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#define GL_TEXTURE2_ARB 0x84C2
|
||||
#define GL_TEXTURE3_ARB 0x84C3
|
||||
|
||||
#define GL_COMBINE 0x8570
|
||||
#define GL_COMBINE4_NV 0x8503
|
||||
#define GL_COMBINE_RGB 0x8571
|
||||
#define GL_COMBINE_ALPHA 0x8572
|
||||
|
||||
#define GL_SOURCE0_RGB 0x8580
|
||||
#define GL_SOURCE1_RGB 0x8581
|
||||
#define GL_SOURCE2_RGB 0x8582
|
||||
#define GL_SOURCE3_RGB 0x8583
|
||||
#define GL_SOURCE0_ALPHA 0x8588
|
||||
#define GL_SOURCE1_ALPHA 0x8589
|
||||
#define GL_SOURCE2_ALPHA 0x858A
|
||||
#define GL_SOURCE3_ALPHA 0x858B
|
||||
#define GL_OPERAND0_RGB 0x8590
|
||||
#define GL_OPERAND1_RGB 0x8591
|
||||
#define GL_OPERAND2_RGB 0x8592
|
||||
#define GL_OPERAND3_RGB 0x8593
|
||||
#define GL_OPERAND0_ALPHA 0x8598
|
||||
#define GL_OPERAND1_ALPHA 0x8599
|
||||
#define GL_OPERAND2_ALPHA 0x859A
|
||||
#define GL_OPERAND3_ALPHA 0x859B
|
||||
|
||||
// NOTE: some Linux platforms would need those prototypes
|
||||
#if defined(MACOS_X)
|
||||
typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
|
||||
@@ -506,6 +528,34 @@ extern void ( APIENTRY * qglVertex4sv )(const GLshort *v);
|
||||
extern void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
|
||||
extern void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
// GL_ARB_texture_compression
|
||||
extern void (APIENTRY* qglCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
|
||||
extern void (APIENTRY* qglCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
|
||||
extern void (APIENTRY* qglCompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
|
||||
extern void (APIENTRY* qglCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
|
||||
extern void (APIENTRY* qglGetCompressedTexImageARB)(GLenum target, GLint lod, void* img);
|
||||
#ifndef GL_COMPRESSED_RGB_ARB
|
||||
#define GL_COMPRESSED_ALPHA_ARB 0x84E9
|
||||
#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
|
||||
#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
|
||||
#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
|
||||
#define GL_COMPRESSED_RGB_ARB 0x84ED
|
||||
#define GL_COMPRESSED_RGBA_ARB 0x84EE
|
||||
#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
|
||||
#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
|
||||
#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
|
||||
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
|
||||
#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
|
||||
#endif
|
||||
|
||||
// GL_EXT_texture_compression_s3tc
|
||||
#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
|
||||
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
|
||||
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
|
||||
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
|
||||
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
|
||||
#endif
|
||||
|
||||
#if defined( _WIN32 )
|
||||
|
||||
extern int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
|
||||
|
||||
@@ -355,3 +355,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#define qglVertexPointer glVertexPointer
|
||||
#define qglViewport glViewport
|
||||
|
||||
#define qglCompressedTexImage3DARB glCompressedTexImage3D
|
||||
#define qglCompressedTexImage2DARB glCompressedTexImage2D
|
||||
#define qglCompressedTexSubImage3DARB glCompressedTexSubImage3D
|
||||
#define qglCompressedTexSubImage2DARB glCompressedTexSubImage2D
|
||||
#define qglGetCompressedTexImageARB glGetCompressedTexImage
|
||||
+199
-41
@@ -34,6 +34,16 @@ static float s_flipMatrix[16] = {
|
||||
0, 0, 0, 1
|
||||
};
|
||||
|
||||
void GL_SetFogColor(const vec4_t fColor) {
|
||||
glState.fFogColor[0] = fColor[0];
|
||||
glState.fFogColor[1] = fColor[1];
|
||||
glState.fFogColor[2] = fColor[2];
|
||||
glState.fFogColor[3] = fColor[3];
|
||||
|
||||
if (!(glState.glStateBits & GLS_FOG_COLOR)) {
|
||||
qglFogfv(GL_FOG_COLOR, glState.fFogColor);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** GL_Bind
|
||||
@@ -188,6 +198,10 @@ void GL_TexEnv( int env )
|
||||
case GL_ADD:
|
||||
qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
|
||||
break;
|
||||
case GL_COMBINE4_NV:
|
||||
case GL_COMBINE:
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
|
||||
break;
|
||||
default:
|
||||
ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed\n", env );
|
||||
break;
|
||||
@@ -202,7 +216,7 @@ void GL_TexEnv( int env )
|
||||
*/
|
||||
void GL_State( unsigned long stateBits )
|
||||
{
|
||||
unsigned long diff = stateBits ^ glState.glStateBits;
|
||||
unsigned long diff = glState.glStateBits ^ (glState.externalSetState | stateBits);
|
||||
|
||||
if ( !diff )
|
||||
{
|
||||
@@ -354,6 +368,35 @@ void GL_State( unsigned long stateBits )
|
||||
}
|
||||
}
|
||||
|
||||
if ((diff & GLS_MULTITEXTURE_ENV) || (diff & GLS_MULTITEXTURE))
|
||||
{
|
||||
if (stateBits & GLS_MULTITEXTURE_ENV)
|
||||
{
|
||||
GL_TexEnv(GL_COMBINE4_NV);
|
||||
}
|
||||
else if (stateBits & GLS_MULTITEXTURE)
|
||||
{
|
||||
if (glState.cntTexEnvExt != GLS_MULTITEXTURE)
|
||||
{
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, 34165.0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, 8448.0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, 0x47057700);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, 0x44400000);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, 5890.0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, 0x44400000);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, 0x47057700);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, 770.0);
|
||||
glState.cntTexEnvExt = GLS_MULTITEXTURE;
|
||||
}
|
||||
|
||||
GL_TexEnv(GL_COMBINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_TexEnv(GL_MODULATE);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// alpha test
|
||||
//
|
||||
@@ -382,7 +425,109 @@ void GL_State( unsigned long stateBits )
|
||||
}
|
||||
}
|
||||
|
||||
glState.glStateBits = stateBits;
|
||||
|
||||
|
||||
if (diff & GLS_CLAMP_EDGE)
|
||||
{
|
||||
float clampValue;
|
||||
|
||||
if (r_forceClampToEdge->value)
|
||||
{
|
||||
if (stateBits & GLS_CLAMP_EDGE) {
|
||||
clampValue = 33071.0;
|
||||
}
|
||||
else {
|
||||
clampValue = 10497.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stateBits & GLS_CLAMP_EDGE) {
|
||||
clampValue = 10496.0;
|
||||
}
|
||||
else {
|
||||
clampValue = 10497.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (qglActiveTextureARB)
|
||||
{
|
||||
int currenttmu = glState.currenttmu;
|
||||
|
||||
GL_SelectTexture(0);
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clampValue);
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clampValue);
|
||||
|
||||
GL_SelectTexture(1);
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clampValue);
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clampValue);
|
||||
|
||||
GL_SelectTexture(currenttmu);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_SelectTexture(0);
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clampValue);
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clampValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (diff & GLS_FOG)
|
||||
{
|
||||
if (glState.externalSetState & GLS_FOG)
|
||||
{
|
||||
qglEnable(GL_FOG);
|
||||
|
||||
if (stateBits & GLS_FOG_BLACK)
|
||||
{
|
||||
vec4_t fBlackFogColor = { 0, 0, 0, 1 };
|
||||
qglFogfv(GL_FOG_COLOR, fBlackFogColor);
|
||||
}
|
||||
else if (stateBits & GLS_FOG_WHITE)
|
||||
{
|
||||
vec4_t fWhiteFogColor = { 1, 1, 1, 1 };
|
||||
qglFogfv(GL_FOG_COLOR, fWhiteFogColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Use the global fog
|
||||
qglFogfv(GL_FOG_COLOR, glState.fFogColor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qglDisable(GL_FOG);
|
||||
}
|
||||
}
|
||||
else if (glState.externalSetState & GLS_FOG)
|
||||
{
|
||||
if (diff & GLS_FOG_ENABLED)
|
||||
{
|
||||
if (stateBits & GLS_FOG_ENABLED) {
|
||||
qglEnable(GL_FOG);
|
||||
}
|
||||
else {
|
||||
qglDisable(GL_FOG);
|
||||
}
|
||||
}
|
||||
|
||||
if (diff & GLS_FOG_COLOR)
|
||||
{
|
||||
if (stateBits & GLS_FOG_BLACK)
|
||||
{
|
||||
vec4_t fBlackFogColor = { 0, 0, 0, 1 };
|
||||
qglFogfv(GL_FOG_COLOR, fBlackFogColor);
|
||||
}
|
||||
else if (stateBits & GLS_FOG_WHITE)
|
||||
{
|
||||
vec4_t fWhiteFogColor = { 1, 1, 1, 1 };
|
||||
qglFogfv(GL_FOG_COLOR, fWhiteFogColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glState.glStateBits = stateBits | glState.externalSetState;
|
||||
}
|
||||
|
||||
|
||||
@@ -450,23 +595,33 @@ void RB_BeginDrawingView (void) {
|
||||
//
|
||||
SetViewportAndScissor();
|
||||
|
||||
R_UploadDlights();
|
||||
|
||||
// ensures that depth writes are enabled for the depth clear
|
||||
GL_State( GLS_DEFAULT );
|
||||
// clear relevant buffers
|
||||
clearBits = GL_DEPTH_BUFFER_BIT;
|
||||
|
||||
if ( r_measureOverdraw->integer || r_shadows->integer == 2 )
|
||||
if ( r_measureOverdraw->integer || r_shadows->integer == 3 )
|
||||
{
|
||||
clearBits |= GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) )
|
||||
|
||||
if (!( backEnd.refdef.rdflags & RDF_NOWORLDMODEL))
|
||||
{
|
||||
clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used
|
||||
#ifdef _DEBUG
|
||||
qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f ); // FIXME: get color of sky
|
||||
#else
|
||||
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky
|
||||
#endif
|
||||
if (backEnd.viewParms.farplane_distance && tr.skyRendered && tr.portalRendered)
|
||||
{
|
||||
clearBits |= GL_COLOR_BUFFER_BIT;
|
||||
qglClearColor(glState.fFogColor[0], glState.fFogColor[1], glState.fFogColor[2], glState.fFogColor[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (r_fastsky->integer)
|
||||
{
|
||||
clearBits |= GL_COLOR_BUFFER_BIT;
|
||||
qglClearColor(0.5, 0.5, 1.0, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
qglClear( clearBits );
|
||||
|
||||
@@ -553,6 +708,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||
depthRange = qfalse;
|
||||
|
||||
backEnd.pc.c_surfaces += numDrawSurfs;
|
||||
backEnd.numSpheresUsed = 0;
|
||||
|
||||
for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
|
||||
if ( drawSurf->sort == oldSort ) {
|
||||
@@ -561,7 +717,14 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||
continue;
|
||||
}
|
||||
oldSort = drawSurf->sort;
|
||||
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &dlightMap, &bStaticModel );
|
||||
if (*drawSurf->surface != SF_SPRITE) {
|
||||
R_DecomposeSort(drawSurf->sort, &entityNum, &shader, &dlightMap, &bStaticModel);
|
||||
} else {
|
||||
shader = tr.sortedShaders[((refSprite_t*)drawSurf->surface)->shaderNum];
|
||||
entityNum = ENTITYNUM_WORLD;
|
||||
dlightMap = 0;
|
||||
bStaticModel = qfalse;
|
||||
}
|
||||
|
||||
//
|
||||
// change the tess parameters if needed
|
||||
@@ -587,6 +750,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||
oldDlightMap = dlightMap;
|
||||
}
|
||||
|
||||
backEnd.currentSphere = &backEnd.spareSphere;
|
||||
//
|
||||
// change the modelview matrix if needed
|
||||
//
|
||||
@@ -643,7 +807,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||
if ( depthRange ) {
|
||||
qglDepthRange (0, 0.3);
|
||||
} else {
|
||||
qglDepthRange (0, 1);
|
||||
qglDepthRange (0, 1.875);
|
||||
}
|
||||
oldDepthRange = depthRange;
|
||||
}
|
||||
@@ -697,7 +861,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||
}
|
||||
else
|
||||
{
|
||||
backEnd.currentSphere = &backEnd.spheres[backEnd.currentEntity->lightingSphere];
|
||||
backEnd.currentSphere = &backEnd.spheres[backEnd.numSpheresUsed];
|
||||
backEnd.currentEntity->lightingSphere = backEnd.numSpheresUsed++;
|
||||
backEnd.currentEntity->sphereCalculated = 1;
|
||||
}
|
||||
@@ -708,6 +872,10 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||
}
|
||||
}
|
||||
|
||||
if (*drawSurf->surface == SF_SPRITE) {
|
||||
backEnd.shaderStartTime = ((refSprite_t*)drawSurf->surface)->shaderTime;
|
||||
}
|
||||
|
||||
// add the triangles for this surface
|
||||
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
|
||||
}
|
||||
@@ -722,7 +890,16 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||
// go back to the world modelview matrix
|
||||
qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
|
||||
if ( depthRange ) {
|
||||
qglDepthRange (0, 1);
|
||||
qglDepthRange (0, 1.875);
|
||||
}
|
||||
|
||||
RB_ShadowFinish();
|
||||
RB_RenderFlares();
|
||||
R_DrawLensFlares();
|
||||
if (g_bInfoworldtris)
|
||||
{
|
||||
g_bInfoworldtris = 0;
|
||||
R_PrintInfoWorldtris();
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -814,12 +991,12 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, int componen
|
||||
ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
|
||||
}
|
||||
|
||||
GL_Bind( tr.scratchImage[0] );
|
||||
GL_Bind( tr.scratchImage );
|
||||
|
||||
// if the scratchImage isn't in the format we want, specify it as a new texture
|
||||
if ( cols != tr.scratchImage[0]->width || rows != tr.scratchImage[0]->height ) {
|
||||
tr.scratchImage[0]->width = tr.scratchImage[0]->uploadWidth = cols;
|
||||
tr.scratchImage[0]->height = tr.scratchImage[0]->uploadHeight = rows;
|
||||
if ( cols != tr.scratchImage->width || rows != tr.scratchImage->height ) {
|
||||
tr.scratchImage->width = tr.scratchImage->uploadWidth = cols;
|
||||
tr.scratchImage->height = tr.scratchImage->uploadHeight = rows;
|
||||
qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
|
||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
@@ -852,29 +1029,6 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, int componen
|
||||
qglEnd ();
|
||||
}
|
||||
|
||||
void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
|
||||
|
||||
GL_Bind( tr.scratchImage[client] );
|
||||
|
||||
// if the scratchImage isn't in the format we want, specify it as a new texture
|
||||
if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
|
||||
tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
|
||||
tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
|
||||
qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
|
||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
|
||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
|
||||
} else {
|
||||
if (dirty) {
|
||||
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
|
||||
// it and don't try and do a texture compression
|
||||
qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
RB_SetColor
|
||||
@@ -969,6 +1123,10 @@ const void *RB_StretchPic ( const void *data ) {
|
||||
return (const void *)(cmd + 1);
|
||||
}
|
||||
|
||||
void RB_SetupFog() {
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
|
||||
+153
-186
@@ -261,6 +261,14 @@ static void R_LoadLightmaps(gamelump_t* l) {
|
||||
if ( r_lightmap->integer == 2 ) {
|
||||
ri.Printf( PRINT_ALL, "Brightest lightmap value: %d\n", ( int ) ( maxIntensity * 255 ) );
|
||||
}
|
||||
|
||||
if (r_fastdlights->integer) {
|
||||
s_worldData.lighting = NULL;
|
||||
}
|
||||
else {
|
||||
s_worldData.lighting = ri.Hunk_Alloc(l->length);
|
||||
Com_Memcpy(s_worldData.lighting, l->buffer, l->length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -457,7 +465,11 @@ R_UnpackTerraPatch
|
||||
================
|
||||
*/
|
||||
void R_UnpackTerraPatch(cTerraPatch_t* pPacked, cTerraPatchUnpacked_t* pUnpacked) {
|
||||
int i;
|
||||
int i, j;
|
||||
union {
|
||||
int16_t v;
|
||||
uint8_t b[2];
|
||||
} flags;
|
||||
|
||||
pUnpacked->byDirty = qfalse;
|
||||
pUnpacked->visCountCheck = 0;
|
||||
@@ -468,41 +480,54 @@ void R_UnpackTerraPatch(cTerraPatch_t* pPacked, cTerraPatchUnpacked_t* pUnpacked
|
||||
Com_Error(ERR_DROP, "invalid map: terrain has lmapScale <= 0");
|
||||
}
|
||||
|
||||
pUnpacked->drawinfo.lmapStep = (pPacked->lmapScale / 64);
|
||||
pUnpacked->drawinfo.lmapSize = (pPacked->lmapScale * 8) | 1;
|
||||
pUnpacked->drawinfo.lmapStep = (float)(pPacked->lmapScale / 64);
|
||||
pUnpacked->drawinfo.lmapSize = (float)((pPacked->lmapScale * 8) + 1);
|
||||
pUnpacked->s = ((float)pPacked->s + 0.5) * 0.0078125;
|
||||
pUnpacked->t = ((float)pPacked->t + 0.5) * 0.0078125;
|
||||
|
||||
//if( s_worldData.lighting ) {
|
||||
// pUnpacked->drawinfo.lmData = &s_worldData.lighting[ 3 * ( ( pPacked->t << 7 ) + pPacked->s + ( pPacked->iLightMap << 14 ) ) ];
|
||||
//} else {
|
||||
// pUnpacked->drawinfo.lmData = NULL;
|
||||
//}
|
||||
|
||||
// fixme: is it important to have a lightmap data?
|
||||
pUnpacked->drawinfo.lmData = NULL;
|
||||
|
||||
memcpy(pUnpacked->texCoord, pPacked->texCoord, sizeof(pUnpacked->texCoord));
|
||||
pUnpacked->x0 = ((int)pPacked->x << 6);
|
||||
pUnpacked->y0 = ((int)pPacked->y << 6);
|
||||
pUnpacked->z0 = pPacked->iBaseHeight;
|
||||
pUnpacked->shader = ShaderForShaderNum(pPacked->iShader, pPacked->iLightMap);
|
||||
pUnpacked->iNorth = pPacked->iNorth;
|
||||
pUnpacked->iEast = pPacked->iEast;
|
||||
pUnpacked->iSouth = pPacked->iSouth;
|
||||
pUnpacked->iWest = pPacked->iWest;
|
||||
|
||||
for (i = 0; i < 63; i++)
|
||||
{
|
||||
pUnpacked->varTree[0][i / 4].fVariance = pPacked->varTree[0][i].flags >> 12;
|
||||
pUnpacked->varTree[1][i / 4].fVariance = pPacked->varTree[1][i].flags >> 12;
|
||||
if( s_worldData.lighting ) {
|
||||
pUnpacked->drawinfo.lmData = &s_worldData.lighting[pPacked->iLightMap * (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3) + 3 * pPacked->s + 3 * 128 * pPacked->t];
|
||||
} else {
|
||||
pUnpacked->drawinfo.lmData = NULL;
|
||||
}
|
||||
|
||||
memcpy(pUnpacked->heightmap, pPacked->heightmap, sizeof(pUnpacked->heightmap));
|
||||
for (i = 0; i < 2; i++) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
pUnpacked->texCoord[i][j][0] = LittleFloat(pPacked->texCoord[i][j][0]);
|
||||
pUnpacked->texCoord[i][j][1] = LittleFloat(pPacked->texCoord[i][j][1]);
|
||||
}
|
||||
}
|
||||
|
||||
pUnpacked->x0 = ((int)pPacked->x << 6);
|
||||
pUnpacked->y0 = ((int)pPacked->y << 6);
|
||||
pUnpacked->z0 = LittleShort(pPacked->iBaseHeight);
|
||||
pUnpacked->shader = ShaderForShaderNum(LittleShort(pPacked->iShader), LittleShort(pPacked->iLightMap));
|
||||
pUnpacked->iNorth = LittleShort(pPacked->iNorth);
|
||||
pUnpacked->iEast = LittleShort(pPacked->iEast);
|
||||
pUnpacked->iSouth = LittleShort(pPacked->iSouth);
|
||||
pUnpacked->iWest = LittleShort(pPacked->iWest);
|
||||
|
||||
for (i = 0; i < 63; i++)
|
||||
{
|
||||
flags.v = pPacked->varTree[0][i].flags;
|
||||
flags.b[1] &= 7;
|
||||
pUnpacked->varTree[0][i].fVariance = LittleShort(flags.v);
|
||||
pUnpacked->varTree[0][i].s.flags = LittleShort(pPacked->varTree[0][i].flags) >> 12;
|
||||
|
||||
flags.v = pPacked->varTree[1][i].flags;
|
||||
flags.b[1] &= 7;
|
||||
pUnpacked->varTree[1][i].fVariance = LittleShort(flags.v);
|
||||
pUnpacked->varTree[1][i].s.flags = LittleShort(pPacked->varTree[1][i].flags) >> 12;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(pUnpacked->heightmap) / sizeof(pUnpacked->heightmap[0]); i++) {
|
||||
pUnpacked->heightmap[i] = pPacked->heightmap[i];
|
||||
}
|
||||
|
||||
pUnpacked->zmax = 0;
|
||||
pUnpacked->flags = pPacked->flags;
|
||||
|
||||
for (i = 0; i < sizeof(pUnpacked->heightmap); i++)
|
||||
for (i = 0; i < sizeof(pUnpacked->heightmap) / sizeof(pUnpacked->heightmap[0]); i++)
|
||||
{
|
||||
if (pUnpacked->zmax < pUnpacked->heightmap[i]) {
|
||||
pUnpacked->zmax = pUnpacked->heightmap[i];
|
||||
@@ -590,9 +615,6 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int
|
||||
|
||||
lightmapNum = LittleLong( ds->lightmapNum );
|
||||
|
||||
// get fog volume
|
||||
surf->fogIndex = LittleLong( ds->fogNum ) + 1;
|
||||
|
||||
// get shader value
|
||||
surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapNum );
|
||||
if ( r_singleShader->integer && !surf->shader->isSky ) {
|
||||
@@ -644,6 +666,42 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int
|
||||
SetPlaneSignbits( &cv->plane );
|
||||
cv->plane.type = PlaneTypeForNormal( cv->plane.normal );
|
||||
|
||||
if (tr.numLightmaps && lightmapNum != -1 && surf->shader->lightmapIndex >= 0)
|
||||
{
|
||||
float inv;
|
||||
|
||||
cv->lmX = LittleLong(ds->lightmapX);
|
||||
cv->lmY = LittleLong(ds->lightmapY);
|
||||
cv->lmWidth = LittleLong(ds->lightmapWidth);
|
||||
cv->lmHeight = LittleLong(ds->lightmapHeight);
|
||||
|
||||
if (s_worldData.lighting) {
|
||||
cv->lmData = &s_worldData.lighting[lightmapNum * (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3) + 3 * cv->lmX + 3 * 128 * cv->lmY];
|
||||
} else {
|
||||
cv->lmData = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
cv->lmOrigin[j] = LittleFloat(ds->lightmapOrigin[j]);
|
||||
cv->lmVecs[0][j] = LittleFloat(ds->lightmapVecs[0][j]);
|
||||
cv->lmVecs[1][j] = LittleFloat(ds->lightmapVecs[1][j]);
|
||||
}
|
||||
|
||||
inv = VectorNormalize2(cv->lmVecs[0], cv->lmInverseVecs[0]);
|
||||
cv->lmInverseVecs[0][0] *= 1.0 / inv;
|
||||
cv->lmInverseVecs[0][1] *= 1.0 / inv;
|
||||
cv->lmInverseVecs[0][2] *= 1.0 / inv;
|
||||
|
||||
inv = VectorNormalize2(cv->lmVecs[1], cv->lmInverseVecs[1]);
|
||||
cv->lmInverseVecs[1][0] *= 1.0 / inv;
|
||||
cv->lmInverseVecs[1][1] *= 1.0 / inv;
|
||||
cv->lmInverseVecs[1][2] *= 1.0 / inv;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv->lmData = NULL;
|
||||
}
|
||||
surf->data = (surfaceType_t *)cv;
|
||||
}
|
||||
|
||||
@@ -702,6 +760,19 @@ static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, msurface_t *surf ) {
|
||||
grid = R_SubdividePatchToGrid( width, height, points );
|
||||
surf->data = (surfaceType_t *)grid;
|
||||
|
||||
if (tr.numLightmaps && lightmapNum != -1 && surf->shader->lightmapIndex >= 0)
|
||||
{
|
||||
grid->lmX = LittleLong(ds->lightmapX);
|
||||
grid->lmY = LittleLong(ds->lightmapY);
|
||||
grid->lmWidth = LittleLong(ds->lightmapWidth);
|
||||
grid->lmHeight = LittleLong(ds->lightmapHeight);
|
||||
if (s_worldData.lighting) {
|
||||
grid->lmData = &s_worldData.lighting[lightmapNum * (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3) + 3 * grid->lmX + 3 * 128 * grid->lmY];
|
||||
} else {
|
||||
grid->lmData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// copy the level of detail origin, which is the center
|
||||
// of the group of all curves that must subdivide the same
|
||||
// to avoid cracking
|
||||
@@ -1886,129 +1957,13 @@ static void R_LoadPlanes(gamelump_t* l) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LoadFogs
|
||||
|
||||
=================
|
||||
*/
|
||||
static void R_LoadFogs(gamelump_t* l, gamelump_t* brushesLump, gamelump_t* sidesLump) {
|
||||
int i;
|
||||
fog_t* out;
|
||||
dfog_t* fogs;
|
||||
dbrush_t* brushes, * brush;
|
||||
dbrushside_t* sides;
|
||||
int count, brushesCount, sidesCount;
|
||||
int sideNum;
|
||||
int planeNum;
|
||||
shader_t* shader;
|
||||
float d;
|
||||
int firstSide;
|
||||
|
||||
fogs = l->buffer;
|
||||
if (l->length % sizeof(*fogs)) {
|
||||
ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
|
||||
}
|
||||
count = l->length / sizeof(*fogs);
|
||||
|
||||
// create fog strucutres for them
|
||||
s_worldData.numfogs = count + 1;
|
||||
s_worldData.fogs = ri.Hunk_Alloc(s_worldData.numfogs * sizeof(*out));
|
||||
out = s_worldData.fogs + 1;
|
||||
|
||||
if (!count) {
|
||||
return;
|
||||
}
|
||||
|
||||
brushes = brushesLump->buffer;
|
||||
if (brushesLump->length % sizeof(*brushes)) {
|
||||
ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
|
||||
}
|
||||
brushesCount = brushesLump->length / sizeof(*brushes);
|
||||
|
||||
sides = sidesLump->buffer;
|
||||
if (sidesLump->length % sizeof(*sides)) {
|
||||
ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
|
||||
}
|
||||
sidesCount = sidesLump->length / sizeof(*sides);
|
||||
|
||||
for (i = 0; i < count; i++, fogs++) {
|
||||
out->originalBrushNumber = LittleLong(fogs->brushNum);
|
||||
|
||||
if ((unsigned)out->originalBrushNumber >= brushesCount) {
|
||||
ri.Error(ERR_DROP, "fog brushNumber out of range");
|
||||
}
|
||||
brush = brushes + out->originalBrushNumber;
|
||||
|
||||
firstSide = LittleLong(brush->firstSide);
|
||||
|
||||
if ((unsigned)firstSide > sidesCount - 6) {
|
||||
ri.Error(ERR_DROP, "fog brush sideNumber out of range");
|
||||
}
|
||||
|
||||
// brushes are always sorted with the axial sides first
|
||||
sideNum = firstSide + 0;
|
||||
planeNum = LittleLong(sides[sideNum].planeNum);
|
||||
out->bounds[0][0] = -s_worldData.planes[planeNum].dist;
|
||||
|
||||
sideNum = firstSide + 1;
|
||||
planeNum = LittleLong(sides[sideNum].planeNum);
|
||||
out->bounds[1][0] = s_worldData.planes[planeNum].dist;
|
||||
|
||||
sideNum = firstSide + 2;
|
||||
planeNum = LittleLong(sides[sideNum].planeNum);
|
||||
out->bounds[0][1] = -s_worldData.planes[planeNum].dist;
|
||||
|
||||
sideNum = firstSide + 3;
|
||||
planeNum = LittleLong(sides[sideNum].planeNum);
|
||||
out->bounds[1][1] = s_worldData.planes[planeNum].dist;
|
||||
|
||||
sideNum = firstSide + 4;
|
||||
planeNum = LittleLong(sides[sideNum].planeNum);
|
||||
out->bounds[0][2] = -s_worldData.planes[planeNum].dist;
|
||||
|
||||
sideNum = firstSide + 5;
|
||||
planeNum = LittleLong(sides[sideNum].planeNum);
|
||||
out->bounds[1][2] = s_worldData.planes[planeNum].dist;
|
||||
|
||||
// get information from the shader for fog parameters
|
||||
shader = R_FindShader(fogs->shader, LIGHTMAP_NONE, qtrue, qtrue, qtrue, qtrue);
|
||||
|
||||
out->parms = shader->fogParms;
|
||||
|
||||
out->colorInt = ColorBytes4(shader->fogParms.color[0] * tr.identityLight,
|
||||
shader->fogParms.color[1] * tr.identityLight,
|
||||
shader->fogParms.color[2] * tr.identityLight, 1.0);
|
||||
|
||||
d = shader->fogParms.depthForOpaque < 1 ? 1 : shader->fogParms.depthForOpaque;
|
||||
out->tcScale = 1.0f / (d * 8);
|
||||
|
||||
// set the gradient vector
|
||||
sideNum = LittleLong(fogs->visibleSide);
|
||||
|
||||
if (sideNum == -1) {
|
||||
out->hasSurface = qfalse;
|
||||
}
|
||||
else {
|
||||
out->hasSurface = qtrue;
|
||||
planeNum = LittleLong(sides[firstSide + sideNum].planeNum);
|
||||
VectorSubtract(vec3_origin, s_worldData.planes[planeNum].normal, out->surface);
|
||||
out->surface[3] = -s_worldData.planes[planeNum].dist;
|
||||
}
|
||||
|
||||
out++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_LoadLightGrid
|
||||
|
||||
================
|
||||
*/
|
||||
void R_LoadLightGrid(gamelump_t* l) {
|
||||
void R_LoadLightGrid(gamelump_t* plPal, gamelump_t* plOffsets, gamelump_t* plData) {
|
||||
int i;
|
||||
vec3_t maxs;
|
||||
int numGridPoints;
|
||||
@@ -2017,35 +1972,51 @@ void R_LoadLightGrid(gamelump_t* l) {
|
||||
|
||||
w = &s_worldData;
|
||||
|
||||
w->lightGridInverseSize[0] = 1.0f / w->lightGridSize[0];
|
||||
w->lightGridInverseSize[1] = 1.0f / w->lightGridSize[1];
|
||||
w->lightGridInverseSize[2] = 1.0f / w->lightGridSize[2];
|
||||
if (!plPal->buffer || !plOffsets->buffer || !plData->buffer) {
|
||||
ri.Printf(PRINT_WARNING, "WARNING: No light grid data present\n");
|
||||
w->lightGridOffsets = 0;
|
||||
w->lightGridData = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
w->lightGridSize[0] = 32.0;
|
||||
w->lightGridSize[1] = 32.0;
|
||||
w->lightGridSize[2] = 32.0;
|
||||
w->lightGridOOSize[0] = 1.0f / w->lightGridSize[0];
|
||||
w->lightGridOOSize[1] = 1.0f / w->lightGridSize[1];
|
||||
w->lightGridOOSize[2] = 1.0f / w->lightGridSize[2];
|
||||
|
||||
wMins = w->bmodels[0].bounds[0];
|
||||
wMaxs = w->bmodels[0].bounds[1];
|
||||
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
w->lightGridOrigin[i] = w->lightGridSize[i] * ceil( wMins[i] / w->lightGridSize[i] );
|
||||
w->lightGridMins[i] = w->lightGridSize[i] * ceil( wMins[i] / w->lightGridSize[i] );
|
||||
maxs[i] = w->lightGridSize[i] * floor( wMaxs[i] / w->lightGridSize[i] );
|
||||
w->lightGridBounds[i] = (maxs[i] - w->lightGridOrigin[i])/w->lightGridSize[i] + 1;
|
||||
w->lightGridBounds[i] = (maxs[i] - w->lightGridMins[i])/w->lightGridSize[i] + 1;
|
||||
}
|
||||
|
||||
numGridPoints = w->lightGridBounds[0] * w->lightGridBounds[1] * w->lightGridBounds[2];
|
||||
numGridPoints = w->lightGridBounds[0] * w->lightGridBounds[1] + w->lightGridBounds[0];
|
||||
|
||||
if (l->length != numGridPoints * 8) {
|
||||
ri.Printf(PRINT_WARNING, "WARNING: light grid mismatch\n");
|
||||
if (plOffsets->length != numGridPoints * 2) {
|
||||
ri.Printf(PRINT_WARNING, "WARNING: light grid offset size mismatch\n");
|
||||
w->lightGridOffsets = NULL;
|
||||
w->lightGridData = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
w->lightGridData = ri.Hunk_Alloc(l->length);
|
||||
Com_Memcpy(w->lightGridData, (void*)l->buffer, l->length);
|
||||
|
||||
// deal with overbright bits
|
||||
for ( i = 0 ; i < numGridPoints ; i++ ) {
|
||||
R_ColorShiftLightingBytesAlpha( &w->lightGridData[i*8], &w->lightGridData[i*8] );
|
||||
R_ColorShiftLightingBytesAlpha( &w->lightGridData[i*8+3], &w->lightGridData[i*8+3] );
|
||||
if (plPal->length != 768) {
|
||||
ri.Printf(PRINT_WARNING, "WARNING: light grid palette size mismatch\n");
|
||||
w->lightGridOffsets = NULL;
|
||||
w->lightGridData = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
w->lightGridOffsets = ri.Hunk_Alloc(plOffsets->length);
|
||||
Com_Memcpy(w->lightGridOffsets, plOffsets->buffer, plOffsets->length);
|
||||
Com_Memcpy(w->lightGridPalette, plPal->buffer, sizeof(s_worldData.lightGridPalette));
|
||||
|
||||
w->lightGridData = ri.Hunk_Alloc(plData->length);
|
||||
Com_Memcpy(w->lightGridData, plData->buffer, plData->length);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2070,17 +2041,16 @@ void R_LoadStaticModelData(gamelump_t* lump) {
|
||||
}
|
||||
|
||||
s_worldData.numStaticModelData = lump->length / (sizeof(byte) * 3);
|
||||
s_worldData.staticModelData = ri.Hunk_Alloc(s_worldData.numStaticModelData * (sizeof(byte) * 4));
|
||||
s_worldData.staticModelData = (byte*)ri.Hunk_Alloc(s_worldData.numStaticModelData * sizeof(color4ub_t));
|
||||
|
||||
pSrcColors = lump->buffer;
|
||||
pDstColors = s_worldData.staticModelData;
|
||||
|
||||
for (i = 0; i < lump->length; i += 3)
|
||||
{
|
||||
pDstColors[0] = pSrcColors[0];
|
||||
pDstColors[1] = pSrcColors[1];
|
||||
pDstColors[2] = pSrcColors[2];
|
||||
pDstColors[3] = -1;
|
||||
for (i = 0; i < lump->length; i += sizeof(byte) * 3)
|
||||
{
|
||||
// Colors are stored as integers
|
||||
*(unsigned int*)pDstColors = LittleLong(*(unsigned int*)pSrcColors);
|
||||
pDstColors[3] = 0xFF;
|
||||
|
||||
pSrcColors += sizeof(byte) * 3;
|
||||
pDstColors += sizeof(byte) * 4;
|
||||
@@ -2094,11 +2064,15 @@ R_CopyStaticModel
|
||||
*/
|
||||
void R_CopyStaticModel(cStaticModel_t* pSM, cStaticModelUnpacked_t* pUnpackedSM) {
|
||||
pUnpackedSM->visCount = 0;
|
||||
VectorCopy(pSM->angles, pUnpackedSM->angles);
|
||||
VectorCopy(pSM->origin, pUnpackedSM->origin);
|
||||
pUnpackedSM->scale = pSM->scale;
|
||||
pUnpackedSM->firstVertexData = pSM->firstVertexData * 4 / 3;
|
||||
pUnpackedSM->numVertexData = pSM->numVertexData;
|
||||
pUnpackedSM->angles[0] = LittleFloat(pSM->angles[0]);
|
||||
pUnpackedSM->angles[1] = LittleFloat(pSM->angles[1]);
|
||||
pUnpackedSM->angles[2] = LittleFloat(pSM->angles[2]);
|
||||
pUnpackedSM->origin[0] = LittleFloat(pSM->origin[0]);
|
||||
pUnpackedSM->origin[1] = LittleFloat(pSM->origin[1]);
|
||||
pUnpackedSM->origin[2] = LittleFloat(pSM->origin[2]);
|
||||
pUnpackedSM->scale = LittleFloat(pSM->scale);
|
||||
pUnpackedSM->firstVertexData = LittleLong(pSM->firstVertexData) * sizeof(color4ub_t) / (sizeof(byte) * 3);
|
||||
pUnpackedSM->numVertexData = LittleLong(pSM->numVertexData);
|
||||
memcpy(pUnpackedSM->model, pSM->model, sizeof(pUnpackedSM->model));
|
||||
}
|
||||
|
||||
@@ -2259,9 +2233,9 @@ void RE_LoadWorldMap( const char *name ) {
|
||||
c_gridVerts = 0;
|
||||
|
||||
i = LittleLong(header.version);
|
||||
if (i < BSP_BASE_VERSION || i > BSP_VERSION) {
|
||||
if (i < BSP_MIN_VERSION || i > BSP_MAX_VERSION) {
|
||||
ri.Error(ERR_DROP, "RE_LoadWorldMap: %s has wrong version number (%i should be between %i and %i)",
|
||||
name, i, BSP_BASE_VERSION, BSP_VERSION);
|
||||
name, i, BSP_MIN_VERSION, BSP_MAX_VERSION);
|
||||
}
|
||||
|
||||
// load into heap
|
||||
@@ -2319,13 +2293,7 @@ void RE_LoadWorldMap( const char *name ) {
|
||||
_R(75);
|
||||
R_FreeLump(&lump2);
|
||||
_R(76);
|
||||
numbrushsides = R_LoadLump(h, &header.lumps[LUMP_BRUSHSIDES], &lump2, sizeof(dbrushside_t));
|
||||
numbrushes = R_LoadLump(h, &header.lumps[LUMP_BRUSHES], &lump, sizeof(dbrush_t));
|
||||
numFogs = R_LoadLump(h, &header.lumps[LUMP_DUMMY10], &lump3, sizeof(dfog_t));
|
||||
R_LoadFogs(&lump3, &lump, &lump2);
|
||||
R_FreeLump(&lump);
|
||||
R_FreeLump(&lump2);
|
||||
R_FreeLump(&lump3);
|
||||
numFogs = 0;
|
||||
nummodels = R_LoadLump(h, &header.lumps[LUMP_MODELS], &lump, sizeof(bmodel_t));
|
||||
_R(77);
|
||||
R_LoadSubmodels(&lump);
|
||||
@@ -2344,8 +2312,7 @@ void RE_LoadWorldMap( const char *name ) {
|
||||
_R(84);
|
||||
g_iGridDataSize = R_LoadLump(h, &header.lumps[LUMP_LIGHTGRIDDATA], &lump3, sizeof(byte));
|
||||
_R(85);
|
||||
//R_LoadLightGrid( &lump, &lump2, &lump3 );
|
||||
R_LoadLightGrid(&lump3);
|
||||
R_LoadLightGrid( &lump, &lump2, &lump3 );
|
||||
_R(86);
|
||||
R_FreeLump(&lump);
|
||||
_R(87);
|
||||
|
||||
@@ -42,6 +42,16 @@ R_PerformanceCounters
|
||||
=====================
|
||||
*/
|
||||
void R_PerformanceCounters( void ) {
|
||||
if (fps->integer) {
|
||||
ri.SetPerformanceCounters(
|
||||
backEnd.pc.c_totalIndexes / 3,
|
||||
backEnd.pc.c_vertexes,
|
||||
R_SumOfUsedImages(),
|
||||
pc_save.c_totalIndexes / 3,
|
||||
pc_save.c_vertexes,
|
||||
backEnd.pc.c_characterlights
|
||||
);
|
||||
}
|
||||
if ( !r_speeds->integer ) {
|
||||
// clear the counters even if we aren't printing
|
||||
Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
|
||||
|
||||
@@ -236,17 +236,17 @@ void RE_DrawBackground_TexSubImage(int cols, int rows, int bgr, byte* data) {
|
||||
format = GL_RGB;
|
||||
}
|
||||
|
||||
GL_Bind(tr.scratchImage[0]);
|
||||
GL_Bind(tr.scratchImage);
|
||||
|
||||
if (cols == tr.scratchImage[0]->width && rows == tr.scratchImage[0]->height && format == tr.scratchImage[0]->internalFormat)
|
||||
if (cols == tr.scratchImage->width && rows == tr.scratchImage->height && format == tr.scratchImage->internalFormat)
|
||||
{
|
||||
qglTexSubImage2D(3553, 0, 0, 0, cols, rows, format, 5121, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr.scratchImage[0]->uploadWidth = cols;
|
||||
tr.scratchImage[0]->uploadHeight = rows;
|
||||
tr.scratchImage[0]->internalFormat = format;
|
||||
tr.scratchImage->uploadWidth = cols;
|
||||
tr.scratchImage->uploadHeight = rows;
|
||||
tr.scratchImage->internalFormat = format;
|
||||
qglTexImage2D(GL_TEXTURE_2D, 0, 3, cols, rows, 0, format, 5121, data);
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9729.0);
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9729.0);
|
||||
|
||||
@@ -197,32 +197,13 @@ RB_AddDlightFlares
|
||||
void RB_AddDlightFlares( void ) {
|
||||
dlight_t *l;
|
||||
int i, j, k;
|
||||
fog_t *fog;
|
||||
|
||||
if ( !r_flares->integer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
l = backEnd.refdef.dlights;
|
||||
fog = tr.world->fogs;
|
||||
for (i=0 ; i<backEnd.refdef.num_dlights ; i++, l++) {
|
||||
|
||||
// find which fog volume the light is in
|
||||
for ( j = 1 ; j < tr.world->numfogs ; j++ ) {
|
||||
fog = &tr.world->fogs[j];
|
||||
for ( k = 0 ; k < 3 ; k++ ) {
|
||||
if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( k == 3 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( j == tr.world->numfogs ) {
|
||||
j = 0;
|
||||
}
|
||||
|
||||
RB_AddFlare( (void *)l, j, l->origin, l->color, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
+257
-80
@@ -49,6 +49,8 @@ int gl_filter_max = GL_LINEAR;
|
||||
#define FILE_HASH_SIZE 1024
|
||||
static image_t* hashTable[FILE_HASH_SIZE];
|
||||
|
||||
extern qboolean scr_initialized;
|
||||
|
||||
/*
|
||||
** R_GammaCorrect
|
||||
*/
|
||||
@@ -297,6 +299,10 @@ lighting range
|
||||
*/
|
||||
void R_LightScaleTexture (unsigned *in, int inwidth, int inheight, qboolean only_gamma )
|
||||
{
|
||||
if (!tr.needsLightScale) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( only_gamma )
|
||||
{
|
||||
if ( !glConfig.deviceSupportsGamma )
|
||||
@@ -546,36 +552,62 @@ static void Upload32(
|
||||
// select proper internal format
|
||||
if ( samples == 3 )
|
||||
{
|
||||
if ( glConfig.textureCompression == TC_S3TC )
|
||||
if (!force32bit)
|
||||
{
|
||||
internalFormat = GL_RGB4_S3TC;
|
||||
}
|
||||
else if ( r_texturebits->integer == 16 )
|
||||
{
|
||||
internalFormat = GL_RGB5;
|
||||
}
|
||||
else if ( r_texturebits->integer == 32 )
|
||||
{
|
||||
internalFormat = GL_RGB8;
|
||||
if (r_texturebits->integer == 16)
|
||||
{
|
||||
internalFormat = GL_RGB5;
|
||||
}
|
||||
else if (r_texturebits->integer == 32)
|
||||
{
|
||||
internalFormat = GL_RGB8;
|
||||
}
|
||||
else if (r_colorbits->integer == 16)
|
||||
{
|
||||
internalFormat = GL_RGBA4;
|
||||
}
|
||||
else if (r_colorbits->integer == 32)
|
||||
{
|
||||
internalFormat = GL_RGBA8;
|
||||
}
|
||||
else
|
||||
{
|
||||
internalFormat = 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
internalFormat = 3;
|
||||
internalFormat = GL_RGB8;
|
||||
}
|
||||
}
|
||||
else if ( samples == 4 )
|
||||
{
|
||||
if ( r_texturebits->integer == 16 )
|
||||
if (!force32bit)
|
||||
{
|
||||
internalFormat = GL_RGBA4;
|
||||
}
|
||||
else if ( r_texturebits->integer == 32 )
|
||||
{
|
||||
internalFormat = GL_RGBA8;
|
||||
if (r_texturebits->integer == 16)
|
||||
{
|
||||
internalFormat = GL_RGBA4;
|
||||
}
|
||||
else if (r_texturebits->integer == 32)
|
||||
{
|
||||
internalFormat = GL_RGBA8;
|
||||
}
|
||||
else if (r_colorbits->integer == 16)
|
||||
{
|
||||
internalFormat = GL_RGBA4;
|
||||
}
|
||||
else if (r_colorbits->integer == 32)
|
||||
{
|
||||
internalFormat = GL_RGBA8;
|
||||
}
|
||||
else
|
||||
{
|
||||
internalFormat = 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
internalFormat = 4;
|
||||
internalFormat = GL_RGB8;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -664,6 +696,161 @@ done:
|
||||
ri.Hunk_FreeTempMemory( resampledBuffer );
|
||||
}
|
||||
|
||||
static void UploadCompressed(
|
||||
byte* data,
|
||||
int width,
|
||||
int height,
|
||||
int numMipmaps,
|
||||
int iMipmapsAvailable,
|
||||
qboolean picmip,
|
||||
int glCompressMode,
|
||||
int* format,
|
||||
int* pUploadWidth,
|
||||
int* pUploadHeight,
|
||||
int* pBytesUsed
|
||||
) {
|
||||
byte* offset;
|
||||
int i;
|
||||
int iStartImage;
|
||||
int size;
|
||||
int blockSize;
|
||||
int scaled_width, scaled_height;
|
||||
|
||||
offset = data;
|
||||
iStartImage = 0;
|
||||
if (picmip) {
|
||||
iStartImage = r_picmip->integer;
|
||||
}
|
||||
|
||||
if (iStartImage > 0 && iStartImage >= iMipmapsAvailable) {
|
||||
iStartImage = iMipmapsAvailable - 1;
|
||||
}
|
||||
|
||||
scaled_width = width;
|
||||
scaled_height = height;
|
||||
if (iStartImage)
|
||||
{
|
||||
scaled_width = width >> iStartImage;
|
||||
scaled_height = height >> iStartImage;
|
||||
}
|
||||
while (scaled_width > glConfig.maxTextureSize || scaled_height > glConfig.maxTextureSize)
|
||||
{
|
||||
scaled_width >>= 1;
|
||||
scaled_height >>= 1;
|
||||
++iStartImage;
|
||||
}
|
||||
if (iStartImage > 0 && iStartImage >= iMipmapsAvailable)
|
||||
{
|
||||
iStartImage = iMipmapsAvailable - 1;
|
||||
scaled_width = width >> (iMipmapsAvailable - 1);
|
||||
scaled_height = height >> (iMipmapsAvailable - 1);
|
||||
}
|
||||
|
||||
*pUploadWidth = scaled_width;
|
||||
*pUploadHeight = scaled_height;
|
||||
*format = glCompressMode;
|
||||
blockSize = 16;
|
||||
|
||||
if (glCompressMode == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || glCompressMode == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
|
||||
blockSize = 8;
|
||||
}
|
||||
|
||||
scaled_width = width;
|
||||
scaled_height = height;
|
||||
|
||||
for (i = iStartImage; i; i--) {
|
||||
int w, h;
|
||||
|
||||
w = scaled_width + 3;
|
||||
if (scaled_width + 3 < 0) {
|
||||
w = scaled_width + 6;
|
||||
}
|
||||
w >>= 2;
|
||||
|
||||
if (w > 1) {
|
||||
h = scaled_height + 3;
|
||||
if (scaled_height + 3 < 0) {
|
||||
h = scaled_height + 6;
|
||||
}
|
||||
|
||||
h >>= 2;
|
||||
if (h > 1) {
|
||||
offset += blockSize * w * h;
|
||||
}
|
||||
}
|
||||
|
||||
scaled_width >>= 1;
|
||||
scaled_height >>= 1;
|
||||
if (!scaled_width) scaled_width = 1;
|
||||
if (!scaled_height) scaled_height = 1;
|
||||
}
|
||||
|
||||
*pBytesUsed = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (scaled_width)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
if (!scaled_height) scaled_height = 1;
|
||||
w = scaled_width + 3;
|
||||
if (scaled_width + 3 < 0) w = scaled_width + 6;
|
||||
w >>= 2;
|
||||
|
||||
h = scaled_height + 3;
|
||||
if (scaled_height + 3 < 0) h = scaled_height + 6;
|
||||
h >>= 2;
|
||||
|
||||
size = blockSize * w * h;
|
||||
if (w > 1 && h > 1) *pBytesUsed += size;
|
||||
|
||||
qglCompressedTexImage2DARB(3553, i - iStartImage, glCompressMode, scaled_width, scaled_height, 0, size, data);
|
||||
GL_CheckErrors();
|
||||
|
||||
if (i < iMipmapsAvailable)
|
||||
{
|
||||
w = scaled_width + 3;
|
||||
if (scaled_width + 3 < 0) {
|
||||
w = scaled_width + 6;
|
||||
}
|
||||
|
||||
if (w >> 2 > 1)
|
||||
{
|
||||
h = scaled_height + 3;
|
||||
if (scaled_height + 3 < 0) {
|
||||
h = scaled_height + 6;
|
||||
}
|
||||
|
||||
if (h >> 2 > 1)
|
||||
data += size;
|
||||
}
|
||||
}
|
||||
scaled_width >>= 1;
|
||||
scaled_height >>= 1;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (!scaled_height) {
|
||||
break;
|
||||
}
|
||||
|
||||
scaled_width = 1;
|
||||
}
|
||||
|
||||
if (numMipmaps > 1) {
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
||||
}
|
||||
else
|
||||
{
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
||||
GL_CheckErrors();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
@@ -727,6 +914,7 @@ image_t* R_CreateImage(
|
||||
image->allowPicmip = allowPicmip;
|
||||
image->dynamicallyUpdated = dynamicallyUpdated;
|
||||
image->force32bit = force32bit;
|
||||
image->UseCount = 0;
|
||||
|
||||
strcpy (image->imgName, name);
|
||||
|
||||
@@ -748,6 +936,22 @@ image_t* R_CreateImage(
|
||||
|
||||
GL_Bind(image);
|
||||
|
||||
if (glCompressMode) {
|
||||
UploadCompressed(
|
||||
pic,
|
||||
image->width,
|
||||
image->height,
|
||||
image->numMipmaps,
|
||||
iMipmapsAvailable,
|
||||
allowPicmip,
|
||||
glCompressMode,
|
||||
&image->internalFormat,
|
||||
&image->uploadWidth,
|
||||
&image->uploadHeight,
|
||||
&image->bytesUsed
|
||||
);
|
||||
}
|
||||
|
||||
Upload32(
|
||||
(unsigned*)pic,
|
||||
image->width,
|
||||
@@ -777,6 +981,7 @@ image_t* R_CreateImage(
|
||||
hash = generateHashValue(name);
|
||||
image->next = hashTable[hash];
|
||||
hashTable[hash] = image;
|
||||
image->r_sequence = r_sequencenumber;
|
||||
|
||||
return image;
|
||||
}
|
||||
@@ -1881,6 +2086,7 @@ Loads any of the supported image types into a cannonical
|
||||
*/
|
||||
static void R_LoadImage(const char* name, byte** pic, int* width, int* height, qboolean* hasAlpha, int* glCompressMode, int* numMipmaps, int* piMipmapsAvailable) {
|
||||
int len;
|
||||
char tempName[MAX_STRING_TOKENS + 1];
|
||||
|
||||
*hasAlpha = qfalse;
|
||||
*glCompressMode = 0;
|
||||
@@ -1918,6 +2124,12 @@ static void R_LoadImage(const char* name, byte** pic, int* width, int* height, q
|
||||
LoadJPG(name, pic, width, height);
|
||||
*piMipmapsAvailable = 1;
|
||||
}
|
||||
|
||||
if (scr_initialized)
|
||||
{
|
||||
sprintf(tempName, "n%s", name);
|
||||
UI_LoadResource(tempName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2057,61 +2269,6 @@ static void R_CreateDlightImage( void ) {
|
||||
tr.dlightImage = R_CreateImage("*dlight", (byte *)data, DLIGHT_SIZE, DLIGHT_SIZE, 0, 1, qfalse, qfalse, qfalse, qfalse, GL_CLAMP, GL_CLAMP);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
R_InitFogTable
|
||||
=================
|
||||
*/
|
||||
void R_InitFogTable( void ) {
|
||||
int i;
|
||||
float d;
|
||||
float exp;
|
||||
|
||||
exp = 0.5;
|
||||
|
||||
for ( i = 0 ; i < FOG_TABLE_SIZE ; i++ ) {
|
||||
d = pow ( (float)i/(FOG_TABLE_SIZE-1), exp );
|
||||
|
||||
tr.fogTable[i] = d;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_FogFactor
|
||||
|
||||
Returns a 0.0 to 1.0 fog density value
|
||||
This is called for each texel of the fog texture on startup
|
||||
and for each vertex of transparent shaders in fog dynamically
|
||||
================
|
||||
*/
|
||||
float R_FogFactor( float s, float t ) {
|
||||
float d;
|
||||
|
||||
s -= 1.0/512;
|
||||
if ( s < 0 ) {
|
||||
return 0;
|
||||
}
|
||||
if ( t < 1.0/32 ) {
|
||||
return 0;
|
||||
}
|
||||
if ( t < 31.0/32 ) {
|
||||
s *= (t - 1.0f/32.0f) / (30.0f/32.0f);
|
||||
}
|
||||
|
||||
// we need to leave a lot of clamp range
|
||||
s *= 8;
|
||||
|
||||
if ( s > 1.0 ) {
|
||||
s = 1.0;
|
||||
}
|
||||
|
||||
d = tr.fogTable[ (int)(s * (FOG_TABLE_SIZE-1)) ];
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_CreateDefaultImage
|
||||
@@ -2146,6 +2303,7 @@ static void R_CreateDefaultImage( void ) {
|
||||
data[x][DEFAULT_SIZE-1][3] = 255;
|
||||
}
|
||||
tr.defaultImage = R_CreateImage("*default", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, 1, 1, qfalse, qfalse, qfalse, qfalse, GL_REPEAT, GL_REPEAT);
|
||||
tr.defaultImage->r_sequence = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2155,6 +2313,8 @@ R_CreateBuiltinImages
|
||||
*/
|
||||
void R_CreateBuiltinImages( void ) {
|
||||
int x,y;
|
||||
int i;
|
||||
byte lightmap_buffer[128 * 128 * 4];
|
||||
byte data[DEFAULT_SIZE][DEFAULT_SIZE][4];
|
||||
|
||||
R_CreateDefaultImage();
|
||||
@@ -2162,6 +2322,7 @@ void R_CreateBuiltinImages( void ) {
|
||||
// we use a solid white image instead of disabling texturing
|
||||
Com_Memset( data, 255, sizeof( data ) );
|
||||
tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, 0, 1, qfalse, qfalse, qfalse, qfalse, GL_REPEAT, GL_REPEAT);
|
||||
tr.whiteImage->r_sequence = -1;
|
||||
|
||||
// with overbright bits active, we need an image which is some fraction of full color,
|
||||
// for default lightmaps, etc
|
||||
@@ -2174,14 +2335,18 @@ void R_CreateBuiltinImages( void ) {
|
||||
}
|
||||
}
|
||||
|
||||
tr.identityLightImage = R_CreateImage("*identityLight", (byte *)data, 8, 8, 0, 1, qfalse, qfalse, qfalse, qfalse, GL_REPEAT, GL_REPEAT);
|
||||
|
||||
|
||||
for(x=0;x<32;x++) {
|
||||
// scratchimage is usually used for cinematic drawing
|
||||
tr.scratchImage[x] = R_CreateImage("*scratch", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, 0, 1, qtrue, qfalse, qfalse, qfalse, GL_REPEAT, GL_REPEAT);
|
||||
Com_Memset(lightmap_buffer, 0xFFFFFFFF, sizeof(lightmap_buffer));
|
||||
for (i = 0; i < 15; i++) {
|
||||
tr.dlightImages[i] = R_CreateImage("*lightmapD%i", lightmap_buffer, LIGHTMAP_SIZE, LIGHTMAP_SIZE, 0, 1, qfalse, qfalse, qfalse, 0, GL_CLAMP, GL_CLAMP);
|
||||
tr.dlightImages[i]->r_sequence = -1;
|
||||
}
|
||||
|
||||
tr.identityLightImage = R_CreateImage("*identityLight", (byte *)data, 8, 8, 0, 1, qfalse, qfalse, qfalse, qfalse, GL_REPEAT, GL_REPEAT);
|
||||
tr.identityLightImage->r_sequence = -1;
|
||||
|
||||
tr.scratchImage = R_CreateImage("*scratch", (byte*)data, DEFAULT_SIZE, DEFAULT_SIZE, 0, 1, qtrue, qfalse, qfalse, qfalse, GL_CLAMP, GL_CLAMP);
|
||||
tr.scratchImage->r_sequence = -1;
|
||||
|
||||
R_CreateDlightImage();
|
||||
}
|
||||
|
||||
@@ -2228,7 +2393,6 @@ void R_SetColorMappings( void ) {
|
||||
tr.identityLight = 1.0f / (1 << tr.overbrightBits);
|
||||
tr.identityLightByte = 255 * tr.identityLight;
|
||||
|
||||
|
||||
if ( r_intensity->value <= 1 ) {
|
||||
ri.Cvar_Set( "r_intensity", "1" );
|
||||
}
|
||||
@@ -2240,6 +2404,15 @@ void R_SetColorMappings( void ) {
|
||||
}
|
||||
|
||||
g = r_gamma->value;
|
||||
if (!glConfig.deviceSupportsGamma && g != 1.0) {
|
||||
tr.needsLightScale = qtrue;
|
||||
}
|
||||
else if (r_intensity->value != 1.0) {
|
||||
tr.needsLightScale = qtrue;
|
||||
}
|
||||
else {
|
||||
tr.needsLightScale = qfalse;
|
||||
}
|
||||
|
||||
shift = tr.overbrightBits;
|
||||
|
||||
@@ -2280,6 +2453,10 @@ R_InitImages
|
||||
*/
|
||||
void R_InitImages( void ) {
|
||||
Com_Memset(hashTable, 0, sizeof(hashTable));
|
||||
// clear images
|
||||
Com_Memset(tr.images, 0, sizeof(tr.images));
|
||||
tr.numImages = 0;
|
||||
|
||||
// build brightness translation tables
|
||||
R_SetColorMappings();
|
||||
|
||||
|
||||
+43
-2
@@ -841,6 +841,13 @@ void GL_SetDefaultState( void )
|
||||
qglEnable( GL_SCISSOR_TEST );
|
||||
qglDisable( GL_CULL_FACE );
|
||||
qglDisable( GL_BLEND );
|
||||
|
||||
qglFogi(GL_FOG_MODE, GL_LINEAR);
|
||||
|
||||
glState.fFogColor[0] = 0.0;
|
||||
glState.fFogColor[1] = 0.0;
|
||||
glState.fFogColor[2] = 0.0;
|
||||
glState.fFogColor[3] = 1.0;
|
||||
}
|
||||
|
||||
const char* RE_GetGraphicsInfo() {
|
||||
@@ -1009,7 +1016,7 @@ void R_Register( void )
|
||||
#else
|
||||
r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||
#endif
|
||||
r_ignoreFastPath = ri.Cvar_Get("r_ignoreFastPath", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
||||
r_ignoreFastPath = ri.Cvar_Get("r_ignoreFastPath", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||
r_subdivisions = ri.Cvar_Get("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH);
|
||||
|
||||
//
|
||||
@@ -1200,6 +1207,21 @@ void R_Register( void )
|
||||
ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
|
||||
}
|
||||
|
||||
void R_InitExtensions() {
|
||||
// FIXME: qglTextureEnvCombineExists
|
||||
glState.cntTexEnvExt = 0;
|
||||
glState.cntnvblendmode = 0;
|
||||
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, 34165.0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, 8448.0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, 0x47057700);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, 0x44400000);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, 5890.0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, 0x44400000);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, 0x47057700);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, 770.0);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_Init
|
||||
@@ -1224,6 +1246,11 @@ void R_Init( void ) {
|
||||
}
|
||||
Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) );
|
||||
|
||||
tr.worldEntity.e.shaderRGBA[0] = -1;
|
||||
tr.worldEntity.e.shaderRGBA[1] = 0;
|
||||
tr.worldEntity.e.shaderRGBA[2] = -1;
|
||||
tr.worldEntity.e.shaderRGBA[3] = -1;
|
||||
|
||||
//
|
||||
// init function tables
|
||||
//
|
||||
@@ -1251,10 +1278,16 @@ void R_Init( void ) {
|
||||
}
|
||||
}
|
||||
|
||||
R_InitFogTable();
|
||||
tr.rendererhandle = ri.Milliseconds();
|
||||
|
||||
if (!tr.rendererhandle) {
|
||||
tr.rendererhandle = -1;
|
||||
}
|
||||
|
||||
R_NoiseInit();
|
||||
|
||||
R_Sky_Init();
|
||||
|
||||
R_Register();
|
||||
|
||||
max_polys = r_maxpolys->integer;
|
||||
@@ -1292,12 +1325,19 @@ void R_Init( void ) {
|
||||
|
||||
InitOpenGL();
|
||||
|
||||
R_InitExtensions();
|
||||
|
||||
R_InitImages();
|
||||
|
||||
R_StartupShaders();
|
||||
|
||||
R_ModelInit();
|
||||
|
||||
R_LevelMarksInit();
|
||||
|
||||
tr.pFontDebugStrings = R_LoadFont("verdana-14");
|
||||
g_bInfoworldtris = qfalse;
|
||||
|
||||
err = qglGetError();
|
||||
if ( err != GL_NO_ERROR )
|
||||
ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err);
|
||||
@@ -1422,6 +1462,7 @@ refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {
|
||||
re.UnregisterServerModel = RE_UnregisterServerModel;
|
||||
re.RegisterShader = RE_RegisterShader;
|
||||
re.RegisterShaderNoMip = RE_RegisterShaderNoMip;
|
||||
re.RefreshShaderNoMip = RE_RefreshShaderNoMip;
|
||||
re.LoadWorld = RE_LoadWorldMap;
|
||||
re.PrintBSPFileSizes = RE_PrintBSPFileSizes;
|
||||
re.MapVersion = RE_MapVersion;
|
||||
|
||||
+349
-239
@@ -29,6 +29,25 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#define DLIGHT_MINIMUM_RADIUS 16
|
||||
// never calculate a range less than this to prevent huge light numbers
|
||||
|
||||
typedef struct {
|
||||
dlight_t *dl;
|
||||
float power;
|
||||
vec3_t origin;
|
||||
} incidentLight_t;
|
||||
|
||||
typedef struct {
|
||||
int dlightMap;
|
||||
int allocated[128];
|
||||
byte lightmap_buffer[65536];
|
||||
byte* srcBase;
|
||||
byte* dstBase;
|
||||
incidentLight_t lights[32];
|
||||
int numLights;
|
||||
} dlightInfo_t;
|
||||
|
||||
dlightInfo_t dli;
|
||||
|
||||
void R_SetupEntityLightingGrid(trRefEntity_t* ent);
|
||||
|
||||
/*
|
||||
===============
|
||||
@@ -109,12 +128,17 @@ static byte* R_GetLightGridPalettedColor(int iColor)
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void R_GetLightingGridValue(vec3_t vPos, vec3_t vLight)
|
||||
void R_GetLightingGridValue(const vec3_t vPos, vec3_t vLight)
|
||||
{
|
||||
if (!tr.world || !tr.world->lightGridData || !tr.world->lightGridOffsets) {
|
||||
vLight[0] = vLight[1] = vLight[2] = tr.identityLightByte;
|
||||
}
|
||||
|
||||
vLight[0] = vLight[1] = vLight[2] = tr.identityLightByte;
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void R_GetLightingGridValueFast(vec3_t vPos, vec3_t vLight)
|
||||
void R_GetLightingGridValueFast(const vec3_t vPos, vec3_t vLight)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
@@ -129,6 +153,261 @@ void R_GetLightingForSmoke(vec3_t vLight, vec3_t vOrigin)
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
static int RB_GetEntityGridLighting()
|
||||
{
|
||||
int iColor;
|
||||
int i;
|
||||
dlight_t* dl;
|
||||
float power;
|
||||
vec3_t vLight;
|
||||
vec3_t dir;
|
||||
float d;
|
||||
float* lightOrigin;
|
||||
|
||||
lightOrigin = backEnd.currentSphere->traceOrigin;
|
||||
if (!(backEnd.refdef.rdflags & RDF_NOWORLDMODEL) && tr.world->lightGridData) {
|
||||
R_GetLightingGridValue(backEnd.currentSphere->traceOrigin, vLight);
|
||||
} else {
|
||||
vLight[0] = vLight[1] = vLight[2] = tr.identityLight * 150.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < backEnd.refdef.num_dlights; i++) {
|
||||
dl = &backEnd.refdef.dlights[i];
|
||||
VectorSubtract(dl->origin, lightOrigin, dir);
|
||||
d = VectorLengthSquared(dir);
|
||||
|
||||
power = dl->radius * dl->radius;
|
||||
if (power >= d) {
|
||||
d = dl->radius * 7500.0 / d;
|
||||
VectorMA(vLight, d, dl->color, vLight);
|
||||
}
|
||||
}
|
||||
|
||||
if (tr.overbrightShift)
|
||||
{
|
||||
vLight[0] = tr.overbrightMult * vLight[0];
|
||||
vLight[1] = tr.overbrightMult * vLight[1];
|
||||
vLight[2] = tr.overbrightMult * vLight[2];
|
||||
}
|
||||
|
||||
// normalize
|
||||
if (vLight[0] < 255.0 || vLight[1] < 255.0 || vLight[2] < 255.0) {
|
||||
float scale = 255.0 / fmin(vLight[0], fmin(vLight[1], vLight[2]));
|
||||
VectorScale(vLight, scale, vLight);
|
||||
}
|
||||
|
||||
// clamp ambient
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (vLight[i] > tr.identityLightByte) {
|
||||
vLight[i] = tr.identityLightByte;
|
||||
}
|
||||
}
|
||||
|
||||
// save out the byte packet version
|
||||
((byte*)&iColor)[0] = myftol(vLight[0]);
|
||||
((byte*)&iColor)[1] = myftol(vLight[1]);
|
||||
((byte*)&iColor)[2] = myftol(vLight[2]);
|
||||
((byte*)&iColor)[3] = 0xff;
|
||||
|
||||
return iColor;
|
||||
|
||||
#if 0
|
||||
int i;
|
||||
dlight_t* dl;
|
||||
float power;
|
||||
vec3_t dir;
|
||||
float d;
|
||||
vec3_t lightDir;
|
||||
vec3_t lightOrigin;
|
||||
int ambientlightInt = 0;
|
||||
trRefEntity_t *ent = backEnd.currentEntity;
|
||||
trRefdef_t *refdef = &backEnd.refdef;
|
||||
|
||||
//
|
||||
// trace a sample point down to find ambient light
|
||||
//
|
||||
if (ent->e.renderfx & RF_LIGHTING_ORIGIN) {
|
||||
// seperate lightOrigins are needed so an object that is
|
||||
// sinking into the ground can still be lit, and so
|
||||
// multi-part models can be lit identically
|
||||
VectorCopy(ent->e.lightingOrigin, lightOrigin);
|
||||
}
|
||||
else {
|
||||
VectorCopy(ent->e.origin, lightOrigin);
|
||||
}
|
||||
|
||||
// if NOWORLDMODEL, only use dynamic lights (menu system, etc)
|
||||
if (!(refdef->rdflags & RDF_NOWORLDMODEL)
|
||||
&& tr.world->lightGridData) {
|
||||
R_SetupEntityLightingGrid(ent);
|
||||
}
|
||||
else {
|
||||
ent->ambientLight[0] = ent->ambientLight[1] =
|
||||
ent->ambientLight[2] = tr.identityLight * 150;
|
||||
ent->directedLight[0] = ent->directedLight[1] =
|
||||
ent->directedLight[2] = tr.identityLight * 150;
|
||||
VectorCopy(tr.sunDirection, ent->lightDir);
|
||||
}
|
||||
|
||||
// bonus items and view weapons have a fixed minimum add
|
||||
if (1 /* ent->e.renderfx & RF_MINLIGHT */) {
|
||||
// give everything a minimum light add
|
||||
ent->ambientLight[0] += tr.identityLight * 32;
|
||||
ent->ambientLight[1] += tr.identityLight * 32;
|
||||
ent->ambientLight[2] += tr.identityLight * 32;
|
||||
}
|
||||
|
||||
//
|
||||
// modify the light by dynamic lights
|
||||
//
|
||||
d = VectorLength(ent->directedLight);
|
||||
VectorScale(ent->lightDir, d, lightDir);
|
||||
|
||||
for (i = 0; i < refdef->num_dlights; i++) {
|
||||
dl = &refdef->dlights[i];
|
||||
VectorSubtract(dl->origin, lightOrigin, dir);
|
||||
d = VectorNormalize(dir);
|
||||
|
||||
power = DLIGHT_AT_RADIUS * (dl->radius * dl->radius);
|
||||
if (d < DLIGHT_MINIMUM_RADIUS) {
|
||||
d = DLIGHT_MINIMUM_RADIUS;
|
||||
}
|
||||
d = power / (d * d);
|
||||
|
||||
VectorMA(ent->directedLight, d, dl->color, ent->directedLight);
|
||||
VectorMA(lightDir, d, dir, lightDir);
|
||||
}
|
||||
|
||||
// clamp ambient
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (ent->ambientLight[i] > tr.identityLightByte) {
|
||||
ent->ambientLight[i] = tr.identityLightByte;
|
||||
}
|
||||
}
|
||||
|
||||
// save out the byte packet version
|
||||
((byte*)&ambientlightInt)[0] = myftol(ent->ambientLight[0]);
|
||||
((byte*)&ambientlightInt)[1] = myftol(ent->ambientLight[1]);
|
||||
((byte*)&ambientlightInt)[2] = myftol(ent->ambientLight[2]);
|
||||
((byte*)&ambientlightInt)[3] = 0xff;
|
||||
|
||||
// transform the direction to local space
|
||||
VectorNormalize(lightDir);
|
||||
ent->lightDir[0] = DotProduct(lightDir, ent->e.axis[0]);
|
||||
ent->lightDir[1] = DotProduct(lightDir, ent->e.axis[1]);
|
||||
ent->lightDir[2] = DotProduct(lightDir, ent->e.axis[2]);
|
||||
|
||||
return ambientlightInt;
|
||||
#endif
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void RB_SetupEntityGridLighting()
|
||||
{
|
||||
trRefEntity_t* ent;
|
||||
int iColor;
|
||||
|
||||
if (backEnd.currentEntity->bLightGridCalculated) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ent = backEnd.currentEntity; ent->e.parentEntity != ENTITYNUM_NONE; ent = &backEnd.refdef.entities[ent->e.parentEntity])
|
||||
{
|
||||
trRefEntity_t* newref = &backEnd.refdef.entities[ent->e.parentEntity];
|
||||
if (newref == ent) {
|
||||
assert(!"backEnd.refdef.entities[ent->e.parentEntity] refers to itself\n");
|
||||
iColor = newref->iGridLighting;
|
||||
break;
|
||||
}
|
||||
|
||||
if (newref->bLightGridCalculated) {
|
||||
iColor = newref->iGridLighting;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ent->e.parentEntity == ENTITYNUM_NONE) {
|
||||
iColor = RB_GetEntityGridLighting();
|
||||
}
|
||||
|
||||
ent = backEnd.currentEntity;
|
||||
for (;;)
|
||||
{
|
||||
ent->bLightGridCalculated = 1;
|
||||
ent->iGridLighting = iColor;
|
||||
if (ent->e.parentEntity == ENTITYNUM_NONE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ent == &backEnd.refdef.entities[ent->e.parentEntity]) {
|
||||
assert(!"backEnd.refdef.entities[ent->e.parentEntity] refers to itself\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ent = &backEnd.refdef.entities[ent->e.parentEntity];
|
||||
}
|
||||
}
|
||||
|
||||
void RB_SetupStaticModelGridLighting(trRefdef_t* refdef, cStaticModelUnpacked_t* ent, const vec3_t lightOrigin)
|
||||
{
|
||||
int iColor;
|
||||
int i;
|
||||
dlight_t* dl;
|
||||
float power;
|
||||
vec3_t vLight;
|
||||
vec3_t dir;
|
||||
float d;
|
||||
|
||||
if (ent->bLightGridCalculated) {
|
||||
return;
|
||||
}
|
||||
ent->bLightGridCalculated = qtrue;
|
||||
|
||||
if (!(refdef->rdflags & RDF_NOWORLDMODEL) && tr.world->lightGridData) {
|
||||
R_GetLightingGridValue(backEnd.currentSphere->traceOrigin, vLight);
|
||||
}
|
||||
else {
|
||||
vLight[0] = vLight[1] = vLight[2] = tr.identityLight * 150.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < refdef->num_dlights; i++) {
|
||||
dl = &refdef->dlights[i];
|
||||
VectorSubtract(dl->origin, lightOrigin, dir);
|
||||
d = VectorLengthSquared(dir);
|
||||
|
||||
power = dl->radius * dl->radius;
|
||||
if (power >= d) {
|
||||
d = dl->radius * 7500.0 / d;
|
||||
VectorMA(vLight, d, dl->color, vLight);
|
||||
}
|
||||
}
|
||||
|
||||
if (tr.overbrightShift)
|
||||
{
|
||||
vLight[0] = tr.overbrightMult * vLight[0];
|
||||
vLight[1] = tr.overbrightMult * vLight[1];
|
||||
vLight[2] = tr.overbrightMult * vLight[2];
|
||||
}
|
||||
|
||||
// normalize
|
||||
if (vLight[0] < 255.0 || vLight[1] < 255.0 || vLight[2] < 255.0) {
|
||||
float scale = 255.0 / fmin(vLight[0], fmin(vLight[1], vLight[2]));
|
||||
VectorScale(vLight, scale, vLight);
|
||||
}
|
||||
|
||||
// clamp ambient
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (vLight[i] > tr.identityLightByte) {
|
||||
vLight[i] = tr.identityLightByte;
|
||||
}
|
||||
}
|
||||
|
||||
// save out the byte packet version
|
||||
((byte*)&ent->iGridLighting)[0] = myftol(vLight[0]);
|
||||
((byte*)&ent->iGridLighting)[1] = myftol(vLight[1]);
|
||||
((byte*)&ent->iGridLighting)[2] = myftol(vLight[2]);
|
||||
((byte*)&ent->iGridLighting)[3] = 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
@@ -141,131 +420,6 @@ LIGHT SAMPLING
|
||||
extern cvar_t *r_ambientScale;
|
||||
extern cvar_t *r_directedScale;
|
||||
|
||||
/*
|
||||
=================
|
||||
R_SetupEntityLightingGrid
|
||||
|
||||
=================
|
||||
*/
|
||||
static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) {
|
||||
vec3_t lightOrigin;
|
||||
int pos[3];
|
||||
int i, j;
|
||||
byte *gridData;
|
||||
float frac[3];
|
||||
int gridStep[3];
|
||||
vec3_t direction;
|
||||
float totalFactor;
|
||||
|
||||
if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
|
||||
// seperate lightOrigins are needed so an object that is
|
||||
// sinking into the ground can still be lit, and so
|
||||
// multi-part models can be lit identically
|
||||
VectorCopy( ent->e.lightingOrigin, lightOrigin );
|
||||
} else {
|
||||
VectorCopy( ent->e.origin, lightOrigin );
|
||||
}
|
||||
|
||||
VectorSubtract( lightOrigin, tr.world->lightGridOrigin, lightOrigin );
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
float v;
|
||||
|
||||
v = lightOrigin[i]*tr.world->lightGridInverseSize[i];
|
||||
pos[i] = floor( v );
|
||||
frac[i] = v - pos[i];
|
||||
if ( pos[i] < 0 ) {
|
||||
pos[i] = 0;
|
||||
} else if ( pos[i] >= tr.world->lightGridBounds[i] - 1 ) {
|
||||
pos[i] = tr.world->lightGridBounds[i] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
VectorClear( ent->ambientLight );
|
||||
VectorClear( ent->directedLight );
|
||||
VectorClear( direction );
|
||||
|
||||
assert( tr.world->lightGridData ); // bk010103 - NULL with -nolight maps
|
||||
|
||||
// trilerp the light value
|
||||
gridStep[0] = 8;
|
||||
gridStep[1] = 8 * tr.world->lightGridBounds[0];
|
||||
gridStep[2] = 8 * tr.world->lightGridBounds[0] * tr.world->lightGridBounds[1];
|
||||
gridData = tr.world->lightGridData + pos[0] * gridStep[0]
|
||||
+ pos[1] * gridStep[1] + pos[2] * gridStep[2];
|
||||
|
||||
totalFactor = 0;
|
||||
for ( i = 0 ; i < 8 ; i++ ) {
|
||||
float factor;
|
||||
byte *data;
|
||||
int lat, lng;
|
||||
vec3_t normal;
|
||||
#if idppc
|
||||
float d0, d1, d2, d3, d4, d5;
|
||||
#endif
|
||||
factor = 1.0;
|
||||
data = gridData;
|
||||
for ( j = 0 ; j < 3 ; j++ ) {
|
||||
if ( i & (1<<j) ) {
|
||||
factor *= frac[j];
|
||||
data += gridStep[j];
|
||||
} else {
|
||||
factor *= (1.0f - frac[j]);
|
||||
}
|
||||
}
|
||||
|
||||
if ( !(data[0]+data[1]+data[2]) ) {
|
||||
continue; // ignore samples in walls
|
||||
}
|
||||
totalFactor += factor;
|
||||
#if idppc
|
||||
d0 = data[0]; d1 = data[1]; d2 = data[2];
|
||||
d3 = data[3]; d4 = data[4]; d5 = data[5];
|
||||
|
||||
ent->ambientLight[0] += factor * d0;
|
||||
ent->ambientLight[1] += factor * d1;
|
||||
ent->ambientLight[2] += factor * d2;
|
||||
|
||||
ent->directedLight[0] += factor * d3;
|
||||
ent->directedLight[1] += factor * d4;
|
||||
ent->directedLight[2] += factor * d5;
|
||||
#else
|
||||
ent->ambientLight[0] += factor * data[0];
|
||||
ent->ambientLight[1] += factor * data[1];
|
||||
ent->ambientLight[2] += factor * data[2];
|
||||
|
||||
ent->directedLight[0] += factor * data[3];
|
||||
ent->directedLight[1] += factor * data[4];
|
||||
ent->directedLight[2] += factor * data[5];
|
||||
#endif
|
||||
lat = data[7];
|
||||
lng = data[6];
|
||||
lat *= (FUNCTABLE_SIZE/256);
|
||||
lng *= (FUNCTABLE_SIZE/256);
|
||||
|
||||
// decode X as cos( lat ) * sin( long )
|
||||
// decode Y as sin( lat ) * sin( long )
|
||||
// decode Z as cos( long )
|
||||
|
||||
normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
|
||||
normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
|
||||
normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
|
||||
|
||||
VectorMA( direction, factor, normal, direction );
|
||||
}
|
||||
|
||||
if ( totalFactor > 0 && totalFactor < 0.99 ) {
|
||||
totalFactor = 1.0f / totalFactor;
|
||||
VectorScale( ent->ambientLight, totalFactor, ent->ambientLight );
|
||||
VectorScale( ent->directedLight, totalFactor, ent->directedLight );
|
||||
}
|
||||
|
||||
VectorScale( ent->ambientLight, r_ambientScale->value, ent->ambientLight );
|
||||
VectorScale( ent->directedLight, r_directedScale->value, ent->directedLight );
|
||||
|
||||
VectorNormalize2( direction, ent->lightDir );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
LogLight
|
||||
@@ -295,121 +449,77 @@ static void LogLight( trRefEntity_t *ent ) {
|
||||
ri.Printf( PRINT_ALL, "amb:%i dir:%i\n", max1, max2 );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_SetupEntityLighting
|
||||
|
||||
Calculates all the lighting values that will be used
|
||||
by the Calc_* functions
|
||||
=================
|
||||
*/
|
||||
void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
|
||||
int i;
|
||||
dlight_t *dl;
|
||||
float power;
|
||||
vec3_t dir;
|
||||
float d;
|
||||
vec3_t lightDir;
|
||||
vec3_t lightOrigin;
|
||||
|
||||
// lighting calculations
|
||||
if ( ent->lightingCalculated ) {
|
||||
return;
|
||||
}
|
||||
ent->lightingCalculated = qtrue;
|
||||
|
||||
//
|
||||
// trace a sample point down to find ambient light
|
||||
//
|
||||
if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
|
||||
// seperate lightOrigins are needed so an object that is
|
||||
// sinking into the ground can still be lit, and so
|
||||
// multi-part models can be lit identically
|
||||
VectorCopy( ent->e.lightingOrigin, lightOrigin );
|
||||
} else {
|
||||
VectorCopy( ent->e.origin, lightOrigin );
|
||||
}
|
||||
|
||||
// if NOWORLDMODEL, only use dynamic lights (menu system, etc)
|
||||
if ( !(refdef->rdflags & RDF_NOWORLDMODEL )
|
||||
&& tr.world->lightGridData ) {
|
||||
R_SetupEntityLightingGrid( ent );
|
||||
} else {
|
||||
ent->ambientLight[0] = ent->ambientLight[1] =
|
||||
ent->ambientLight[2] = tr.identityLight * 150;
|
||||
ent->directedLight[0] = ent->directedLight[1] =
|
||||
ent->directedLight[2] = tr.identityLight * 150;
|
||||
VectorCopy( tr.sunDirection, ent->lightDir );
|
||||
}
|
||||
|
||||
// bonus items and view weapons have a fixed minimum add
|
||||
if ( 1 /* ent->e.renderfx & RF_MINLIGHT */ ) {
|
||||
// give everything a minimum light add
|
||||
ent->ambientLight[0] += tr.identityLight * 32;
|
||||
ent->ambientLight[1] += tr.identityLight * 32;
|
||||
ent->ambientLight[2] += tr.identityLight * 32;
|
||||
}
|
||||
|
||||
//
|
||||
// modify the light by dynamic lights
|
||||
//
|
||||
d = VectorLength( ent->directedLight );
|
||||
VectorScale( ent->lightDir, d, lightDir );
|
||||
|
||||
for ( i = 0 ; i < refdef->num_dlights ; i++ ) {
|
||||
dl = &refdef->dlights[i];
|
||||
VectorSubtract( dl->origin, lightOrigin, dir );
|
||||
d = VectorNormalize( dir );
|
||||
|
||||
power = DLIGHT_AT_RADIUS * ( dl->radius * dl->radius );
|
||||
if ( d < DLIGHT_MINIMUM_RADIUS ) {
|
||||
d = DLIGHT_MINIMUM_RADIUS;
|
||||
}
|
||||
d = power / ( d * d );
|
||||
|
||||
VectorMA( ent->directedLight, d, dl->color, ent->directedLight );
|
||||
VectorMA( lightDir, d, dir, lightDir );
|
||||
}
|
||||
|
||||
// clamp ambient
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
if ( ent->ambientLight[i] > tr.identityLightByte ) {
|
||||
ent->ambientLight[i] = tr.identityLightByte;
|
||||
}
|
||||
}
|
||||
|
||||
// save out the byte packet version
|
||||
((byte *)&ent->ambientLightInt)[0] = myftol( ent->ambientLight[0] );
|
||||
((byte *)&ent->ambientLightInt)[1] = myftol( ent->ambientLight[1] );
|
||||
((byte *)&ent->ambientLightInt)[2] = myftol( ent->ambientLight[2] );
|
||||
((byte *)&ent->ambientLightInt)[3] = 0xff;
|
||||
|
||||
// transform the direction to local space
|
||||
VectorNormalize( lightDir );
|
||||
ent->lightDir[0] = DotProduct( lightDir, ent->e.axis[0] );
|
||||
ent->lightDir[1] = DotProduct( lightDir, ent->e.axis[1] );
|
||||
ent->lightDir[2] = DotProduct( lightDir, ent->e.axis[2] );
|
||||
void R_ClearRealDlights() {
|
||||
memset(dli.allocated, 0, sizeof(dli.allocated));
|
||||
dli.dlightMap = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightForPoint
|
||||
=================
|
||||
*/
|
||||
int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir )
|
||||
{
|
||||
trRefEntity_t ent;
|
||||
|
||||
// bk010103 - this segfaults with -nolight maps
|
||||
if ( tr.world->lightGridData == NULL )
|
||||
return qfalse;
|
||||
void R_UploadDlights() {
|
||||
int i, h;
|
||||
|
||||
Com_Memset(&ent, 0, sizeof(ent));
|
||||
VectorCopy( point, ent.e.origin );
|
||||
R_SetupEntityLightingGrid( &ent );
|
||||
VectorCopy(ent.ambientLight, ambientLight);
|
||||
VectorCopy(ent.directedLight, directedLight);
|
||||
VectorCopy(ent.lightDir, lightDir);
|
||||
if (!tr.pc.c_dlightSurfaces) {
|
||||
return;
|
||||
}
|
||||
|
||||
h = 0;
|
||||
for (i = 0; i < 128; ++i)
|
||||
{
|
||||
if (h < dli.allocated[i]) {
|
||||
h = dli.allocated[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (h)
|
||||
{
|
||||
if (h > 128) {
|
||||
ri.Error(ERR_DROP, "R_UploadDlights: bad allocated height");
|
||||
}
|
||||
|
||||
GL_Bind(tr.dlightImages[dli.dlightMap]);
|
||||
qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, h, GL_RGBA, GL_UNSIGNED_BYTE, dli.lightmap_buffer);
|
||||
|
||||
tr.pc.c_dlightMaps++;
|
||||
memset(dli.allocated, 0, sizeof(dli.allocated));
|
||||
}
|
||||
}
|
||||
|
||||
qboolean R_AllocLMBlock(int w, int h, int* x, int* y) {
|
||||
int i, j;
|
||||
int best, best2;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
best = 128;
|
||||
for (i = 0; i < 128 - w; i++)
|
||||
{
|
||||
best2 = 0;
|
||||
|
||||
for (j = 0; j < w && dli.allocated[i] < best; j++)
|
||||
{
|
||||
if (best2 < dli.allocated[i]) {
|
||||
best2 = dli.allocated[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (j == w)
|
||||
{
|
||||
*x = i;
|
||||
*y = best2;
|
||||
best = best2;
|
||||
}
|
||||
}
|
||||
|
||||
if (h + best <= 128) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (dli.dlightMap == 14) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
R_UploadDlights();
|
||||
dli.dlightMap++;
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
+102
-50
@@ -129,7 +129,7 @@ typedef struct {
|
||||
vec3_t traceOrigin;
|
||||
float radius;
|
||||
struct mnode_s* leaves[8];
|
||||
void(*TessFunction) ();
|
||||
void(*TessFunction) (unsigned char* dstColors);
|
||||
union {
|
||||
unsigned char level[4];
|
||||
int value;
|
||||
@@ -170,17 +170,19 @@ typedef struct {
|
||||
float axisLength; // compensate for non-normalized axis
|
||||
|
||||
qboolean needDlights; // true for bmodels that touch a dlight
|
||||
qboolean lightingCalculated;
|
||||
vec3_t lightDir; // normalized direction towards light
|
||||
vec3_t ambientLight; // color normalized to 0-255
|
||||
int ambientLightInt; // 32 bit rgba packed
|
||||
vec3_t directedLight;
|
||||
|
||||
qboolean bLightGridCalculated;
|
||||
int iGridLighting;
|
||||
float lodpercentage[2];
|
||||
qboolean sphereCalculated;
|
||||
int lightingSphere;
|
||||
|
||||
//
|
||||
// old lighting variables
|
||||
//
|
||||
vec3_t lightDir; // normalized direction towards light
|
||||
vec3_t ambientLight; // color normalized to 0-255
|
||||
int ambientLightInt; // 32 bit rgba packed
|
||||
vec3_t directedLight;
|
||||
} trRefEntity_t;
|
||||
|
||||
typedef struct refSprite_s {
|
||||
@@ -441,7 +443,7 @@ typedef struct {
|
||||
qboolean active;
|
||||
|
||||
textureBundle_t bundle[NUM_TEXTURE_BUNDLES];
|
||||
int multitextureEnv;
|
||||
int multitextureEnv; // 0, GL_MODULATE, GL_ADD (FIXME: put in stage)
|
||||
|
||||
waveForm_t rgbWave;
|
||||
colorGen_t rgbGen;
|
||||
@@ -540,8 +542,6 @@ typedef struct shader_s {
|
||||
|
||||
float portalRange; // distance to fog out at
|
||||
|
||||
int multitextureEnv; // 0, GL_MODULATE, GL_ADD (FIXME: put in stage)
|
||||
|
||||
cullType_t cullType; // CT_FRONT_SIDED, CT_BACK_SIDED, or CT_TWO_SIDED
|
||||
qboolean polygonOffset; // set for decals and other items that must be offset
|
||||
qboolean noMipMaps; // for console fonts, 2D elements, etc.
|
||||
@@ -615,21 +615,29 @@ typedef struct {
|
||||
int num_entities;
|
||||
trRefEntity_t *entities;
|
||||
|
||||
int num_sprites;
|
||||
refSprite_t *sprites;
|
||||
|
||||
int num_dlights;
|
||||
struct dlight_s *dlights;
|
||||
|
||||
int numTerMarks;
|
||||
struct srfMarkFragment_s *terMarks;
|
||||
|
||||
int numPolys;
|
||||
struct srfPoly_s *polys;
|
||||
|
||||
int numDrawSurfs;
|
||||
struct drawSurf_s *drawSurfs;
|
||||
|
||||
int numSpriteSurfs;
|
||||
struct drawSurf_s* spriteSurfs;
|
||||
int numStaticModels;
|
||||
struct cStaticModelUnpacked_s* staticModels;
|
||||
int numStaticModelData;
|
||||
unsigned char* staticModelData;
|
||||
int numSpriteSurfs;
|
||||
struct drawSurf_s *spriteSurfs;
|
||||
|
||||
int numStaticModels;
|
||||
struct cStaticModelUnpacked_s *staticModels;
|
||||
|
||||
int numStaticModelData;
|
||||
unsigned char *staticModelData;
|
||||
qboolean sky_portal;
|
||||
float sky_alpha;
|
||||
vec3_t sky_origin;
|
||||
@@ -685,7 +693,7 @@ typedef struct {
|
||||
int viewportX, viewportY, viewportWidth, viewportHeight;
|
||||
float fovX, fovY;
|
||||
float projectionMatrix[16];
|
||||
cplane_t frustum[4];
|
||||
cplane_t frustum[5];
|
||||
vec3_t visBounds[2];
|
||||
float zFar;
|
||||
depthfog_t fog;
|
||||
@@ -718,9 +726,9 @@ typedef struct drawSurf_s {
|
||||
typedef struct srfPoly_s {
|
||||
surfaceType_t surfaceType;
|
||||
qhandle_t hShader;
|
||||
int fogIndex;
|
||||
int numVerts;
|
||||
polyVert_t *verts;
|
||||
int renderfx;
|
||||
} srfPoly_t;
|
||||
|
||||
typedef struct srfMarkFragment_s {
|
||||
@@ -829,7 +837,10 @@ typedef struct {
|
||||
|
||||
typedef union varnodeUnpacked_u {
|
||||
float fVariance;
|
||||
byte flags;
|
||||
struct {
|
||||
byte flags;
|
||||
unsigned char unused[3];
|
||||
} s;
|
||||
} varnodeUnpacked_t;
|
||||
|
||||
typedef unsigned short terraInt;
|
||||
@@ -893,7 +904,7 @@ typedef struct cTerraPatchUnpacked_s {
|
||||
unsigned int uiDistRecalc;
|
||||
float s;
|
||||
float t;
|
||||
float texCoord[2][2][2];
|
||||
vec2_t texCoord[2][2];
|
||||
float x0;
|
||||
float y0;
|
||||
float z0;
|
||||
@@ -1023,6 +1034,7 @@ typedef struct {
|
||||
int numShaders;
|
||||
dshader_t *shaders;
|
||||
|
||||
int numBmodels;
|
||||
bmodel_t *bmodels;
|
||||
|
||||
int numplanes;
|
||||
@@ -1038,13 +1050,11 @@ typedef struct {
|
||||
int nummarksurfaces;
|
||||
msurface_t **marksurfaces;
|
||||
|
||||
int numfogs;
|
||||
fog_t *fogs;
|
||||
|
||||
vec3_t lightGridOrigin;
|
||||
vec3_t lightGridMins;
|
||||
vec3_t lightGridSize;
|
||||
vec3_t lightGridInverseSize;
|
||||
vec3_t lightGridOOSize;
|
||||
int lightGridBounds[3];
|
||||
unsigned short* lightGridOffsets;
|
||||
byte *lightGridData;
|
||||
byte lightGridPalette[768];
|
||||
|
||||
@@ -1069,9 +1079,7 @@ typedef struct {
|
||||
const byte *vis; // may be passed in by CM_LoadMap to save space
|
||||
|
||||
byte *novis; // clusterBytes of 0xff
|
||||
|
||||
char *entityString;
|
||||
char *entityParsePoint;
|
||||
byte *lighting;
|
||||
} world_t;
|
||||
|
||||
//======================================================================
|
||||
@@ -1157,6 +1165,8 @@ typedef struct {
|
||||
int c_leafs;
|
||||
int c_dlightSurfaces;
|
||||
int c_dlightSurfacesCulled;
|
||||
int c_dlightMaps;
|
||||
int c_dlightTexels;
|
||||
} frontEndCounters_t;
|
||||
|
||||
#define FOG_TABLE_SIZE 256
|
||||
@@ -1172,12 +1182,16 @@ typedef struct {
|
||||
qboolean finishCalled;
|
||||
int texEnv[2];
|
||||
int faceCulling;
|
||||
unsigned long glStateBits;
|
||||
int cntTexEnvExt;
|
||||
int cntnvblendmode;
|
||||
long unsigned int glStateBits;
|
||||
long unsigned int externalSetState;
|
||||
vec4_t fFogColor;
|
||||
} glstate_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int c_surfaces, c_shaders, c_vertexes, c_indexes, c_totalIndexes;
|
||||
int c_surfaces, c_shaders, c_vertexes, c_indexes, c_totalIndexes, c_characterlights;
|
||||
float c_overDraw;
|
||||
|
||||
int c_dlightVertexes;
|
||||
@@ -1243,12 +1257,13 @@ typedef struct {
|
||||
const byte *externalVisData; // from RE_SetWorldVisData, shared with CM_Load
|
||||
|
||||
image_t *defaultImage;
|
||||
image_t *scratchImage[32];
|
||||
image_t *scratchImage;
|
||||
image_t *fogImage;
|
||||
image_t *dlightImage; // inverse-quare highlight for projective adding
|
||||
image_t *flareImage;
|
||||
image_t *whiteImage; // full of 0xff
|
||||
image_t *identityLightImage; // full of tr.identityLightByte
|
||||
image_t *dlightImages[15];
|
||||
|
||||
shader_t *defaultShader;
|
||||
shader_t *shadowShader;
|
||||
@@ -1278,6 +1293,9 @@ typedef struct {
|
||||
|
||||
orientationr_t ori; // for current entity
|
||||
|
||||
portalsky_t portalsky;
|
||||
qboolean skyRendered;
|
||||
qboolean portalRendered;
|
||||
trRefdef_t refdef;
|
||||
|
||||
int viewCluster;
|
||||
@@ -1313,7 +1331,6 @@ typedef struct {
|
||||
float triangleTable[FUNCTABLE_SIZE];
|
||||
float sawToothTable[FUNCTABLE_SIZE];
|
||||
float inverseSawToothTable[FUNCTABLE_SIZE];
|
||||
float fogTable[FOG_TABLE_SIZE];
|
||||
|
||||
spherel_t sSunLight;
|
||||
spherel_t sLights[1532];
|
||||
@@ -1557,6 +1574,8 @@ void R_DebugCircle(const vec3_t org, float radius, float r, float g, float b, fl
|
||||
void R_DebugLine(const vec3_t start, const vec3_t end, float r, float g, float b, float alpha);
|
||||
void R_RenderView( viewParms_t *parms );
|
||||
|
||||
qboolean SurfIsOffscreen(const srfSurfaceFace_t* surface, shader_t* shader, int entityNum);
|
||||
|
||||
void R_AddMD3Surfaces( trRefEntity_t *e );
|
||||
void R_AddNullModelSurfaces( trRefEntity_t *e );
|
||||
void R_AddBeamSurfaces( trRefEntity_t *e );
|
||||
@@ -1573,18 +1592,24 @@ void R_AddDrawSurf(surfaceType_t* surface, shader_t* shader, int dlightMap);
|
||||
#define CULL_IN 0 // completely unclipped
|
||||
#define CULL_CLIP 1 // clipped by one or more planes
|
||||
#define CULL_OUT 2 // completely outside the clipping planes
|
||||
void R_LocalNormalToWorld (vec3_t local, vec3_t world);
|
||||
void R_LocalPointToWorld (vec3_t local, vec3_t world);
|
||||
void R_LocalNormalToWorld (const vec3_t local, vec3_t world);
|
||||
void R_LocalPointToWorld (const vec3_t local, vec3_t world);
|
||||
int R_CullLocalBoxOffset(const vec3_t offset, vec3_t bounds[2]);
|
||||
int R_CullLocalBox (vec3_t bounds[2]);
|
||||
int R_CullPointAndRadius( vec3_t origin, float radius );
|
||||
int R_CullLocalPointAndRadius( vec3_t origin, float radius );
|
||||
int R_DistanceCullLocalPointAndRadius(float fDist, const vec3_t pt, float radius);
|
||||
int R_DistanceCullPointAndRadius(float fDist, const vec3_t pt, float radius);
|
||||
|
||||
void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *ori );
|
||||
void R_RotateForStaticModel(cStaticModelUnpacked_t* SM, const viewParms_t* viewParms, orientationr_t* ori );
|
||||
void R_RotateForViewer(void);
|
||||
void R_SetupFrustum(void);
|
||||
|
||||
/*
|
||||
** GL wrapper/helper functions
|
||||
*/
|
||||
void GL_SetFogColor(const vec4_t fColor);
|
||||
void GL_Bind( image_t *image );
|
||||
void GL_SetDefaultState (void);
|
||||
void GL_SelectTexture( int unit );
|
||||
@@ -1616,11 +1641,19 @@ void GL_Cull( int cullType );
|
||||
#define GLS_DSTBLEND_BITS 0x000000f0
|
||||
|
||||
#define GLS_DEPTHMASK_TRUE 0x00000100
|
||||
#define GLS_POLYMODE_LINE 0x00000200
|
||||
#define GLS_DEPTHTEST_DISABLE 0x00000400
|
||||
#define GLS_DEPTHFUNC_EQUAL 0x00000800
|
||||
|
||||
#define GLS_POLYMODE_LINE 0x00001000
|
||||
#define GLS_CLAMP_EDGE 0x00001000
|
||||
#define GLS_MULTITEXTURE 0x00002000
|
||||
#define GLS_MULTITEXTURE_ENV 0x00004000
|
||||
#define GLS_FOG 0x00008000
|
||||
|
||||
#define GLS_DEPTHFUNC_EQUAL 0x00020000
|
||||
#define GLS_FOG_ENABLED 0x00010000
|
||||
#define GLS_FOG_BLACK 0x00020000
|
||||
#define GLS_FOG_WHITE 0x00040000
|
||||
#define GLS_FOG_COLOR (GLS_FOG_BLACK | GLS_FOG_WHITE)
|
||||
|
||||
#define GLS_ATEST_GT_0 0x10000000
|
||||
#define GLS_ATEST_LT_80 0x20000000
|
||||
@@ -1684,8 +1717,6 @@ void R_SkinList_f( void );
|
||||
const void *RB_TakeScreenshotCmd( const void *data );
|
||||
void R_ScreenShot_f( void );
|
||||
|
||||
void R_InitFogTable( void );
|
||||
float R_FogFactor( float s, float t );
|
||||
void R_InitImages( void );
|
||||
void R_DeleteTextures( void );
|
||||
int R_SumOfUsedImages( void );
|
||||
@@ -1697,6 +1728,7 @@ skin_t *R_GetSkinByHandle( qhandle_t hSkin );
|
||||
//
|
||||
qhandle_t RE_RegisterShader( const char *name );
|
||||
qhandle_t RE_RegisterShaderNoMip( const char *name );
|
||||
qhandle_t RE_RefreshShaderNoMip(const char* name);
|
||||
qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage);
|
||||
|
||||
shader_t* R_FindShader(const char* name, int lightmapIndex, qboolean mipRawImage, qboolean picmip, qboolean wrapx, qboolean wrapy);
|
||||
@@ -1789,8 +1821,8 @@ void RB_CheckOverflow( int verts, int indexes );
|
||||
|
||||
void RB_StageIteratorGeneric( void );
|
||||
void RB_StageIteratorSky( void );
|
||||
void RB_StageIteratorVertexLitTexture( void );
|
||||
void RB_StageIteratorLightmappedMultitexture( void );
|
||||
void RB_StageIteratorVertexLitTextureUnfogged( void );
|
||||
void RB_StageIteratorLightmappedMultitextureUnfogged( void );
|
||||
|
||||
void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, byte *color );
|
||||
void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, byte *color, float s1, float t1, float s2, float t2 );
|
||||
@@ -1806,8 +1838,15 @@ WORLD MAP
|
||||
============================================================
|
||||
*/
|
||||
|
||||
extern terraTri_t* g_pTris;
|
||||
extern terrainVert_t* g_pVert;
|
||||
|
||||
void R_AddBrushModelSurfaces( trRefEntity_t *e );
|
||||
void R_GetInlineModelBounds(int iIndex, vec3_t vMins, vec3_t vMaxs);
|
||||
int R_SphereInLeafs(vec_t* p, float r, mnode_t** nodes, int nMaxNodes);
|
||||
mnode_t* R_PointInLeaf(const vec3_t p);
|
||||
int R_DlightTerrain(cTerraPatchUnpacked_t* surf, int dlightBits);
|
||||
int R_CheckDlightTerrain(cTerraPatchUnpacked_t* surf, int dlightBits);
|
||||
void R_AddWorldSurfaces( void );
|
||||
qboolean R_inPVS( const vec3_t p1, const vec3_t p2 );
|
||||
|
||||
@@ -1835,19 +1874,22 @@ LIGHTS
|
||||
*/
|
||||
|
||||
void R_DlightBmodel( bmodel_t *bmodel );
|
||||
void R_GetLightingGridValue(const vec3_t vPos, vec3_t vLight);
|
||||
void R_GetLightingForDecal(vec3_t vLight, vec3_t vFacing, vec3_t vOrigin);
|
||||
void R_GetLightingForSmoke(vec3_t vLight, vec3_t vOrigin);
|
||||
void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent );
|
||||
void RB_SetupEntityGridLighting();
|
||||
void RB_SetupStaticModelGridLighting(trRefdef_t* refdef, cStaticModelUnpacked_t* ent, const vec3_t lightOrigin);
|
||||
void R_TransformDlights( int count, dlight_t *dl, orientationr_t *ori );
|
||||
int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir );
|
||||
void RB_Light_Real(const color4ub_t colors);
|
||||
void RB_Light_Real(unsigned char* colors);
|
||||
void RB_Sphere_BuildDLights();
|
||||
void RB_Sphere_SetupEntity();
|
||||
void RB_Grid_SetupEntity();
|
||||
void RB_Grid_SetupStaticModel();
|
||||
void RB_Light_Fullbright(const color4ub_t colors);
|
||||
void RB_Light_Fullbright(unsigned char* colors);
|
||||
void R_Sphere_InitLights();
|
||||
int R_GatherLightSources(const vec3_t vPos, vec3_t* pvLightPos, vec3_t* pvLightIntensity, int iMaxLights);
|
||||
void R_UploadDlights();
|
||||
|
||||
|
||||
/*
|
||||
@@ -1859,6 +1901,7 @@ SHADOWS
|
||||
*/
|
||||
|
||||
void RB_ShadowTessEnd( void );
|
||||
void RB_ComputeShadowVolume();
|
||||
void RB_ShadowFinish( void );
|
||||
void RB_ProjectionShadowDeform( void );
|
||||
|
||||
@@ -1923,7 +1966,7 @@ void RE_AddRefEntityToScene( const refEntity_t *ent, int parentEntityNumber);
|
||||
void RE_AddRefSpriteToScene(const refEntity_t* ent);
|
||||
void RE_AddTerrainMarkToScene(int iTerrainIndex, qhandle_t hShader, int numVerts, const polyVert_t* verts, int renderfx);
|
||||
refEntity_t* RE_GetRenderEntity(int entityNumber);
|
||||
qboolean RE_AddPolyToScene(qhandle_t hShader, int numVerts, const polyVert_t* verts, int numPolys);
|
||||
qboolean RE_AddPolyToScene(qhandle_t hShader, int numVerts, polyVert_t* verts, int renderfx);
|
||||
void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b, int type );
|
||||
void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b );
|
||||
void RE_RenderScene( const refdef_t *fd );
|
||||
@@ -1963,6 +2006,7 @@ void R_LevelMarksLoad(const char* szBSPName);
|
||||
void R_LevelMarksInit();
|
||||
void R_LevelMarksFree();
|
||||
void R_UpdateLevelMarksSystem();
|
||||
void R_AddPermanentMarkFragmentSurfaces(void** pFirstMarkFragment, int iNumMarkFragment);
|
||||
|
||||
/*
|
||||
=============================================================
|
||||
@@ -1994,6 +2038,7 @@ SUN FLARE
|
||||
=============================================================
|
||||
*/
|
||||
void R_InitLensFlare();
|
||||
void R_DrawLensFlares();
|
||||
|
||||
/*
|
||||
=============================================================
|
||||
@@ -2013,6 +2058,7 @@ TERRAIN
|
||||
|
||||
=============================================================
|
||||
*/
|
||||
void R_MarkTerrainPatch(cTerraPatchUnpacked_t* pPatch);
|
||||
void R_AddTerrainSurfaces();
|
||||
void R_InitTerrain();
|
||||
void R_TerrainPrepareFrame();
|
||||
@@ -2047,9 +2093,11 @@ void R_PrintInfoStaticModels();
|
||||
void R_AddSkelSurfaces(trRefEntity_t* ent);
|
||||
void R_AddStaticModelSurfaces(void);
|
||||
float R_CalcLod(const vec3_t origin, float radius);
|
||||
void R_PrintInfoWorldtris(void);
|
||||
|
||||
extern int g_nStaticSurfaces;
|
||||
extern qboolean g_bInfostaticmodels;
|
||||
extern qboolean g_bInfoworldtris;
|
||||
|
||||
/*
|
||||
=============================================================
|
||||
@@ -2090,15 +2138,11 @@ void R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t
|
||||
void RB_DeformTessGeometry( void );
|
||||
|
||||
void RB_CalcEnvironmentTexCoords( float *dstTexCoords );
|
||||
void RB_CalcFogTexCoords( float *dstTexCoords );
|
||||
void RB_CalcScrollTexCoords( const float scroll[2], float *dstTexCoords );
|
||||
void RB_CalcRotateTexCoords( float rotSpeed, float *dstTexCoords );
|
||||
void RB_CalcScaleTexCoords( const float scale[2], float *dstTexCoords );
|
||||
void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *dstTexCoords );
|
||||
void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *dstTexCoords );
|
||||
void RB_CalcModulateColorsByFog( unsigned char *dstColors );
|
||||
void RB_CalcModulateAlphasByFog( unsigned char *dstColors );
|
||||
void RB_CalcModulateRGBAsByFog( unsigned char *dstColors );
|
||||
void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors );
|
||||
void RB_CalcWaveColor(const waveForm_t* wf, unsigned char* dstColors, unsigned char* constantColor);
|
||||
void RB_CalcAlphaFromEntity( unsigned char *dstColors );
|
||||
@@ -2141,6 +2185,14 @@ RENDERER BACK END COMMAND QUEUE
|
||||
|
||||
#define MAX_RENDER_COMMANDS 0x40000
|
||||
|
||||
typedef struct suninfo_s {
|
||||
vec3_t color;
|
||||
vec3_t direction;
|
||||
vec3_t flaredirection;
|
||||
char szFlareName[64];
|
||||
qboolean exists;
|
||||
} suninfo_t;
|
||||
|
||||
typedef struct {
|
||||
byte cmds[MAX_RENDER_COMMANDS];
|
||||
int used;
|
||||
@@ -2214,8 +2266,8 @@ typedef enum {
|
||||
// these are sort of arbitrary limits.
|
||||
// the limits apply to the sum of all scenes in a frame --
|
||||
// the main view, all the 3D icons, etc
|
||||
#define MAX_POLYS 600
|
||||
#define MAX_POLYVERTS 3000
|
||||
#define MAX_POLYS 4096
|
||||
#define MAX_POLYVERTS 16384
|
||||
#define MAX_TERMARKS 1024
|
||||
|
||||
// all of the information needed by the back end must be
|
||||
|
||||
+130
-59
@@ -49,7 +49,7 @@ R_CullLocalBox
|
||||
Returns CULL_IN, CULL_CLIP, or CULL_OUT
|
||||
=================
|
||||
*/
|
||||
int R_CullLocalBox (vec3_t bounds[2]) {
|
||||
int R_CullLocalBoxOffset(const vec3_t offset, vec3_t bounds[2]) {
|
||||
int i, j;
|
||||
vec3_t transformed[8];
|
||||
float dists[8];
|
||||
@@ -69,6 +69,7 @@ int R_CullLocalBox (vec3_t bounds[2]) {
|
||||
v[2] = bounds[(i>>2)&1][2];
|
||||
|
||||
VectorCopy( tr.ori.origin, transformed[i] );
|
||||
VectorAdd(transformed[i], offset, transformed[i]);
|
||||
VectorMA( transformed[i], v[0], tr.ori.axis[0], transformed[i] );
|
||||
VectorMA( transformed[i], v[1], tr.ori.axis[1], transformed[i] );
|
||||
VectorMA( transformed[i], v[2], tr.ori.axis[2], transformed[i] );
|
||||
@@ -76,7 +77,7 @@ int R_CullLocalBox (vec3_t bounds[2]) {
|
||||
|
||||
// check against frustum planes
|
||||
anyBack = 0;
|
||||
for (i = 0 ; i < 4 ; i++) {
|
||||
for (i = 0 ; i < tr.viewParms.fog.extrafrustums + 4 ; i++) {
|
||||
frust = &tr.viewParms.frustum[i];
|
||||
|
||||
front = back = 0;
|
||||
@@ -105,6 +106,10 @@ int R_CullLocalBox (vec3_t bounds[2]) {
|
||||
return CULL_CLIP; // partially clipped
|
||||
}
|
||||
|
||||
int R_CullLocalBox(vec3_t bounds[2]) {
|
||||
return R_CullLocalBoxOffset(vec3_origin, bounds);
|
||||
}
|
||||
|
||||
/*
|
||||
** R_CullLocalPointAndRadius
|
||||
*/
|
||||
@@ -155,6 +160,35 @@ int R_CullPointAndRadius( vec3_t pt, float radius )
|
||||
return CULL_IN; // completely inside frustum
|
||||
}
|
||||
|
||||
int R_DistanceCullLocalPointAndRadius(float fDist, const vec3_t pt, float radius) {
|
||||
vec3_t transformed;
|
||||
|
||||
R_LocalPointToWorld(pt, transformed);
|
||||
|
||||
return R_DistanceCullPointAndRadius(fDist, transformed, radius);
|
||||
}
|
||||
|
||||
int R_DistanceCullPointAndRadius(float fDist, const vec3_t pt, float radius) {
|
||||
if (!r_nocull->integer)
|
||||
{
|
||||
vec3_t vDelta;
|
||||
float fLengthSquared;
|
||||
float fTotalDistSquared;
|
||||
|
||||
VectorSubtract(pt, tr.viewParms.ori.origin, vDelta);
|
||||
fLengthSquared = VectorLengthSquared(vDelta);
|
||||
fTotalDistSquared = (fDist + radius) * (fDist + radius);
|
||||
|
||||
if ((fDist + radius) * (fDist + radius) < vDelta[2] + fLengthSquared) {
|
||||
return CULL_OUT;
|
||||
} else if ((fDist - radius) * (fDist - radius) > vDelta[2] + fLengthSquared) {
|
||||
return CULL_IN;
|
||||
}
|
||||
}
|
||||
|
||||
return CULL_CLIP;
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
@@ -162,7 +196,7 @@ R_LocalNormalToWorld
|
||||
|
||||
=================
|
||||
*/
|
||||
void R_LocalNormalToWorld (vec3_t local, vec3_t world) {
|
||||
void R_LocalNormalToWorld (const vec3_t local, vec3_t world) {
|
||||
world[0] = local[0] * tr.ori.axis[0][0] + local[1] * tr.ori.axis[1][0] + local[2] * tr.ori.axis[2][0];
|
||||
world[1] = local[0] * tr.ori.axis[0][1] + local[1] * tr.ori.axis[1][1] + local[2] * tr.ori.axis[2][1];
|
||||
world[2] = local[0] * tr.ori.axis[0][2] + local[1] * tr.ori.axis[1][2] + local[2] * tr.ori.axis[2][2];
|
||||
@@ -174,7 +208,7 @@ R_LocalPointToWorld
|
||||
|
||||
=================
|
||||
*/
|
||||
void R_LocalPointToWorld (vec3_t local, vec3_t world) {
|
||||
void R_LocalPointToWorld (const vec3_t local, vec3_t world) {
|
||||
world[0] = local[0] * tr.ori.axis[0][0] + local[1] * tr.ori.axis[1][0] + local[2] * tr.ori.axis[2][0] + tr.ori.origin[0];
|
||||
world[1] = local[0] * tr.ori.axis[0][1] + local[1] * tr.ori.axis[1][1] + local[2] * tr.ori.axis[2][1] + tr.ori.origin[1];
|
||||
world[2] = local[0] * tr.ori.axis[0][2] + local[1] * tr.ori.axis[1][2] + local[2] * tr.ori.axis[2][2] + tr.ori.origin[2];
|
||||
@@ -581,6 +615,70 @@ void R_SetupFrustum (void) {
|
||||
tr.viewParms.frustum[i].dist = DotProduct (tr.viewParms.ori.origin, tr.viewParms.frustum[i].normal);
|
||||
SetPlaneSignbits( &tr.viewParms.frustum[i] );
|
||||
}
|
||||
|
||||
if (tr.portalsky.inUse) {
|
||||
tr.viewParms.farplane_distance = 0.0;
|
||||
}
|
||||
else if (r_farplane->integer)
|
||||
{
|
||||
tr.viewParms.farplane_distance = r_farplane->value;
|
||||
|
||||
sscanf(
|
||||
r_farplane_color->string,
|
||||
"%f %f %f",
|
||||
&tr.viewParms.farplane_color[0],
|
||||
&tr.viewParms.farplane_color[1],
|
||||
&tr.viewParms.farplane_color[2]);
|
||||
|
||||
tr.viewParms.farplane_cull = !r_farplane_nocull->integer;
|
||||
}
|
||||
|
||||
if (tr.viewParms.farplane_distance)
|
||||
{
|
||||
vec3_t farPoint;
|
||||
float realPlaneLen;
|
||||
float tmp;
|
||||
vec4_t fogColor;
|
||||
|
||||
tr.viewParms.fog.len = tr.viewParms.farplane_distance;
|
||||
tr.viewParms.fog.oolen = 1.0 / tr.viewParms.farplane_distance;
|
||||
|
||||
farPoint[0] = tr.viewParms.ori.origin[0] + tr.viewParms.ori.axis[0][0] * tr.viewParms.farplane_distance;
|
||||
farPoint[1] = tr.viewParms.ori.origin[1] + tr.viewParms.ori.axis[0][1] * tr.viewParms.farplane_distance;
|
||||
farPoint[2] = tr.viewParms.ori.origin[2] + tr.viewParms.ori.axis[0][2] * tr.viewParms.farplane_distance;
|
||||
|
||||
VectorNegate(tr.viewParms.ori.axis[0], tr.viewParms.frustum[4].normal);
|
||||
tr.viewParms.frustum[4].type = PLANE_NON_AXIAL;
|
||||
tr.viewParms.frustum[4].dist = DotProduct(farPoint, tr.viewParms.frustum[4].normal);
|
||||
SetPlaneSignbits(&tr.viewParms.frustum[4]);
|
||||
|
||||
tr.viewParms.fog.enabled = r_farplane_nofog->integer == 0;
|
||||
tr.viewParms.fog.extrafrustums = tr.viewParms.farplane_cull;
|
||||
|
||||
if (!r_farplane_nofog->integer)
|
||||
{
|
||||
qglFogf(GL_FOG_END, tr.viewParms.farplane_distance);
|
||||
|
||||
fogColor[0] = tr.viewParms.farplane_color[0] * tr.identityLight;
|
||||
fogColor[1] = tr.viewParms.farplane_color[1] * tr.identityLight;
|
||||
fogColor[2] = tr.viewParms.farplane_color[2] * tr.identityLight;
|
||||
fogColor[3] = 1.0;
|
||||
|
||||
GL_SetFogColor(fogColor);
|
||||
glState.externalSetState |= GLS_FOG;
|
||||
}
|
||||
else
|
||||
{
|
||||
glState.externalSetState &= ~GLS_FOG;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tr.viewParms.fog.enabled = 0;
|
||||
tr.viewParms.fog.extrafrustums = 0;
|
||||
|
||||
glState.externalSetState &= ~GLS_FOG;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -837,27 +935,26 @@ static qboolean IsMirror( const drawSurf_t *drawSurf, int entityNum )
|
||||
**
|
||||
** Determines if a surface is completely offscreen.
|
||||
*/
|
||||
static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128] ) {
|
||||
qboolean SurfIsOffscreen(const srfSurfaceFace_t* surface, shader_t* shader, int entityNum) {
|
||||
float shortest = 100000000;
|
||||
int entityNum;
|
||||
int numTriangles;
|
||||
shader_t *shader;
|
||||
int dlighted;
|
||||
qboolean bStaticModel;
|
||||
qboolean doRange;
|
||||
orientationr_t surfOr;
|
||||
unsigned int* indices;
|
||||
vec4_t clip, eye;
|
||||
int i;
|
||||
unsigned int pointOr = 0;
|
||||
unsigned int pointAnd = (unsigned int)~0;
|
||||
|
||||
|
||||
if ( glConfig.smpActive ) { // FIXME! we can't do RB_BeginSurface/RB_EndSurface stuff with smp!
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
R_RotateForViewer();
|
||||
|
||||
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &dlighted, &bStaticModel );
|
||||
RB_BeginSurface( shader );
|
||||
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
|
||||
if (entityNum == ENTITYNUM_WORLD) {
|
||||
surfOr = tr.viewParms.world;
|
||||
} else {
|
||||
R_RotateForEntity(&tr.refdef.entities[entityNum], &tr.viewParms, &surfOr);
|
||||
}
|
||||
|
||||
assert( tess.numVertexes < 128 );
|
||||
|
||||
@@ -920,21 +1017,27 @@ static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
// mirrors can early out at this point, since we don't do a fade over distance
|
||||
// with them (although we could)
|
||||
if ( IsMirror( drawSurf, entityNum ) )
|
||||
if (shader->fDistRange > 0.0)
|
||||
{
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
if ( shortest > (tess.shader->portalRange*tess.shader->portalRange) )
|
||||
{
|
||||
return qtrue;
|
||||
if (shortest > (tess.shader->portalRange * tess.shader->portalRange))
|
||||
{
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
static qboolean DrawSurfIsOffscreen(drawSurf_t* drawSurf) {
|
||||
int entityNum;
|
||||
shader_t* shader;
|
||||
int dlighted;
|
||||
qboolean bStaticModel;
|
||||
|
||||
R_DecomposeSort(drawSurf->sort, &entityNum, &shader, &dlighted, &bStaticModel);
|
||||
return SurfIsOffscreen((srfSurfaceFace_t*)drawSurf->surface, shader, entityNum);
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
R_MirrorViewBySurface
|
||||
@@ -943,7 +1046,6 @@ Returns qtrue if another view has been rendered
|
||||
========================
|
||||
*/
|
||||
qboolean R_MirrorViewBySurface (drawSurf_t *drawSurf, int entityNum) {
|
||||
vec4_t clipDest[128];
|
||||
viewParms_t newParms;
|
||||
viewParms_t oldParms;
|
||||
orientation_t surface, camera;
|
||||
@@ -959,7 +1061,7 @@ qboolean R_MirrorViewBySurface (drawSurf_t *drawSurf, int entityNum) {
|
||||
}
|
||||
|
||||
// trivially reject portal/mirror
|
||||
if ( SurfIsOffscreen( drawSurf, clipDest ) ) {
|
||||
if (DrawSurfIsOffscreen( drawSurf ) ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
@@ -992,39 +1094,6 @@ qboolean R_MirrorViewBySurface (drawSurf_t *drawSurf, int entityNum) {
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_SpriteFogNum
|
||||
|
||||
See if a sprite is inside a fog volume
|
||||
=================
|
||||
*/
|
||||
int R_SpriteFogNum( trRefEntity_t *ent ) {
|
||||
int i, j;
|
||||
fog_t *fog;
|
||||
|
||||
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
|
||||
fog = &tr.world->fogs[i];
|
||||
for ( j = 0 ; j < 3 ; j++ ) {
|
||||
if ( ent->e.origin[j] - ent->e.radius >= fog->bounds[1][j] ) {
|
||||
break;
|
||||
}
|
||||
if ( ent->e.origin[j] + ent->e.radius <= fog->bounds[0][j] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( j == 3 ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================================================================
|
||||
|
||||
@@ -1602,6 +1671,8 @@ void R_RenderView (viewParms_t *parms) {
|
||||
|
||||
R_SetupFrustum ();
|
||||
|
||||
R_Sky_Reset();
|
||||
|
||||
R_GenerateDrawSurfs();
|
||||
|
||||
R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf );
|
||||
|
||||
@@ -158,8 +158,7 @@ void R_BoxSurfaces_r(mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **li
|
||||
//
|
||||
surf = *mark;
|
||||
// check if the surface has NOIMPACT or NOMARKS set
|
||||
if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) )
|
||||
|| ( surf->shader->contentFlags & CONTENTS_FOG ) ) {
|
||||
if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) ) ) {
|
||||
surf->viewCount = tr.viewCount;
|
||||
}
|
||||
// extra check for surfaces to avoid list overflows
|
||||
@@ -244,6 +243,38 @@ void R_AddMarkFragments(int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_POL
|
||||
(*returnedFragments)++;
|
||||
}
|
||||
|
||||
void R_AddMarkFragmentsToTerrain(
|
||||
cTerraPatchUnpacked_t* pTerPatch,
|
||||
int numPlanes,
|
||||
vec3_t* normals,
|
||||
float* dists,
|
||||
int maxPoints,
|
||||
const vec3_t pointBuffer,
|
||||
markFragment_t* fragmentBuffer,
|
||||
int* returnedPoints,
|
||||
int* returnedFragments
|
||||
)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void R_TessellateMarkFragments(
|
||||
int* pReturnedPoints,
|
||||
int* pReturnedFragments,
|
||||
int numsurfaces, surfaceType_t** surfaces,
|
||||
const vec3_t projectionDir, int numPlanes,
|
||||
vec3_t* normals,
|
||||
float* dists,
|
||||
int maxPoints,
|
||||
const vec3_t pointBuffer,
|
||||
int maxFragments,
|
||||
markFragment_t* fragmentBuffer,
|
||||
float fRadiusSquared
|
||||
)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_MarkFragments
|
||||
@@ -441,6 +472,11 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
|
||||
return returnedFragments;
|
||||
}
|
||||
|
||||
void R_BoxSurfacesForBModel_r(bmodel_t* pBmodel, const vec3_t mins, const vec3_t maxs, surfaceType_t** list, int listsize, int* listlength, const vec3_t dir)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
int R_MarkFragmentsForInlineModel(clipHandle_t bmodel, const vec3_t angles, const vec3_t origin, int numPoints,
|
||||
const vec3_t* points, const vec3_t projection, int maxPoints, vec3_t pointBuffer,
|
||||
int maxFragments, markFragment_t* fragmentBuffer, float radiusSquared)
|
||||
|
||||
@@ -24,22 +24,325 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
#include "tr_local.h"
|
||||
|
||||
typedef struct lmEditPoly_s {
|
||||
srfMarkFragment_t surf;
|
||||
shader_t* shader;
|
||||
int viewCount;
|
||||
polyVert_t verts[8];
|
||||
mnode_t* pLeafs[8];
|
||||
int iNumLeafs;
|
||||
} lmEditPoly_t;
|
||||
|
||||
typedef struct lmEditMarkDef_s {
|
||||
struct lmEditMarkDef_s* pNextMark;
|
||||
struct lmEditMarkDef_s* pPrevMark;
|
||||
shader_t* markShader;
|
||||
vec3_t vPos;
|
||||
vec3_t vProjection;
|
||||
float fRadius;
|
||||
float fHeightScale;
|
||||
float fWidthScale;
|
||||
float fRotation;
|
||||
float color[4];
|
||||
qboolean bDoLighting;
|
||||
lmEditPoly_t* pMarkEditPolys;
|
||||
int iNumEditPolys;
|
||||
vec3_t vPathCorners[4];
|
||||
} lmEditMarkDef_t;
|
||||
|
||||
typedef struct lmPoly_s {
|
||||
srfMarkFragment_t surf;
|
||||
shader_t* shader;
|
||||
int viewCount;
|
||||
} lmPoly_t;
|
||||
|
||||
typedef struct {
|
||||
qboolean bLevelMarksLoaded;
|
||||
char szDCLFilename[MAX_QPATH];
|
||||
lmPoly_t* pMarkFragments;
|
||||
qboolean bAutoApplySettings;
|
||||
lmEditPoly_t* pFreeEditPolys;
|
||||
lmEditMarkDef_t activeMarkDefs;
|
||||
lmEditMarkDef_t* pFreeMarkDefs;
|
||||
lmEditMarkDef_t* pCurrentMark;
|
||||
qboolean bPathLayingMode;
|
||||
treadMark_t treadMark;
|
||||
lmEditMarkDef_t* pTreadMarkStartDecal;
|
||||
lmEditMarkDef_t* pTreadMarkEndDecal;
|
||||
} lmGlobals_t;
|
||||
|
||||
typedef struct {
|
||||
int ident;
|
||||
int version;
|
||||
int checksum;
|
||||
int iNumDecals;
|
||||
int iNumFragments;
|
||||
} dclHeader_t;
|
||||
|
||||
typedef struct {
|
||||
char shader[MAX_RES_NAME];
|
||||
vec3_t vPos;
|
||||
vec3_t vProjection;
|
||||
float fRadius;
|
||||
float fHeightScale;
|
||||
float fWidthScale;
|
||||
float fRotation;
|
||||
float color[4];
|
||||
qboolean bDoLighting;
|
||||
} dclSavedMarkDef_t;
|
||||
|
||||
typedef struct {
|
||||
char shader[MAX_RES_NAME];
|
||||
int fogIndex;
|
||||
int iIndex;
|
||||
int iNumVerts;
|
||||
} dclSavedMarkPoly_t;
|
||||
|
||||
cvar_t* dcl_editmode;
|
||||
cvar_t* dcl_showcurrent;
|
||||
cvar_t* dcl_autogetinfo;
|
||||
cvar_t* dcl_shiftstep;
|
||||
cvar_t* dcl_shader;
|
||||
cvar_t* dcl_radius;
|
||||
cvar_t* dcl_heightscale;
|
||||
cvar_t* dcl_widthscale;
|
||||
cvar_t* dcl_rotation;
|
||||
cvar_t* dcl_r;
|
||||
cvar_t* dcl_g;
|
||||
cvar_t* dcl_b;
|
||||
cvar_t* dcl_alpha;
|
||||
cvar_t* dcl_dolighting;
|
||||
cvar_t* dcl_doworld;
|
||||
cvar_t* dcl_doterrain;
|
||||
cvar_t* dcl_dobmodels;
|
||||
cvar_t* dcl_dostring;
|
||||
cvar_t* dcl_pathmode;
|
||||
cvar_t* dcl_maxsegment;
|
||||
cvar_t* dcl_minsegment;
|
||||
cvar_t* dcl_maxoffset;
|
||||
cvar_t* dcl_texturescale;
|
||||
lmGlobals_t lm;
|
||||
vec3_t vec_upwards;
|
||||
|
||||
void DCLC_Save(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void R_LevelMarksLoad(const char* szBSPName)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void R_RemoveEditPolyFromPointerList(lmEditPoly_t* pPoly, void** pFragmentList, int* piNumFragments)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void R_FreeMarkFragments(lmEditMarkDef_t* pMark)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void R_InitMarkDef(lmEditMarkDef_t* pMark)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
lmEditMarkDef_t* R_AllocateMarkDef(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lmEditPoly_t* R_AllocateEditPoly(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qboolean R_AddEditPolyToPointerList(lmEditPoly_t* pPoly, void*** pFragmentList, int* piNumFragments)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
lmEditMarkDef_t* R_ApplyLevelDecal(const vec3_t vPos, const vec3_t vDir, qboolean bUseCurrent, qboolean bUseCurrentSettings, int iPathIndex)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DCLC_Make(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_Reapply(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_Delete(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_SelectNext(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_SelectPrev(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_SelectCh(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_SelectChNxt(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_GetInfo(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_ShiftUp(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_ShiftDown(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_ShiftLeft(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_ShiftRight(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void DCLC_RandomRoll(void)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void R_LevelMarksInit()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
memset(&lm, 0, sizeof(lm));
|
||||
|
||||
dcl_editmode = ri.Cvar_Get("dcl_editmode", "0", CVAR_LATCH);
|
||||
dcl_showcurrent = ri.Cvar_Get("dcl_showcurrent", "1", 0);
|
||||
dcl_autogetinfo = ri.Cvar_Get("dcl_autogetinfo", "1", 0);
|
||||
dcl_shiftstep = ri.Cvar_Get("dcl_shiftstep", "4", 0);
|
||||
dcl_shader = ri.Cvar_Get("dcl_shader", "blastmark", 0);
|
||||
dcl_radius = ri.Cvar_Get("dcl_radius", "16", 0);
|
||||
dcl_heightscale = ri.Cvar_Get("dcl_heightscale", "1", 0);
|
||||
dcl_widthscale = ri.Cvar_Get("dcl_widthscale", "1", 0);
|
||||
dcl_rotation = ri.Cvar_Get("dcl_rotation", "0", 0);
|
||||
dcl_r = ri.Cvar_Get("dcl_r", "1", 0);
|
||||
dcl_g = ri.Cvar_Get("dcl_g", "1", 0);
|
||||
dcl_b = ri.Cvar_Get("dcl_b", "1", 0);
|
||||
dcl_alpha = ri.Cvar_Get("dcl_alpha", "1", 0);
|
||||
dcl_dolighting = ri.Cvar_Get("dcl_dolighting", "1", 0);
|
||||
dcl_doworld = ri.Cvar_Get("dcl_doworld", "1", 0);
|
||||
dcl_doterrain = ri.Cvar_Get("dcl_doterrain", "1", 0);
|
||||
dcl_dobmodels = ri.Cvar_Get("dcl_dobmodels", "1", 0);
|
||||
dcl_dostring = ri.Cvar_Get("dcl_dostring", "apply to all", 0);
|
||||
dcl_pathmode = ri.Cvar_Get("dcl_pathmode", "0", 0);
|
||||
dcl_maxsegment = ri.Cvar_Get("dcl_maxsegment", "512", 0);
|
||||
dcl_minsegment = ri.Cvar_Get("dcl_minsegment", "24", 0);
|
||||
dcl_maxoffset = ri.Cvar_Get("dcl_maxoffset", "10", 0);
|
||||
dcl_texturescale = ri.Cvar_Get("dcl_texturescale", "32", 0);
|
||||
|
||||
if (dcl_editmode->integer)
|
||||
{
|
||||
ri.Cmd_AddCommand("dclc_make", DCLC_Make);
|
||||
ri.Cmd_AddCommand("dclc_reapply", DCLC_Reapply);
|
||||
ri.Cmd_AddCommand("dclc_delete", DCLC_Delete);
|
||||
ri.Cmd_AddCommand("dclc_selectnext", DCLC_SelectNext);
|
||||
ri.Cmd_AddCommand("dclc_selectprev", DCLC_SelectPrev);
|
||||
ri.Cmd_AddCommand("dclc_selectch", DCLC_SelectCh);
|
||||
ri.Cmd_AddCommand("dclc_selectchnxt", DCLC_SelectChNxt);
|
||||
ri.Cmd_AddCommand("dclc_getinfo", DCLC_GetInfo);
|
||||
ri.Cmd_AddCommand("dclc_shiftup", DCLC_ShiftUp);
|
||||
ri.Cmd_AddCommand("dclc_shiftdown", DCLC_ShiftDown);
|
||||
ri.Cmd_AddCommand("dclc_shiftleft", DCLC_ShiftLeft);
|
||||
ri.Cmd_AddCommand("dclc_shiftright", DCLC_ShiftRight);
|
||||
ri.Cmd_AddCommand("dclc_randomroll", DCLC_RandomRoll);
|
||||
ri.Cmd_AddCommand("dclc_save", DCLC_Save);
|
||||
|
||||
lm.activeMarkDefs.pNextMark = &lm.activeMarkDefs;
|
||||
lm.activeMarkDefs.pPrevMark = &lm.activeMarkDefs;
|
||||
}
|
||||
}
|
||||
|
||||
void R_LevelMarksFree()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
int i;
|
||||
|
||||
if (!dcl_editmode->integer) {
|
||||
return;
|
||||
}
|
||||
|
||||
ri.Cmd_RemoveCommand("dclc_make");
|
||||
ri.Cmd_RemoveCommand("dclc_reapply");
|
||||
ri.Cmd_RemoveCommand("dclc_delete");
|
||||
ri.Cmd_RemoveCommand("dclc_selectnext");
|
||||
ri.Cmd_RemoveCommand("dclc_selectprev");
|
||||
ri.Cmd_RemoveCommand("dclc_selectch");
|
||||
ri.Cmd_RemoveCommand("dclc_selectchnxt");
|
||||
ri.Cmd_RemoveCommand("dclc_getinfo");
|
||||
ri.Cmd_RemoveCommand("dclc_shiftup");
|
||||
ri.Cmd_RemoveCommand("dclc_shiftdown");
|
||||
ri.Cmd_RemoveCommand("dclc_shiftleft");
|
||||
ri.Cmd_RemoveCommand("dclc_shiftright");
|
||||
ri.Cmd_RemoveCommand("dclc_randomroll");
|
||||
ri.Cmd_RemoveCommand("dclc_save");
|
||||
|
||||
for (i = 0; i < tr.world->numBmodels; i++)
|
||||
{
|
||||
bmodel_t* pBmodel = &tr.world->bmodels[i];
|
||||
if (pBmodel->iNumMarkFragment && pBmodel->pFirstMarkFragment)
|
||||
{
|
||||
ri.Free(pBmodel->pFirstMarkFragment);
|
||||
pBmodel->pFirstMarkFragment = NULL;
|
||||
pBmodel->iNumMarkFragment = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = tr.world->numDecisionNodes; i < tr.world->numnodes; i++)
|
||||
{
|
||||
mnode_t* pLeaf = &tr.world->nodes[i];
|
||||
|
||||
if (pLeaf->iNumMarkFragment)
|
||||
{
|
||||
if (pLeaf->pFirstMarkFragment)
|
||||
{
|
||||
ri.Free(pLeaf->pFirstMarkFragment);
|
||||
pLeaf->pFirstMarkFragment = NULL;
|
||||
pLeaf->iNumMarkFragment = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_UpdateLevelMarksSystem()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void R_AddPermanentMarkFragmentSurfaces(void** pFirstMarkFragment, int iNumMarkFragment) {
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
@@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
#define LL(x) x=LittleLong(x)
|
||||
|
||||
qboolean g_bInfoworldtris;
|
||||
|
||||
/*
|
||||
** R_GetModelByHandle
|
||||
*/
|
||||
@@ -869,13 +871,6 @@ void R_AddSkelSurfaces( trRefEntity_t *ent ) {
|
||||
ent->e.hasMorph = qtrue;
|
||||
}
|
||||
|
||||
//
|
||||
// set up lighting now that we know we aren't culled
|
||||
//
|
||||
if( !personalModel || r_shadows->integer > 1 ) {
|
||||
R_SetupEntityLighting( &tr.refdef, ent );
|
||||
}
|
||||
|
||||
//
|
||||
// draw all meshes
|
||||
//
|
||||
|
||||
+81
-68
@@ -32,6 +32,12 @@ int r_firstSceneDlight;
|
||||
int r_numentities;
|
||||
int r_firstSceneEntity;
|
||||
|
||||
int r_numsprites;
|
||||
int r_firstSceneSprite;
|
||||
|
||||
int r_numtermarks;
|
||||
int r_firstSceneTerMark;
|
||||
|
||||
int r_numpolys;
|
||||
int r_firstScenePoly;
|
||||
|
||||
@@ -63,6 +69,12 @@ void R_ToggleSmpFrame( void ) {
|
||||
r_numentities = 0;
|
||||
r_firstSceneEntity = 0;
|
||||
|
||||
r_numsprites = 0;
|
||||
r_firstSceneSprite = 0;
|
||||
|
||||
r_numtermarks = 0;
|
||||
r_firstSceneTerMark = 0;
|
||||
|
||||
r_numpolys = 0;
|
||||
r_firstScenePoly = 0;
|
||||
|
||||
@@ -79,6 +91,8 @@ RE_ClearScene
|
||||
void RE_ClearScene( void ) {
|
||||
r_firstSceneDlight = r_numdlights;
|
||||
r_firstSceneEntity = r_numentities;
|
||||
r_firstSceneSprite = r_numsprites;
|
||||
r_firstSceneTerMark = r_numtermarks;
|
||||
r_firstScenePoly = r_numpolys;
|
||||
}
|
||||
|
||||
@@ -117,83 +131,28 @@ RE_AddPolyToScene
|
||||
|
||||
=====================
|
||||
*/
|
||||
qboolean RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) {
|
||||
qboolean RE_AddPolyToScene(qhandle_t hShader, int numVerts, polyVert_t* verts, int renderfx) {
|
||||
srfPoly_t *poly;
|
||||
int i, j;
|
||||
int fogIndex;
|
||||
fog_t *fog;
|
||||
vec3_t bounds[2];
|
||||
|
||||
if ( !tr.registered ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
if ( !hShader ) {
|
||||
ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n");
|
||||
if (numVerts + r_numpolyverts > max_polyverts || r_numpolys >= max_polys) {
|
||||
ri.Printf(PRINT_WARNING, "Exceeded MAX POLYS\n");
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
for ( j = 0; j < numPolys; j++ ) {
|
||||
if ( r_numpolyverts + numVerts > max_polyverts || r_numpolys >= max_polys ) {
|
||||
/*
|
||||
NOTE TTimo this was initially a PRINT_WARNING
|
||||
but it happens a lot with high fighting scenes and particles
|
||||
since we don't plan on changing the const and making for room for those effects
|
||||
simply cut this message to developer only
|
||||
*/
|
||||
ri.Printf( PRINT_DEVELOPER, "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n");
|
||||
return qfalse;
|
||||
}
|
||||
poly = &backEndData[tr.smpFrame]->polys[r_numpolys];
|
||||
poly->surfaceType = SF_POLY;
|
||||
poly->hShader = hShader;
|
||||
poly->numVerts = numVerts;
|
||||
poly->verts = &backEndData[tr.smpFrame]->polyVerts[r_numpolyverts];
|
||||
poly->renderfx = renderfx;
|
||||
|
||||
poly = &backEndData[tr.smpFrame]->polys[r_numpolys];
|
||||
poly->surfaceType = SF_POLY;
|
||||
poly->hShader = hShader;
|
||||
poly->numVerts = numVerts;
|
||||
poly->verts = &backEndData[tr.smpFrame]->polyVerts[r_numpolyverts];
|
||||
|
||||
Com_Memcpy( poly->verts, &verts[numVerts*j], numVerts * sizeof( *verts ) );
|
||||
|
||||
if ( glConfig.hardwareType == GLHW_RAGEPRO ) {
|
||||
poly->verts->modulate[0] = 255;
|
||||
poly->verts->modulate[1] = 255;
|
||||
poly->verts->modulate[2] = 255;
|
||||
poly->verts->modulate[3] = 255;
|
||||
}
|
||||
// done.
|
||||
r_numpolys++;
|
||||
r_numpolyverts += numVerts;
|
||||
|
||||
// if no world is loaded
|
||||
if ( tr.world == NULL ) {
|
||||
fogIndex = 0;
|
||||
}
|
||||
// see if it is in a fog volume
|
||||
else if ( tr.world->numfogs == 1 ) {
|
||||
fogIndex = 0;
|
||||
} else {
|
||||
// find which fog volume the poly is in
|
||||
VectorCopy( poly->verts[0].xyz, bounds[0] );
|
||||
VectorCopy( poly->verts[0].xyz, bounds[1] );
|
||||
for ( i = 1 ; i < poly->numVerts ; i++ ) {
|
||||
AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
|
||||
}
|
||||
for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) {
|
||||
fog = &tr.world->fogs[fogIndex];
|
||||
if ( bounds[1][0] >= fog->bounds[0][0]
|
||||
&& bounds[1][1] >= fog->bounds[0][1]
|
||||
&& bounds[1][2] >= fog->bounds[0][2]
|
||||
&& bounds[0][0] <= fog->bounds[1][0]
|
||||
&& bounds[0][1] <= fog->bounds[1][1]
|
||||
&& bounds[0][2] <= fog->bounds[1][2] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( fogIndex == tr.world->numfogs ) {
|
||||
fogIndex = 0;
|
||||
}
|
||||
}
|
||||
poly->fogIndex = fogIndex;
|
||||
}
|
||||
Com_Memcpy(poly->verts, verts, sizeof(polyVert_t) * numVerts);
|
||||
++r_numpolys;
|
||||
r_numpolyverts += numVerts;
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
@@ -254,7 +213,33 @@ void RE_AddRefEntityToScene( const refEntity_t *ent, int parentEntityNumber) {
|
||||
}
|
||||
|
||||
backEndData[tr.smpFrame]->entities[r_numentities].e = *ent;
|
||||
backEndData[tr.smpFrame]->entities[r_numentities].lightingCalculated = qfalse;
|
||||
backEndData[tr.smpFrame]->entities[r_numentities].bLightGridCalculated = qfalse;
|
||||
backEndData[tr.smpFrame]->entities[r_numentities].sphereCalculated = qfalse;
|
||||
|
||||
if (parentEntityNumber != ENTITYNUM_NONE)
|
||||
{
|
||||
int i;
|
||||
|
||||
//
|
||||
// Find the parent entity to attach to
|
||||
//
|
||||
for (i = r_firstSceneEntity; i < r_numentities; i++)
|
||||
{
|
||||
if (backEndData[tr.smpFrame]->entities[i].e.entityNumber == parentEntityNumber)
|
||||
{
|
||||
backEndData[tr.smpFrame]->entities[r_numentities].e.parentEntity = i - r_firstSceneEntity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == r_numentities) {
|
||||
backEndData[tr.smpFrame]->entities[i].e.parentEntity = ENTITYNUM_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
backEndData[tr.smpFrame]->entities[r_numentities].e.parentEntity = ENTITYNUM_NONE;
|
||||
}
|
||||
|
||||
r_numentities++;
|
||||
}
|
||||
@@ -387,6 +372,14 @@ void RE_RenderScene( const refdef_t *fd ) {
|
||||
}
|
||||
}
|
||||
|
||||
// copy the sky data
|
||||
tr.refdef.sky_alpha = fd->sky_alpha;
|
||||
tr.refdef.sky_portal = fd->sky_portal;
|
||||
|
||||
VectorCopy(fd->sky_origin, tr.refdef.sky_origin);
|
||||
VectorCopy(fd->sky_axis[0], tr.refdef.sky_axis[0]);
|
||||
VectorCopy(fd->sky_axis[1], tr.refdef.sky_axis[1]);
|
||||
VectorCopy(fd->sky_axis[2], tr.refdef.sky_axis[2]);
|
||||
|
||||
// derived info
|
||||
|
||||
@@ -398,12 +391,20 @@ void RE_RenderScene( const refdef_t *fd ) {
|
||||
tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
|
||||
tr.refdef.entities = &backEndData[tr.smpFrame]->entities[r_firstSceneEntity];
|
||||
|
||||
tr.refdef.num_sprites = r_numsprites - r_firstSceneSprite;
|
||||
tr.refdef.sprites = &backEndData[tr.smpFrame]->sprites[r_firstSceneSprite];
|
||||
|
||||
tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
|
||||
tr.refdef.dlights = &backEndData[tr.smpFrame]->dlights[r_firstSceneDlight];
|
||||
|
||||
tr.refdef.numTerMarks = r_numtermarks - r_firstSceneTerMark;
|
||||
tr.refdef.terMarks = &backEndData[tr.smpFrame]->terMarks[r_firstSceneTerMark];
|
||||
|
||||
tr.refdef.numPolys = r_numpolys - r_firstScenePoly;
|
||||
tr.refdef.polys = &backEndData[tr.smpFrame]->polys[r_firstScenePoly];
|
||||
|
||||
backEndData[tr.smpFrame]->staticModelData = tr.refdef.staticModelData;
|
||||
|
||||
// turn off dynamic lighting globally by clearing all the
|
||||
// dlights if it needs to be disabled or if vertex lighting is enabled
|
||||
if (r_vertexLight->integer == 1 ) {
|
||||
@@ -424,6 +425,8 @@ void RE_RenderScene( const refdef_t *fd ) {
|
||||
// The refdef takes 0-at-the-top y coordinates, so
|
||||
// convert to GL's 0-at-the-bottom space
|
||||
//
|
||||
tr.skyRendered = qfalse;
|
||||
tr.portalRendered = qfalse;
|
||||
Com_Memset( &parms, 0, sizeof( parms ) );
|
||||
parms.viewportX = tr.refdef.x;
|
||||
parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height );
|
||||
@@ -441,12 +444,22 @@ void RE_RenderScene( const refdef_t *fd ) {
|
||||
|
||||
VectorCopy( fd->vieworg, parms.pvsOrigin );
|
||||
|
||||
// copy the farplane data
|
||||
parms.farplane_distance = fd->farplane_distance;
|
||||
parms.farplane_color[0] = fd->farplane_color[0];
|
||||
parms.farplane_color[1] = fd->farplane_color[1];
|
||||
parms.farplane_color[2] = fd->farplane_color[2];
|
||||
parms.farplane_cull = fd->farplane_cull;
|
||||
|
||||
R_ClearRealDlights();
|
||||
R_RenderView( &parms );
|
||||
|
||||
// the next scene rendered in this frame will tack on after this one
|
||||
r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
|
||||
r_firstSceneEntity = r_numentities;
|
||||
r_firstSceneSprite = r_numsprites;
|
||||
r_firstSceneDlight = r_numdlights;
|
||||
r_firstSceneTerMark = r_numtermarks;
|
||||
r_firstScenePoly = r_numpolys;
|
||||
|
||||
tr.frontEndMsec += ri.Milliseconds() - startTime;
|
||||
|
||||
+214
-113
@@ -306,7 +306,6 @@ to overflow.
|
||||
==============
|
||||
*/
|
||||
void RB_BeginSurface( shader_t *shader ) {
|
||||
|
||||
tess.numIndexes = 0;
|
||||
tess.numVertexes = 0;
|
||||
tess.shader = shader;
|
||||
@@ -316,12 +315,6 @@ void RB_BeginSurface( shader_t *shader ) {
|
||||
tess.numPasses = shader->numUnfoggedPasses;
|
||||
tess.currentStageIteratorFunc = shader->optimalStageIteratorFunc;
|
||||
|
||||
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
|
||||
if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) {
|
||||
tess.shaderTime = tess.shader->clampTime;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -354,6 +347,37 @@ static void DrawMultitextured( shaderCommands_t *input, int stage ) {
|
||||
qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] );
|
||||
R_BindAnimatedImage( &pStage->bundle[0] );
|
||||
|
||||
if (pStage->stateBits & GLS_MULTITEXTURE_ENV)
|
||||
{
|
||||
glState.cntnvblendmode = pStage->multitextureEnv;
|
||||
glState.cntTexEnvExt = GLS_MULTITEXTURE_ENV;
|
||||
|
||||
if (pStage->multitextureEnv == GL_ADD)
|
||||
{
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, 260.0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, 33984.0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, 0x44400000);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, 0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, 33985.0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, 0x44400000);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, 0x44400000);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE3_RGB, 0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND3_RGB, 0x44404000);
|
||||
}
|
||||
else if (pStage->multitextureEnv == GL_MODULATE)
|
||||
{
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, 33984.0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, 0x44400000);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, 33985.0);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, 0x44400000);
|
||||
}
|
||||
else
|
||||
{
|
||||
ri.Printf(3, "Unknown MT mode for: %s\n", input->shader);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// lightmap/secondary pass
|
||||
//
|
||||
@@ -361,23 +385,38 @@ static void DrawMultitextured( shaderCommands_t *input, int stage ) {
|
||||
qglEnable( GL_TEXTURE_2D );
|
||||
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
if ( r_lightmap->integer ) {
|
||||
if ( r_lightmap->integer && pStage->bundle[1].isLightmap ) {
|
||||
GL_TexEnv( GL_REPLACE );
|
||||
} else if (pStage->stateBits & GLS_MULTITEXTURE_ENV) {
|
||||
glState.cntTexEnvExt = GLS_MULTITEXTURE_ENV;
|
||||
|
||||
GL_TexEnv(GL_COMBINE);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, 34165);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, 0x47057700);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, 0x44400000);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, 34168);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, 0x44400000);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, 0x47057700);
|
||||
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, 0x44407700000);
|
||||
} else {
|
||||
GL_TexEnv( tess.shader->multitextureEnv );
|
||||
GL_TexEnv( pStage->multitextureEnv );
|
||||
}
|
||||
|
||||
qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[1] );
|
||||
|
||||
R_BindAnimatedImage( &pStage->bundle[1] );
|
||||
if (!input->dlightMap || !pStage->bundle[1].isLightmap) {
|
||||
R_BindAnimatedImage(&pStage->bundle[1]);
|
||||
} else {
|
||||
GL_Bind(&tr.identityLightImage[input->dlightMap]);
|
||||
}
|
||||
|
||||
R_DrawElements( input->numIndexes, input->indexes );
|
||||
|
||||
qglDisable(GL_TEXTURE_2D);
|
||||
//
|
||||
// disable texturing on TEXTURE1, then select TEXTURE0
|
||||
//
|
||||
//qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
qglDisable( GL_TEXTURE_2D );
|
||||
qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
GL_SelectTexture( 0 );
|
||||
}
|
||||
@@ -636,43 +675,6 @@ static void ProjectDlightTexture( void ) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
RB_FogPass
|
||||
|
||||
Blends a fog texture on top of everything else
|
||||
===================
|
||||
*/
|
||||
static void RB_FogPass( void ) {
|
||||
fog_t *fog;
|
||||
int i;
|
||||
|
||||
qglEnableClientState( GL_COLOR_ARRAY );
|
||||
qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );
|
||||
|
||||
qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
|
||||
qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] );
|
||||
|
||||
fog = tr.world->fogs + tess.fogNum;
|
||||
|
||||
for ( i = 0; i < tess.numVertexes; i++ ) {
|
||||
* ( int * )&tess.svars.colors[i] = fog->colorInt;
|
||||
}
|
||||
|
||||
RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[0] );
|
||||
|
||||
GL_Bind( tr.fogImage );
|
||||
|
||||
if ( tess.shader->fogPass == FP_EQUAL ) {
|
||||
GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
|
||||
} else {
|
||||
GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
|
||||
}
|
||||
|
||||
R_DrawElements( tess.numIndexes, tess.indexes );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
ComputeColors
|
||||
@@ -764,9 +766,98 @@ static void ComputeColors( shaderStage_t *pStage )
|
||||
break;
|
||||
case CGEN_LIGHTING_SPHERICAL:
|
||||
case CGEN_STATIC:
|
||||
if (!r_drawspherelights->integer)
|
||||
if (!r_drawspherelights->integer) {
|
||||
break;
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
if (!backEnd.currentStaticModel) {
|
||||
if (backEnd.currentSphere->TessFunction) {
|
||||
backEnd.currentSphere->TessFunction((unsigned char*)tess.svars.colors);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tess.vertexColorValid) {
|
||||
ri.Printf(PRINT_WARNING, "Vertex color specified for shader '%s', but vertex colors are not valid for this model\n", tess.shader->name);
|
||||
}
|
||||
|
||||
if (backEnd.currentStaticModel->useSpecialLighting)
|
||||
{
|
||||
for (i = 0; i < tess.numVertexes; i++)
|
||||
{
|
||||
int j;
|
||||
vec3_t colorout;
|
||||
int r, g, b;
|
||||
|
||||
colorout[0] = tess.vertexColors[i][0];
|
||||
colorout[1] = tess.vertexColors[i][1];
|
||||
colorout[2] = tess.vertexColors[i][2];
|
||||
|
||||
for (j = 0; j < backEnd.currentStaticModel->numdlights; j++)
|
||||
{
|
||||
float ooLightDistSquared;
|
||||
float dot;
|
||||
vec3_t diff;
|
||||
dlight_t* dl;
|
||||
|
||||
dl = &backEnd.refdef.dlights[backEnd.currentStaticModel->dlights[j].index];
|
||||
VectorSubtract(backEnd.currentStaticModel->dlights[j].transformed, tess.xyz[i], diff);
|
||||
|
||||
dot = DotProduct(diff, tess.normal[i]);
|
||||
if (dot >= 0)
|
||||
{
|
||||
float ooLen;
|
||||
|
||||
ooLen = 1.0 / VectorLengthSquared(diff);
|
||||
ooLightDistSquared = dot * (7500.0 * dl->radius * ooLen * sqrt(ooLen));
|
||||
colorout[0] = dl->color[0] * ooLightDistSquared + colorout[0];
|
||||
colorout[1] = dl->color[1] * ooLightDistSquared + colorout[1];
|
||||
colorout[2] = dl->color[2] * ooLightDistSquared + colorout[2];
|
||||
}
|
||||
}
|
||||
|
||||
r = colorout[0];
|
||||
g = colorout[1];
|
||||
b = colorout[2];
|
||||
|
||||
if (tr.overbrightShift)
|
||||
{
|
||||
r = (int)((float)r * tr.overbrightMult);
|
||||
g = (int)((float)g * tr.overbrightMult);
|
||||
b = (int)((float)b * tr.overbrightMult);
|
||||
}
|
||||
|
||||
if (r > 0xFF || g > 0xFF || b > 0xFF)
|
||||
{
|
||||
float t;
|
||||
|
||||
t = 255.0 / (float)Q_max(r, Q_max(g, b));
|
||||
|
||||
r = (int)((float)r * t);
|
||||
g = (int)((float)g * t);
|
||||
b = (int)((float)b * t);
|
||||
}
|
||||
|
||||
tess.svars.colors[i][0] = r;
|
||||
tess.svars.colors[i][1] = g;
|
||||
tess.svars.colors[i][2] = b;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tr.identityLight == 1.0)
|
||||
{
|
||||
Com_Memcpy(tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof(tess.vertexColors[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < tess.numVertexes; i++) {
|
||||
tess.svars.colors[i][0] = tess.vertexColors[i][0] * tr.identityLight;
|
||||
tess.svars.colors[i][1] = tess.vertexColors[i][1] * tr.identityLight;
|
||||
tess.svars.colors[i][2] = tess.vertexColors[i][2] * tr.identityLight;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CGEN_CONSTANT:
|
||||
RB_CalcColorFromConstant((unsigned char*)tess.svars.colors, pStage->colorConst);
|
||||
@@ -978,9 +1069,6 @@ static void ComputeTexCoords( shaderStage_t *pStage ) {
|
||||
tess.svars.texcoords[b][i][1] = DotProduct( tess.xyz[i], pStage->bundle[b].tcGenVectors[1] );
|
||||
}
|
||||
break;
|
||||
case TCGEN_FOG:
|
||||
RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[b] );
|
||||
break;
|
||||
case TCGEN_ENVIRONMENT_MAPPED:
|
||||
RB_CalcEnvironmentTexCoords( ( float * ) tess.svars.texcoords[b] );
|
||||
break;
|
||||
@@ -1048,54 +1136,64 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||
{
|
||||
int stage;
|
||||
|
||||
for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
|
||||
for (stage = 0; stage < MAX_SHADER_STAGES; stage++)
|
||||
{
|
||||
shaderStage_t *pStage = tess.xstages[stage];
|
||||
shaderStage_t* pStage = tess.xstages[stage];
|
||||
|
||||
if ( !pStage )
|
||||
if (!pStage)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ComputeColors( pStage );
|
||||
ComputeTexCoords( pStage );
|
||||
if (pStage->alphaGen == AGEN_SKYALPHA && tr.refdef.sky_alpha < 0.01) {
|
||||
continue;
|
||||
}
|
||||
else if (pStage->alphaGen == AGEN_ONE_MINUS_SKYALPHA && tr.refdef.sky_alpha > 0.99) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !setArraysOnce )
|
||||
ComputeTexCoords(pStage);
|
||||
ComputeColors(pStage);
|
||||
|
||||
if (!setArraysOnce)
|
||||
{
|
||||
qglEnableClientState( GL_COLOR_ARRAY );
|
||||
qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors );
|
||||
qglEnableClientState(GL_COLOR_ARRAY);
|
||||
qglColorPointer(4, GL_UNSIGNED_BYTE, 0, input->svars.colors);
|
||||
}
|
||||
|
||||
//
|
||||
// do multitexture
|
||||
//
|
||||
if ( pStage->bundle[1].image[0] != 0 )
|
||||
if (pStage->bundle[1].image[0] != 0)
|
||||
{
|
||||
DrawMultitextured( input, stage );
|
||||
DrawMultitextured(input, stage);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (backEnd.in2D) {
|
||||
GL_State(pStage->stateBits | GLS_DEPTHTEST_DISABLE);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
GL_State(pStage->stateBits);
|
||||
}
|
||||
|
||||
if ( !setArraysOnce )
|
||||
if (!setArraysOnce)
|
||||
{
|
||||
qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] );
|
||||
qglTexCoordPointer(2, GL_FLOAT, 0, input->svars.texcoords[0]);
|
||||
}
|
||||
|
||||
//
|
||||
// set state
|
||||
//
|
||||
if ( pStage->bundle[0].vertexLightmap && r_vertexLight->integer && r_lightmap->integer )
|
||||
if (pStage->bundle[0].vertexLightmap && r_vertexLight->integer && r_lightmap->integer)
|
||||
{
|
||||
GL_Bind( tr.whiteImage );
|
||||
} else {
|
||||
GL_Bind(tr.whiteImage);
|
||||
}
|
||||
else {
|
||||
if (input->dlightMap && tess.xstages[stage]->bundle[0].isLightmap) {
|
||||
GL_Bind(&tr.identityLightImage[input->dlightMap]);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
R_BindAnimatedImage(&pStage->bundle[0]);
|
||||
}
|
||||
}
|
||||
@@ -1103,10 +1201,10 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||
//
|
||||
// draw
|
||||
//
|
||||
R_DrawElements( input->numIndexes, input->indexes );
|
||||
R_DrawElements(input->numIndexes, input->indexes);
|
||||
}
|
||||
// allow skipping out to show just lightmaps during development
|
||||
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) )
|
||||
if (r_lightmap->integer && (pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -1158,21 +1256,21 @@ void RB_StageIteratorGeneric( void )
|
||||
// to avoid compiling those arrays since they will change
|
||||
// during multipass rendering
|
||||
//
|
||||
if ( tess.numPasses > 1 || input->shader->multitextureEnv )
|
||||
if (tess.numPasses > 1 || (tess.xstages[0] && tess.xstages[0]->multitextureEnv))
|
||||
{
|
||||
setArraysOnce = qfalse;
|
||||
qglDisableClientState (GL_COLOR_ARRAY);
|
||||
qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
qglDisableClientState(GL_COLOR_ARRAY);
|
||||
qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
setArraysOnce = qtrue;
|
||||
|
||||
qglEnableClientState( GL_COLOR_ARRAY);
|
||||
qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );
|
||||
qglEnableClientState(GL_COLOR_ARRAY);
|
||||
qglColorPointer(4, GL_UNSIGNED_BYTE, 0, tess.svars.colors);
|
||||
|
||||
qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
|
||||
qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] );
|
||||
qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
qglTexCoordPointer(2, GL_FLOAT, 0, tess.svars.texcoords[0]);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1228,7 +1326,7 @@ void RB_StageIteratorGeneric( void )
|
||||
/*
|
||||
** RB_StageIteratorVertexLitTexture
|
||||
*/
|
||||
void RB_StageIteratorVertexLitTexture( void )
|
||||
void RB_StageIteratorVertexLitTextureUnfogged( void )
|
||||
{
|
||||
shaderCommands_t *input;
|
||||
shader_t *shader;
|
||||
@@ -1237,10 +1335,16 @@ void RB_StageIteratorVertexLitTexture( void )
|
||||
|
||||
shader = input->shader;
|
||||
|
||||
//
|
||||
// compute colors
|
||||
//
|
||||
RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors );
|
||||
if (backEnd.currentSphere->TessFunction && r_drawspherelights->integer) {
|
||||
backEnd.currentSphere->TessFunction((unsigned char*)tess.svars.colors);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// compute colors
|
||||
//
|
||||
RB_CalcLightGridColor((unsigned char*)tess.svars.colors);
|
||||
}
|
||||
|
||||
//
|
||||
// log this call
|
||||
@@ -1283,17 +1387,10 @@ void RB_StageIteratorVertexLitTexture( void )
|
||||
//
|
||||
// now do any dynamic lighting needed
|
||||
//
|
||||
if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) {
|
||||
if ( tess.dlightBits && !tess.dlightMap && tess.shader->sort <= SS_OPAQUE ) {
|
||||
ProjectDlightTexture();
|
||||
}
|
||||
|
||||
//
|
||||
// now do fog
|
||||
//
|
||||
if ( tess.fogNum && tess.shader->fogPass ) {
|
||||
RB_FogPass();
|
||||
}
|
||||
|
||||
//
|
||||
// unlock arrays
|
||||
//
|
||||
@@ -1306,7 +1403,7 @@ void RB_StageIteratorVertexLitTexture( void )
|
||||
|
||||
//define REPLACE_MODE
|
||||
|
||||
void RB_StageIteratorLightmappedMultitexture( void ) {
|
||||
void RB_StageIteratorLightmappedMultitextureUnfogged( void ) {
|
||||
shaderCommands_t *input;
|
||||
|
||||
input = &tess;
|
||||
@@ -1359,7 +1456,11 @@ void RB_StageIteratorLightmappedMultitexture( void ) {
|
||||
} else {
|
||||
GL_TexEnv( GL_MODULATE );
|
||||
}
|
||||
R_BindAnimatedImage( &tess.xstages[0]->bundle[1] );
|
||||
if (tess.dlightMap && tess.xstages[0]->bundle[1].isLightmap) {
|
||||
GL_Bind(&tr.identityLightImage[tess.dlightMap]);
|
||||
} else {
|
||||
R_BindAnimatedImage(&tess.xstages[0]->bundle[1]);
|
||||
}
|
||||
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][1] );
|
||||
|
||||
@@ -1388,17 +1489,10 @@ void RB_StageIteratorLightmappedMultitexture( void ) {
|
||||
//
|
||||
// now do any dynamic lighting needed
|
||||
//
|
||||
if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) {
|
||||
if ( tess.dlightBits && !tess.dlightMap && tess.shader->sort <= SS_OPAQUE ) {
|
||||
ProjectDlightTexture();
|
||||
}
|
||||
|
||||
//
|
||||
// now do fog
|
||||
//
|
||||
if ( tess.fogNum && tess.shader->fogPass ) {
|
||||
RB_FogPass();
|
||||
}
|
||||
|
||||
//
|
||||
// unlock arrays
|
||||
//
|
||||
@@ -1419,7 +1513,6 @@ void RB_EndSurface( void ) {
|
||||
if (input->numIndexes == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (input->indexes[SHADER_MAX_INDEXES-1] != 0) {
|
||||
ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_INDEXES hit");
|
||||
}
|
||||
@@ -1427,8 +1520,12 @@ void RB_EndSurface( void ) {
|
||||
ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_VERTEXES hit");
|
||||
}
|
||||
|
||||
if (tess.xyz[SHADER_MAX_VERTEXES - 1][0] && r_shadows->integer != 3) {
|
||||
tess.xyz[SHADER_MAX_VERTEXES - 1][0] = 0;
|
||||
}
|
||||
|
||||
if ( tess.shader == tr.shadowShader ) {
|
||||
RB_ShadowTessEnd();
|
||||
RB_ComputeShadowVolume();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1450,15 +1547,19 @@ void RB_EndSurface( void ) {
|
||||
//
|
||||
tess.currentStageIteratorFunc();
|
||||
|
||||
//
|
||||
// draw debugging stuff
|
||||
//
|
||||
if ( r_showtris->integer ) {
|
||||
DrawTris (input);
|
||||
}
|
||||
if ( r_shownormals->integer ) {
|
||||
DrawNormals (input);
|
||||
if (!(tr.refdef.rdflags & RDF_NOWORLDMODEL) && !backEnd.in2D)
|
||||
{
|
||||
//
|
||||
// draw debugging stuff
|
||||
//
|
||||
if (r_showtris->integer && developer->integer) {
|
||||
DrawTris(input);
|
||||
}
|
||||
if (r_shownormals->integer && developer->integer) {
|
||||
DrawNormals(input);
|
||||
}
|
||||
}
|
||||
|
||||
// clear shader so we can tell we don't have any unclosed surfaces
|
||||
tess.numIndexes = 0;
|
||||
|
||||
|
||||
+30
-149
@@ -792,65 +792,6 @@ void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors )
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** RB_CalcModulateColorsByFog
|
||||
*/
|
||||
void RB_CalcModulateColorsByFog( unsigned char *colors ) {
|
||||
int i;
|
||||
float texCoords[SHADER_MAX_VERTEXES][2];
|
||||
|
||||
// calculate texcoords so we can derive density
|
||||
// this is not wasted, because it would only have
|
||||
// been previously called if the surface was opaque
|
||||
RB_CalcFogTexCoords( texCoords[0] );
|
||||
|
||||
for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
|
||||
float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
|
||||
colors[0] *= f;
|
||||
colors[1] *= f;
|
||||
colors[2] *= f;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** RB_CalcModulateAlphasByFog
|
||||
*/
|
||||
void RB_CalcModulateAlphasByFog( unsigned char *colors ) {
|
||||
int i;
|
||||
float texCoords[SHADER_MAX_VERTEXES][2];
|
||||
|
||||
// calculate texcoords so we can derive density
|
||||
// this is not wasted, because it would only have
|
||||
// been previously called if the surface was opaque
|
||||
RB_CalcFogTexCoords( texCoords[0] );
|
||||
|
||||
for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
|
||||
float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
|
||||
colors[3] *= f;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** RB_CalcModulateRGBAsByFog
|
||||
*/
|
||||
void RB_CalcModulateRGBAsByFog( unsigned char *colors ) {
|
||||
int i;
|
||||
float texCoords[SHADER_MAX_VERTEXES][2];
|
||||
|
||||
// calculate texcoords so we can derive density
|
||||
// this is not wasted, because it would only have
|
||||
// been previously called if the surface was opaque
|
||||
RB_CalcFogTexCoords( texCoords[0] );
|
||||
|
||||
for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
|
||||
float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
|
||||
colors[0] *= f;
|
||||
colors[1] *= f;
|
||||
colors[2] *= f;
|
||||
colors[3] *= f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
@@ -860,95 +801,6 @@ TEX COORDS
|
||||
====================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
========================
|
||||
RB_CalcFogTexCoords
|
||||
|
||||
To do the clipped fog plane really correctly, we should use
|
||||
projected textures, but I don't trust the drivers and it
|
||||
doesn't fit our shader data.
|
||||
========================
|
||||
*/
|
||||
void RB_CalcFogTexCoords( float *st ) {
|
||||
int i;
|
||||
float *v;
|
||||
float s, t;
|
||||
float eyeT;
|
||||
qboolean eyeOutside;
|
||||
fog_t *fog;
|
||||
vec3_t local;
|
||||
vec4_t fogDistanceVector, fogDepthVector;
|
||||
|
||||
fog = tr.world->fogs + tess.fogNum;
|
||||
|
||||
// all fogging distance is based on world Z units
|
||||
VectorSubtract( backEnd.ori.origin, backEnd.viewParms.ori.origin, local );
|
||||
fogDistanceVector[0] = -backEnd.ori.modelMatrix[2];
|
||||
fogDistanceVector[1] = -backEnd.ori.modelMatrix[6];
|
||||
fogDistanceVector[2] = -backEnd.ori.modelMatrix[10];
|
||||
fogDistanceVector[3] = DotProduct( local, backEnd.viewParms.ori.axis[0] );
|
||||
|
||||
// scale the fog vectors based on the fog's thickness
|
||||
fogDistanceVector[0] *= fog->tcScale;
|
||||
fogDistanceVector[1] *= fog->tcScale;
|
||||
fogDistanceVector[2] *= fog->tcScale;
|
||||
fogDistanceVector[3] *= fog->tcScale;
|
||||
|
||||
// rotate the gradient vector for this orientation
|
||||
if ( fog->hasSurface ) {
|
||||
fogDepthVector[0] = fog->surface[0] * backEnd.ori.axis[0][0] +
|
||||
fog->surface[1] * backEnd.ori.axis[0][1] + fog->surface[2] * backEnd.ori.axis[0][2];
|
||||
fogDepthVector[1] = fog->surface[0] * backEnd.ori.axis[1][0] +
|
||||
fog->surface[1] * backEnd.ori.axis[1][1] + fog->surface[2] * backEnd.ori.axis[1][2];
|
||||
fogDepthVector[2] = fog->surface[0] * backEnd.ori.axis[2][0] +
|
||||
fog->surface[1] * backEnd.ori.axis[2][1] + fog->surface[2] * backEnd.ori.axis[2][2];
|
||||
fogDepthVector[3] = -fog->surface[3] + DotProduct( backEnd.ori.origin, fog->surface );
|
||||
|
||||
eyeT = DotProduct( backEnd.ori.viewOrigin, fogDepthVector ) + fogDepthVector[3];
|
||||
} else {
|
||||
eyeT = 1; // non-surface fog always has eye inside
|
||||
}
|
||||
|
||||
// see if the viewpoint is outside
|
||||
// this is needed for clipping distance even for constant fog
|
||||
|
||||
if ( eyeT < 0 ) {
|
||||
eyeOutside = qtrue;
|
||||
} else {
|
||||
eyeOutside = qfalse;
|
||||
}
|
||||
|
||||
fogDistanceVector[3] += 1.0/512;
|
||||
|
||||
// calculate density for each point
|
||||
for (i = 0, v = tess.xyz[0] ; i < tess.numVertexes ; i++, v += 4) {
|
||||
// calculate the length in fog
|
||||
s = DotProduct( v, fogDistanceVector ) + fogDistanceVector[3];
|
||||
t = DotProduct( v, fogDepthVector ) + fogDepthVector[3];
|
||||
|
||||
// partially clipped fogs use the T axis
|
||||
if ( eyeOutside ) {
|
||||
if ( t < 1.0 ) {
|
||||
t = 1.0/32; // point is outside, so no fogging
|
||||
} else {
|
||||
t = 1.0/32 + 30.0/32 * t / ( t - eyeT ); // cut the distance at the fog plane
|
||||
}
|
||||
} else {
|
||||
if ( t < 0 ) {
|
||||
t = 1.0/32; // point is outside, so no fogging
|
||||
} else {
|
||||
t = 31.0/32;
|
||||
}
|
||||
}
|
||||
|
||||
st[0] = s;
|
||||
st[1] = t;
|
||||
st += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** RB_CalcEnvironmentTexCoords
|
||||
*/
|
||||
@@ -1158,7 +1010,36 @@ void RB_CalcSpecularAlpha(unsigned char* alphas, float alphaMax, vec3_t lightOri
|
||||
|
||||
void RB_CalcLightGridColor(unsigned char* colors)
|
||||
{
|
||||
// FIXME/ unimplemented
|
||||
int i;
|
||||
|
||||
if (!backEnd.currentEntity) {
|
||||
for (i = 0; i < tess.numVertexes; i++) {
|
||||
colors[i * 4] = backEnd.currentStaticModel->iGridLighting;
|
||||
colors[i * 4 + 1] = backEnd.currentStaticModel->iGridLighting;
|
||||
colors[i * 4 + 2] = backEnd.currentStaticModel->iGridLighting;
|
||||
colors[i * 4 + 3] = backEnd.currentStaticModel->iGridLighting;
|
||||
}
|
||||
}
|
||||
else if (backEnd.currentEntity != &tr.worldEntity) {
|
||||
for (i = 0; i < tess.numVertexes; i++) {
|
||||
colors[i * 4] = backEnd.currentEntity->iGridLighting;
|
||||
colors[i * 4 + 1] = backEnd.currentEntity->iGridLighting;
|
||||
colors[i * 4 + 2] = backEnd.currentEntity->iGridLighting;
|
||||
colors[i * 4 + 3] = backEnd.currentEntity->iGridLighting;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Com_Printf(
|
||||
"##### shader '%s' incorrectly uses rgbGen lightingGrid or lightingSpherical; was rgbGen vertex intended?\n",
|
||||
tess.shader->name);
|
||||
|
||||
for (i = 0; i < tess.numVertexes; i++) {
|
||||
colors[i * 4] = 0xFF;
|
||||
colors[i * 4 + 1] = 0xFF;
|
||||
colors[i * 4 + 2] = 0xFF;
|
||||
colors[i * 4 + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RB_CalcAlphaFromDotView(unsigned char* colors, float alphaMin, float alphaMax)
|
||||
|
||||
+530
-281
File diff suppressed because it is too large.
Load diff
+16
-13
@@ -45,19 +45,6 @@ static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
|
||||
static int numEdgeDefs[SHADER_MAX_VERTEXES];
|
||||
static int facing[SHADER_MAX_INDEXES/3];
|
||||
|
||||
void R_AddEdgeDef( int i1, int i2, int facing ) {
|
||||
int c;
|
||||
|
||||
c = numEdgeDefs[ i1 ];
|
||||
if ( c == MAX_EDGE_DEFS ) {
|
||||
return; // overflow
|
||||
}
|
||||
edgeDefs[ i1 ][ c ].i2 = i2;
|
||||
edgeDefs[ i1 ][ c ].facing = facing;
|
||||
|
||||
numEdgeDefs[ i1 ]++;
|
||||
}
|
||||
|
||||
void R_RenderShadowEdges( void ) {
|
||||
int i;
|
||||
|
||||
@@ -139,6 +126,19 @@ void R_RenderShadowEdges( void ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void R_AddEdgeDef(int i1, int i2, int facing) {
|
||||
int c;
|
||||
|
||||
c = numEdgeDefs[i1];
|
||||
if (c == MAX_EDGE_DEFS) {
|
||||
return; // overflow
|
||||
}
|
||||
edgeDefs[i1][c].i2 = i2;
|
||||
edgeDefs[i1][c].facing = facing;
|
||||
|
||||
numEdgeDefs[i1]++;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
RB_ShadowTessEnd
|
||||
@@ -248,6 +248,9 @@ void RB_ShadowTessEnd( void ) {
|
||||
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
}
|
||||
|
||||
void RB_ComputeShadowVolume() {
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
|
||||
@@ -811,7 +811,7 @@ void RB_StageIteratorSky( void ) {
|
||||
if ( r_showsky->integer ) {
|
||||
qglDepthRange( 0.0, 0.0 );
|
||||
} else {
|
||||
qglDepthRange( 1.0, 1.0 );
|
||||
qglDepthRange( 1.875, 1.875 );
|
||||
}
|
||||
|
||||
// draw the outer skybox
|
||||
|
||||
@@ -26,15 +26,129 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
void R_Sky_Init()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
tr.portalsky.inUse = qfalse;
|
||||
tr.portalsky.numSurfs = 0;
|
||||
}
|
||||
|
||||
void R_Sky_Reset()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
if (tr.portalsky.inUse) {
|
||||
return;
|
||||
}
|
||||
|
||||
tr.portalsky.mins[0] = 8192.0;
|
||||
tr.portalsky.mins[1] = 8192.0;
|
||||
tr.portalsky.mins[2] = 8192.0;
|
||||
tr.portalsky.maxs[0] = -8192.0;
|
||||
tr.portalsky.maxs[1] = -8192.0;
|
||||
tr.portalsky.maxs[2] = -8192.0;
|
||||
tr.portalsky.cntNode = 0;
|
||||
tr.portalsky.numSurfs = 0;
|
||||
}
|
||||
|
||||
void R_Sky_AddSurf(msurface_t* surf)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
if (tr.portalsky.inUse)
|
||||
{
|
||||
static int last_sky_warning = 0;
|
||||
|
||||
if (tr.refdef.time - 1000 > last_sky_warning)
|
||||
{
|
||||
ri.Printf(3, "WARNING: sky being drawn in a sky portal! Bad! Bad!\n");
|
||||
last_sky_warning = tr.refdef.time;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (tr.portalsky.numSurfs < 32) {
|
||||
tr.portalsky.skySurfs[tr.portalsky.numSurfs++] = surf;
|
||||
}
|
||||
|
||||
if (tr.portalsky.cntNode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (tr.portalsky.mins[i] >= tr.portalsky.cntNode->mins[i]) {
|
||||
tr.portalsky.mins[i] = tr.portalsky.cntNode->mins[i];
|
||||
}
|
||||
|
||||
if (tr.portalsky.maxs[i] >= tr.portalsky.cntNode->maxs[i]) {
|
||||
tr.portalsky.maxs[i] = tr.portalsky.cntNode->maxs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_Sky_Render() {
|
||||
int i;
|
||||
viewParms_t newParms, oldParms;
|
||||
mnode_t* leaf;
|
||||
|
||||
if (!tr.portalsky.numSurfs) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tr.refdef.sky_portal) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tr.skyRendered) {
|
||||
// already rendered
|
||||
return;
|
||||
}
|
||||
|
||||
if (tr.portalsky.inUse)
|
||||
{
|
||||
ri.Printf(PRINT_WARNING, "WARNING: Recursive skies found! Make that not happen!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < tr.portalsky.numSurfs; i++) {
|
||||
if (!SurfIsOffscreen((const srfSurfaceFace_t*)tr.portalsky.skySurfs[i]->data, tr.portalsky.skySurfs[i]->shader, ENTITYNUM_WORLD)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == tr.portalsky.numSurfs) {
|
||||
return;
|
||||
}
|
||||
|
||||
tr.skyRendered = qtrue;
|
||||
oldParms = tr.viewParms;
|
||||
newParms = tr.viewParms;
|
||||
|
||||
if (r_skyportal->integer)
|
||||
{
|
||||
if (sscanf(r_skyportal_origin->string, "%f %f %f", &newParms.ori.origin[0], &newParms.ori.origin[1], &newParms.ori.origin[2]) != 3)
|
||||
{
|
||||
ri.Printf(PRINT_WARNING, "WARNING: Invalid sky portal origin: %s\n", r_skyportal_origin->string);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy(tr.refdef.sky_origin, newParms.ori.origin);
|
||||
MatrixMultiply(newParms.ori.axis, tr.refdef.sky_axis, newParms.ori.axis);
|
||||
}
|
||||
|
||||
tr.portalsky.inUse = qtrue;
|
||||
VectorCopy(newParms.ori.origin, newParms.pvsOrigin);
|
||||
|
||||
leaf = R_PointInLeaf(newParms.pvsOrigin);
|
||||
if (leaf) {
|
||||
R_RenderView(&newParms);
|
||||
}
|
||||
|
||||
tr.viewParms = oldParms;
|
||||
|
||||
tr.portalsky.inUse = qfalse;
|
||||
tr.portalsky.numSurfs = 0;
|
||||
R_RotateForViewer();
|
||||
R_SetupFrustum();
|
||||
}
|
||||
|
||||
void R_Sky_ChangeFrustum() {
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
@@ -24,13 +24,40 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
#include "tr_local.h"
|
||||
|
||||
vec3_t spheredef[6];
|
||||
suninfo_t s_sun;
|
||||
static vec3_t ambientlight;
|
||||
static qboolean bEntityOverbright;
|
||||
static int iEntityLightingMax;
|
||||
static int light_reference_count = 0;
|
||||
|
||||
int compare_light_intensities(const void* p1, const void* p2)
|
||||
{
|
||||
return ((const reallightinfo_t*)p2)->fIntensity - ((const reallightinfo_t*)p1)->fIntensity;
|
||||
}
|
||||
|
||||
static void RB_OptimizeLights()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
static void RB_Light_CubeMap(const color4ub_t colors)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void RB_Light_Real(const color4ub_t colors)
|
||||
void RB_Light_Real(unsigned char* colors)
|
||||
{
|
||||
int i, j;
|
||||
float* normal;
|
||||
float* xyz;
|
||||
unsigned char* color;
|
||||
vec3_t v;
|
||||
vec3_t colorout;
|
||||
float fDot;
|
||||
reallightinfo_t* pLight;
|
||||
|
||||
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
@@ -42,16 +69,90 @@ static void RB_Sphere_Light_Sun()
|
||||
static qboolean RB_Sphere_CalculateSphereOrigin()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
static bool RB_Sphere_SetupGlobals()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
int i;
|
||||
|
||||
if (backEnd.refdef.rdflags & RDF_NOWORLDMODEL) {
|
||||
if (!(backEnd.refdef.rdflags & RDF_FULLBRIGHT)) {
|
||||
backEnd.currentSphere->TessFunction = &RB_Light_Fullbright;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!(backEnd.refdef.rdflags & RDF_FULLBRIGHT)) {
|
||||
if (!RB_Sphere_CalculateSphereOrigin()) {
|
||||
backEnd.currentSphere->TessFunction = &RB_CalcLightGridColor;
|
||||
|
||||
if (!backEnd.currentEntity->bLightGridCalculated) {
|
||||
RB_SetupEntityGridLighting();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (backEnd.refdef.vieworg[0] == 0 && backEnd.refdef.vieworg[1] == 0 && backEnd.refdef.vieworg[2] == 0) {
|
||||
backEnd.currentSphere->TessFunction = &RB_Light_Fullbright;
|
||||
return false;
|
||||
}
|
||||
|
||||
VectorCopy(backEnd.refdef.vieworg, backEnd.currentSphere->worldOrigin);
|
||||
VectorClear(backEnd.currentSphere->origin);
|
||||
backEnd.currentSphere->radius = 2.0;
|
||||
}
|
||||
|
||||
light_reference_count++;
|
||||
for (i = 0; i < 8; i++) {
|
||||
backEnd.currentSphere->leaves[i] = 0;
|
||||
}
|
||||
|
||||
R_SphereInLeafs(backEnd.currentSphere->worldOrigin, backEnd.currentSphere->radius, backEnd.currentSphere->leaves, 8);
|
||||
|
||||
backEnd.currentSphere->TessFunction = &RB_Light_Real;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool RB_Sphere_ResetPointColors()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
vec3_t light_offset, amb;
|
||||
|
||||
R_GetLightingGridValue(backEnd.currentSphere->worldOrigin, light_offset);
|
||||
light_offset[0] = ambientlight[0] + light_offset[0] * 0.18;
|
||||
light_offset[1] = ambientlight[1] + light_offset[1] * 0.18;
|
||||
light_offset[2] = ambientlight[2] + light_offset[2] * 0.18;
|
||||
if (tr.refdef.rdflags & RDF_FULLBRIGHT)
|
||||
{
|
||||
float fMin = tr.identityLight * 20.0;
|
||||
|
||||
if (fMin <= light_offset[0] || fMin <= light_offset[1] || fMin <= light_offset[2]) {
|
||||
light_offset[0] += fMin;
|
||||
light_offset[1] += fMin;
|
||||
light_offset[2] += fMin;
|
||||
}
|
||||
}
|
||||
|
||||
backEnd.currentSphere->ambient.level[0] = r_entlight_scale->value * tr.overbrightMult * light_offset[0];
|
||||
if (backEnd.currentSphere->ambient.level[0] >= 255.0) {
|
||||
backEnd.currentSphere->ambient.level[0] = -1;
|
||||
}
|
||||
|
||||
backEnd.currentSphere->ambient.level[1] = r_entlight_scale->value * tr.overbrightMult * light_offset[0];
|
||||
if (backEnd.currentSphere->ambient.level[1] >= 255.0) {
|
||||
backEnd.currentSphere->ambient.level[1] = -1;
|
||||
}
|
||||
|
||||
backEnd.currentSphere->ambient.level[2] = r_entlight_scale->value * tr.overbrightMult * light_offset[0];
|
||||
if (backEnd.currentSphere->ambient.level[2] >= 255.0) {
|
||||
backEnd.currentSphere->ambient.level[2] = -1;
|
||||
}
|
||||
|
||||
backEnd.currentSphere->ambient.level[3] = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void RB_Sphere_DrawDebugLine(const spherel_t* thislight, float falloff, const vec3_t origin)
|
||||
@@ -81,7 +182,19 @@ void RB_Sphere_BuildDLights()
|
||||
|
||||
void RB_Sphere_SetupEntity()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
if (r_light_nolight->integer)
|
||||
{
|
||||
backEnd.currentSphere->TessFunction = &RB_Light_Fullbright;
|
||||
}
|
||||
else if (RB_Sphere_SetupGlobals() && RB_Sphere_ResetPointColors())
|
||||
{
|
||||
backEnd.currentSphere->numRealLights = 0;
|
||||
RB_Sphere_Light_Sun();
|
||||
RB_Sphere_BuildStaticLights();
|
||||
RB_Sphere_BuildDLights();
|
||||
backEnd.pc.c_characterlights += backEnd.currentSphere->numRealLights;
|
||||
RB_OptimizeLights();
|
||||
}
|
||||
}
|
||||
|
||||
void RB_Grid_SetupEntity()
|
||||
@@ -91,17 +204,103 @@ void RB_Grid_SetupEntity()
|
||||
|
||||
void RB_Grid_SetupStaticModel()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
RB_SetupStaticModelGridLighting(&tr.refdef, backEnd.currentStaticModel, backEnd.currentStaticModel->origin);
|
||||
}
|
||||
|
||||
void RB_Light_Fullbright(const color4ub_t colors)
|
||||
void RB_Light_Fullbright(unsigned char* colors)
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
memset((void*)colors, 0xFF, tess.numVertexes);
|
||||
}
|
||||
|
||||
void R_Sphere_InitLights()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
const char* ents;
|
||||
const char* ret;
|
||||
qboolean bFlareDirSet;
|
||||
|
||||
ents = ri.CM_EntityString();
|
||||
bFlareDirSet = qfalse;
|
||||
s_sun.szFlareName[0] = 0;
|
||||
s_sun.exists = qfalse;
|
||||
|
||||
for (int i = 0; i < 128; i++) {
|
||||
backEnd.spheres[i].TessFunction = &RB_Light_Real;
|
||||
}
|
||||
|
||||
VectorClear(ambientlight);
|
||||
backEnd.spareSphere.TessFunction = &RB_Light_Real;
|
||||
backEnd.currentSphere = &backEnd.spareSphere;
|
||||
bEntityOverbright = qfalse;
|
||||
iEntityLightingMax = tr.identityLightByte;
|
||||
s_sun.color[0] = s_sun.color[1] = s_sun.color[2] = tr.overbrightMult * 70;
|
||||
|
||||
while (ents)
|
||||
{
|
||||
ret = COM_Parse((char**)&ents);
|
||||
if (*ret == '{' || *ret == '}') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(ret, "suncolor") || !strcmp(ret, "sunlight"))
|
||||
{
|
||||
sscanf(COM_Parse((char**)&ents), "%f %f %f", &s_sun.color[0], &s_sun.color[1], &s_sun.color[2]);
|
||||
s_sun.color[0] *= tr.overbrightMult;
|
||||
s_sun.color[1] *= tr.overbrightMult;
|
||||
s_sun.color[2] *= tr.overbrightMult;
|
||||
s_sun.exists = qtrue;
|
||||
}
|
||||
else if (!strcmp(ret, "sundirection"))
|
||||
{
|
||||
vec3_t dir;
|
||||
|
||||
sscanf(COM_Parse((char**)&ents), "%f %f %f", &dir[0], &dir[1], &dir[2]);
|
||||
AngleVectorsLeft(dir, s_sun.direction, 0, 0);
|
||||
|
||||
s_sun.exists = qtrue;
|
||||
if (!bFlareDirSet)
|
||||
{
|
||||
s_sun.flaredirection[0] = s_sun.direction[0];
|
||||
s_sun.flaredirection[1] = s_sun.direction[1];
|
||||
s_sun.flaredirection[2] = s_sun.direction[2];
|
||||
}
|
||||
}
|
||||
else if (!strcmp(ret, "sunflaredirection"))
|
||||
{
|
||||
vec3_t dir;
|
||||
|
||||
sscanf(COM_Parse((char**)&ents), "%f %f %f", &dir[0], &dir[1], &dir[2]);
|
||||
AngleVectorsLeft(dir, s_sun.flaredirection, 0, 0);
|
||||
bFlareDirSet = qtrue;
|
||||
}
|
||||
else if (!strcmp(ret, "sunflarename"))
|
||||
{
|
||||
strcpy(s_sun.szFlareName, COM_Parse((char**)&ents));
|
||||
}
|
||||
else if (!strcmp(ret, "ambientlight"))
|
||||
{
|
||||
sscanf(COM_Parse((char**)&ents), "%f %f %f", &ambientlight[0], &ambientlight[1], &ambientlight[2]);
|
||||
}
|
||||
else if (!strcmp(ret, "overbright"))
|
||||
{
|
||||
ret = COM_Parse((char**)&ents);
|
||||
if (strcmp(ret, "world") || strcmp(ret, "none"))
|
||||
{
|
||||
bEntityOverbright = qtrue;
|
||||
iEntityLightingMax = 0xFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COM_Parse((char**)&ents);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_sun.exists)
|
||||
{
|
||||
if (!s_sun.szFlareName[0]) {
|
||||
strcpy(s_sun.szFlareName, "sun");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int R_GatherLightSources(const vec3_t vPos, vec3_t* pvLightPos, vec3_t* pvLightIntensity, int iMaxLights)
|
||||
|
||||
@@ -56,14 +56,11 @@ void R_InitStaticModels(void) {
|
||||
g = (int)((float)tr.world->staticModelData[i * 4 + 1] * tr.overbrightMult);
|
||||
b = (int)((float)tr.world->staticModelData[i * 4 + 2] * tr.overbrightMult);
|
||||
|
||||
if ((r | g | b) & 0xFFFFFF00)
|
||||
if (r > 0xFF || g > 0xFF || b > 0xFF)
|
||||
{
|
||||
float t;
|
||||
unsigned long long rgb;
|
||||
|
||||
rgb = (g + (~((unsigned long long)(r - g) >> 32) & (r - g)) - b);
|
||||
|
||||
t = 255.0 / (float)(b + (~(rgb & 0x00000000FFFFFFFF) & rgb));
|
||||
t = 255.0 / (float)Q_max(r, Q_max(g, b));
|
||||
|
||||
r = (int)((float)r * t);
|
||||
g = (int)((float)g * t);
|
||||
@@ -117,7 +114,7 @@ void R_InitStaticModels(void) {
|
||||
surf->hShader[k] = sh->index;
|
||||
}
|
||||
else {
|
||||
surf->hShader[k] = NULL;
|
||||
surf->hShader[k] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -326,6 +323,7 @@ void R_AddStaticModelSurfaces(void) {
|
||||
{
|
||||
skelHeaderGame_t* skelmodel = TIKI_GetSkel(tiki->mesh[mesh]);
|
||||
skelSurfaceGame_t* surface;
|
||||
staticSurface_t* s_surface;
|
||||
shader_t* shader;
|
||||
|
||||
if (!skelmodel) {
|
||||
@@ -336,7 +334,7 @@ void R_AddStaticModelSurfaces(void) {
|
||||
// draw all surfaces
|
||||
//
|
||||
surface = skelmodel->pSurfaces;
|
||||
for (j = 0; j < skelmodel->numSurfaces; j++, surface = surface->pNext, dsurf++)
|
||||
for (j = 0; j < skelmodel->numSurfaces; j++, ofsStaticData += surface->numVerts, surface = surface->pNext, dsurf++)
|
||||
{
|
||||
if (g_nStaticSurfaces >= MAX_STATIC_MODELS_SURFS)
|
||||
{
|
||||
@@ -344,18 +342,44 @@ void R_AddStaticModelSurfaces(void) {
|
||||
continue;
|
||||
}
|
||||
|
||||
g_staticSurfaces[g_nStaticSurfaces].ident = SF_TIKI_STATIC;
|
||||
g_staticSurfaces[g_nStaticSurfaces].ofsStaticData = ofsStaticData;
|
||||
g_staticSurfaces[g_nStaticSurfaces].surface = surface;
|
||||
g_staticSurfaces[g_nStaticSurfaces].meshNum = mesh;
|
||||
s_surface = &g_staticSurfaces[g_nStaticSurfaces++];
|
||||
s_surface->ident = SF_TIKI_STATIC;
|
||||
s_surface->ofsStaticData = ofsStaticData;
|
||||
s_surface->surface = surface;
|
||||
s_surface->meshNum = mesh;
|
||||
|
||||
shader = tr.shaders[dsurf->hShader[0]];
|
||||
|
||||
SM->bRendered = qtrue;
|
||||
R_AddDrawSurf((surfaceType_t*)&g_staticSurfaces[g_nStaticSurfaces], shader, 0);
|
||||
if (shader->numUnfoggedPasses == 1)
|
||||
{
|
||||
if (shader->unfoggedStages[0]->alphaGen == AGEN_DIST_FADE)
|
||||
{
|
||||
if (R_DistanceCullPointAndRadius(shader->fDistNear + shader->fDistRange, tiki_worldorigin, SM->cull_radius) == CULL_OUT) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (shader->unfoggedStages[0]->alphaGen == AGEN_ONE_MINUS_DIST_FADE)
|
||||
{
|
||||
if (R_DistanceCullPointAndRadius(shader->fDistNear, tiki_worldorigin, SM->cull_radius) == CULL_IN) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_nStaticSurfaces++;
|
||||
ofsStaticData += surface->numVerts;
|
||||
SM->bRendered = qtrue;
|
||||
R_AddDrawSurf((surfaceType_t*)s_surface, shader, 0);
|
||||
|
||||
if (r_showstaticlod->integer) {
|
||||
//
|
||||
// FIXME: draw debug lods
|
||||
//
|
||||
}
|
||||
|
||||
if (r_showstaticbboxes->integer) {
|
||||
//
|
||||
// FIXME: draw debug bbox
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,7 +390,34 @@ void R_AddStaticModelSurfaces(void) {
|
||||
|
||||
void RB_Static_BuildDLights()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
int i;
|
||||
|
||||
backEnd.currentStaticModel->useSpecialLighting = backEnd.refdef.num_dlights > 0;
|
||||
backEnd.currentStaticModel->numdlights = 0;
|
||||
|
||||
if (!backEnd.currentStaticModel->useSpecialLighting) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < backEnd.refdef.num_dlights && backEnd.currentStaticModel->numdlights != 32; i++) {
|
||||
vec3_t lightorigin, delta;
|
||||
|
||||
VectorCopy(backEnd.refdef.dlights[i].origin, lightorigin);
|
||||
VectorSubtract(lightorigin, backEnd.currentStaticModel->origin, delta);
|
||||
if (backEnd.refdef.dlights[i].radius * 2.0 >= VectorLength(delta)) {
|
||||
MatrixTransformVectorRight(
|
||||
backEnd.currentStaticModel->axis,
|
||||
delta,
|
||||
backEnd.currentStaticModel->dlights[backEnd.currentStaticModel->numdlights].transformed
|
||||
);
|
||||
|
||||
backEnd.currentStaticModel->dlights[backEnd.currentStaticModel->numdlights++].index = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!backEnd.currentStaticModel->numdlights) {
|
||||
backEnd.currentStaticModel->useSpecialLighting = qfalse;
|
||||
}
|
||||
}
|
||||
|
||||
void R_InfoStaticModels_f()
|
||||
@@ -452,19 +503,24 @@ void RB_StaticMesh(staticSurface_t* staticSurf) {
|
||||
Vector4Copy(surf->pStaticXyz[j], tess.xyz[baseVertex + j]);
|
||||
Vector4Copy(surf->pStaticNormal[j], tess.normal[baseVertex + j]);
|
||||
tess.texCoords[baseVertex + j][0][0] = surf->pStaticTexCoords[j][0][0];
|
||||
tess.texCoords[baseVertex + j][0][1] = surf->pStaticTexCoords[j][0][1];
|
||||
tess.texCoords[baseVertex + j][0][1] = surf->pStaticTexCoords[j][0][1];
|
||||
tess.texCoords[baseVertex + j][1][0] = surf->pStaticTexCoords[j][1][0];
|
||||
tess.texCoords[baseVertex + j][1][1] = surf->pStaticTexCoords[j][1][1];
|
||||
}
|
||||
|
||||
if (backEndData[backEnd.smpFrame]->staticModelData) {
|
||||
color4ub_t* in = (color4ub_t*)&backEndData[backEnd.smpFrame]->staticModelData[backEnd.currentStaticModel->firstVertexData + staticSurf->ofsStaticData];
|
||||
color4ub_t* out = &tess.vertexColors[baseVertex];
|
||||
const size_t offset = backEnd.currentStaticModel->firstVertexData + staticSurf->ofsStaticData * sizeof(color4ub_t);
|
||||
assert(offset < tr.world->numStaticModelData * sizeof(color4ub_t));
|
||||
assert(offset + render_count * sizeof(color4ub_t) <= tr.world->numStaticModelData * sizeof(color4ub_t));
|
||||
|
||||
for (i = 0; i < render_count; i++, in++, out++)
|
||||
const color4ub_t* in = (const color4ub_t*)&backEndData[backEnd.smpFrame]->staticModelData[offset];
|
||||
|
||||
for (i = 0; i < render_count; i++)
|
||||
{
|
||||
(*out)[0] = (*in)[0];
|
||||
(*out)[1] = (*in)[1];
|
||||
(*out)[2] = (*in)[2];
|
||||
(*out)[3] = (*in)[3];
|
||||
tess.vertexColors[baseVertex + i][0] = in[i][0];
|
||||
tess.vertexColors[baseVertex + i][1] = in[i][1];
|
||||
tess.vertexColors[baseVertex + i][2] = in[i][2];
|
||||
tess.vertexColors[baseVertex + i][3] = in[i][3];
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -28,3 +28,8 @@ void R_InitLensFlare()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
|
||||
void R_DrawLensFlares()
|
||||
{
|
||||
// FIXME: unimplemented
|
||||
}
|
||||
+106
-12
@@ -343,6 +343,7 @@ RB_SurfaceFace
|
||||
*/
|
||||
void RB_SurfaceFace( srfSurfaceFace_t *surf ) {
|
||||
int i;
|
||||
qboolean needsNormal;
|
||||
unsigned *indices, *tessIndexes;
|
||||
float *v;
|
||||
float *normal;
|
||||
@@ -366,27 +367,48 @@ void RB_SurfaceFace( srfSurfaceFace_t *surf ) {
|
||||
|
||||
tess.numIndexes += surf->numIndices;
|
||||
|
||||
numPoints = surf->numPoints;
|
||||
|
||||
needsNormal = qfalse;
|
||||
if (tess.shader->needsNormal || tess.shader->needsLSpherical || tr.refdef.num_dlights) {
|
||||
needsNormal = qtrue;
|
||||
}
|
||||
|
||||
v = surf->points[0];
|
||||
|
||||
ndx = tess.numVertexes;
|
||||
|
||||
numPoints = surf->numPoints;
|
||||
|
||||
if ( tess.shader->needsNormal || tess.shader->needsLSpherical || tr.refdef.num_dlights ) {
|
||||
if (needsNormal) {
|
||||
normal = surf->plane.normal;
|
||||
for ( i = 0, ndx = tess.numVertexes; i < numPoints; i++, ndx++ ) {
|
||||
VectorCopy( normal, tess.normal[ndx] );
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0, v = surf->points[0], ndx = tess.numVertexes; i < numPoints; i++, v += VERTEXSIZE, ndx++ ) {
|
||||
VectorCopy( v, tess.xyz[ndx]);
|
||||
tess.texCoords[ndx][0][0] = v[3];
|
||||
tess.texCoords[ndx][0][1] = v[4];
|
||||
tess.texCoords[ndx][1][0] = v[5];
|
||||
tess.texCoords[ndx][1][1] = v[6];
|
||||
* ( unsigned int * ) &tess.vertexColors[ndx] = * ( unsigned int * ) &v[7];
|
||||
tess.vertexDlightBits[ndx] = dlightBits;
|
||||
if (tess.dlightMap)
|
||||
{
|
||||
|
||||
for (i = 0, v = surf->points[0], ndx = tess.numVertexes; i < numPoints; i++, v += VERTEXSIZE, ndx++) {
|
||||
VectorCopy(v, tess.xyz[ndx]);
|
||||
tess.texCoords[ndx][0][0] = v[3];
|
||||
tess.texCoords[ndx][0][1] = v[4];
|
||||
tess.texCoords[ndx][1][0] = v[5] + surf->lightmapOffset[0];
|
||||
tess.texCoords[ndx][1][1] = v[6] + surf->lightmapOffset[1];
|
||||
*(unsigned int*)&tess.vertexColors[ndx] = *(unsigned int*)&v[7];
|
||||
tess.vertexDlightBits[ndx] = dlightBits;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0, v = surf->points[0], ndx = tess.numVertexes; i < numPoints; i++, v += VERTEXSIZE, ndx++) {
|
||||
VectorCopy(v, tess.xyz[ndx]);
|
||||
tess.texCoords[ndx][0][0] = v[3];
|
||||
tess.texCoords[ndx][0][1] = v[4];
|
||||
tess.texCoords[ndx][1][0] = v[5];
|
||||
tess.texCoords[ndx][1][1] = v[6];
|
||||
*(unsigned int*)&tess.vertexColors[ndx] = *(unsigned int*)&v[7];
|
||||
tess.vertexDlightBits[ndx] = dlightBits;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -718,7 +740,79 @@ void RB_SurfaceSkip( void *surf ) {
|
||||
}
|
||||
|
||||
void RB_DrawTerrainTris(srfTerrain_t* p) {
|
||||
// FIXME: unimplemented
|
||||
int i;
|
||||
terraInt numv;
|
||||
int dlightBits;
|
||||
|
||||
if (tess.numVertexes + p->nVerts >= SHADER_MAX_VERTEXES || tess.numIndexes + p->nTris * 3 >= SHADER_MAX_INDEXES) {
|
||||
RB_CheckOverflow(p->nVerts, 3 * p->nTris);
|
||||
}
|
||||
|
||||
dlightBits = p->dlightBits[backEnd.smpFrame];
|
||||
tess.dlightBits |= dlightBits;
|
||||
if (p->dlightMap[backEnd.smpFrame])
|
||||
{
|
||||
float lmScale = (1 / 128.0) / p->lmapStep;
|
||||
|
||||
for (i = p->iVertHead; i; i = g_pVert[i].iNext) {
|
||||
assert(tess.numVertexes < SHADER_MAX_VERTEXES);
|
||||
|
||||
VectorCopy(g_pVert[i].xyz, tess.xyz[tess.numVertexes]);
|
||||
tess.texCoords[tess.numVertexes][0][0] = g_pVert[i].texCoords[0][0];
|
||||
tess.texCoords[tess.numVertexes][0][1] = g_pVert[i].texCoords[0][1];
|
||||
tess.texCoords[tess.numVertexes][1][0] = g_pVert[i].texCoords[1][0] * lmScale + p->lmapX;
|
||||
tess.texCoords[tess.numVertexes][1][1] = g_pVert[i].texCoords[1][1] * lmScale + p->lmapY;
|
||||
tess.normal[tess.numVertexes][0] = 0;
|
||||
tess.normal[tess.numVertexes][1] = 0;
|
||||
tess.normal[tess.numVertexes][2] = 1.0;
|
||||
tess.vertexColors[tess.numVertexes][0] = -1;
|
||||
tess.vertexColors[tess.numVertexes][1] = -1;
|
||||
tess.vertexColors[tess.numVertexes][2] = -1;
|
||||
tess.vertexColors[tess.numVertexes][3] = -1;
|
||||
|
||||
g_pVert[i].iVertArray = tess.numVertexes;
|
||||
tess.numVertexes++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = p->iVertHead; i; i = g_pVert[i].iNext) {
|
||||
assert(tess.numVertexes < SHADER_MAX_VERTEXES);
|
||||
|
||||
VectorCopy(g_pVert[i].xyz, tess.xyz[tess.numVertexes]);
|
||||
tess.texCoords[tess.numVertexes][0][0] = g_pVert[i].texCoords[0][0];
|
||||
tess.texCoords[tess.numVertexes][0][1] = g_pVert[i].texCoords[0][1];
|
||||
tess.texCoords[tess.numVertexes][1][0] = g_pVert[i].texCoords[1][0];
|
||||
tess.texCoords[tess.numVertexes][1][1] = g_pVert[i].texCoords[1][1];
|
||||
tess.vertexDlightBits[tess.numVertexes] = dlightBits;
|
||||
tess.normal[tess.numVertexes][0] = 0;
|
||||
tess.normal[tess.numVertexes][1] = 0;
|
||||
tess.normal[tess.numVertexes][2] = 1.0;
|
||||
tess.vertexColors[tess.numVertexes][0] = -1;
|
||||
tess.vertexColors[tess.numVertexes][1] = -1;
|
||||
tess.vertexColors[tess.numVertexes][2] = -1;
|
||||
tess.vertexColors[tess.numVertexes][3] = -1;
|
||||
|
||||
g_pVert[i].iVertArray = tess.numVertexes;
|
||||
tess.numVertexes++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = p->iTriHead; i; i = g_pTris[i].iNext)
|
||||
{
|
||||
assert(tess.numVertexes < SHADER_MAX_INDEXES);
|
||||
|
||||
//
|
||||
// Make sure these can be drawn
|
||||
//
|
||||
if (g_pTris[i].byConstChecks & 4)
|
||||
{
|
||||
tess.indexes[tess.numIndexes] = g_pVert[g_pTris[i].iPt[0]].iVertArray;
|
||||
tess.indexes[tess.numIndexes + 1] = g_pVert[g_pTris[i].iPt[1]].iVertArray;
|
||||
tess.indexes[tess.numIndexes + 2] = g_pVert[g_pTris[i].iPt[2]].iVertArray;
|
||||
tess.numIndexes += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = {
|
||||
|
||||
+1367
-21
File diff suppressed because it is too large.
Load diff
+48
-14
@@ -407,46 +407,56 @@ static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits )
|
||||
if ( !r_nocull->integer ) {
|
||||
int r;
|
||||
|
||||
if ( planeBits & 1 ) {
|
||||
if (planeBits & 1) {
|
||||
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[0]);
|
||||
if (r == 2) {
|
||||
return; // culled
|
||||
}
|
||||
if ( r == 1 ) {
|
||||
if (r == 1) {
|
||||
planeBits &= ~1; // all descendants will also be in front
|
||||
}
|
||||
}
|
||||
|
||||
if ( planeBits & 2 ) {
|
||||
if (planeBits & 2) {
|
||||
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[1]);
|
||||
if (r == 2) {
|
||||
return; // culled
|
||||
}
|
||||
if ( r == 1 ) {
|
||||
if (r == 1) {
|
||||
planeBits &= ~2; // all descendants will also be in front
|
||||
}
|
||||
}
|
||||
|
||||
if ( planeBits & 4 ) {
|
||||
if (planeBits & 4) {
|
||||
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[2]);
|
||||
if (r == 2) {
|
||||
return; // culled
|
||||
}
|
||||
if ( r == 1 ) {
|
||||
if (r == 1) {
|
||||
planeBits &= ~4; // all descendants will also be in front
|
||||
}
|
||||
}
|
||||
|
||||
if ( planeBits & 8 ) {
|
||||
if (planeBits & 8) {
|
||||
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[3]);
|
||||
if (r == 2) {
|
||||
return; // culled
|
||||
}
|
||||
if ( r == 1 ) {
|
||||
if (r == 1) {
|
||||
planeBits &= ~8; // all descendants will also be in front
|
||||
}
|
||||
}
|
||||
|
||||
if (planeBits & 16) {
|
||||
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[4]);
|
||||
if (r == 2) {
|
||||
return; // culled
|
||||
}
|
||||
if (r == 1) {
|
||||
planeBits &= ~16; // all descendants will also be in front
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( node->contents != -1 ) {
|
||||
@@ -488,6 +498,8 @@ static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits )
|
||||
tr.viewParms.visBounds[1][2] = node->maxs[2];
|
||||
}
|
||||
|
||||
tr.portalsky.cntNode = node;
|
||||
|
||||
if (r_drawbrushes->integer) {
|
||||
// add the individual surfaces
|
||||
mark = node->firstmarksurface;
|
||||
@@ -501,20 +513,42 @@ static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits )
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: terrain
|
||||
// FIXME: static decals
|
||||
// FIXME: static models
|
||||
if (r_drawterrain->integer)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < node->numTerraPatches; i++) {
|
||||
R_MarkTerrainPatch(tr.world->visTerraPatches[node->firstTerraPatch + i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (r_drawstaticdecals->integer) {
|
||||
if (node->pFirstMarkFragment) {
|
||||
R_AddPermanentMarkFragmentSurfaces(node->pFirstMarkFragment, node->iNumMarkFragment);
|
||||
}
|
||||
}
|
||||
|
||||
if (r_drawstaticmodels->integer) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < node->numStaticModels; i++) {
|
||||
tr.world->visStaticModels[node->firstStaticModel + i]->visCount = tr.visCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int R_SphereInLeafs(vec_t* p, float r, mnode_t** nodes, int nMaxNodes) {
|
||||
// FIXME: unimplemented
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
===============
|
||||
R_PointInLeaf
|
||||
===============
|
||||
*/
|
||||
static mnode_t *R_PointInLeaf( const vec3_t p ) {
|
||||
mnode_t *R_PointInLeaf( const vec3_t p ) {
|
||||
mnode_t *node;
|
||||
float d;
|
||||
cplane_t *plane;
|
||||
@@ -685,7 +719,7 @@ void R_AddWorldSurfaces (void) {
|
||||
tr.refdef.num_dlights = 32;
|
||||
}
|
||||
R_TransformDlights(tr.refdef.num_dlights, tr.refdef.dlights, &tr.viewParms.world);
|
||||
R_RecursiveWorldNode(tr.world->nodes, 15, (1 << tr.refdef.num_dlights) - 1);
|
||||
R_RecursiveWorldNode(tr.world->nodes, tr.viewParms.fog.extrafrustums ? 31 : 15, (1 << tr.refdef.num_dlights) - 1);
|
||||
|
||||
if (r_drawterrain->integer) {
|
||||
R_AddTerrainSurfaces();
|
||||
|
||||
+28
-6
@@ -439,9 +439,15 @@ gotnewcl:
|
||||
Com_DPrintf( "Going from CS_FREE to CS_CONNECTED for %s\n", newcl->name );
|
||||
|
||||
newcl->state = CS_CONNECTED;
|
||||
newcl->nextSnapshotTime = svs.time;
|
||||
newcl->lastPacketTime = svs.time;
|
||||
newcl->lastConnectTime = svs.time;
|
||||
if (sv_maxclients->integer > 1) {
|
||||
newcl->nextSnapshotTime = svs.time + 800;
|
||||
newcl->lastPacketTime = svs.time + 800;
|
||||
newcl->lastConnectTime = svs.time + 800;
|
||||
} else {
|
||||
newcl->nextSnapshotTime = svs.time + 300;
|
||||
newcl->lastPacketTime = svs.time + 300;
|
||||
newcl->lastConnectTime = svs.time + 300;
|
||||
}
|
||||
|
||||
// when we receive the first packet from the client, we will
|
||||
// notice that it is from a different serverid and that the
|
||||
@@ -530,6 +536,19 @@ void SV_DropClient( client_t *drop, const char *reason ) {
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_GAME_PROTOCOL >= 15
|
||||
|
||||
void MSG_WriteServerFrameTime(msg_t* msg, float f) {
|
||||
MSG_WriteFloat(msg, f);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void MSG_WriteServerFrameTime(msg_t* msg, float f) {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
================
|
||||
SV_SendClientGameState
|
||||
@@ -583,7 +602,7 @@ void SV_SendClientGameState( client_t *client ) {
|
||||
if (sv.configstrings[start][0]) {
|
||||
MSG_WriteSVC( &msg, svc_configstring );
|
||||
MSG_WriteShort( &msg, start );
|
||||
MSG_WriteString( &msg, sv.configstrings[start] );
|
||||
MSG_WriteScrambledBigString( &msg, sv.configstrings[start] );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -604,7 +623,10 @@ void SV_SendClientGameState( client_t *client ) {
|
||||
MSG_WriteLong( &msg, client - svs.clients);
|
||||
|
||||
// write the checksum feed
|
||||
MSG_WriteLong( &msg, sv.checksumFeed);
|
||||
MSG_WriteLong( &msg, 0);
|
||||
|
||||
// write the server frametime to the client (only on TA/TT)
|
||||
MSG_WriteServerFrameTime(&msg, sv.frameTime);
|
||||
|
||||
// deliver this to the client
|
||||
SV_SendMessageToClient( &msg, client );
|
||||
@@ -1310,7 +1332,7 @@ static qboolean SV_ClientCommand( client_t *cl, msg_t *msg ) {
|
||||
qboolean clientOk = qtrue;
|
||||
|
||||
seq = MSG_ReadLong( msg );
|
||||
s = MSG_ReadString( msg );
|
||||
s = MSG_ReadScrambledString( msg );
|
||||
|
||||
// see if we have already executed it
|
||||
if ( cl->lastClientCommand >= seq ) {
|
||||
|
||||
@@ -521,6 +521,7 @@ void SV_ClearServer(void) {
|
||||
}
|
||||
}
|
||||
Com_Memset (&sv, 0, sizeof(sv));
|
||||
sv.frameTime = 1.0 / sv_fps->value;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1012,7 +1013,7 @@ void SV_Init( void ) {
|
||||
sv_showloss = Cvar_Get ("sv_showloss", "0", 0);
|
||||
sv_padPackets = Cvar_Get ("sv_padPackets", "0", 0);
|
||||
sv_killserver = Cvar_Get ("sv_killserver", "0", 0);
|
||||
sv_mapChecksum = Cvar_Get ("sv_mapChecksum", "", CVAR_ROM);
|
||||
sv_mapChecksum = Cvar_Get ("sv_mapChecksum", "", CVAR_ROM | CVAR_SERVERINFO);
|
||||
sv_drawentities = Cvar_Get( "sv_drawentities", "1", 0 );
|
||||
sv_deeptracedebug = Cvar_Get( "sv_deeptracedebug", "0", 0 );
|
||||
sv_chatter = Cvar_Get( "sv_chatter", "0", 0 );
|
||||
|
||||
Loaded 100 of 136 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user