diff --git a/engine/Makefile b/engine/Makefile
index 9447e4f02..b5b1225b7 100644
--- a/engine/Makefile
+++ b/engine/Makefile
@@ -324,7 +324,7 @@ ifeq ($(FTE_TARGET),vc)
else
WARNINGFLAGS=-Wall -Wno-pointer-sign
- GNUC_FUNCS= -Dstrnicmp=strncasecmp -Dstricmp=strcasecmp -D_vsnprintf=vsnprintf -D_snprintf=snprintf
+ GNUC_FUNCS= -Dstrnicmp=strncasecmp -Dstricmp=strcasecmp
endif
BASE_CFLAGS=$(WARNINGFLAGS) $(GNUC_FUNCS) -I$(CLIENT_DIR) -I$(SERVER_DIR) -I$(COMMON_DIR) -I$(GL_DIR) -I$(D3D_DIR) -I$(PROGS_DIR) -I$(BOTLIB_DIR) -I$(LIBS_DIR) -I$(LIBS_DIR)/dxsdk9/include -I$(LIBS_DIR)/sdl/include -I/usr/include/SDL -I$(LIBS_DIR)/sdl/include/SDL -I./libs/freetype2/include -I./libs/freetype2/include/freetype -I./libs/speex -DBOTLIB $(SVNREVISION)
@@ -335,10 +335,11 @@ DEBUG_CFLAGS=-ggdb -g
RELEASE_CFLAGS?=-O3 -ffast-math $(CPUOPTIMIZATIONS)
#incase our compiler doesn't support it (mingw)
-ifeq ($(shell $(CC) -rdynamic 2>&1 | grep unrecognised),)
+ifeq ($(shell LANG=c $(CC) -rdynamic 2>&1 | grep unrecognized),)
DEBUG_CFLAGS+= -rdynamic
endif
+OBJS+=$(SPEEX_OBJS)
PROFILE_CFLAGS=-pg
DX7SDK=-I./libs/dxsdk7/include/
@@ -347,6 +348,49 @@ GLCFLAGS=-DGLQUAKE
D3DCFLAGS=-DD3DQUAKE
NPFTECFLAGS=-DNPFTE
+SPEEX_OBJS = \
+ bits.o \
+ buffer.o \
+ cb_search.o \
+ exc_10_16_table.o \
+ exc_10_32_table.o \
+ exc_20_32_table.o \
+ exc_5_256_table.o \
+ exc_5_64_table.o \
+ exc_8_128_table.o \
+ fftwrap.o \
+ filterbank.o \
+ filters.o \
+ gain_table.o \
+ gain_table_lbr.o \
+ hexc_10_32_table.o \
+ hexc_table.o \
+ high_lsp_tables.o \
+ jitter.o \
+ kiss_fft.o \
+ kiss_fftr.o \
+ lpc.o \
+ lsp.o \
+ lsp_tables_nb.o \
+ ltp.o \
+ mdf.o \
+ modes.o \
+ modes_wb.o \
+ nb_celp.o \
+ preprocess.o \
+ quant_lsp.o \
+ resample.o \
+ sb_celp.o \
+ scal.o \
+ smallft.o \
+ speex.o \
+ speex_callbacks.o \
+ speex_header.o \
+ stereo.o \
+ vbr.o \
+ vq.o \
+ window.o
+
CLIENT_OBJS = \
textedit.o \
fragstats.o \
@@ -731,6 +775,8 @@ ifeq ($(shell echo $(FTE_TARGET)|grep -E -v "win(32|64)$$"),)
BITS=64
endif
+ BASELDFLAGS=
+
SV_CFLAGS=$(SERVER_ONLY_CFLAGS) $(W32_CFLAGS)
LIBS_DIR = $(BASE_DIR)/libs
@@ -985,6 +1031,13 @@ endif
VPATH = $(BASE_DIR) : $(CLIENT_DIR) : $(GL_DIR) : $(COMMON_DIR) : $(SERVER_DIR) : $(HTTP_DIR) : $(BASE_DIR)/irc : $(BASE_DIR)/email : $(QUX_DIR) : $(PROGS_DIR) : $(NACL_DIR) : $(SNDCODEC_DIR) : $(D3D_DIR) : $(BOTLIB_DIR)
+ifneq ($(findstring -DSPEEX_STATIC, $(CFLAGS)),)
+ #add these to statically link libspeex
+ VPATH += : $(BASE_DIR)/libs/speex-1.2rc1/libspeex
+ BASE_CFLAGS += -DSPEEX_STATIC -I$(BASE_DIR)/libs/speex-1.2rc1/include -DFIXED_POINT -DUSE_KISS_FFT -DEXPORT=""
+ CLIENT_OBJS += $(SPEEX_OBJS)
+endif
+
# This is for linking the FTE icon to the MinGW target
$(OUT_DIR)/resources.o : winquake.rc
$(WINDRES) -I$(CLIENT_DIR) -O coff $< $@
@@ -1054,75 +1107,75 @@ $(OUT_DIR)/$(EXE_NAME): $(PRECOMPHEADERS) $(foreach fn, $(CUSTOMOBJS) $(foreac
$(DO_LD) $(foreach fn, $(CUSTOMOBJS) $(foreach ol, $(OBJS) $(LTO_END), $($(ol))),$(if $(findstring ltox,$(fn)),$(subst ltox,-x ,$(fn)),$(OUT_DIR)/$(fn)) ) $(LDFLAGS)
_out-rel:
- $(MAKE) $(OUT_DIR)/$(EXE_NAME) EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(WCFLAGS) $(RELEASE_CFLAGS)" LDFLAGS="$(BASELDFLAGS) $(LDFLAGS) $(RELEASE_LDFLAGS)" OBJS="$(OBJS)"
+ @$(MAKE) $(OUT_DIR)/$(EXE_NAME) EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(WCFLAGS) $(RELEASE_CFLAGS)" LDFLAGS="$(BASELDFLAGS) $(LDFLAGS) $(RELEASE_LDFLAGS)" OBJS="$(OBJS)"
$(STRIP) $(STRIPFLAGS) $(OUT_DIR)/$(EXE_NAME)
_out-dbg:
- $(MAKE) $(OUT_DIR)/$(EXE_NAME) EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(WCFLAGS) $(DEBUG_CFLAGS)" LDFLAGS="$(BASELDFLAGS) $(LDFLAGS) $(DEBUG_LDFLAGS)" OBJS="$(OBJS)"
+ @$(MAKE) $(OUT_DIR)/$(EXE_NAME) EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(WCFLAGS) $(DEBUG_CFLAGS)" LDFLAGS="$(BASELDFLAGS) $(LDFLAGS) $(DEBUG_LDFLAGS)" OBJS="$(OBJS)"
_out-profile:
- $(MAKE) $(OUT_DIR)/$(EXE_NAME) EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(WCFLAGS) $(PROFILE_CFLAGS)" LDFLAGS="$(BASELDFLAGS) $(LDFLAGS) $(PROFILE_LDFLAGS)" OBJS="$(OBJS)"
+ @$(MAKE) $(OUT_DIR)/$(EXE_NAME) EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(WCFLAGS) $(PROFILE_CFLAGS)" LDFLAGS="$(BASELDFLAGS) $(LDFLAGS) $(PROFILE_LDFLAGS)" OBJS="$(OBJS)"
_cl-rel: reldir
- $(MAKE) _out-rel EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(CLIENT_ONLY_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS"
+ @$(MAKE) _out-rel EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(CLIENT_ONLY_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS"
_cl-dbg: debugdir
- $(MAKE) _out-dbg EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(CLIENT_ONLY_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS"
+ @$(MAKE) _out-dbg EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(CLIENT_ONLY_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS"
_cl-profile: reldir
- $(MAKE) _out-profile EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(CLIENT_ONLY_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS"
+ @$(MAKE) _out-profile EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(CLIENT_ONLY_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS"
_clsv-rel: reldir
- $(MAKE) _out-rel EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(JOINT_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS SERVER_OBJS"
+ @$(MAKE) _out-rel EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(JOINT_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS SERVER_OBJS"
_clsv-dbg: debugdir
- $(MAKE) _out-dbg EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(JOINT_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS SERVER_OBJS"
+ @$(MAKE) _out-dbg EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(JOINT_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS SERVER_OBJS"
_clsv-profile: reldir
- $(MAKE) _out-profile EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(JOINT_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS SERVER_OBJS"
+ @$(MAKE) _out-profile EXE_NAME="$(EXE_NAME)" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(JOINT_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" SOBJS="$(SOBJS)" OBJS="SOBJS COMMON_OBJS CLIENT_OBJS PROGS_OBJS SERVER_OBJS"
sv-tmp: reldir debugdir
- $(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(SV_EXE_NAME)" WCFLAGS="$(SV_CFLAGS)" LDFLAGS="$(SV_LDFLAGS) $(LDFLAGS)" OBJS="SV_OBJS"
+ @$(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(SV_EXE_NAME)" WCFLAGS="$(SV_CFLAGS)" LDFLAGS="$(SV_LDFLAGS) $(LDFLAGS)" OBJS="SV_OBJS"
sv-rel:
- $(MAKE) sv-tmp TYPE=_out-rel OUT_DIR="$(RELEASE_DIR)/$(SV_DIR)"
+ @$(MAKE) sv-tmp TYPE=_out-rel OUT_DIR="$(RELEASE_DIR)/$(SV_DIR)"
sv-dbg:
- $(MAKE) sv-tmp TYPE=_out-dbg OUT_DIR="$(DEBUG_DIR)/$(SV_DIR)"
+ @$(MAKE) sv-tmp TYPE=_out-dbg OUT_DIR="$(DEBUG_DIR)/$(SV_DIR)"
sv-profile:
- $(MAKE) sv-tmp TYPE=_out-profile OUT_DIR="$(PROFILE_DIR)/$(SV_DIR)"
+ @$(MAKE) sv-tmp TYPE=_out-profile OUT_DIR="$(PROFILE_DIR)/$(SV_DIR)"
d3dcl-tmp:
- $(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(D3DCL_EXE_NAME)" WCFLAGS="$(D3D_CFLAGS)" LDFLAGS="$(D3D_LDFLAGS) $(LDFLAGS)" SOBJS="$(D3DCL_OBJS)"
+ @$(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(D3DCL_EXE_NAME)" WCFLAGS="$(D3D_CFLAGS)" LDFLAGS="$(D3D_LDFLAGS) $(LDFLAGS)" SOBJS="$(D3DCL_OBJS)"
d3d-tmp:
- $(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(D3D_EXE_NAME)" WCFLAGS="$(D3D_CFLAGS)" LDFLAGS="$(D3D_LDFLAGS) $(LDFLAGS)" SOBJS="$(D3DCL_OBJS)"
+ @$(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(D3D_EXE_NAME)" WCFLAGS="$(D3D_CFLAGS)" LDFLAGS="$(D3D_LDFLAGS) $(LDFLAGS)" SOBJS="$(D3DCL_OBJS)"
d3dcl-rel:
- $(MAKE) d3dcl-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(D3DCL_DIR)"
+ @$(MAKE) d3dcl-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(D3DCL_DIR)"
d3dcl-dbg:
- $(MAKE) d3dcl-tmp TYPE=_cl-dbg OUT_DIR="$(DEBUG_DIR)/$(D3DCL_DIR)"
+ @$(MAKE) d3dcl-tmp TYPE=_cl-dbg OUT_DIR="$(DEBUG_DIR)/$(D3DCL_DIR)"
d3dcl-profile:
- $(MAKE) d3dcl-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(D3DCL_DIR)"
+ @$(MAKE) d3dcl-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(D3DCL_DIR)"
d3d-rel:
- $(MAKE) d3d-tmp TYPE=_clsv-rel OUT_DIR="$(RELEASE_DIR)/$(D3DB_DIR)"
+ @$(MAKE) d3d-tmp TYPE=_clsv-rel OUT_DIR="$(RELEASE_DIR)/$(D3DB_DIR)"
d3d-dbg:
- $(MAKE) d3d-tmp TYPE=_clsv-dbg OUT_DIR="$(DEBUG_DIR)/$(D3DB_DIR)"
+ @$(MAKE) d3d-tmp TYPE=_clsv-dbg OUT_DIR="$(DEBUG_DIR)/$(D3DB_DIR)"
d3d-profile:
- $(MAKE) d3d-tmp TYPE=_clsv-profile OUT_DIR="$(PROFILE_DIR)/$(D3DB_DIR)"
+ @$(MAKE) d3d-tmp TYPE=_clsv-profile OUT_DIR="$(PROFILE_DIR)/$(D3DB_DIR)"
npqtvcl-tmp:
- $(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(NPFTECL_DLL_NAME)" WCFLAGS="$(NPFTE_CFLAGS)" LDFLAGS="$(NPFTE_LDFLAGS) $(LDFLAGS)" SOBJS="$(NPFTECL_OBJS)"
+ @$(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(NPFTECL_DLL_NAME)" WCFLAGS="$(NPFTE_CFLAGS)" LDFLAGS="$(NPFTE_LDFLAGS) $(LDFLAGS)" SOBJS="$(NPFTECL_OBJS)"
npfte-tmp:
- $(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(NPFTE_DLL_NAME)" WCFLAGS="$(NPFTE_CFLAGS)" LDFLAGS="$(NPFTE_LDFLAGS) $(LDFLAGS)" SOBJS="$(NPFTECL_OBJS)"
+ @$(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(NPFTE_DLL_NAME)" WCFLAGS="$(NPFTE_CFLAGS)" LDFLAGS="$(NPFTE_LDFLAGS) $(LDFLAGS)" SOBJS="$(NPFTECL_OBJS)"
npqtvcl-rel:
- $(MAKE) npqtvcl-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(NPFTECL_DIR)"
+ @$(MAKE) npqtvcl-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(NPFTECL_DIR)"
npqtvcl-dbg:
- $(MAKE) npqtvcl-tmp TYPE=_cl-dbg OUT_DIR="$(DEBUG_DIR)/$(NPFTECL_DIR)"
+ @$(MAKE) npqtvcl-tmp TYPE=_cl-dbg OUT_DIR="$(DEBUG_DIR)/$(NPFTECL_DIR)"
npqtvcl-profile:
- $(MAKE) npqtvcl-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(NPFTECL_DIR)"
+ @$(MAKE) npqtvcl-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(NPFTECL_DIR)"
npfte-rel:
- $(MAKE) npfte-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(NPFTEB_DIR)"
+ @$(MAKE) npfte-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(NPFTEB_DIR)"
cp $(RELEASE_DIR)/npfte.dll npfte/plugins
cd npfte && zip $(abspath $(RELEASE_DIR)/npfte.xpi) install.rdf plugins/npfte.dll
rm -rf /tmp/npfte
@@ -1132,54 +1185,54 @@ npfte-rel:
cd $(RELEASE_DIR)/ && ../npfte/crxmake.sh /tmp/npfte ../npfte/chrome.pem
rm -rf /tmp/npfte
npfte-dbg:
- $(MAKE) npfte-tmp TYPE=_clsv-dbg OUT_DIR="$(DEBUG_DIR)/$(NPFTEB_DIR)"
+ @$(MAKE) npfte-tmp TYPE=_clsv-dbg OUT_DIR="$(DEBUG_DIR)/$(NPFTEB_DIR)"
npfte-profile:
- $(MAKE) npfte-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(NPFTEB_DIR)"
+ @$(MAKE) npfte-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(NPFTEB_DIR)"
glcl-tmp:
- $(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(GLCL_EXE_NAME)" WCFLAGS="$(GL_CFLAGS)" LDFLAGS="$(GL_LDFLAGS) $(LDFLAGS)" SOBJS="$(GLCL_OBJS)"
+ @$(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(GLCL_EXE_NAME)" WCFLAGS="$(GL_CFLAGS)" LDFLAGS="$(GL_LDFLAGS) $(LDFLAGS)" SOBJS="$(GLCL_OBJS)"
gl-tmp:
- $(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(GL_EXE_NAME)" WCFLAGS="$(GL_CFLAGS)" LDFLAGS="$(GL_LDFLAGS) $(LDFLAGS)" SOBJS="$(GLCL_OBJS)"
+ @$(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(GL_EXE_NAME)" WCFLAGS="$(GL_CFLAGS)" LDFLAGS="$(GL_LDFLAGS) $(LDFLAGS)" SOBJS="$(GLCL_OBJS)"
glcl-rel:
- $(MAKE) glcl-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(GLCL_DIR)"
+ @$(MAKE) glcl-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(GLCL_DIR)"
glcl-dbg:
- $(MAKE) glcl-tmp TYPE=_cl-dbg OUT_DIR="$(DEBUG_DIR)/$(GLCL_DIR)"
+ @$(MAKE) glcl-tmp TYPE=_cl-dbg OUT_DIR="$(DEBUG_DIR)/$(GLCL_DIR)"
glcl-profile:
- $(MAKE) glcl-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(GLCL_DIR)"
+ @$(MAKE) glcl-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(GLCL_DIR)"
gl-rel:
- $(MAKE) gl-tmp TYPE=_clsv-rel OUT_DIR="$(RELEASE_DIR)/$(GLB_DIR)"
+ @$(MAKE) gl-tmp TYPE=_clsv-rel OUT_DIR="$(RELEASE_DIR)/$(GLB_DIR)"
gl-dbg:
- $(MAKE) gl-tmp TYPE=_clsv-dbg OUT_DIR="$(DEBUG_DIR)/$(GLB_DIR)"
+ @$(MAKE) gl-tmp TYPE=_clsv-dbg OUT_DIR="$(DEBUG_DIR)/$(GLB_DIR)"
gl-profile:
- $(MAKE) gl-tmp TYPE=_clsv-profile OUT_DIR="$(PROFILE_DIR)/$(GLB_DIR)"
+ @$(MAKE) gl-tmp TYPE=_clsv-profile OUT_DIR="$(PROFILE_DIR)/$(GLB_DIR)"
mingl-tmp: reldir
- $(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(MINGL_EXE_NAME)" WCFLAGS="$(GL_CFLAGS) -DMINIMAL" LDFLAGS="$(GL_LDFLAGS) $(LDFLAGS)" SOBJS="$(GLCL_OBJS)"
+ @$(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(MINGL_EXE_NAME)" WCFLAGS="$(GL_CFLAGS) -DMINIMAL" LDFLAGS="$(GL_LDFLAGS) $(LDFLAGS)" SOBJS="$(GLCL_OBJS)"
mingl-rel:
- $(MAKE) mingl-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(MINGL_DIR)"
+ @$(MAKE) mingl-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(MINGL_DIR)"
mingl-dbg:
- $(MAKE) mingl-tmp TYPE=_cl-dbg OUT_DIR="$(DEBUG_DIR)/$(MINGL_DIR)"
+ @$(MAKE) mingl-tmp TYPE=_cl-dbg OUT_DIR="$(DEBUG_DIR)/$(MINGL_DIR)"
mingl-profile:
- $(MAKE) mingl-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(MINGL_DIR)"
+ @$(MAKE) mingl-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(MINGL_DIR)"
mcl-tmp:
- $(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(MCL_EXE_NAME)" WCFLAGS="$(M_CFLAGS)" LDFLAGS="$(M_LDFLAGS) $(LDFLAGS)" SOBJS="$(MCL_OBJS)"
+ @$(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(MCL_EXE_NAME)" WCFLAGS="$(M_CFLAGS)" LDFLAGS="$(M_LDFLAGS) $(LDFLAGS)" SOBJS="$(MCL_OBJS)"
m-tmp:
- $(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(M_EXE_NAME)" WCFLAGS="$(M_CFLAGS)" LDFLAGS="$(M_LDFLAGS) $(LDFLAGS)" SOBJS="$(MCL_OBJS)"
+ @$(MAKE) $(TYPE) OUT_DIR="$(OUT_DIR)" EXE_NAME="$(M_EXE_NAME)" WCFLAGS="$(M_CFLAGS)" LDFLAGS="$(M_LDFLAGS) $(LDFLAGS)" SOBJS="$(MCL_OBJS)"
mcl-rel:
- $(MAKE) mcl-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(MCL_DIR)"
+ @$(MAKE) mcl-tmp TYPE=_cl-rel OUT_DIR="$(RELEASE_DIR)/$(MCL_DIR)"
mcl-dbg:
- $(MAKE) mcl-tmp TYPE=_cl-dbg OUT_DIR="$(DEBUG_DIR)/$(MCL_DIR)"
+ @$(MAKE) mcl-tmp TYPE=_cl-dbg OUT_DIR="$(DEBUG_DIR)/$(MCL_DIR)"
mcl-profile:
- $(MAKE) mcl-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(MCL_DIR)"
+ @$(MAKE) mcl-tmp TYPE=_cl-profile OUT_DIR="$(PROFILE_DIR)/$(MCL_DIR)"
m-rel:
- $(MAKE) m-tmp TYPE=_clsv-rel OUT_DIR="$(RELEASE_DIR)/$(MB_DIR)"
+ @$(MAKE) m-tmp TYPE=_clsv-rel OUT_DIR="$(RELEASE_DIR)/$(MB_DIR)"
m-dbg:
- $(MAKE) m-tmp TYPE=_clsv-dbg OUT_DIR="$(DEBUG_DIR)/$(MB_DIR)"
+ @$(MAKE) m-tmp TYPE=_clsv-dbg OUT_DIR="$(DEBUG_DIR)/$(MB_DIR)"
m-profile:
- $(MAKE) m-tmp TYPE=_clsv-profile OUT_DIR="$(PROFILE_DIR)/$(MB_DIR)"
+ @$(MAKE) m-tmp TYPE=_clsv-profile OUT_DIR="$(PROFILE_DIR)/$(MB_DIR)"
.PHONY: m-tmp mcl-tmp mingl-tmp glcl-tmp gl-tmp sv-tmp _clsv-dbg _clsv-rel _cl-dbg _cl-rel _out-rel _out-dbg
@@ -1313,9 +1366,9 @@ droid-opt: droid/build.xml droid/ftekeystore
#build FTE as a library, then build the java+package (release). also installs it onto the 'current' device.
droid-dbg: droid/build.xml
- $(MAKE) FTE_TARGET=droid gl-dbg
- @mkdir -p droid/libs/armeabi
- @cp $(DEBUG_DIR)/libftedroid.so droid/libs/armeabi/
+ $(foreach a, $(DROID_ARCH), $(MAKE) FTE_TARGET=droid gl-dbg DROID_ARCH=$a; )
+ @$(foreach a, $(DROID_ARCH), mkdir -p droid/libs/$a; )
+ -@$(foreach a, $(DROID_ARCH), cp $(DEBUG_DIR)/gl_droid-$a/libftedroid.so droid/libs/$a/libftedroid.so; )
@cd droid && $(ANT) debug && $(ANT) debug install
cp droid/bin/FTEDroid-debug.apk $(DEBUG_DIR)/FTEDroid.apk
diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c
index 3a0eaa52b..886c6db2d 100644
--- a/engine/client/cl_ents.c
+++ b/engine/client/cl_ents.c
@@ -820,7 +820,7 @@ void CLFTE_ParseEntities(void)
break;
/*update the prediction info if needed*/
- if (e->u.q1.pmovetype)
+// if (e->u.q1.pmovetype)
{
frame_t *fram;
fram = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c
index 21927b382..2acb5778d 100644
--- a/engine/client/cl_main.c
+++ b/engine/client/cl_main.c
@@ -3273,6 +3273,7 @@ void CL_Init (void)
Cmd_AddCommand ("god", NULL); //cheats
Cmd_AddCommand ("give", NULL);
Cmd_AddCommand ("noclip", NULL);
+ Cmd_AddCommand ("notarget", NULL);
Cmd_AddCommand ("fly", NULL);
Cmd_AddCommand ("setpos", NULL);
@@ -3465,15 +3466,6 @@ double Host_Frame (double time)
// if (cls.demoplayback && cl_demospeed.value>0)
// realframetime *= cl_demospeed.value; // this probably screws up other timings
-#ifndef CLIENTONLY
- if (sv.state)
- {
- RSpeedRemark();
- SV_Frame();
- RSpeedEnd(RSPEED_SERVER);
- }
-#endif
-
if (cl.gamespeed<0.1)
cl.gamespeed = 1;
time *= cl.gamespeed;
@@ -3510,7 +3502,17 @@ double Host_Frame (double time)
if (idlesec > 0.1)
idlesec = 0.1; // limit to at least 10 fps
if ((realtime - oldrealtime) < idlesec)
+ {
+#ifndef CLIENTONLY
+ if (sv.state)
+ {
+ RSpeedRemark();
+ SV_Frame();
+ RSpeedEnd(RSPEED_SERVER);
+ }
+#endif
return idlesec - (realtime - oldrealtime);
+ }
}
/*
@@ -3598,7 +3600,6 @@ double Host_Frame (double time)
// fetch results from server
CL_ReadPackets ();
- CL_CalcClientTime();
// send intentions now
// resend a connection request if necessary
@@ -3620,6 +3621,19 @@ double Host_Frame (double time)
RSpeedEnd(RSPEED_PROTOCOL);
+#ifndef CLIENTONLY
+ if (sv.state)
+ {
+ float ohft = host_frametime;
+ RSpeedRemark();
+ SV_Frame();
+ RSpeedEnd(RSPEED_SERVER);
+ host_frametime = ohft;
+ CL_ReadPackets ();
+ }
+#endif
+ CL_CalcClientTime();
+
// update video
if (host_speeds.ival)
time1 = Sys_DoubleTime ();
diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c
index f457391ad..44f17c984 100644
--- a/engine/client/cl_parse.c
+++ b/engine/client/cl_parse.c
@@ -1032,7 +1032,14 @@ int CL_LoadModels(int stage, qboolean dontactuallyload)
s = Info_ValueForKey(cl.serverinfo, "*csprogs");
if (anycsqc || *s || cls.demoplayback) //only allow csqc if the server says so, and the 'checksum' matches.
{
- unsigned int chksum = strtoul(s, NULL, 0);
+ char *endptr;
+ unsigned int chksum = strtoul(s, &endptr, 0);
+ if (*endptr)
+ {
+ Con_Printf("corrupt *csprogs key in serverinfo\n");
+ anycsqc = true;
+ chksum = 0;
+ }
SCR_SetLoadingFile("csprogs");
if (!CSQC_Init(anycsqc, chksum))
{
@@ -1291,8 +1298,9 @@ void Sound_CheckDownloads (void)
if (*s) //only allow csqc if the server says so, and the 'checksum' matches.
{
extern cvar_t cl_download_csprogs, cl_nocsqc;
- unsigned int chksum = strtoul(s, NULL, 0);
- if (cl_nocsqc.ival || cls.demoplayback)
+ char *endptr;
+ unsigned int chksum = strtoul(s, &endptr, 0);
+ if (cl_nocsqc.ival || cls.demoplayback || *endptr)
{
}
else if (cl_download_csprogs.ival)
diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c
index 14bc25d5a..edee50dce 100644
--- a/engine/client/cl_pred.c
+++ b/engine/client/cl_pred.c
@@ -981,7 +981,11 @@ void CL_PredictMovePNum (int pnum)
{
if (cl_lerp_players.ival && !cls.demoplayback)
{
- lerpents_t *le = &cl.lerpplayers[spec_track[pnum]];
+ lerpents_t *le;
+ if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
+ le = &cl.lerpents[spec_track[pnum]+1];
+ else
+ le = &cl.lerpplayers[spec_track[pnum]];
org = le->origin;
vel = vec3_origin;
}
diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c
index 21ee1cd20..e6c8ed814 100644
--- a/engine/client/cl_screen.c
+++ b/engine/client/cl_screen.c
@@ -1744,8 +1744,18 @@ void SCR_SetUpToDrawConsole (void)
// decide on the height of the console
if (!scr_disabled_for_loading)
{
- if ((key_dest == key_console || key_dest == key_game) && !cl.sendprespawn && cl.worldmodel && cl.worldmodel->needload)
- Con_ForceActiveNow();
+ float fullscreenpercent = 1;
+#ifdef ANDROID
+ //android has an onscreen imm that we don't want to obscure
+ fullscreenpercent = scr_consize.value;
+#endif
+ if ((key_dest == key_console || key_dest == key_game) && (!cl.sendprespawn && cl.worldmodel && cl.worldmodel->needload))
+ {
+ key_dest = key_console;
+ scr_conlines = scr_con_current = vid.height * fullscreenpercent;
+ }
+ else if ((key_dest == key_console || key_dest == key_game) && SCR_GetLoadingStage() == LS_NONE && cls.state < ca_active)
+ scr_con_current = scr_conlines = vid.height * fullscreenpercent;
else if (key_dest == key_console || scr_chatmode)
{
scr_conlines = vid.height*scr_consize.value; // half screen
diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c
index 182271b36..f42527c2d 100644
--- a/engine/client/cl_tent.c
+++ b/engine/client/cl_tent.c
@@ -521,6 +521,7 @@ CL_ClearTEnts
void CL_ClearTEnts (void)
{
CL_ClearTEntParticleState();
+ CL_ShutdownTEnts();
cl_beams_max = 0;
BZ_Free(cl_beams);
diff --git a/engine/client/console.c b/engine/client/console.c
index ca9013fd9..f78806c54 100644
--- a/engine/client/console.c
+++ b/engine/client/console.c
@@ -772,8 +772,16 @@ void VARGS Con_DPrintf (char *fmt, ...)
char msg[MAXPRINTMSG];
extern cvar_t log_developer;
+#ifdef CRAZYDEBUGGING
+ va_start (argptr,fmt);
+ vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
+ va_end (argptr);
+ Sys_Printf("%s", msg);
+ return;
+#else
if (!developer.value && !log_developer.value)
return; // early exit
+#endif
va_start (argptr,fmt);
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
diff --git a/engine/client/in_droid.c b/engine/client/in_droid.c
index ad4f4eb77..194b7460f 100644
--- a/engine/client/in_droid.c
+++ b/engine/client/in_droid.c
@@ -5,7 +5,9 @@
extern qboolean mouse_active;
cvar_t m_filter = CVARF("m_filter", "0", CVAR_ARCHIVE);
-cvar_t m_strafeonright = CVARFD("m_strafeonright", "1", CVAR_ARCHIVE, "If 1, touching the right half of the touchscreen will strafe/move, while the left side will turn.");
+cvar_t m_strafeonleft = CVARFD("m_strafeonleft", "1", CVAR_ARCHIVE, "If 1, touching the right half of the touchscreen will strafe/move, while the left side will turn.");
+cvar_t m_fatpressthreshold = CVARFD("m_fatpressthreshold", "0.5", CVAR_ARCHIVE, "How fat your thumb has to be to register a fat press.");
+cvar_t m_slidethreshold = CVARFD("m_slidethreshold", "5", CVAR_ARCHIVE, "How far your finger needs to move to be considered a slide event.");
extern cvar_t _windowed_mouse;
@@ -32,6 +34,7 @@ struct eventlist_s
struct
{
float x, y;
+ float tsize; //the size of the touch
} mouse;
struct
{
@@ -72,13 +75,14 @@ void IN_Shutdown(void)
void IN_ReInit()
{
- Cvar_Register (&m_filter, "input controls");
- Cvar_Register (&m_strafeonright, "input controls");
}
void IN_Init(void)
{
- IN_ReInit();
+ Cvar_Register (&m_filter, "input controls");
+ Cvar_Register (&m_strafeonleft, "input controls");
+ Cvar_Register (&m_fatpressthreshold, "input controls");
+ Cvar_Register (&m_slidethreshold, "input controls");
}
/*on android, each 'pointer' is a separate touch location*/
@@ -95,31 +99,44 @@ void IN_Commands(void)
if (ev->keyboard.scancode == K_MOUSE1 && ev->devid < MAXPOINTERS)
{
if (Key_MouseShouldBeFree())
- ptr[ev->devid].down = false;
+ ptr[ev->devid].down = 0;
else
{
if (ev->type == IEV_KEYDOWN)
{
- ptr[ev->devid].down = true;
+ ptr[ev->devid].down = 1;
ptr[ev->devid].movedist = 0;
ptr[ev->devid].downpos[0] = ptr[ev->devid].oldpos[0];
ptr[ev->devid].downpos[1] = ptr[ev->devid].oldpos[1];
ptr[ev->devid].move[0] = 0;
ptr[ev->devid].move[1] = 0;
+
+ if (ev->mouse.tsize > m_fatpressthreshold.value)
+ {
+ int key = (m_strafeonleft.ival && ptr[ev->devid].downpos[0] > vid.pixelwidth/2)?K_MOUSE2:K_MOUSE1;
+ Key_Event(ev->devid, key, 0, true);
+ ptr[ev->devid].down = 2;
+ }
}
else
{
+ if (ptr[ev->devid].down > 1)
+ {
+ int key = (m_strafeonleft.ival && ptr[ev->devid].downpos[0] > vid.pixelwidth/2)?K_MOUSE2:K_MOUSE1;
+ Key_Event(ev->devid, key, 0, false);
+ ptr[ev->devid].down = 1;
+ }
if (ptr[ev->devid].down)
{
- if (ptr[ev->devid].movedist < 5)
+ if (ptr[ev->devid].movedist < m_slidethreshold.value)
{
/*if its on the right, make it a mouse2*/
- int key = (m_strafeonright.ival && ptr[ev->devid].downpos[0] > vid.pixelwidth/2)?K_MOUSE3:K_MOUSE1;
+ int key = (m_strafeonleft.ival && ptr[ev->devid].downpos[0] > vid.pixelwidth/2)?K_MOUSE2:K_MOUSE1;
Key_Event(ev->devid, key, 0, true);
Key_Event(ev->devid, key, 0, false);
}
}
- ptr[ev->devid].down = false;
+ ptr[ev->devid].down = 0;
}
break;
}
@@ -130,8 +147,11 @@ void IN_Commands(void)
/*mouse cursors only really work with one pointer*/
if (ev->devid == 0)
{
- mousecursor_x = bound(0, ev->mouse.x, vid.width - 1);
- mousecursor_y = bound(0, ev->mouse.y, vid.height - 1);
+ float fl;
+ fl = ev->mouse.x * vid.width / vid.pixelwidth;
+ mousecursor_x = bound(0, fl, vid.width-1);
+ fl = ev->mouse.y * vid.height / vid.pixelheight;
+ mousecursor_y = bound(0, fl, vid.height-1);
}
if (ev->devid < MAXPOINTERS)
@@ -143,6 +163,20 @@ void IN_Commands(void)
ptr[ev->devid].oldpos[0] = ev->mouse.x;
ptr[ev->devid].oldpos[1] = ev->mouse.y;
+
+
+ if (ptr[ev->devid].down > 1 && ev->mouse.tsize < m_fatpressthreshold.value)
+ {
+ int key = (m_strafeonleft.ival && ptr[ev->devid].downpos[0] > vid.pixelwidth/2)?K_MOUSE2:K_MOUSE1;
+ Key_Event(ev->devid, key, 0, false);
+ ptr[ev->devid].down = 1;
+ }
+ if (ptr[ev->devid].down == 1 && ev->mouse.tsize > m_fatpressthreshold.value)
+ {
+ int key = (m_strafeonleft.ival && ptr[ev->devid].downpos[0] > vid.pixelwidth/2)?K_MOUSE2:K_MOUSE1;
+ Key_Event(ev->devid, key, 0, true);
+ ptr[ev->devid].down = 2;
+ }
}
break;
}
@@ -169,7 +203,7 @@ static void IN_Update(qboolean ingame)
{
if (!CSQC_MouseMove(ptr[i].move[0], ptr[i].move[1], i))
{
- if (ptr[i].down && m_strafeonright.ival && ptr[i].downpos[0] > vid.pixelwidth/2 && ingame)
+ if (ptr[i].down && m_strafeonleft.ival && ptr[i].downpos[0] > vid.pixelwidth/2 && ingame)
{
mousestrafe_x += ptr[i].oldpos[0] - ptr[i].downpos[0];
mousestrafe_y += ptr[i].oldpos[1] - ptr[i].downpos[1];
@@ -273,7 +307,7 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_keypress(JNIEnv *env, jobje
}
JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_motion(JNIEnv *env, jobject obj,
- jint act, jint ptrid, jfloat x, jfloat y)
+ jint act, jint ptrid, jfloat x, jfloat y, jfloat size)
{
struct eventlist_s *ev = in_newevent();
if (!ev)
@@ -290,6 +324,7 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_motion(JNIEnv *env, jobject
ev->type = IEV_MOUSEABS;
ev->mouse.x = x;
ev->mouse.y = y;
+ ev->mouse.tsize = size;
}
in_finishevent();
}
diff --git a/engine/client/in_macos.c b/engine/client/in_macos.c
index 14970e053..683f232f7 100644
--- a/engine/client/in_macos.c
+++ b/engine/client/in_macos.c
@@ -83,7 +83,7 @@ void IN_Move (float *movements, int pnum)
}
else
{
- cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x;
+ cl.playerview[pnum].viewanglechange[YAW] -= m_yaw.value * mouse_x;
}
if (in_mlook.state[pnum])
@@ -91,7 +91,7 @@ void IN_Move (float *movements, int pnum)
if (in_mlook.state[pnum] && !(in_strafe.state[pnum] & 1))
{
- cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y;
+ cl.playerview[pnum].viewanglechange[PITCH] += m_pitch.value * mouse_y;
}
else
{
diff --git a/engine/client/in_morphos.c b/engine/client/in_morphos.c
index adada42db..dec655ee7 100644
--- a/engine/client/in_morphos.c
+++ b/engine/client/in_morphos.c
@@ -281,13 +281,13 @@ void IN_Move (float *movements, int pnum)
}
else
{
- cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x;
+ cl.playerview[pnum].viewanglechange[YAW] -= m_yaw.value * mouse_x;
}
if (in_mlook.state[pnum] & 1)
V_StopPitchDrift (pnum);
if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1)) {
- cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y;
+ cl.playerview[pnum].viewanglechange[PITCH] += m_pitch.value * mouse_y;
} else {
if (movements)
{
diff --git a/engine/client/in_sdl.c b/engine/client/in_sdl.c
index 7bd97f0b4..2b9aec277 100644
--- a/engine/client/in_sdl.c
+++ b/engine/client/in_sdl.c
@@ -315,14 +315,14 @@ void IN_Move (float *movements, int pnum) //add mouse movement to cmd
if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) ))
movements[1] += m_side.value * mouse_x;
else
- cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x;
+ cl.playerview[pnum].viewanglechange[YAW] -= m_yaw.value * mouse_x;
if (in_mlook.state[pnum] & 1)
V_StopPitchDrift (pnum);
if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1))
{
- cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y;
+ cl.playerview[pnum].viewanglechange[PITCH] += m_pitch.value * mouse_y;
}
else
{
diff --git a/engine/client/keys.c b/engine/client/keys.c
index 73d72878a..c80374de6 100644
--- a/engine/client/keys.c
+++ b/engine/client/keys.c
@@ -161,7 +161,12 @@ keyname_t keynames[] =
{"LWIN", K_LWIN},
{"RWIN", K_RWIN},
{"APP", K_APP},
-
+ {"MENU", K_APP},
+ {"SEARCH", K_SEARCH},
+ {"POWER", K_POWER},
+ {"VOLUP", K_VOLUP},
+ {"VOLDOWN", K_VOLDOWN},
+
{"JOY1", K_JOY1},
{"JOY2", K_JOY2},
{"JOY3", K_JOY3},
@@ -390,28 +395,41 @@ qboolean Key_GetConsoleSelectionBox(int *sx, int *sy, int *ex, int *ey)
{
extern int mousecursor_x, mousecursor_y;
- if (!con_mousedown[2])
- {
- *sx = *sy = *ex = *ey = 0;
- return false;
- }
- *sx = con_mousedown[0];
- *sy = con_mousedown[1];
- *ex = mousecursor_x;
- *ey = mousecursor_y;
+ *sx = *sy = *ex = *ey = 0;
- return true;
+ if (con_mousedown[2] == 1)
+ {
+ while (mousecursor_y - con_mousedown[1] > 8 && con_current->display->older)
+ {
+ con_mousedown[1] += 8;
+ con_current->display = con_current->display->older;
+ }
+ while (mousecursor_y - con_mousedown[1] < -8 && con_current->display->newer)
+ {
+ con_mousedown[1] -= 8;
+ con_current->display = con_current->display->newer;
+ }
+ }
+ else if (con_mousedown[2] == 2)
+ {
+ *sx = con_mousedown[0];
+ *sy = con_mousedown[1];
+ *ex = mousecursor_x;
+ *ey = mousecursor_y;
+ return true;
+ }
+ return false;
}
void Key_ConsoleRelease(int key, int unicode)
{
if (key == K_MOUSE1)
- con_mousedown[2] = false;
- if (key == K_MOUSE2 && con_mousedown[2])
+ con_mousedown[2] = 0;
+ if (key == K_MOUSE2 && con_mousedown[2] == 2)
{
extern int mousecursor_x, mousecursor_y;
char *buffer;
- con_mousedown[2] = false;
+ con_mousedown[2] = 0;
buffer = Con_CopyConsole();
if (!buffer)
return;
@@ -478,9 +496,9 @@ void Key_Console (unsigned int unicode, int key)
}
}
else if (key == K_MOUSE2)
- con_mousedown[2] = true;
+ con_mousedown[2] = 2;
else
- con_mousedown[2] = false;
+ con_mousedown[2] = 1;
return;
}
diff --git a/engine/client/keys.h b/engine/client/keys.h
index 4ce83ef0a..1d195e7f8 100644
--- a/engine/client/keys.h
+++ b/engine/client/keys.h
@@ -155,6 +155,9 @@ K_AUX32 = 238,
K_LWIN = 239,
K_RWIN = 240,
K_APP = 241,
+K_SEARCH = 242,
+K_VOLUP = 243,
+K_VOLDOWN = 244,
K_MAX = 256
};
diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c
index a50a1f6b5..f3574c113 100644
--- a/engine/client/m_mp3.c
+++ b/engine/client/m_mp3.c
@@ -3289,10 +3289,6 @@ sfxcache_t *S_MP3_Locate(sfx_t *sfx, sfxcache_t *buf, int start, int length)
#ifndef WAVE_FORMAT_MPEGLAYER3
#define WAVE_FORMAT_MPEGLAYER3 0x0055
-#define MPEGLAYER3_WFX_EXTRA_BYTES 12
-#define MPEGLAYER3_FLAG_PADDING_OFF 2
-#define MPEGLAYER3_ID_MPEG 1
-
typedef struct
{
WAVEFORMATEX wfx;
@@ -3303,6 +3299,11 @@ typedef struct
WORD nCodecDelay;
} MPEGLAYER3WAVEFORMAT;
#endif
+#ifndef MPEGLAYER3_ID_MPEG
+#define MPEGLAYER3_WFX_EXTRA_BYTES 12
+#define MPEGLAYER3_FLAG_PADDING_OFF 2
+#define MPEGLAYER3_ID_MPEG 1
+#endif
qboolean S_LoadMP3Sound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
{
diff --git a/engine/client/net_master.c b/engine/client/net_master.c
index a673ea594..7c10a0aeb 100644
--- a/engine/client/net_master.c
+++ b/engine/client/net_master.c
@@ -628,6 +628,17 @@ void Master_AddMaster (char *address, int type, char *description)
master = mast;
}
+void MasterInfo_Shutdown(void)
+{
+ master_t *mast;
+ while(master)
+ {
+ mast = master;
+ master = mast->next;
+ Z_Free(mast);
+ }
+}
+
void Master_AddMasterHTTP (char *address, int mastertype, char *description)
{
master_t *mast;
@@ -1539,11 +1550,11 @@ void MasterInfo_Refresh(void)
//q3
{
- //Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quake3", MT_MASTERHTTPQW, "gameaholic's Q3 master");
- Master_AddMaster("master.quake3arena.com:27950", MT_MASTERQ3, "Quake3 master server.");
- Master_AddMaster("masterserver.exhale.de:27950", MT_MASTERQ3, "team exhale");
- //Master_AddMaster("master3.quake3arena.com:27950", MT_MASTERQ3, "Quake3 master3 server.");
- Master_AddMaster("255.255.255.255:27960", MT_BCASTQ3, "Nearby Quake3 UDP servers.");
+ //Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quake3", MT_MASTERHTTPQW, "gameaholic's Q3 master");
+ Master_AddMaster("master.quake3arena.com:27950", MT_MASTERQ3, "Quake3 master server.");
+ Master_AddMaster("masterserver.exhale.de:27950", MT_MASTERQ3, "team exhale");
+ //Master_AddMaster("master3.quake3arena.com:27950", MT_MASTERQ3, "Quake3 master3 server.");
+ Master_AddMaster("255.255.255.255:27960", MT_BCASTQ3, "Nearby Quake3 UDP servers.");
}
}
diff --git a/engine/client/p_script.c b/engine/client/p_script.c
index 8cd65ebe3..581b8e9e6 100644
--- a/engine/client/p_script.c
+++ b/engine/client/p_script.c
@@ -246,7 +246,7 @@ typedef struct part_type_s {
float gravity;
vec3_t friction;
float clipbounce;
- int stainonimpact;
+ float stainonimpact;
vec3_t dl_rgb;
float dl_radius;
@@ -1135,13 +1135,15 @@ static void P_ParticleEffect_f(void)
ptype->rgbrandsync[2] = atof(value);
else if (!strcmp(var, "stains"))
- ptype->stainonimpact = atoi(value);
+ ptype->stainonimpact = atof(value);
else if (!strcmp(var, "blend"))
{
if (!strcmp(value, "add"))
ptype->looks.blendmode = BM_ADD;
else if (!strcmp(value, "subtract"))
ptype->looks.blendmode = BM_SUBTRACT;
+ else if (!strcmp(value, "invmod"))
+ ptype->looks.blendmode = BM_INVMOD;
else if (!strcmp(value, "blendcolour") || !strcmp(value, "blendcolor"))
ptype->looks.blendmode = BM_BLENDCOLOUR;
else
@@ -2187,6 +2189,16 @@ static void PScript_Shutdown (void)
Cmd_RemoveCommand("r_beaminfo");
#endif
+ while (numparticletypes > 0)
+ {
+ numparticletypes--;
+ if (part_type[numparticletypes].ramp)
+ BZ_Free(part_type[numparticletypes].ramp);
+ }
+ BZ_Free (part_type);
+ part_type = NULL;
+ part_run_list = NULL;
+
BZ_Free (particles);
BZ_Free (beams);
BZ_Free (decals);
@@ -5354,10 +5366,16 @@ static void PScript_DrawParticleTypes (void)
{
if (traces-->0&&tr(oldorg, p->org, stop, normal))
{
- R_AddStain(stop, (p->rgba[1]*-10+p->rgba[2]*-10),
- (p->rgba[0]*-10+p->rgba[2]*-10),
- (p->rgba[0]*-10+p->rgba[1]*-10),
- 30*p->rgba[3]*type->stainonimpact);
+ if (type->stainonimpact < 0)
+ R_AddStain(stop, (p->rgba[0]*-1),
+ (p->rgba[1]*-1),
+ (p->rgba[2]*-1),
+ p->scale*-type->stainonimpact);
+ else
+ R_AddStain(stop, (p->rgba[1]*-10+p->rgba[2]*-10),
+ (p->rgba[0]*-10+p->rgba[2]*-10),
+ (p->rgba[0]*-10+p->rgba[1]*-10),
+ 30*p->rgba[3]*type->stainonimpact);
p->die = -1;
continue;
}
diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c
index 6f89b821b..c65906e3b 100644
--- a/engine/client/pr_csqc.c
+++ b/engine/client/pr_csqc.c
@@ -1223,6 +1223,7 @@ static void QCBUILTIN PF_R_GetViewFlag(progfuncs_t *prinst, struct globalvars_s
case VF_SIZE:
r[0] = r_refdef.vrect.width;
r[1] = r_refdef.vrect.height;
+ r[2] = 0;
break;
case VF_MIN_X:
diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c
index 9a007ae07..805f9e832 100644
--- a/engine/client/pr_menu.c
+++ b/engine/client/pr_menu.c
@@ -603,6 +603,8 @@ void QCBUILTIN PF_CL_drawrawstring (progfuncs_t *prinst, struct globalvars_s *pr
}
while(*text)
{
+ //FIXME: which charset is this meant to be using?
+ //quakes? 8859-1? utf8? some weird hacky mixture?
x = Font_DrawScaleChar(x, y, size[0], size[1], CON_WHITEMASK|/*0xe000|*/(*text++&0xff));
}
Font_InvalidateColour();
diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c
index c9f68fb77..3d87663df 100644
--- a/engine/client/r_2d.c
+++ b/engine/client/r_2d.c
@@ -92,6 +92,23 @@ void R2D_Shutdown(void)
Cvar_Unhook(&crosshair);
Cvar_Unhook(&crosshairimage);
Cvar_Unhook(&crosshaircolor);
+
+ BZ_Free(cl_stris);
+ cl_stris = NULL;
+ BZ_Free(cl_strisvertv);
+ cl_strisvertv = NULL;
+ BZ_Free(cl_strisvertc);
+ cl_strisvertc = NULL;
+ BZ_Free(cl_strisvertt);
+ cl_strisvertt = NULL;
+ BZ_Free(cl_strisidx);
+ cl_strisidx = NULL;
+ cl_numstrisidx = 0;
+ cl_maxstrisidx = 0;
+ cl_numstrisvert = 0;
+ cl_maxstrisvert = 0;
+ cl_numstris = 0;
+ cl_maxstris = 0;
}
/*
diff --git a/engine/client/r_partset.c b/engine/client/r_partset.c
index f0ea34091..56d74489e 100644
--- a/engine/client/r_partset.c
+++ b/engine/client/r_partset.c
@@ -1624,6 +1624,8 @@ char *particle_set_high =
"friction 4\n"
"scalefactor 0.825\n"
"blend add\n"
+"spawnmode spiral\n"
+"spawnvel -50\n"
"}\n"
/////////////////////////////////////////
@@ -1658,46 +1660,91 @@ char *particle_set_high =
//{
//}
+"r_part te_blood\n"
+"{\n"
+"texture fte_bloodparticle\n"
+"blend subtract\n"
+"count 1\n"
+"scale 32\n"
+"alpha 0\n"
+"die 1\n"
+"randomvel 64\n"
+"veladd 10\n"
+"rotationspeed 90\n"
+"rotationstart 0 360\n"
+"rgb 64 128 128\n"
+"rgbdelta -64 -128 -128\n"
+"gravity 200\n"
+"scalefactor 0.8\n"
+// scaledelta -10
+"}\n"
+
+"r_part pe_73\n"
+"{\n"
+"assoc te_blood\n"
+"}\n"
+
+"r_part te_lightningblood\n"
+"{\n"
+"texture fte_bloodparticle\n"
+"blend subtract\n"
+"count 1\n"
+"scale 32\n"
+"alpha 0\n"
+"die 1\n"
+"randomvel 64\n"
+"veladd 10\n"
+"rotationspeed 90\n"
+"rotationstart 0 360\n"
+"rgb 0 128 128\n"
+"rgbdelta 0 -128 -128\n"
+"gravity 200\n"
+"scalefactor 0.8\n"
+"}\n"
+
/////////////////////////////////////////
//zombie body-part blood trails
"r_part tr_slightblood\n"
"{\n"
-"texture \"particles/fteparticlefont.tga\"\n"
-"tcoords 1 1 63 63 256 2 64\n"
+"texture fte_bloodparticle\n"
+"blend subtract\n"
+// tcoords 1 1 63 63 256 2 64
"step 16\n"
"scale 64\n"
-"alpha 0.6\n"
+"alpha 0\n"
"die 1\n"
"randomvel 32\n"
"veladd 10\n"
"rotationspeed 90\n"
"rotationstart 0 360\n"
-"rgb 32 0 0\n"
+"rgb 64 128 128 \n"
+"rgbdelta -64 -128 -128\n"
"gravity 200\n"
"scalefactor 0.8\n"
"scaledelta -10\n"
-"stains 5\n"
+"stains -0.5\n"
"}\n"
//////////////////////////////////////////
//regular ol' blood trails
"r_part tr_blood\n"
"{\n"
-"texture \"particles/fteparticlefont.tga\"\n"
-"tcoords 1 1 63 63 256 2 64\n"
-"step 4\n"
+"texture fte_bloodparticle\n"
+"blend subtract\n"
+"step 8\n"
"scale 64\n"
-"alpha 0.3\n"
+"alpha 0\n"
"die 1\n"
"randomvel 32\n"
"veladd 10\n"
"rotationspeed 90\n"
"rotationstart 0 360\n"
-"rgb 64 0 0\n"
+"rgb 32 128 128 \n"
+"rgbdelta -32 -128 -128\n"
"gravity 200\n"
"scalefactor 0.8\n"
"scaledelta -10\n"
-"stains 5\n"
+"stains -0.5\n"
"}\n"
//////////////////////////////////
@@ -1729,6 +1776,8 @@ char *particle_set_high =
"randomvel 2\n"
"friction 4\n"
"scalefactor 0.825\n"
+"spawnmode spiral\n"
+"spawnvel 25\n"
"blend add\n"
"}\n"
diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c
index 7e3e9f014..6c29a1cd3 100644
--- a/engine/client/r_surf.c
+++ b/engine/client/r_surf.c
@@ -2286,7 +2286,7 @@ void Surf_DrawWorld (void)
=============================================================================
*/
-#ifdef TERRAIN
+#if 0//def TERRAIN
// returns a texture number and the position inside it
int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader)
{
@@ -2685,9 +2685,7 @@ void Surf_DeInit(void)
void Surf_Clear(model_t *mod)
{
- batch_t *b;
vbo_t *vbo;
- int i;
if (mod->fromgame == fg_doom3)
return;/*they're on the hunk*/
while(mod->vbos)
@@ -2748,6 +2746,51 @@ void Surf_LightmapMode(void)
}
}
+//needs to be followed by a BE_UploadAllLightmaps at some point
+int Surf_NewLightmaps(int count, int width, int height)
+{
+ int first = numlightmaps;
+ int i, k;
+
+ if (!count)
+ return -1;
+
+ i = numlightmaps + count;
+ lightmap = BZ_Realloc(lightmap, sizeof(*lightmap)*(i));
+ while(i > first)
+ {
+ i--;
+
+ lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*8 + sizeof(stmap)*3)*width*height);
+ lightmap[i]->width = width;
+ lightmap[i]->height = height;
+ lightmap[i]->lightmaps = (qbyte*)(lightmap[i]+1);
+ lightmap[i]->deluxmaps = (qbyte*)(lightmap[i]->lightmaps+4*width*height);
+ lightmap[i]->stainmaps = (stmap*)(lightmap[i]->deluxmaps+4*width*height);
+
+ lightmap[i]->modified = true;
+// lightmap[i]->shader = NULL;
+ lightmap[i]->external = false;
+ // reset stainmap since it now starts at 255
+ memset(lightmap[i]->stainmaps, 255, width*height*3*sizeof(stmap));
+
+ //clear out the deluxmaps incase there is none on the map.
+ for (k = 0; k < width*height*3; k+=3)
+ {
+ lightmap[i]->deluxmaps[k+0] = 128;
+ lightmap[i]->deluxmaps[k+1] = 128;
+ lightmap[i]->deluxmaps[k+2] = 255;
+ }
+
+ TEXASSIGN(lightmap[i]->lightmap_texture, R_AllocNewTexture("***lightmap***", width, height));
+ TEXASSIGN(lightmap[i]->deluxmap_texture, R_AllocNewTexture("***deluxmap***", width, height));
+ }
+
+ numlightmaps += count;
+
+ return first;
+}
+
/*
==================
GL_BuildLightmaps
@@ -2759,16 +2802,13 @@ Groups surfaces into their respective batches (based on the lightmap number).
*/
void Surf_BuildLightmaps (void)
{
- int i, j, k, t;
+ int i, j, t;
model_t *m;
int shift;
msurface_t *surf;
- batch_t *batch, *bstop;
- vec3_t sn;
+ batch_t *batch;
int sortid;
int ptype;
- void *mem;
- unsigned int memsize;
int newfirst;
r_framecount = 1; // no dlightcache
@@ -2783,6 +2823,11 @@ void Surf_BuildLightmaps (void)
Surf_LightmapMode();
+ r_oldviewleaf = NULL;
+ r_oldviewleaf2 = NULL;
+ r_oldviewcluster = -1;
+ r_oldviewcluster2 = -1;
+
if (cl.worldmodel->fromgame == fg_doom)
return; //no lightmaps.
@@ -2793,6 +2838,12 @@ void Surf_BuildLightmaps (void)
m = cl.model_precache[j];
if (!m)
break;
+
+#ifdef TERRAIN
+ if (m->terrain)
+ Terr_PurgeTerrainModel(m, true);
+#endif
+
if (m->type != mod_brush)
continue;
@@ -2807,41 +2858,7 @@ void Surf_BuildLightmaps (void)
if (*m->name == '*' && m->fromgame == fg_quake3) //FIXME: should be all bsp formats
newfirst = cl.model_precache[1]->lightmaps.first;
else
- {
- newfirst = numlightmaps;
-
- i = numlightmaps + m->lightmaps.count;
- lightmap = BZ_Realloc(lightmap, sizeof(*lightmap)*(i));
- while(i > numlightmaps)
- {
- i--;
-
- lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*8 + sizeof(stmap)*3)*m->lightmaps.width*m->lightmaps.height);
- lightmap[i]->width = m->lightmaps.width;
- lightmap[i]->height = m->lightmaps.height;
- lightmap[i]->lightmaps = (qbyte*)(lightmap[i]+1);
- lightmap[i]->deluxmaps = (qbyte*)(lightmap[i]->lightmaps+4*lightmap[i]->width*lightmap[i]->height);
- lightmap[i]->stainmaps = (stmap*)(lightmap[i]->deluxmaps+4*lightmap[i]->width*lightmap[i]->height);
-
- lightmap[i]->modified = true;
- // lightmap[i]->shader = NULL;
- lightmap[i]->external = false;
- // reset stainmap since it now starts at 255
- memset(lightmap[i]->stainmaps, 255, LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3*sizeof(stmap));
-
- //clear out the deluxmaps incase there is none on the map.
- for (k = 0; k < lightmap[i]->width*lightmap[i]->height*3; k+=3)
- {
- lightmap[i]->deluxmaps[k+0] = 128;
- lightmap[i]->deluxmaps[k+1] = 128;
- lightmap[i]->deluxmaps[k+2] = 255;
- }
-
- TEXASSIGN(lightmap[i]->lightmap_texture, R_AllocNewTexture("***lightmap***", lightmap[i]->width, lightmap[i]->height));
- TEXASSIGN(lightmap[i]->deluxmap_texture, R_AllocNewTexture("***deluxmap***", lightmap[i]->width, lightmap[i]->height));
- }
- numlightmaps += m->lightmaps.count;
- }
+ newfirst = Surf_NewLightmaps(m->lightmaps.count, m->lightmaps.width, m->lightmaps.height);
//fixup batch lightmaps
for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++)
diff --git a/engine/client/render.h b/engine/client/render.h
index 9034db804..4201ad770 100644
--- a/engine/client/render.h
+++ b/engine/client/render.h
@@ -222,7 +222,7 @@ typedef struct {
int height;
glRect_t rectchange;
glRect_t deluxrectchange;
-#ifdef TERRAIN
+#if 0 //def TERRAIN
int allocated[LMBLOCK_WIDTH];
#endif
qbyte *lightmaps;//[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT];
diff --git a/engine/client/renderer.c b/engine/client/renderer.c
index 1cd9ee731..8fdfceeca 100644
--- a/engine/client/renderer.c
+++ b/engine/client/renderer.c
@@ -210,8 +210,14 @@ extern cvar_t r_novis;
extern cvar_t r_speeds;
extern cvar_t r_waterwarp;
+#ifdef ANDROID
+//on android, these numbers seem to be generating major weirdness, so disable these.
+cvar_t r_polygonoffset_submodel_factor = SCVAR("r_polygonoffset_submodel_factor", "0");
+cvar_t r_polygonoffset_submodel_offset = SCVAR("r_polygonoffset_submodel_offset", "0");
+#else
cvar_t r_polygonoffset_submodel_factor = SCVAR("r_polygonoffset_submodel_factor", "0.05");
cvar_t r_polygonoffset_submodel_offset = SCVAR("r_polygonoffset_submodel_offset", "25");
+#endif
cvar_t r_polygonoffset_stencil_factor = SCVAR("r_polygonoffset_stencil_factor", "0.01");
cvar_t r_polygonoffset_stencil_offset = SCVAR("r_polygonoffset_stencil_offset", "1");
@@ -2384,7 +2390,19 @@ void R_InitParticleTexture (void)
data[y*16+x][3] = exptexture[x][y]*255/9.0;
}
}
- explosiontexture = R_LoadTexture32("", 16, 16, data, IF_NOMIPMAP|IF_NOPICMIP);
+ explosiontexture = R_LoadTexture32("fte_fuzzyparticle", 16, 16, data, IF_NOMIPMAP|IF_NOPICMIP);
+
+ for (x=0 ; x<16 ; x++)
+ {
+ for (y=0 ; y<16 ; y++)
+ {
+ data[y*16+x][0] = exptexture[x][y]*255/9.0;
+ data[y*16+x][1] = exptexture[x][y]*255/9.0;
+ data[y*16+x][2] = exptexture[x][y]*255/9.0;
+ data[y*16+x][3] = exptexture[x][y]*255/9.0;
+ }
+ }
+ R_LoadTexture32("fte_bloodparticle", 16, 16, data, IF_NOMIPMAP|IF_NOPICMIP);
memset(data, 255, sizeof(data));
for (y = 0;y < PARTICLETEXTURESIZE;y++)
diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c
index 612c57368..0cba54448 100644
--- a/engine/client/snd_dma.c
+++ b/engine/client/snd_dma.c
@@ -225,6 +225,24 @@ static struct
void *driverctx; /*capture driver context*/
} s_speex;
+#ifdef SPEEX_STATIC
+#define qspeex_lib_get_mode speex_lib_get_mode
+#define qspeex_bits_init speex_bits_init
+#define qspeex_bits_reset speex_bits_reset
+#define qspeex_bits_write speex_bits_write
+
+#define qspeex_preprocess_state_init speex_preprocess_state_init
+#define qspeex_preprocess_ctl speex_preprocess_ctl
+#define qspeex_preprocess_run speex_preprocess_run
+
+#define qspeex_encoder_init speex_encoder_init
+#define qspeex_encoder_ctl speex_encoder_ctl
+#define qspeex_encode_int speex_encode_int
+
+#define qspeex_decoder_init speex_decoder_init
+#define qspeex_decode_int speex_decode_int
+#define qspeex_bits_read_from speex_bits_read_from
+#else
static const SpeexMode *(VARGS *qspeex_lib_get_mode)(int mode);
static void (VARGS *qspeex_bits_init)(SpeexBits *bits);
static void (VARGS *qspeex_bits_reset)(SpeexBits *bits);
@@ -267,6 +285,7 @@ static dllfunction_t qspeexdspfuncs[] =
{NULL}
};
+#endif
snd_capture_driver_t DSOUND_Capture;
snd_capture_driver_t OSS_Capture;
@@ -275,6 +294,8 @@ static qboolean S_Speex_Init(void)
{
int i;
const SpeexMode *mode;
+
+#ifndef SPEEX_STATIC
if (s_speex.inited)
return s_speex.loaded;
s_speex.inited = true;
@@ -292,6 +313,7 @@ static qboolean S_Speex_Init(void)
Con_Printf("libspeexdsp not found. Voice chat is not available.\n");
return false;
}
+#endif
mode = qspeex_lib_get_mode(SPEEX_MODEID_NB);
diff --git a/engine/client/sys_droid.c b/engine/client/sys_droid.c
index cc4912b09..d3c9b7547 100644
--- a/engine/client/sys_droid.c
+++ b/engine/client/sys_droid.c
@@ -20,6 +20,9 @@ qboolean isDedicated = false;
void *sys_window; /*public so the renderer can attach to the correct place*/
static qboolean sys_running = false;
int sys_glesversion;
+cvar_t sys_vibrate = CVAR("sys_vibrate", "1");
+cvar_t sys_osk = CVAR("sys_osk", "0"); //to be toggled
+cvar_t sys_keepscreenon = CVAR("sys_keepscreenon", "1"); //to be toggled
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, DISTRIBUTION"Droid", __VA_ARGS__))
@@ -27,9 +30,23 @@ int sys_glesversion;
static void *sys_memheap;
static unsigned int sys_lastframe;
-JNIEXPORT int JNICALL Java_com_fteqw_FTEDroidEngine_frame(JNIEnv *env, jobject obj,
+static unsigned int vibrateduration;
+
+void Sys_Vibrate(int count)
+{
+ vibrateduration = count*10*sys_vibrate.value;
+}
+JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_getvibrateduration(JNIEnv *env, jobject obj)
+{
+ unsigned int dur = vibrateduration;
+ vibrateduration = 0;
+ return dur;
+}
+
+JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_frame(JNIEnv *env, jobject obj,
jfloat ax, jfloat ay, jfloat az)
{
+ int ret;
static vec3_t oac;
#ifdef SERVERONLY
SV_Frame();
@@ -38,6 +55,9 @@ JNIEXPORT int JNICALL Java_com_fteqw_FTEDroidEngine_frame(JNIEnv *env, jobject o
double tdelta = (now - sys_lastframe) * 0.001;
if (oac[0] != ax || oac[1] != ay || oac[2] != az)
{
+ //down: x= +9.8
+ //left: y= -9.8
+ //up: z= +9.8
CSQC_Accelerometer(ax, ay, az);
oac[0] = ax;
oac[1] = ay;
@@ -47,9 +67,14 @@ JNIEXPORT int JNICALL Java_com_fteqw_FTEDroidEngine_frame(JNIEnv *env, jobject o
sys_lastframe = now;
#endif
- if (key_dest == key_console || key_dest == key_message)
- return 1;
- return 0;
+ ret = 0;
+ if (key_dest == key_console || key_dest == key_message || (key_dest == key_game && cls.state == ca_disconnected) || sys_osk.ival)
+ ret |= 1;
+ if (vibrateduration)
+ ret |= 2;
+ if (sys_keepscreenon.ival)
+ ret |= 4;
+ return ret;
}
JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject obj,
@@ -78,7 +103,7 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject o
parms.basedir = NULL; /*filled in later*/
parms.argc = 3;
parms.argv = args;
- parms.memsize = 16*1024*1024;
+ parms.memsize = 512*1024*1024;
parms.membase = sys_memheap = malloc(parms.memsize);
if (!parms.membase)
{
@@ -249,6 +274,9 @@ void Sys_SendKeyEvents(void)
}
void Sys_Init(void)
{
+ Cvar_Register(&sys_vibrate, "android stuff");
+ Cvar_Register(&sys_osk, "android stuff");
+ Cvar_Register(&sys_keepscreenon, "android stuff");
}
qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate)
diff --git a/engine/client/view.c b/engine/client/view.c
index 38cefa9fa..cde705aac 100644
--- a/engine/client/view.c
+++ b/engine/client/view.c
@@ -392,6 +392,10 @@ void V_ParseDamage (int pnum)
if (count < 10)
count = 10;
+#ifdef ANDROID
+ Sys_Vibrate(count);
+#endif
+
if (v_damagecshift.value >= 0)
count *= v_damagecshift.value;
diff --git a/engine/client/wad.c b/engine/client/wad.c
index dc741292c..4b091e3f1 100644
--- a/engine/client/wad.c
+++ b/engine/client/wad.c
@@ -639,15 +639,12 @@ void Mod_ParseInfoFromEntityLump(model_t *wmodel, char *data, char *mapname) //a
else if (!strcmp("fog", key))
{
char *s;
- Q_strncpyz(key, com_token, sizeof(key));
- s = COM_Parse(key);
- cl.fog_density = atof(com_token);
- s = COM_Parse(s);
- cl.fog_colour[0] = atof(com_token);
- s = COM_Parse(s);
- cl.fog_colour[1] = atof(com_token);
- s = COM_Parse(s);
- cl.fog_colour[2] = atof(com_token);
+ void CL_Fog_f(void);
+ key[0] = 'f';
+ key[1] = ' ';
+ Q_strncpyz(key+2, com_token, sizeof(key)-2);
+ Cmd_TokenizeString(key, false, false);
+ CL_Fog_f();
}
else if (!strcmp("sky", key)) // for Quake2 maps
{
diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h
index a8b4f19e8..12a1acb46 100644
--- a/engine/common/bothdefs.h
+++ b/engine/common/bothdefs.h
@@ -233,7 +233,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef ANDROID
#undef RTLIGHTS
+#ifndef SPEEX_STATIC
#undef VOICECHAT
+#endif
#undef TEXTEDITOR
#endif
#ifdef NACL
@@ -360,6 +362,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#else
#define PLATFORM "Win32"
#endif
+ #elif defined(ANDROID)
+ #define PLATFORM "Android" /*technically also linux*/
#elif defined(__linux__)
#if defined(__amd64__)
#define PLATFORM "Linux64"
diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c
index 1eb111828..e06a3bafc 100644
--- a/engine/common/com_mesh.c
+++ b/engine/common/com_mesh.c
@@ -712,6 +712,7 @@ static float Alias_CalculateSkeletalNormals(galiasinfo_t *model)
Z_Free(inversepose);
Z_Free(normals);
Z_Free(xyz);
+ Z_Free(mvert);
model = next;
modnum++;
diff --git a/engine/common/common.c b/engine/common/common.c
index b31a52c35..afb5e2b1a 100644
--- a/engine/common/common.c
+++ b/engine/common/common.c
@@ -2210,7 +2210,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
continue;
}
}
- if (*str == '&' && str[1] == 'c')
+ else if (*str == '&' && str[1] == 'c')
{
// ezQuake color codes
@@ -2261,6 +2261,15 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
}
}
}
+ else if (*str == '&' && str[1] == 'r')
+ {
+ ext = (COLOR_WHITE << CON_FGSHIFT) | (ext&~CON_FGMASK);
+ if (!keepmarkup)
+ {
+ str+=2;
+ continue;
+ }
+ }
messedup:
if (!--outsize)
break;
@@ -2270,6 +2279,8 @@ messedup:
{
if (strchr("\n\r\t ", *str))
*out++ = (unsigned char)(*str++) | (ext&~CON_HIGHCHARSMASK);
+ else if (*str >= 32 && *str < 127 && !(ext&CON_HIGHCHARSMASK))
+ *out++ = (unsigned char)(*str++) | ext;
else
*out++ = (unsigned char)(*str++) | ext | 0xe000;
}
@@ -3324,6 +3335,13 @@ void COM_Version_f (void)
#endif
}
+void COM_CrashMe_f(void)
+{
+ int *crashaddr = (int*)0x05;
+
+ *crashaddr = 0;
+}
+
/*
================
COM_Init
@@ -3360,7 +3378,7 @@ void COM_Init (void)
Cmd_AddCommand ("flocate", COM_Locate_f); //prints the pak or whatever where this file can be found.
Cmd_AddCommand ("version", COM_Version_f); //prints the pak or whatever where this file can be found.
- Cmd_AddCommand ("crashme", (void*)1); //debugging feature, makes it jump to an invalid address
+ Cmd_AddCommand ("crashme", COM_CrashMe_f);
COM_InitFilesystem ();
COM_CheckRegistered ();
diff --git a/engine/common/console.h b/engine/common/console.h
index dcf74b34e..63a93d6df 100644
--- a/engine/common/console.h
+++ b/engine/common/console.h
@@ -169,7 +169,7 @@ void Con_PrintCon (console_t *con, char *txt);
void Con_NotifyBox (char *text); // during startup for sound / cd warnings
#ifdef CRAZYDEBUGGING
-#define TRACE(x) Con_Printf x
+#define TRACE(x) Sys_Printf x
#else
#define TRACE(x)
#endif
diff --git a/engine/common/fs.c b/engine/common/fs.c
index 8196f8b21..d4eeb8ace 100644
--- a/engine/common/fs.c
+++ b/engine/common/fs.c
@@ -1645,6 +1645,40 @@ char *FS_GetBasedir(void)
{
return com_quakedir;
}
+
+void FS_CleanDir(char *in, char *out, int outlen)
+{
+ char *end;
+ if (!outlen)
+ return;
+ end = in + strlen(in);
+ //skip over any trailing slashes
+ while (end > in)
+ {
+ if (end[-1] == '/' || end[-1] == '\\')
+ end--;
+ else
+ break;
+ }
+
+ //skip over the path
+ while (end > in)
+ {
+ if (end[-1] != '/' && end[-1] != '\\')
+ end--;
+ else
+ break;
+ }
+
+ //copy string into the dest
+ while (--outlen)
+ {
+ if (*end == '/' || *end == '\\' || !*end)
+ break;
+ *out++ = *end++;
+ }
+ *out = 0;
+}
/*
================
COM_Gamedir
@@ -1654,9 +1688,9 @@ Sets the gamedir and path to a different directory.
*/
void COM_Gamedir (const char *dir)
{
+ char thispath[64];
searchpath_t *next;
- int plen, dlen;
- char *p;
+ int dlen;
qboolean isbase;
if (!*dir || !strcmp(dir, ".") || strstr(dir, "..") || strstr(dir, "/")
@@ -1674,41 +1708,18 @@ void COM_Gamedir (const char *dir)
isbase = true;
if (next->funcs == &osfilefuncs)
{
- p = next->handle;
- plen = strlen(p);
- if (plen == dlen)
+ FS_CleanDir(next->purepath, thispath, sizeof(thispath));
+ if (!strcmp(dir, thispath))
{
- //no basedir, maybe
- if (!strcmp(p, dir))
+ if (isbase && com_searchpaths == com_base_searchpaths)
{
- if (isbase && com_searchpaths == com_base_searchpaths)
- {
- Q_strncpyz (gamedirfile, dir, sizeof(gamedirfile));
- return;
- }
- if (!isbase)
- return;
- break;
+ Q_strncpyz (gamedirfile, dir, sizeof(gamedirfile));
+ return;
}
+ if (!isbase)
+ return;
+ break;
}
- else if (plen > dlen)
- {
- if (*(p+plen-dlen-1) == '/')
- {
- if (!strcmp(p+plen-dlen, dir))
- {
- if (isbase && com_searchpaths == com_base_searchpaths)
- {
- Q_strncpyz (gamedirfile, dir, sizeof(gamedirfile));
- return;
- }
- if (!isbase)
- return;
- break;
- }
- }
- }
-
}
}
@@ -1807,6 +1818,7 @@ void COM_Gamedir (const char *dir)
#define HEX2CFG "set com_parseutf8 -1\nset gl_font gfx/hexen2\nset in_builtinkeymap 0\nset_calc cl_playerclass int (random * 5) + 1\nset r_particlesdesc \"spikeset tsshaft h2part\"\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\nsv_sound_land \"fx/thngland.wav\"\n"
/*Q3's ui doesn't like empty model/headmodel/handicap cvars, even if the gamecode copes*/
#define Q3CFG "gl_overbright 2\nseta model sarge\nseta headmodel sarge\nseta handicap 100\n"
+#define RMQCFG "sv_bigcoords 1\n"
typedef struct {
const char *argname; //used if this was used as a parameter.
@@ -1834,6 +1846,7 @@ const gamemode_info_t gamemode_info[] = {
{"-spark", "spark", "Spark", {"base/src/progs.src",
"base/qwprogs.dat",
"base/pak0.pak"}, DMFCFG, {"base", }, "Spark"},
+ {"-rmq", "rmq", "RMQ", {NULL}, RMQCFG, {"id1", "qw", "rmq", "fte"}, "Remake Quake"},
//supported commercial mods (some are currently only partially supported)
{"-portals", "h2mp", "FTE-H2MP", {"portals/hexen.rc",
@@ -2147,7 +2160,16 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
com_base_searchpaths = com_searchpaths;
if (oldpaths->isexplicit)
- FS_AddPathHandle(oldpaths->purepath, oldpaths->purepath, oldpaths->funcs, oldpaths->handle, oldpaths->copyprotected, false, true, reloadflags);
+ {
+ if (oldpaths->funcs == &osfilefuncs)
+ {
+ char pure[64];
+ FS_CleanDir(oldpaths->purepath, pure, sizeof(pure));
+ FS_AddPathHandle(pure, oldpaths->purepath, oldpaths->funcs, oldpaths->handle, oldpaths->copyprotected, false, true, reloadflags);
+ }
+ else
+ FS_AddPathHandle(oldpaths->purepath, oldpaths->purepath, oldpaths->funcs, oldpaths->handle, oldpaths->copyprotected, false, true, reloadflags);
+ }
else
oldpaths->funcs->ClosePath(oldpaths->handle);
Z_Free(oldpaths);
diff --git a/engine/common/log.c b/engine/common/log.c
index 4355f84fc..de9bc1ec0 100644
--- a/engine/common/log.c
+++ b/engine/common/log.c
@@ -376,7 +376,7 @@ void Log_Init(void)
// cmd line options, debug options
#ifdef CRAZYDEBUGGING
- Cvar_ForceSet(&log_enable, "1");
+ Cvar_ForceSet(&log_enable[LOG_CONSOLE], "1");
TRACE(("dbg: Con_Init: log_enable forced\n"));
#endif
diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c
index f1cacd879..afee8ca38 100644
--- a/engine/common/pr_bgcmd.c
+++ b/engine/common/pr_bgcmd.c
@@ -3583,7 +3583,7 @@ lh_extension_t QSG_Extensions[] = {
{"EXT_CSQC_SHARED"}, //this is a separate extension because it requires protocol modifications. note: this is also the extension that extends the allowed stats.
- {NULL},
+ {"PEXT_DPFLAGS"},
//{"EXT_CSQC"}, //this is the base csqc extension. I'm not sure what needs to be separate and what does not.
//{"EXT_CSQC_DELTAS"},//this is a separate extension because the feature may be banned in a league due to cheat protection.
diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h
index af0f28a38..16de02a24 100644
--- a/engine/common/pr_common.h
+++ b/engine/common/pr_common.h
@@ -500,4 +500,4 @@ enum
GE_ABSMIN = 14,
GE_ABSMAX = 15,
GE_LIGHT = 16
-};
\ No newline at end of file
+};
diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c
index 24c9305cc..274825e7c 100644
--- a/engine/common/q1bsp.c
+++ b/engine/common/q1bsp.c
@@ -1,6 +1,8 @@
#include "quakedef.h"
#include "pr_common.h"
+
+qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contentmask, trace_t *trace);
/*
============================================================================
@@ -998,6 +1000,14 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3]
}
}
+ if (model->terrain && trace->fraction)
+ {
+ trace_t hmt;
+ Heightmap_Trace(model, forcehullnum, frame, axis, start, end, mins, maxs, hitcontentsmask, &hmt);
+ if (hmt.fraction < trace->fraction)
+ *trace = hmt;
+ }
+
return trace->fraction != 1;
}
diff --git a/engine/common/sys.h b/engine/common/sys.h
index e46712915..2ab7ed836 100644
--- a/engine/common/sys.h
+++ b/engine/common/sys.h
@@ -85,6 +85,8 @@ void Sys_SendKeyEvents (void);
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm);
+void Sys_Vibrate(int count);
+
qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate);
#ifdef MULTITHREAD
diff --git a/engine/common/zone.c b/engine/common/zone.c
index cdc2cd9ed..eb1d979b2 100644
--- a/engine/common/zone.c
+++ b/engine/common/zone.c
@@ -1384,7 +1384,7 @@ void *Hunk_AllocName (int size, char *name)
#ifdef _WIN32
Sys_Error ("Not enough RAM allocated on allocation of \"%s\". Try starting using \"-heapsize 16000\" on the QuakeWorld command line.", name);
#else
- Sys_Error ("Not enough RAM allocated. Try starting using \"-mem 16\" on the QuakeWorld command line.");
+ Sys_Error ("Not enough RAM allocated. Try starting using \"-mem %u\" on the QuakeWorld command line.", (hunk_size + 8*1024*1024) / 1024*1024);
#endif
#endif
diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c
index c515e0d8c..cfd77bf50 100644
--- a/engine/d3d/vid_d3d.c
+++ b/engine/d3d/vid_d3d.c
@@ -1069,9 +1069,6 @@ static void (D3D9_SCR_UpdateScreen) (void)
scr_con_forcedraw = false;
if (noworld)
{
- if ((key_dest == key_console || key_dest == key_game) && SCR_GetLoadingStage() == LS_NONE)
- scr_con_current = vid.height;
-
if (scr_con_current != vid.height)
R2D_ConsoleBackground(0, vid.height, true);
else
diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj
index 9f987525b..10308c913 100644
--- a/engine/dotnet2005/ftequake.vcproj
+++ b/engine/dotnet2005/ftequake.vcproj
@@ -20879,6 +20879,170 @@
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -21207,6 +21371,170 @@
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/engine/droid/AndroidManifest.xml b/engine/droid/AndroidManifest.xml
index b9208c8c1..20dc4c94c 100644
--- a/engine/droid/AndroidManifest.xml
+++ b/engine/droid/AndroidManifest.xml
@@ -7,6 +7,7 @@
+
type == mod_heightmap)
- GL_DrawHeightmapModel(batches, &r_worldentity);
+ if (cl.worldmodel && cl.worldmodel->terrain)
+ Terr_DrawTerrainModel(batches, &r_worldentity);
#endif
if (!r_drawentities.ival)
diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c
index c07543ca8..4b50b2750 100644
--- a/engine/gl/gl_backend.c
+++ b/engine/gl/gl_backend.c
@@ -1618,12 +1618,24 @@ static void colourgen(const shaderpass_t *pass, int cnt, vec4_t *src, vec4_t *ds
}
break;
case RGB_GEN_IDENTITY_LIGHTING:
- //compensate for overbrights
- while((cnt)--)
+ if (shaderstate.curbatch->lightstyle[0] != 255)
{
- dst[cnt][0] = shaderstate.identitylighting;
- dst[cnt][1] = shaderstate.identitylighting;
- dst[cnt][2] = shaderstate.identitylighting;
+ while((cnt)--)
+ {
+ dst[cnt][0] = shaderstate.identitylighting * d_lightstylevalue[shaderstate.curbatch->lightstyle[0]]/256.0f;
+ dst[cnt][1] = shaderstate.identitylighting * d_lightstylevalue[shaderstate.curbatch->lightstyle[0]]/256.0f;
+ dst[cnt][2] = shaderstate.identitylighting * d_lightstylevalue[shaderstate.curbatch->lightstyle[0]]/256.0f;
+ }
+ }
+ else
+ {
+ //compensate for overbrights
+ while((cnt)--)
+ {
+ dst[cnt][0] = shaderstate.identitylighting;
+ dst[cnt][1] = shaderstate.identitylighting;
+ dst[cnt][2] = shaderstate.identitylighting;
+ }
}
break;
default:
@@ -3525,6 +3537,7 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_
shaderstate.sourcevbo = &shaderstate.dummyvbo;
shaderstate.curshader = shader;
shaderstate.flags = beflags;
+ TRACE(("GLBE_DrawMesh_List: shader %s\n", shader->name));
if (shaderstate.curentity != &r_worldentity)
{
BE_SelectEntity(&r_worldentity);
@@ -3719,10 +3732,15 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
continue;
if (batch->buildmeshes)
+ {
+ TRACE(("GLBE_SubmitMeshesSortList: build\n"));
batch->buildmeshes(batch);
+ }
else if (batch->texture)
batch->shader = R_TextureAnimation(batch->ent->framestate.g[FS_REG].frame[0], batch->texture)->shader;
+ TRACE(("GLBE_SubmitMeshesSortList: shader %s\n", batch->shader->name));
+
if (batch->shader->flags & SHADER_NODRAW)
continue;
if (batch->shader->flags & SHADER_NODLIGHT)
@@ -4111,6 +4129,8 @@ void GLBE_DrawWorld (qboolean drawworld, qbyte *vis)
GL_DoSwap();
+ TRACE(("GLBE_DrawWorld: %i %p\n", drawworld, vis));
+
if (!r_refdef.recurse)
{
if (shaderstate.wbatch + 50 > shaderstate.maxwbatches)
@@ -4210,9 +4230,11 @@ void GLBE_DrawWorld (qboolean drawworld, qbyte *vis)
if (vis)
{
RSpeedRemark();
+ TRACE(("GLBE_DrawWorld: drawing lights\n"));
BE_SelectEntity(&r_worldentity);
Sh_DrawLights(vis);
RSpeedEnd(RSPEED_STENCILSHADOWS);
+ TRACE(("GLBE_DrawWorld: lights drawn\n"));
}
#endif
@@ -4239,5 +4261,7 @@ void GLBE_DrawWorld (qboolean drawworld, qbyte *vis)
shaderstate.identitylighting = 1;
shaderstate.mbatches = ob;
+
+ TRACE(("GLBE_DrawWorld: drawn everything\n"));
}
#endif
diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c
index 0a81e6477..ce8d9d1cb 100644
--- a/engine/gl/gl_font.c
+++ b/engine/gl/gl_font.c
@@ -1522,8 +1522,8 @@ float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int ch
}
else
{
- sx = ((px+c->left));
- sy = ((py+c->top));
+ sx = ((px+(c->left*(int)vid.width) / (float)vid.rotpixelwidth));
+ sy = ((py+(c->top*(int)vid.height) / (float)vid.rotpixelheight));
sw = ((c->bmw*cw));
sh = ((c->bmh*ch));
v = Font_BeginChar(fontplanes.texnum[c->texplane]);
diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c
index aa411fb72..eaa262bcf 100644
--- a/engine/gl/gl_heightmap.c
+++ b/engine/gl/gl_heightmap.c
@@ -6,8 +6,6 @@
#include "pr_common.h"
-int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader);
-
//heightmaps work thusly:
//there is one raw heightmap file
//the file is split to 4*4 sections.
@@ -17,21 +15,47 @@ int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader);
//we get 20->130
//perhaps we should build it with multitexture? (no - slower on ati)
+int Surf_NewLightmaps(int count, int width, int height);
+
#define MAXSECTIONS 64 //this many sections max in each direction
#define SECTTEXSIZE 64 //this many texture samples per section
#define SECTHEIGHTSIZE 16 //this many height samples per section
+//each section is this many sections higher in world space, to keep the middle centered at '0 0'
+#define CHUNKBIAS (MAXSECTIONS*MAXSECTIONS/2)
+#define CHUNKLIMIT (MAXSECTIONS*MAXSECTIONS)
+
+#define LMCHUNKS 2
+
+#define HMLMSTRIDE (LMCHUNKS*SECTTEXSIZE)
+
+#define SECTION_MAGIC (*(int*)"HMMS")
+#define SECTION_VER 0
+
+enum
+{
+ SECTION_HASWATER = 1,
+};
+
typedef struct
{
+ int magic;
+ int ver;
+ unsigned int flags;
char texname[4][32];
unsigned int texmap[SECTTEXSIZE][SECTTEXSIZE];
float heights[SECTHEIGHTSIZE*SECTHEIGHTSIZE];
unsigned short holes;
+ float waterheight;
} dsection_t;
typedef struct
{
float heights[SECTHEIGHTSIZE*SECTHEIGHTSIZE];
unsigned short holes;
+ unsigned int flags;
+ float waterheight;
+ struct heightmap_s *hmmod;
+
#ifndef SERVERONLY
char texname[4][32];
int lightmap;
@@ -39,74 +63,142 @@ typedef struct
texnums_t textures;
vbo_t vbo;
- unsigned short minh, maxh;
+ float minh, maxh;
mesh_t mesh;
mesh_t *amesh;
qboolean modified:1;
#endif
} hmsection_t;
-typedef struct {
- char path[MAX_QPATH];
- int numsegsx, numsegsy; //tex/cull sections
- float sectionsize; //each section is this big, in world coords
+typedef struct
+{
hmsection_t *section[MAXSECTIONS*MAXSECTIONS];
+} hmcluster_t;
+typedef struct heightmap_s {
+ char path[MAX_QPATH];
+ int firstsegx, firstsegy;
+ int maxsegx, maxsegy; //tex/cull sections
+ float sectionsize; //each section is this big, in world coords
+ hmcluster_t *cluster[MAXSECTIONS*MAXSECTIONS];
shader_t *skyshader;
shader_t *shader;
mesh_t skymesh;
mesh_t *askymesh;
+ unsigned int exteriorcontents;
+
+ struct lmsect_s
+ {
+ struct lmsect_s *next;
+ int lm, x, y;
+ } *unusedlmsects;
} heightmap_t;
-static void GL_LoadSectionTextures(hmsection_t *s)
+static void Terr_LoadSectionTextures(hmsection_t *s)
{
#ifndef SERVERONLY
+ extern texid_t missing_texture;
//CL_CheckOrEnqueDownloadFile(s->texname[0], NULL, 0);
//CL_CheckOrEnqueDownloadFile(s->texname[1], NULL, 0);
//CL_CheckOrEnqueDownloadFile(s->texname[2], NULL, 0);
//CL_CheckOrEnqueDownloadFile(s->texname[3], NULL, 0);
- s->textures.base = R_LoadHiResTexture(s->texname[0], NULL, 0);
- s->textures.upperoverlay = R_LoadHiResTexture(s->texname[1], NULL, 0);
- s->textures.loweroverlay = R_LoadHiResTexture(s->texname[2], NULL, 0);
- s->textures.fullbright = R_LoadHiResTexture(s->texname[3], NULL, 0);
- s->textures.bump = R_LoadHiResTexture(va("%s_norm", s->texname[0]), NULL, 0);
- s->textures.specular = R_LoadHiResTexture(va("%s_spec", s->texname[0]), NULL, 0);
+ s->textures.base = *s->texname[0]?R_LoadHiResTexture(s->texname[0], NULL, 0):missing_texture;
+ s->textures.upperoverlay = *s->texname[1]?R_LoadHiResTexture(s->texname[1], NULL, 0):missing_texture;
+ s->textures.loweroverlay = *s->texname[2]?R_LoadHiResTexture(s->texname[2], NULL, 0):missing_texture;
+ s->textures.fullbright = *s->texname[3]?R_LoadHiResTexture(s->texname[3], NULL, 0):missing_texture;
+ s->textures.bump = *s->texname[0]?R_LoadHiResTexture(va("%s_norm", s->texname[0]), NULL, 0):r_nulltex;
+ s->textures.specular = *s->texname[0]?R_LoadHiResTexture(va("%s_spec", s->texname[0]), NULL, 0):r_nulltex;
#endif
}
-static char *GL_DiskSectionName(heightmap_t *hm, int sx, int sy)
+static void Terr_InitLightmap(hmsection_t *s)
{
- return va("maps/%s/sect_%02i_%02i.hms", hm->path, sx, sy);
+ heightmap_t *hm = s->hmmod;
+ struct lmsect_s *lms;
+
+ if (!hm->unusedlmsects)
+ {
+ int lm;
+ int i;
+ lm = Surf_NewLightmaps(1, SECTTEXSIZE*LMCHUNKS, SECTTEXSIZE*LMCHUNKS);
+ for (i = 0; i < LMCHUNKS*LMCHUNKS; i++)
+ {
+ lms = malloc(sizeof(*lms));
+ lms->lm = lm;
+ BE_UploadAllLightmaps();
+ lms->x = (i & (LMCHUNKS-1))*SECTTEXSIZE;
+ lms->y = (i / LMCHUNKS)*SECTTEXSIZE;
+ lms->next = hm->unusedlmsects;
+ hm->unusedlmsects = lms;
+ }
+ }
+
+ lms = hm->unusedlmsects;
+ hm->unusedlmsects = lms->next;
+
+ s->lightmap = lms->lm;
+ s->lmx = lms->x;
+ s->lmy = lms->y;
+
+ free(lms);
}
-static hmsection_t *GL_LoadSection(heightmap_t *hm, int sx, int sy)
+
+static char *Terr_DiskSectionName(heightmap_t *hm, int sx, int sy)
{
- hmsection_t *s;
- dsection_t *ds;
+ sx -= CHUNKBIAS;
+ sy -= CHUNKBIAS;
+ //wrap cleanly
+ sx &= CHUNKLIMIT-1;
+ sy &= CHUNKLIMIT-1;
+ return va("maps/%s/sect_%03x_%03x.hms", hm->path, sx, sy);
+}
+static hmsection_t *Terr_LoadSection(heightmap_t *hm, hmsection_t *s, int sx, int sy)
+{
+ dsection_t *ds = NULL;
int i;
#ifndef SERVERONLY
unsigned char *lm;
#endif
- s = malloc(sizeof(*s));
- if (!s)
+ /*queue the file for download if we don't have it yet*/
+ if (FS_LoadFile(Terr_DiskSectionName(hm, sx, sy), &ds) < 0
+#ifndef CLIENTONLY
+ && !sv.state
+#endif
+ )
+ {
+ CL_CheckOrEnqueDownloadFile(Terr_DiskSectionName(hm, sx, sy), NULL, 0);
return NULL;
- memset(s, 0, sizeof(*s));
+ }
+
+ if (ds)
+ {
+ if (ds->magic != SECTION_MAGIC)
+ return NULL;
+ if (ds->ver != SECTION_VER)
+ return NULL;
+ }
+
+ if (!s)
+ {
+ s = malloc(sizeof(*s));
+ if (!s)
+ {
+ FS_FreeFile(ds);
+ return NULL;
+ }
+ memset(s, 0, sizeof(*s));
+ s->lightmap = -1;
+ }
+
+ s->hmmod = hm;
#ifndef SERVERONLY
- s->lightmap = -1;
-
- Q_strncpyz(s->texname[0], va("maps/%s/grass", hm->path), sizeof(s->texname[0]));
- Q_strncpyz(s->texname[1], va("maps/%s/rock", hm->path), sizeof(s->texname[1]));
- Q_strncpyz(s->texname[2], va("maps/%s/road", hm->path), sizeof(s->texname[2]));
- Q_strncpyz(s->texname[3], va("maps/%s/ground", hm->path), sizeof(s->texname[3]));
s->modified = true;
- if (s->lightmap < 0)
- {
- s->lightmap = Surf_LM_AllocBlock(SECTTEXSIZE, SECTTEXSIZE, &s->lmx, &s->lmy, hm->shader);
- BE_UploadAllLightmaps();
- }
+ if (s->lightmap < 0 && qrenderer != QR_NONE)
+ Terr_InitLightmap(s);
#endif
- if (FS_LoadFile(GL_DiskSectionName(hm, sx, sy), &ds) >= 0)
+ if (ds)
{
#ifndef SERVERONLY
Q_strncpyz(s->texname[0], ds->texname[0], sizeof(s->texname[0]));
@@ -114,18 +206,26 @@ static hmsection_t *GL_LoadSection(heightmap_t *hm, int sx, int sy)
Q_strncpyz(s->texname[2], ds->texname[2], sizeof(s->texname[2]));
Q_strncpyz(s->texname[3], ds->texname[3], sizeof(s->texname[3]));
- lm = lightmap[s->lightmap]->lightmaps;
- lm += (s->lmx * LMBLOCK_WIDTH + s->lmy) * lightmap_bytes;
- for (i = 0; i < SECTTEXSIZE; i++)
+ CL_CheckOrEnqueDownloadFile(s->texname[0], NULL, 0);
+ CL_CheckOrEnqueDownloadFile(s->texname[1], NULL, 0);
+ CL_CheckOrEnqueDownloadFile(s->texname[2], NULL, 0);
+ CL_CheckOrEnqueDownloadFile(s->texname[3], NULL, 0);
+
+ if (s->lightmap >= 0)
{
- memcpy(lm, ds->texmap + i, sizeof(ds->texmap[0]));
- lm += (LMBLOCK_WIDTH)*lightmap_bytes;
+ lm = lightmap[s->lightmap]->lightmaps;
+ lm += (s->lmx * HMLMSTRIDE + s->lmy) * lightmap_bytes;
+ for (i = 0; i < SECTTEXSIZE; i++)
+ {
+ memcpy(lm, ds->texmap + i, sizeof(ds->texmap[0]));
+ lm += (HMLMSTRIDE)*lightmap_bytes;
+ }
+ lightmap[s->lightmap]->modified = true;
+ lightmap[s->lightmap]->rectchange.l = 0;
+ lightmap[s->lightmap]->rectchange.t = 0;
+ lightmap[s->lightmap]->rectchange.w = HMLMSTRIDE;
+ lightmap[s->lightmap]->rectchange.h = HMLMSTRIDE;
}
- lightmap[s->lightmap]->modified = true;
- lightmap[s->lightmap]->rectchange.l = 0;
- lightmap[s->lightmap]->rectchange.t = 0;
- lightmap[s->lightmap]->rectchange.w = LMBLOCK_WIDTH;
- lightmap[s->lightmap]->rectchange.h = LMBLOCK_HEIGHT;
#endif
/*load the heights too*/
@@ -152,7 +252,7 @@ static hmsection_t *GL_LoadSection(heightmap_t *hm, int sx, int sy)
if (splatter)
{
lm = lightmap[s->lightmap]->lightmaps;
- lm += (s->lmx * LMBLOCK_WIDTH + s->lmy) * lightmap_bytes;
+ lm += (s->lmx * HMLMSTRIDE + s->lmy) * lightmap_bytes;
for (vx = 0; vx < SECTTEXSIZE; vx++)
{
@@ -171,15 +271,15 @@ static hmsection_t *GL_LoadSection(heightmap_t *hm, int sx, int sy)
lm[3] = splatter[(y + x*sh)*4+3];
lm += 4;
}
- lm += (LMBLOCK_WIDTH - SECTTEXSIZE)*lightmap_bytes;
+ lm += (HMLMSTRIDE - SECTTEXSIZE)*lightmap_bytes;
}
BZ_Free(splatter);
lightmap[s->lightmap]->modified = true;
lightmap[s->lightmap]->rectchange.l = 0;
lightmap[s->lightmap]->rectchange.t = 0;
- lightmap[s->lightmap]->rectchange.w = LMBLOCK_WIDTH;
- lightmap[s->lightmap]->rectchange.h = LMBLOCK_HEIGHT;
+ lightmap[s->lightmap]->rectchange.w = HMLMSTRIDE;
+ lightmap[s->lightmap]->rectchange.h = HMLMSTRIDE;
}
FS_FreeFile(f);
}
@@ -224,78 +324,175 @@ static hmsection_t *GL_LoadSection(heightmap_t *hm, int sx, int sy)
#endif
}
- GL_LoadSectionTextures(s);
-
- hm->section[sx+sy*MAXSECTIONS] = s;
+ Terr_LoadSectionTextures(s);
return s;
}
-static void GL_SaveSection(heightmap_t *hm, int sx, int sy)
+static void Terr_SaveSection(heightmap_t *hm, hmsection_t *s, int sx, int sy)
{
#ifndef SERVERONLY
- hmsection_t *s = hm->section[sx+sy*MAXSECTIONS];
dsection_t ds;
unsigned char *lm;
int i;
+ //if its invalid or doesn't contain all the data...
if (!s || s->lightmap < 0)
return;
+ ds.magic = SECTION_MAGIC;
+ ds.ver = SECTION_VER;
+ ds.flags = 0;
+
Q_strncpyz(ds.texname[0], s->texname[0], sizeof(ds.texname[0]));
Q_strncpyz(ds.texname[1], s->texname[1], sizeof(ds.texname[1]));
Q_strncpyz(ds.texname[2], s->texname[2], sizeof(ds.texname[2]));
Q_strncpyz(ds.texname[3], s->texname[3], sizeof(ds.texname[3]));
lm = lightmap[s->lightmap]->lightmaps;
- lm += (s->lmx * LMBLOCK_WIDTH + s->lmy) * lightmap_bytes;
+ lm += (s->lmx * HMLMSTRIDE + s->lmy) * lightmap_bytes;
for (i = 0; i < SECTTEXSIZE; i++)
{
memcpy(ds.texmap + i, lm, sizeof(ds.texmap[0]));
- lm += (LMBLOCK_WIDTH)*lightmap_bytes;
+ lm += (HMLMSTRIDE)*lightmap_bytes;
}
for (i = 0; i < SECTHEIGHTSIZE*SECTHEIGHTSIZE; i++)
{
ds.heights[i] = LittleFloat(s->heights[i]);
}
+ ds.holes = s->holes;
- FS_WriteFile(GL_DiskSectionName(hm, sx, sy), &ds, sizeof(ds), FS_GAMEONLY);
+ FS_WriteFile(Terr_DiskSectionName(hm, sx, sy), &ds, sizeof(ds), FS_GAMEONLY);
#endif
}
+/*convienience function*/
+static hmsection_t *Terr_GetSection(heightmap_t *hm, int x, int y, qboolean doload)
+{
+ hmcluster_t *cluster;
+ hmsection_t *section;
+ int cx = x / MAXSECTIONS;
+ int cy = y / MAXSECTIONS;
+ int sx = x & (MAXSECTIONS-1);
+ int sy = y & (MAXSECTIONS-1);
+ cluster = hm->cluster[cx + cy*MAXSECTIONS];
+ if (!cluster)
+ {
+ if (doload)
+ {
+ cluster = malloc(sizeof(*cluster));
+ memset(cluster, 0, sizeof(*cluster));
+ hm->cluster[cx + cy*MAXSECTIONS] = cluster;
+ }
+ else
+ return NULL;
+ }
+ section = cluster->section[sx + sy*MAXSECTIONS];
+ if (!section)
+ {
+ if (doload)
+ {
+ section = cluster->section[sx + sy*MAXSECTIONS] = Terr_LoadSection(hm, section, x, y);
+ }
+ }
+ return section;
+}
+
/*save all currently loaded sections*/
void HeightMap_Save(heightmap_t *hm)
{
hmsection_t *s;
int x, y;
- for (x = 0; x < hm->numsegsx; x++)
+ for (x = hm->firstsegx; x < hm->maxsegx; x++)
{
- for (y = 0; y < hm->numsegsy; y++)
+ for (y = hm->firstsegy; y < hm->maxsegy; y++)
{
- s = hm->section[x+y*MAXSECTIONS];
- GL_SaveSection(hm, x, y);
+ s = Terr_GetSection(hm, x, y, false);
+ if (!s)
+ continue;
+ Terr_SaveSection(hm, s, x, y);
}
}
}
-/*purge all sections*/
-void HeightMap_Purge(model_t *mod)
+void Terr_DestroySection(heightmap_t *hm, hmsection_t *s)
+{
+ if (hm && s->lightmap >= 0)
+ {
+ struct lmsect_s *lms;
+
+ lms = malloc(sizeof(*lms));
+ lms->lm = s->lightmap;
+ lms->x = s->lmx;
+ lms->y = s->lmy;
+ lms->next = hm->unusedlmsects;
+ hm->unusedlmsects = lms;
+ }
+
+#ifdef GLQUAKE
+ if (qrenderer == QR_OPENGL)
+ {
+ qglDeleteBuffersARB(1, &s->vbo.coord.gl.vbo);
+ qglDeleteBuffersARB(1, &s->vbo.indicies.gl.vbo);
+ }
+#endif
+
+ free(s->mesh.xyz_array);
+ free(s->mesh.indexes);
+ free(s);
+}
+
+/*purge all sections
+lightmaps only are purged whenever the client rudely kills lightmaps
+we'll reload those when its next seen.
+(lightmaps will already have been destroyed, so no poking them)
+*/
+void Terr_PurgeTerrainModel(model_t *mod, qboolean lightmapsonly)
{
heightmap_t *hm = mod->terrain;
+ hmcluster_t *c;
hmsection_t *s;
- int x, y;
- for (x = 0; x < hm->numsegsx; x++)
+ int cx, cy;
+ int sx, sy;
+ for (cy = 0; cy < MAXSECTIONS; cy++)
+ for (cx = 0; cx < MAXSECTIONS; cx++)
{
- for (y = 0; y < hm->numsegsy; y++)
+ c = hm->cluster[cx + cy*MAXSECTIONS];
+ if (!c)
+ continue;
+
+ for (sy = 0; sy < MAXSECTIONS; sy++)
+ for (sx = 0; sx < MAXSECTIONS; sx++)
{
- s = hm->section[x+y*MAXSECTIONS];
- hm->section[x+y*MAXSECTIONS] = NULL;
- free(s);
+ s = c->section[sx + sy*MAXSECTIONS];
+ if (!s)
+ {
+ }
+ else if (lightmapsonly)
+ s->lightmap = -1;
+ else
+ {
+ c->section[sx+sy*MAXSECTIONS] = NULL;
+
+ Terr_DestroySection(NULL, s);
+ }
}
+ if (!lightmapsonly)
+ {
+ hm->cluster[cx + cy*MAXSECTIONS] = NULL;
+ free(c);
+ }
+ }
+ while (hm->unusedlmsects)
+ {
+ struct lmsect_s *lms;
+ lms = hm->unusedlmsects;
+ hm->unusedlmsects = lms->next;
+ free(lms);
}
}
#ifndef SERVERONLY
-void GL_DrawHeightmapModel (batch_t **batches, entity_t *e)
+void Terr_DrawTerrainModel (batch_t **batches, entity_t *e)
{
//a 512*512 heightmap
//will draw 2 tris per square, drawn twice for detail
@@ -309,6 +506,7 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e)
mesh_t *mesh;
batch_t *b;
hmsection_t *s;
+ int bounds[4];
if (e->model == cl.worldmodel)
{
@@ -336,22 +534,56 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e)
}
}
- for (x = 0; x < hm->numsegsx; x++)
+ if (r_refdef.gfog_rgbd[3] || gl_maxdist.value>0)
{
- mins[0] = (x+0)*hm->sectionsize;
- maxs[0] = (x+1)*hm->sectionsize;
- for (y = 0; y < hm->numsegsy; y++)
- {
- mins[1] = (y+0)*hm->sectionsize;
- maxs[1] = (y+1)*hm->sectionsize;
+ float culldist;
+ extern cvar_t r_fog_exp2;
- s = hm->section[x+y*MAXSECTIONS];
+ if (r_refdef.gfog_rgbd[3])
+ {
+ //figure out the eyespace distance required to reach that fog value
+ culldist = log(0.5/255.0f);
+ if (r_fog_exp2.ival)
+ culldist = sqrt(culldist / (-r_refdef.gfog_rgbd[3] * r_refdef.gfog_rgbd[3]));
+ else
+ culldist = culldist / (-r_refdef.gfog_rgbd[3]);
+ //anything drawn beyond this point is fully obscured by fog
+ culldist += 4096;
+ }
+ else
+ culldist = 999999999999999;
+
+ if (culldist > gl_maxdist.value && gl_maxdist.value>0)
+ culldist = gl_maxdist.value;
+
+ bounds[0] = bound(hm->firstsegx, (r_refdef.vieworg[0] + (CHUNKBIAS + 0)*hm->sectionsize - culldist) / hm->sectionsize, hm->maxsegx);
+ bounds[1] = bound(hm->firstsegx, (r_refdef.vieworg[0] + (CHUNKBIAS + 1)*hm->sectionsize + culldist) / hm->sectionsize, hm->maxsegx);
+ bounds[2] = bound(hm->firstsegy, (r_refdef.vieworg[1] + (CHUNKBIAS + 0)*hm->sectionsize - culldist) / hm->sectionsize, hm->maxsegy);
+ bounds[3] = bound(hm->firstsegy, (r_refdef.vieworg[1] + (CHUNKBIAS + 1)*hm->sectionsize + culldist) / hm->sectionsize, hm->maxsegy);
+ }
+ else
+ {
+ bounds[0] = hm->firstsegx;
+ bounds[1] = hm->maxsegx;
+ bounds[2] = hm->firstsegy;
+ bounds[3] = hm->maxsegy;
+ }
+
+ for (x = bounds[0]; x < bounds[1]; x++)
+ {
+ mins[0] = (x+0 - CHUNKBIAS)*hm->sectionsize;
+ maxs[0] = (x+1 - CHUNKBIAS)*hm->sectionsize;
+ for (y = bounds[2]; y < bounds[3]; y++)
+ {
+ mins[1] = (y+0 - CHUNKBIAS)*hm->sectionsize;
+ maxs[1] = (y+1 - CHUNKBIAS)*hm->sectionsize;
+
+ s = Terr_GetSection(hm, x, y, true);
if (!s)
- {
- s = GL_LoadSection(hm, x, y);
- if (!s)
- continue;
- }
+ continue;
+ if (s->lightmap < 0)
+ Terr_LoadSection(hm, s, x, y);
+
mesh = &s->mesh;
if (s->modified)
{
@@ -362,12 +594,11 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e)
if (s->lightmap < 0)
{
- s->lightmap = Surf_LM_AllocBlock(SECTTEXSIZE, SECTTEXSIZE, &s->lmx, &s->lmy, hm->shader);
- BE_UploadAllLightmaps();
+ Terr_InitLightmap(s);
}
- s->minh = 999999999999999;
- s->maxh = -999999999999999;
+ s->minh = 9999999999999999;
+ s->maxh = -9999999999999999;
if (!mesh->xyz_array)
{
@@ -382,8 +613,8 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e)
for (vy = 0; vy < SECTHEIGHTSIZE; vy++)
{
v = mesh->numvertexes++;
- mesh->xyz_array[v][0] = (x + vx/(SECTHEIGHTSIZE-1.0f)) * hm->sectionsize;
- mesh->xyz_array[v][1] = (y + vy/(SECTHEIGHTSIZE-1.0f)) * hm->sectionsize;
+ mesh->xyz_array[v][0] = (x-CHUNKBIAS + vx/(SECTHEIGHTSIZE-1.0f)) * hm->sectionsize;
+ mesh->xyz_array[v][1] = (y-CHUNKBIAS + vy/(SECTHEIGHTSIZE-1.0f)) * hm->sectionsize;
mesh->xyz_array[v][2] = s->heights[vx + vy*SECTHEIGHTSIZE];
if (s->maxh < mesh->xyz_array[v][2])
@@ -391,18 +622,18 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e)
if (s->minh > mesh->xyz_array[v][2])
s->minh = mesh->xyz_array[v][2];
- mesh->st_array[v][0] = mesh->xyz_array[v][0] / 64;
- mesh->st_array[v][1] = mesh->xyz_array[v][1] / 64;
+ mesh->st_array[v][0] = mesh->xyz_array[v][0] / 128;
+ mesh->st_array[v][1] = mesh->xyz_array[v][1] / 128;
//calc the position in the range -0.5 to 0.5
mesh->lmst_array[0][v][0] = (((float)vx / (SECTHEIGHTSIZE-1))-0.5);
mesh->lmst_array[0][v][1] = (((float)vy / (SECTHEIGHTSIZE-1))-0.5);
//scale down to a half-texel
- mesh->lmst_array[0][v][0] *= (SECTTEXSIZE-1.0f)/LMBLOCK_WIDTH;
- mesh->lmst_array[0][v][1] *= (SECTTEXSIZE-1.0f)/LMBLOCK_HEIGHT;
+ mesh->lmst_array[0][v][0] *= (SECTTEXSIZE-1.0f)/HMLMSTRIDE;
+ mesh->lmst_array[0][v][1] *= (SECTTEXSIZE-1.0f)/HMLMSTRIDE;
//bias it
- mesh->lmst_array[0][v][0] += ((float)SECTTEXSIZE/(LMBLOCK_WIDTH*2)) + ((float)(s->lmy) / LMBLOCK_WIDTH);
- mesh->lmst_array[0][v][1] += ((float)SECTTEXSIZE/(LMBLOCK_HEIGHT*2)) + ((float)(s->lmx) / LMBLOCK_HEIGHT);
+ mesh->lmst_array[0][v][0] += ((float)SECTTEXSIZE/(HMLMSTRIDE*2)) + ((float)(s->lmy) / HMLMSTRIDE);
+ mesh->lmst_array[0][v][1] += ((float)SECTTEXSIZE/(HMLMSTRIDE*2)) + ((float)(s->lmx) / HMLMSTRIDE);
//TODO: include colour tints
}
@@ -416,16 +647,36 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e)
{
for (vy = 0; vy < SECTHEIGHTSIZE-1; vy++)
{
- //TODO: holes
- if (s->holes & (vx / (SECTHEIGHTSIZE/4)) << (vy / (SECTHEIGHTSIZE/4)) )
+ float d1,d2;
+ int holebit;
+
+ //skip generation of the mesh above holes
+ holebit = (vy / (SECTHEIGHTSIZE/4))+(vx / (SECTHEIGHTSIZE/4))*4;
+ holebit = 1u<holes & holebit)
continue;
v = vx + vy*(SECTHEIGHTSIZE);
- mesh->indexes[mesh->numindexes++] = v+0;
- mesh->indexes[mesh->numindexes++] = v+1;
- mesh->indexes[mesh->numindexes++] = v+SECTHEIGHTSIZE;
- mesh->indexes[mesh->numindexes++] = v+1;
- mesh->indexes[mesh->numindexes++] = v+1+SECTHEIGHTSIZE;
- mesh->indexes[mesh->numindexes++] = v+SECTHEIGHTSIZE;
+
+ d1 = fabs(mesh->xyz_array[v][2] - mesh->xyz_array[v+1+SECTHEIGHTSIZE][2]);
+ d2 = fabs(mesh->xyz_array[v+1][2] - mesh->xyz_array[v+SECTHEIGHTSIZE][2]);
+ if (d1 > d2)
+ {
+ mesh->indexes[mesh->numindexes++] = v+0;
+ mesh->indexes[mesh->numindexes++] = v+1;
+ mesh->indexes[mesh->numindexes++] = v+SECTHEIGHTSIZE;
+ mesh->indexes[mesh->numindexes++] = v+1;
+ mesh->indexes[mesh->numindexes++] = v+1+SECTHEIGHTSIZE;
+ mesh->indexes[mesh->numindexes++] = v+SECTHEIGHTSIZE;
+ }
+ else
+ {
+ mesh->indexes[mesh->numindexes++] = v+0;
+ mesh->indexes[mesh->numindexes++] = v+1;
+ mesh->indexes[mesh->numindexes++] = v+1+SECTHEIGHTSIZE;
+ mesh->indexes[mesh->numindexes++] = v+0;
+ mesh->indexes[mesh->numindexes++] = v+1+SECTHEIGHTSIZE;
+ mesh->indexes[mesh->numindexes++] = v+SECTHEIGHTSIZE;
+ }
}
}
@@ -440,7 +691,7 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e)
GL_SelectVBO(0);
s->vbo.texcoord.gl.addr = (void*)((char*)mesh->st_array - (char*)mesh->xyz_array);
s->vbo.texcoord.gl.vbo = s->vbo.coord.gl.vbo;
- s->vbo.lmcoord[0].gl.addr = (void*)((char*)mesh->lmst_array - (char*)mesh->xyz_array);
+ s->vbo.lmcoord[0].gl.addr = (void*)((char*)mesh->lmst_array[0] - (char*)mesh->xyz_array);
s->vbo.lmcoord[0].gl.vbo = s->vbo.coord.gl.vbo;
// Z_Free(mesh->xyz_array);
// mesh->xyz_array = NULL;
@@ -496,31 +747,36 @@ unsigned int Heightmap_PointContentsHM(heightmap_t *hm, float clipmipsz, vec3_t
float x, y;
float z, tz;
int sx, sy;
- int sectidx;
+ unsigned int holebit;
hmsection_t *s;
+ const float wbias = CHUNKBIAS * hm->sectionsize;
- sx = org[0]/hm->sectionsize;
- sy = org[1]/hm->sectionsize;
- if (sx < 0 || sy < 0)
- return FTECONTENTS_SOLID;
- if (sx >= hm->numsegsx || sy >= hm->numsegsy)
- return FTECONTENTS_SOLID;
- sectidx = sx + sy*MAXSECTIONS;
- s = hm->section[sectidx];
+ sx = (org[0]+wbias)/hm->sectionsize;
+ sy = (org[1]+wbias)/hm->sectionsize;
+ if (sx < hm->firstsegx || sy < hm->firstsegy)
+ return hm->exteriorcontents;
+ if (sx >= hm->maxsegx || sy >= hm->maxsegy)
+ return hm->exteriorcontents;
+ s = Terr_GetSection(hm, sx, sy, true);
if (!s)
{
- s = GL_LoadSection(hm, sx, sy);
- if (!s)
- return FTECONTENTS_SOLID;
+ return FTECONTENTS_SOLID;
}
- x = (org[0] - (sx*hm->sectionsize))*(SECTHEIGHTSIZE-1)/hm->sectionsize;
- y = (org[1] - (sy*hm->sectionsize))*(SECTHEIGHTSIZE-1)/hm->sectionsize;
+ x = (org[0]+wbias - (sx*hm->sectionsize))*(SECTHEIGHTSIZE-1)/hm->sectionsize;
+ y = (org[1]+wbias - (sy*hm->sectionsize))*(SECTHEIGHTSIZE-1)/hm->sectionsize;
z = (org[2]+clipmipsz);
+ if (z < s->minh-16)
+ return hm->exteriorcontents;
+
sx = x; x-=sx;
sy = y; y-=sy;
+ holebit = sx*4/SECTHEIGHTSIZE + (sy*4/SECTHEIGHTSIZE)*4;
+ if (s->holes & (1u<1) //the 1, 1 triangle
{
@@ -551,6 +807,9 @@ unsigned int Heightmap_PointContentsHM(heightmap_t *hm, float clipmipsz, vec3_t
}
if (z <= tz)
return FTECONTENTS_SOLID; //contained within
+ if (s->flags & SECTION_HASWATER)
+ if (z < s->waterheight)
+ return FTECONTENTS_WATER;
return FTECONTENTS_EMPTY;
}
@@ -1056,19 +1315,30 @@ static unsigned char *ted_getlightmap(hmsection_t *s, int idx)
int x = idx % SECTTEXSIZE, y = idx / SECTTEXSIZE;
if (s->lightmap < 0)
{
- s->lightmap = Surf_LM_AllocBlock(SECTTEXSIZE, SECTTEXSIZE, &s->lmx, &s->lmy, NULL);
- BE_UploadAllLightmaps();
+ Terr_InitLightmap(s);
}
lightmap[s->lightmap]->modified = true;
lightmap[s->lightmap]->rectchange.l = 0;
lightmap[s->lightmap]->rectchange.t = 0;
- lightmap[s->lightmap]->rectchange.w = LMBLOCK_WIDTH;
- lightmap[s->lightmap]->rectchange.h = LMBLOCK_HEIGHT;
+ lightmap[s->lightmap]->rectchange.w = HMLMSTRIDE;
+ lightmap[s->lightmap]->rectchange.h = HMLMSTRIDE;
lm = lightmap[s->lightmap]->lightmaps;
- lm += ((s->lmx+y) * LMBLOCK_WIDTH + (s->lmy+x)) * lightmap_bytes;
+ lm += ((s->lmx+y) * HMLMSTRIDE + (s->lmy+x)) * lightmap_bytes;
return lm;
}
+static void ted_sethole(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
+{
+ unsigned int bit;
+ unsigned int mask;
+ mask = 1u<modified = true;
+ s->holes = (s->holes & ~mask) | bit;
+}
static void ted_heighttally(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
{
/*raise the terrain*/
@@ -1079,7 +1349,11 @@ static void ted_heightsmooth(void *ctx, hmsection_t *s, int idx, float wx, float
{
s->modified = true;
/*interpolate the terrain towards a certain value*/
- s->heights[idx] = s->heights[idx]*(1-w) + w**(float*)ctx;
+
+ if (IS_NAN(s->heights[idx]))
+ s->heights[idx] = *(float*)ctx;
+ else
+ s->heights[idx] = s->heights[idx]*(1-w) + w**(float*)ctx;
}
static void ted_heightraise(void *ctx, hmsection_t *s, int idx, float wx, float wy, float strength)
{
@@ -1142,9 +1416,51 @@ static void ted_mixnoise(void *ctx, hmsection_t *s, int idx, float wx, float wy,
lm[2] = lm[2]*(1-w) + (v[2]*(w));
}
+static void ted_mixpaint(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
+{
+ unsigned char *lm = ted_getlightmap(s, idx);
+ char *texname = ctx;
+ int t;
+ vec3_t newval;
+ if (w > 1)
+ w = 1;
+
+ for (t = 0; t < 4; t++)
+ {
+ if (!strncmp(s->texname[t], texname, sizeof(s->texname[t])-1))
+ {
+ newval[0] = (t == 0);
+ newval[1] = (t == 1);
+ newval[2] = (t == 2);
+ lm[2] = lm[2]*(1-w) + (255*newval[0]*(w));
+ lm[1] = lm[1]*(1-w) + (255*newval[1]*(w));
+ lm[0] = lm[0]*(1-w) + (255*newval[2]*(w));
+ return;
+ }
+ }
+ for (t = 0; t < 4; t++)
+ {
+ if (!*s->texname[t])
+ {
+ Q_strncpyz(s->texname[t], texname, sizeof(s->texname[t]));
+
+ newval[0] = (t == 0);
+ newval[1] = (t == 1);
+ newval[2] = (t == 2);
+ lm[2] = lm[2]*(1-w) + (255*newval[0]*(w));
+ lm[1] = lm[1]*(1-w) + (255*newval[1]*(w));
+ lm[0] = lm[0]*(1-w) + (255*newval[2]*(w));
+
+ Terr_LoadSectionTextures(s);
+ return;
+ }
+ }
+}
static void ted_mixset(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
{
unsigned char *lm = ted_getlightmap(s, idx);
+ if (w > 1)
+ w = 1;
lm[2] = lm[2]*(1-w) + (255*((float*)ctx)[0]*(w));
lm[1] = lm[1]*(1-w) + (255*((float*)ctx)[1]*(w));
lm[0] = lm[0]*(1-w) + (255*((float*)ctx)[2]*(w));
@@ -1176,10 +1492,10 @@ static void ted_itterate(heightmap_t *hm, float *pos, float radius, float streng
max[0] = ceil((pos[0] + radius)/(hm->sectionsize) + 1);
max[1] = ceil((pos[1] + radius)/(hm->sectionsize) + 1);
- min[0] = bound(0, min[0], hm->numsegsx);
- min[1] = bound(0, min[1], hm->numsegsy);
- max[0] = bound(0, max[0], hm->numsegsx);
- max[1] = bound(0, max[1], hm->numsegsy);
+ min[0] = bound(hm->firstsegx, min[0], hm->maxsegx);
+ min[1] = bound(hm->firstsegx, min[1], hm->maxsegy);
+ max[0] = bound(hm->firstsegx, max[0], hm->maxsegx);
+ max[1] = bound(hm->firstsegx, max[1], hm->maxsegy);
sc[0] = hm->sectionsize/(steps-1);
sc[1] = hm->sectionsize/(steps-1);
@@ -1188,9 +1504,7 @@ static void ted_itterate(heightmap_t *hm, float *pos, float radius, float streng
{
for (sy = min[1]; sy < max[1]; sy++)
{
- s = hm->section[(int)(sx) + (int)(sy)*MAXSECTIONS];
- if (!s)
- s = GL_LoadSection(hm, sx, sy);
+ s = Terr_GetSection(hm, sx, sy, true);
if (!s)
continue;
@@ -1219,16 +1533,18 @@ enum
{
ter_reload,
ter_save,
+ ter_sethole,
ter_height_set,
ter_height_smooth,
+ ter_height_spread,
ter_raise,
ter_lower,
- ter_tex_set,
+ ter_tex_kill,
ter_tex_get,
- ter_mixset,
+ ter_mixpaint,
ter_mixconcentrate,
ter_mixnoise,
- ter_mixblur,
+ ter_mixblur
};
void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@@ -1245,18 +1561,36 @@ void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_glob
G_FLOAT(OFS_RETURN) = 0;
- if (!mod || mod->type != mod_heightmap)
+ if (!mod || !mod->terrain)
return;
hm = mod->terrain;
+ pos[0] += hm->sectionsize * CHUNKBIAS;
+ pos[1] += hm->sectionsize * CHUNKBIAS;
+
switch(action)
{
case ter_reload:
- HeightMap_Purge(mod);
+ Terr_PurgeTerrainModel(mod, false);
break;
case ter_save:
HeightMap_Save(hm);
break;
+ case ter_sethole:
+ {
+ int x, y;
+ hmsection_t *s;
+ x = pos[0]*4 / hm->sectionsize;
+ y = pos[1]*4 / hm->sectionsize;
+ x = bound(hm->firstsegx*4, x, hm->maxsegy*4-1);
+ y = bound(hm->firstsegy*4, y, hm->maxsegy*4-1);
+
+ s = Terr_GetSection(hm, x/4, y/4, true);
+ if (!s)
+ return;
+ ted_sethole(&quant, s, (x&3) + (y&3)*4, x/4, y/4, 0);
+ }
+ break;
case ter_height_set:
ted_itterate(hm, pos, radius, 1, SECTHEIGHTSIZE, ted_heightset, &quant);
break;
@@ -1265,6 +1599,17 @@ void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_glob
tally[1] = 0;
ted_itterate(hm, pos, radius, 1, SECTHEIGHTSIZE, ted_heighttally, &tally);
tally[0] /= tally[1];
+ if (IS_NAN(tally[0]))
+ tally[0] = 0;
+ ted_itterate(hm, pos, radius, 1, SECTHEIGHTSIZE, ted_heightsmooth, &tally);
+ break;
+ case ter_height_spread:
+ tally[0] = 0;
+ tally[1] = 0;
+ ted_itterate(hm, pos, radius/2, 1, SECTHEIGHTSIZE, ted_heighttally, &tally);
+ tally[0] /= tally[1];
+ if (IS_NAN(tally[0]))
+ tally[0] = 0;
ted_itterate(hm, pos, radius, 1, SECTHEIGHTSIZE, ted_heightsmooth, &tally);
break;
case ter_lower:
@@ -1272,8 +1617,11 @@ void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_glob
case ter_raise:
ted_itterate(hm, pos, radius, quant, SECTHEIGHTSIZE, ted_heightraise, &quant);
break;
- case ter_mixset:
- ted_itterate(hm, pos, radius, 1, SECTTEXSIZE, ted_mixset, G_VECTOR(OFS_PARM4));
+// case ter_mixset:
+// ted_itterate(hm, pos, radius, 1, SECTTEXSIZE, ted_mixset, G_VECTOR(OFS_PARM4));
+// break;
+ case ter_mixpaint:
+ ted_itterate(hm, pos, radius, quant/10, SECTTEXSIZE, ted_mixpaint, PR_GetStringOfs(prinst, OFS_PARM4));
break;
case ter_mixconcentrate:
ted_itterate(hm, pos, radius, 1, SECTTEXSIZE, ted_mixconcentrate, NULL);
@@ -1284,55 +1632,79 @@ void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_glob
case ter_mixblur:
Vector4Set(tally, 0, 0, 0, 0);
ted_itterate(hm, pos, radius, 1, SECTTEXSIZE, ted_mixtally, &tally);
- VectorScale(tally, 1/tally[3], tally);
+ VectorScale(tally, 1/(tally[3]*255), tally);
ted_itterate(hm, pos, radius, quant, SECTTEXSIZE, ted_mixset, &tally);
break;
- case ter_tex_set:
- ted_itterate(hm, pos, radius, 1, SECTTEXSIZE, ted_mixset, NULL);
-/* radius *= (float)hm->numsegsx / hm->tilesx;
- for (x = 0; x < hm->numsegsx; x++)
- {
- for (y = 0; y < hm->numsegsy; y++)
- {
- xd = (sc[0] - x) * (float)hm->numsegsx / hm->tilesx;
- yd = (sc[1] - y) * (float)hm->numsegsy / hm->tilesy;
- w = sqrt(radius*radius - (xd*xd+yd*yd));
- if (w > 0)
- {
- s = hm->section[(int)(x) + (int)(y)*MAXSECTIONS];
- if (!s)
- s = GL_LoadSection(hm, x, y);
- if (s)
- {
- if (quant < 0 || quant >= 4)
- quant = 0;
- Q_strncpyz(s->texname[(int)quant], PR_GetStringOfs(prinst, OFS_PARM4), sizeof(s->texname[0]));
- s->modified = true;
-
- GL_LoadSectionTextures(s);
- }
- }
- }
- }
-*/
- break;
case ter_tex_get:
-/*
- x = sc[0]*hm->numsegsx / hm->tilesx;
- y = sc[1]*hm->numsegsy / hm->tilesy;
- x = bound(0, x, hm->numsegsx-1);
- y = bound(0, y, hm->numsegsy-1);
-
- G_INT(OFS_RETURN) = 0;
- s = hm->section[(int)(x) + (int)(y)*MAXSECTIONS];
- if (!s)
- s = GL_LoadSection(hm, x, y);
- if (s)
{
+ int x, y;
+ hmsection_t *s;
+ x = pos[0] / hm->sectionsize;
+ y = pos[1] / hm->sectionsize;
+ x = bound(hm->firstsegx, x, hm->maxsegy-1);
+ y = bound(hm->firstsegy, y, hm->maxsegy-1);
+
+ s = Terr_GetSection(hm, x, y, true);
+ if (!s)
+ return;
x = bound(0, quant, 3);
G_INT(OFS_RETURN) = PR_TempString(prinst, s->texname[x]);
}
-*/
+ break;
+ case ter_tex_kill:
+ {
+ char *killtex = PR_GetStringOfs(prinst, OFS_PARM4);
+ int x, y, t, to;
+ hmsection_t *s;
+ x = pos[0] / hm->sectionsize;
+ y = pos[1] / hm->sectionsize;
+ x = bound(hm->firstsegx, x, hm->maxsegy-1);
+ y = bound(hm->firstsegy, y, hm->maxsegy-1);
+
+ s = Terr_GetSection(hm, x, y, true);
+ if (!s)
+ return;
+ for (t = 0; t < 4; t++)
+ {
+ if (!strcmp(s->texname[t], killtex))
+ {
+ unsigned char *lm = ted_getlightmap(s, 0);
+ s->texname[t][0] = 0;
+ for (to = 0; to < 4; to++)
+ if (*s->texname[to])
+ break;
+ if (to == 4)
+ to = 0;
+
+ if (to == 0 || to == 2)
+ to = 2 - to;
+ if (t == 0 || t == 2)
+ t = 2 - t;
+
+ for (y = 0; y < SECTTEXSIZE; y++)
+ {
+ for (x = 0; x < SECTTEXSIZE; x++, lm+=4)
+ {
+ if (t == 3)
+ {
+ //to won't be 3
+ lm[to] = lm[to] + (255 - (lm[0] + lm[1] + lm[2]));
+ }
+ else
+ {
+ if (to != 3)
+ lm[to] += lm[t];
+ lm[t] = 0;
+ }
+ }
+ lm += SECTTEXSIZE*4*(LMCHUNKS-1);
+ }
+ if (t == 0 || t == 2)
+ t = 2 - t;
+ Terr_LoadSectionTextures(s);
+ }
+ }
+ }
break;
}
}
@@ -1343,20 +1715,51 @@ void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_glob
}
#endif
-qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer)
+void Terr_ParseEntityLump(char *data, float *scale, int *minx, int *maxx, int *miny, int *maxy)
+{
+ char key[128];
+
+ if (data)
+ if ((data=COM_Parse(data))) //read the map info.
+ if (com_token[0] == '{')
+ while (1)
+ {
+ if (!(data=COM_Parse(data)))
+ break; // error
+ if (com_token[0] == '}')
+ break; // end of worldspawn
+ if (com_token[0] == '_')
+ strcpy(key, com_token + 1); //_ vars are for comments/utility stuff that arn't visible to progs. Ignore them.
+ else
+ strcpy(key, com_token);
+ if (!((data=COM_Parse(data))))
+ break; // error
+ if (!strcmp("segmentsize", key)) // for HalfLife maps
+ *scale = atof(com_token);
+ else if (!strcmp("minxsegment", key))
+ *minx = atoi(com_token) + CHUNKBIAS;
+ else if (!strcmp("minysegment", key))
+ *miny = atoi(com_token) + CHUNKBIAS;
+ else if (!strcmp("maxxsegment", key))
+ *maxx = atoi(com_token) + CHUNKBIAS;
+ else if (!strcmp("maxysegment", key))
+ *maxy = atoi(com_token) + CHUNKBIAS;
+ }
+}
+
+
+qboolean Terr_LoadTerrainModel (model_t *mod, void *buffer)
{
heightmap_t *hm;
float skyrotate;
vec3_t skyaxis;
char shadername[MAX_QPATH];
- char entfile[MAX_QPATH];
char skyname[MAX_QPATH];
int numsegsx = 0, numsegsy = 0;
int sectsize = 0;
COM_FileBase(mod->name, shadername, sizeof(shadername));
- Q_snprintfz(entfile, sizeof(entfile), "maps/%s/entities.ent", shadername);
strcpy(shadername, "terrainshader");
strcpy(skyname, "night");
@@ -1372,94 +1775,32 @@ qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer)
return false;
}
- for(;;)
- {
- buffer = COM_Parse(buffer);
- if (!buffer)
- break;
-
- if (!strcmp(com_token, "shadername"))
- {
- buffer = COM_Parse(buffer);
- Q_strncpyz(shadername, com_token, sizeof(shadername));
- }
- else if (!strcmp(com_token, "segmentsize")) //size of each segment in quake units
- {
- buffer = COM_Parse(buffer);
- sectsize = atof(com_token);
- }
- else if (!strcmp(com_token, "entfile"))
- {
- buffer = COM_Parse(buffer);
- Q_strncpyz(entfile, com_token, sizeof(entfile));
- }
- else if (!strcmp(com_token, "skybox"))
- {
- buffer = COM_Parse(buffer);
- Q_strncpyz(skyname, com_token, sizeof(skyname));
- }
- else if (!strcmp(com_token, "skyrotate"))
- {
- buffer = COM_Parse(buffer);
- skyaxis[0] = atof(com_token);
- buffer = COM_Parse(buffer);
- skyaxis[1] = atof(com_token);
- buffer = COM_Parse(buffer);
- skyaxis[2] = atof(com_token);
- skyrotate = VectorNormalize(skyaxis);
- }
- else if (!strcmp(com_token, "texturesegments"))
- {
- buffer = COM_Parse(buffer);
- numsegsx = numsegsy = atoi(com_token);
- }
- else if (!strcmp(com_token, "texturesegmentsx"))
- {
- buffer = COM_Parse(buffer);
- numsegsx = atoi(com_token);
- }
- else if (!strcmp(com_token, "texturesegmentsy"))
- {
- buffer = COM_Parse(buffer);
- numsegsy = atoi(com_token);
- }
- else
- {
- Con_Printf(CON_ERROR "%s, unrecognised token \"%s\" in terrain map\n", mod->name, com_token);
- return false;
- }
- }
-
- if (!sectsize)
- sectsize = 1024;
-
- if (!numsegsx)
- numsegsx = 16;
- if (!numsegsy)
- numsegsy = 16;
-
- if (numsegsx > MAXSECTIONS || numsegsy > MAXSECTIONS)
- {
- Con_Printf(CON_ERROR "%s, heightmap uses too many sections max is %i\n", mod->name, MAXSECTIONS);
- return false;
- }
mod->type = mod_heightmap;
hm = BZ_Malloc(sizeof(*hm));
memset(hm, 0, sizeof(*hm));
COM_FileBase(mod->name, hm->path, sizeof(hm->path));
- mod->entities = COM_LoadHunkFile(entfile);
- if (!mod->entities)
- {
- BZ_Free(hm);
- Con_Printf(CON_ERROR "unable to read %s\n", entfile);
- return false;
- }
+ mod->entities = Hunk_AllocName(strlen(buffer)+1, mod->name);
+ strcpy(mod->entities, buffer);
hm->sectionsize = sectsize;
- hm->numsegsx = numsegsx;
- hm->numsegsy = numsegsy;
+ hm->firstsegx = CHUNKBIAS - 1;
+ hm->firstsegy = CHUNKBIAS - 1;
+ hm->maxsegx = CHUNKBIAS + 1;
+ hm->maxsegy = CHUNKBIAS + 1;
+ hm->exteriorcontents = FTECONTENTS_SKY|FTECONTENTS_SOLID; //sky outside the map
+
+// Terr_ParseEntityLump(hm, mod->entities);
+
+ if (hm->firstsegx < 0)
+ hm->firstsegx = 0;
+ if (hm->firstsegy < 0)
+ hm->firstsegy = 0;
+ if (hm->maxsegx > CHUNKLIMIT)
+ hm->maxsegx = CHUNKLIMIT;
+ if (hm->maxsegy > CHUNKLIMIT)
+ hm->maxsegy = CHUNKLIMIT;
#ifndef SERVERONLY
if (qrenderer != QR_NONE)
@@ -1519,4 +1860,86 @@ qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer)
return true;
}
+
+void *Mod_LoadTerrainInfo(model_t *mod, char *loadname)
+{
+ heightmap_t *hm;
+ float scale = 0;
+ int bounds[4] = {0};
+ if (!mod->entities)
+ return NULL;
+
+ if (!strcmp(loadname, "start"))
+ {
+ bounds[0] = 0;
+ bounds[1] = 4;
+ bounds[2] = 0;
+ bounds[3] = 4;
+ }
+
+ Terr_ParseEntityLump(mod->entities, &scale, &bounds[0], &bounds[1], &bounds[2], &bounds[3]);
+
+ bounds[0] += CHUNKBIAS;
+ bounds[1] += CHUNKBIAS;
+ bounds[2] += CHUNKBIAS;
+ bounds[3] += CHUNKBIAS;
+
+ if (bounds[0] < 0)
+ bounds[0] = 0;
+ if (bounds[2] < 0)
+ bounds[2] = 0;
+ if (bounds[1] > CHUNKLIMIT)
+ bounds[1] = CHUNKLIMIT;
+ if (bounds[3] > CHUNKLIMIT)
+ bounds[3] = CHUNKLIMIT;
+
+ if (!scale && (bounds[0] == bounds[1] || bounds[2] == bounds[3]))
+ return NULL;
+
+ if (scale < 1)
+ scale = 1024;
+
+ hm = Z_Malloc(sizeof(*hm));
+ Q_strncpyz(hm->path, loadname, sizeof(hm->path));
+ hm->sectionsize = scale;
+ hm->firstsegx = bounds[0];
+ hm->maxsegx = bounds[1];
+ hm->firstsegy = bounds[2];
+ hm->maxsegy = bounds[3];
+
+ hm->exteriorcontents = FTECONTENTS_EMPTY; //bsp geometry outside the heightmap
+
+
+#ifndef SERVERONLY
+ if (qrenderer != QR_NONE)
+ {
+ hm->skyshader = R_RegisterCustom(va("skybox_%s", loadname), Shader_DefaultSkybox, NULL);
+ hm->shader = R_RegisterShader("terrainshader",
+ "{\n"
+ "{\n"
+ "map $diffuse\n"
+ "}\n"
+ "{\n"
+ "map $upperoverlay\n"
+ "}\n"
+ "{\n"
+ "map $loweroverlay\n"
+ "}\n"
+ "{\n"
+ "map $fullbright\n"
+ "}\n"
+ "{\n"
+ "map $lightmap\n"
+ "}\n"
+ "program terrain\n"
+ "if r_terraindebug\n"
+ "[\n"
+ "program terraindebug\n"
+ "]\n"
+ "}\n"
+ );
+ }
+#endif
+ return hm;
+}
#endif
diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c
index d581fb252..5683b9ba4 100644
--- a/engine/gl/gl_model.c
+++ b/engine/gl/gl_model.c
@@ -39,7 +39,6 @@ char loadname[32]; // for hunk tags
void CM_Init(void);
-qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer);
qboolean RMod_LoadSpriteModel (model_t *mod, void *buffer);
qboolean RMod_LoadSprite2Model (model_t *mod, void *buffer);
qboolean RMod_LoadBrushModel (model_t *mod, void *buffer);
@@ -400,9 +399,10 @@ void RMod_ClearAll (void)
Surf_Clear(mod);
}
#ifdef TERRAIN
- if (mod->type == mod_heightmap)
+ if (mod->terrain)
{
- HeightMap_Purge(mod);
+ Terr_PurgeTerrainModel(mod, false);
+ mod->terrain = NULL;
}
#endif
@@ -667,10 +667,15 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
while (replstr)
{
replstr = COM_ParseStringSet(replstr);
+
if (replstr)
+ {
+ TRACE(("RMod_LoadModel: Trying to load (replacement) model \"%s.%s\"\n", mdlbase, com_token));
buf = (unsigned *)COM_LoadStackFile (va("%s.%s", mdlbase, com_token), stackbuf, sizeof(stackbuf));
+ }
else
{
+ TRACE(("RMod_LoadModel: Trying to load model \"%s\"\n", mod->name));
buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
if (!buf)
{
@@ -678,6 +683,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
if (doomsprite) // special case needed for doom sprites
{
mod->needload = false;
+ TRACE(("RMod_LoadModel: doomsprite: \"%s\"\n", mod->name));
RMod_LoadDoomSprite(mod);
return mod;
}
@@ -703,12 +709,14 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
//The binary 3d mesh model formats
case RAPOLYHEADER:
case IDPOLYHEADER:
+ TRACE(("RMod_LoadModel: Q1 mdl\n"));
if (!Mod_LoadQ1Model(mod, buf))
continue;
break;
#ifdef MD2MODELS
case MD2IDALIASHEADER:
+ TRACE(("RMod_LoadModel: md2\n"));
if (!Mod_LoadQ2Model(mod, buf))
continue;
break;
@@ -716,6 +724,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
#ifdef MD3MODELS
case MD3_IDENT:
+ TRACE(("RMod_LoadModel: md3\n"));
if (!Mod_LoadQ3Model (mod, buf))
continue;
break;
@@ -723,6 +732,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
#ifdef HALFLIFEMODELS
case (('T'<<24)+('S'<<16)+('D'<<8)+'I'):
+ TRACE(("RMod_LoadModel: HL mdl\n"));
if (!Mod_LoadHLModel (mod, buf))
continue;
break;
@@ -731,12 +741,14 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
//Binary skeletal model formats
#ifdef ZYMOTICMODELS
case (('O'<<24)+('M'<<16)+('Y'<<8)+'Z'):
+ TRACE(("RMod_LoadModel: zym\n"));
if (!Mod_LoadZymoticModel(mod, buf))
continue;
break;
#endif
#ifdef DPMMODELS
case (('K'<<24)+('R'<<16)+('A'<<8)+'D'):
+ TRACE(("RMod_LoadModel: dpm\n"));
if (!Mod_LoadDarkPlacesModel(mod, buf))
continue;
break;
@@ -744,6 +756,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
#ifdef PSKMODELS
case ('A'<<0)+('C'<<8)+('T'<<16)+('R'<<24):
+ TRACE(("RMod_LoadModel: psk\n"));
if (!Mod_LoadPSKModel (mod, buf))
continue;
break;
@@ -751,6 +764,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
#ifdef INTERQUAKEMODELS
case ('I'<<0)+('N'<<8)+('T'<<16)+('E'<<24):
+ TRACE(("RMod_LoadModel: IQM\n"));
if (!Mod_LoadInterQuakeModel (mod, buf))
continue;
break;
@@ -759,12 +773,14 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
//Binary Sprites
#ifdef SP2MODELS
case IDSPRITE2HEADER:
+ TRACE(("RMod_LoadModel: q2 sp2\n"));
if (!RMod_LoadSprite2Model (mod, buf))
continue;
break;
#endif
case IDSPRITEHEADER:
+ TRACE(("RMod_LoadModel: q1 spr\n"));
if (!RMod_LoadSpriteModel (mod, buf))
continue;
break;
@@ -775,6 +791,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
case ('F'<<0)+('B'<<8)+('S'<<16)+('P'<<24):
case ('R'<<0)+('B'<<8)+('S'<<16)+('P'<<24):
case IDBSPHEADER: //looks like id switched to have proper ids
+ TRACE(("RMod_LoadModel: q2/q3/raven/fusion bsp\n"));
if (!Mod_LoadQ2BrushModel (mod, buf))
continue;
break;
@@ -782,6 +799,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
#ifdef MAP_DOOM
case (('D'<<24)+('A'<<16)+('W'<<8)+'I'): //the id is hacked by the FS .wad loader (main wad).
case (('D'<<24)+('A'<<16)+('W'<<8)+'P'): //the id is hacked by the FS .wad loader (patch wad).
+ TRACE(("RMod_LoadModel: doom iwad/pwad map\n"));
if (!Mod_LoadDoomLevel (mod))
continue;
break;
@@ -791,6 +809,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
case 29: //q1
case 28: //prerel
case BSPVERSION_LONG:
+ TRACE(("RMod_LoadModel: hl/q1 bsp\n"));
if (!RMod_LoadBrushModel (mod, buf))
continue;
break;
@@ -802,12 +821,14 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
#ifdef MD5MODELS
if (!strcmp(com_token, "MD5Version")) //doom3 format, text based, skeletal
{
+ TRACE(("RMod_LoadModel: md5mesh/md5anim\n"));
if (!Mod_LoadMD5MeshModel (mod, buf))
continue;
break;
}
if (!strcmp(com_token, "EXTERNALANIM")) //custom format, text based, specifies skeletal models to load and which md5anim files to use.
{
+ TRACE(("RMod_LoadModel: blurgh\n"));
if (!Mod_LoadCompositeAnim (mod, buf))
continue;
break;
@@ -816,6 +837,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
#ifdef MAP_PROC
if (!strcmp(com_token, "CM")) //doom3 map.
{
+ TRACE(("RMod_LoadModel: doom3 CM\n"));
if (!D3_LoadMap_CollisionMap (mod, (char*)buf))
continue;
break;
@@ -824,7 +846,8 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
#ifdef TERRAIN
if (!strcmp(com_token, "terrain")) //custom format, text based.
{
- if (!GL_LoadHeightmapModel(mod, buf))
+ TRACE(("RMod_LoadModel: terrain\n"));
+ if (!Terr_LoadTerrainModel(mod, buf))
continue;
break;
}
@@ -837,6 +860,8 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
P_LoadedModel(mod);
Validation_IncludeFile(mod->name, (char *)buf, com_filesize);
+ TRACE(("RMod_LoadModel: Loaded\n"));
+
return mod;
}
@@ -3816,6 +3841,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
crouchhullfile = NULL;
+ TRACE(("Loading info\n"));
#ifndef CLIENTONLY
if (sv.state) //if the server is running
{
@@ -3832,38 +3858,61 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
// load into heap
if (!isDedicated || ode)
{
+ TRACE(("Loading verts\n"));
noerrors = noerrors && RMod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
+ TRACE(("Loading edges\n"));
noerrors = noerrors && RMod_LoadEdges (&header->lumps[LUMP_EDGES], longm);
+ TRACE(("Loading Surfedges\n"));
noerrors = noerrors && RMod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
}
if (!isDedicated)
{
+ TRACE(("Loading Textures\n"));
noerrors = noerrors && RMod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
+ TRACE(("Loading Lighting\n"));
if (noerrors)
RMod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
}
+ TRACE(("Loading Submodels\n"));
noerrors = noerrors && RMod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
if (noerrors)
+ {
+ TRACE(("Loading CH\n"));
RMod_LoadCrouchHull();
+ }
+ TRACE(("Loading Planes\n"));
noerrors = noerrors && RMod_LoadPlanes (&header->lumps[LUMP_PLANES]);
if (!isDedicated || ode)
{
+ TRACE(("Loading Texinfo\n"));
noerrors = noerrors && RMod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
+ TRACE(("Loading Faces\n"));
noerrors = noerrors && RMod_LoadFaces (&header->lumps[LUMP_FACES], longm, &meshlist);
}
if (!isDedicated)
+ {
+ TRACE(("Loading MarkSurfaces\n"));
noerrors = noerrors && RMod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES], longm);
+ }
if (noerrors)
+ {
+ TRACE(("Loading Vis\n"));
RMod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
+ }
noerrors = noerrors && RMod_LoadLeafs (&header->lumps[LUMP_LEAFS], longm);
+ TRACE(("Loading Nodes\n"));
noerrors = noerrors && RMod_LoadNodes (&header->lumps[LUMP_NODES], longm);
+ TRACE(("Loading Clipnodes\n"));
noerrors = noerrors && RMod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES], longm);
if (noerrors)
{
+ TRACE(("Loading Entities\n"));
RMod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
+ TRACE(("Loading hull 0\n"));
RMod_MakeHull0 ();
}
+ TRACE(("sorting shaders\n"));
if (!isDedicated && noerrors)
Mod_SortShaders();
@@ -3879,8 +3928,11 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
return false;
}
+ TRACE(("LoadBrushModel %i\n", __LINE__));
Q1BSP_LoadBrushes(mod);
+ TRACE(("LoadBrushModel %i\n", __LINE__));
Q1BSP_SetModelFuncs(mod);
+ TRACE(("LoadBrushModel %i\n", __LINE__));
mod->funcs.LightPointValues = GLQ1BSP_LightPointValues;
mod->funcs.StainNode = Q1BSP_StainNode;
mod->funcs.MarkLights = Q1BSP_MarkLights;
@@ -3899,7 +3951,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
mod->hulls[0].available = true;
Q1BSP_CheckHullNodes(&mod->hulls[0]);
-
+TRACE(("LoadBrushModel %i\n", __LINE__));
for (j=1 ; jhulls[j].firstclipnode = bm->headnode[j];
@@ -3925,10 +3977,12 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
memset(&mod->batches, 0, sizeof(mod->batches));
mod->vbos = NULL;
+ TRACE(("LoadBrushModel %i\n", __LINE__));
if (meshlist)
{
RMod_Batches_Build(meshlist, mod, NULL, NULL);
}
+ TRACE(("LoadBrushModel %i\n", __LINE__));
if (i < mod->numsubmodels-1)
{ // duplicate the basic information
@@ -3940,15 +3994,21 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
strcpy (loadmodel->name, name);
mod = loadmodel;
}
+ TRACE(("LoadBrushModel %i\n", __LINE__));
}
#ifdef RUNTIMELIGHTING
+ TRACE(("LoadBrushModel %i\n", __LINE__));
if (lightmodel == lm)
LightLoadEntities(lightmodel->entities);
#endif
-
+TRACE(("LoadBrushModel %i\n", __LINE__));
if (1)
RMod_FixupMinsMaxs();
+TRACE(("LoadBrushModel %i\n", __LINE__));
+#ifdef TERRAIN
+ lm->terrain = Mod_LoadTerrainInfo(lm, loadname);
+#endif
return true;
}
diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c
index 8c3331083..0555e6d62 100644
--- a/engine/gl/gl_rmain.c
+++ b/engine/gl/gl_rmain.c
@@ -665,8 +665,7 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
if (DotProduct(r_refdef.vieworg, plane.normal)-plane.dist < 0)
return;
- //if (!view)
- // return;
+ TRACE(("GLR_DrawPortal: portal type %i\n", portaltype));
oldrefdef = r_refdef;
r_refdef.recurse = true;
@@ -824,6 +823,8 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
GL_CullFace(0);
+ TRACE(("GLR_DrawPortal: portal drawn\n"));
+
#ifdef warningmsg
#pragma warningmsg("warning: there's a bug with rtlights in portals, culling is broken or something. May also be loading the wrong matrix")
#endif
diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c
index dc9001bad..5bcc65dc1 100644
--- a/engine/gl/gl_screen.c
+++ b/engine/gl/gl_screen.c
@@ -188,9 +188,6 @@ void GLSCR_UpdateScreen (void)
{
extern char levelshotname[];
- if ((key_dest == key_console || key_dest == key_game) && SCR_GetLoadingStage() == LS_NONE)
- scr_con_current = scr_conlines = vid.height;
-
//draw the levelshot or the conback fullscreen
if (*levelshotname)
R2D_ScalePic(0, 0, vid.width, vid.height, R2D_SafeCachePic (levelshotname));
diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c
index 2bc2c0795..53da8d1b7 100644
--- a/engine/gl/gl_shader.c
+++ b/engine/gl/gl_shader.c
@@ -3358,11 +3358,14 @@ static qboolean Shader_Parsetok (shader_t *shader, shaderpass_t *pass, shaderkey
}
}
+// Con_Printf("Unknown shader directive: \"%s\"\n", token);
+
// Next Line
while (ptr)
{
token = COM_ParseExt ( ptr, false );
- if ( !token[0] ) {
+ if ( !token[0] )
+ {
break;
}
}
@@ -4605,19 +4608,19 @@ static void Shader_ReadShader(shader_t *s, char *shadersource, int parsemode)
token = COM_ParseExt (&shadersource, true);
if ( !token[0] )
continue;
- else if (token[0] == ']')
- {
- if (--nest <= 0)
- {
- nest++;
+ else if (token[0] == ']')
+ {
+ if (--nest <= 0)
+ {
+ nest++;
if (!strcmp(token, "]["))
- conditionistrue = !conditionistrue;
- else
- break;
- }
- }
- else if (token[0] == '[')
- nest++;
+ conditionistrue = !conditionistrue;
+ else
+ break;
+ }
+ }
+ else if (token[0] == '[')
+ nest++;
else if (conditionistrue)
{
if (token[0] == '{')
diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c
index c16c15c06..240b805e4 100644
--- a/engine/gl/gl_shadow.c
+++ b/engine/gl/gl_shadow.c
@@ -1568,12 +1568,12 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs, srect_t *r)
x2 = 0;
if (y2 < 0)
y2 = 0;
- if (x1 > r_refdef.vrect.width)
- x1 = r_refdef.vrect.width;
+ if (x1 > r_refdef.vrect.width * vid.pixelwidth / vid.width)
+ x1 = r_refdef.vrect.width * vid.pixelwidth / vid.width;
if (y1 > r_refdef.vrect.height * vid.pixelheight / vid.height)
y1 = r_refdef.vrect.height * vid.pixelheight / vid.height;
- if (x2 > r_refdef.vrect.width)
- x2 = r_refdef.vrect.width;
+ if (x2 > r_refdef.vrect.width * vid.pixelwidth / vid.width)
+ x2 = r_refdef.vrect.width * vid.pixelwidth / vid.width;
if (y2 > r_refdef.vrect.height * vid.pixelheight / vid.height)
y2 = r_refdef.vrect.height * vid.pixelheight / vid.height;
r->x = floor(x1);
diff --git a/engine/gl/glmod_doom.c b/engine/gl/glmod_doom.c
index d6ec58a17..89b80f957 100644
--- a/engine/gl/glmod_doom.c
+++ b/engine/gl/glmod_doom.c
@@ -2210,8 +2210,9 @@ void Doom_MarkLights(struct dlight_s *light, int bit, struct mnode_s *node)
void Doom_SetModelFunc(model_t *mod)
{
+#ifndef SERVERONLY
mod->funcs.PurgeModel = Doom_Purge;
-
+#endif
mod->funcs.FatPVS = Doom_FatPVS;
mod->funcs.EdictInFatPVS = Doom_EdictInFatPVS;
mod->funcs.FindTouchedLeafs = Doom_FindTouchedLeafs;
diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h
index d854e123a..f4996aaaa 100644
--- a/engine/gl/glquake.h
+++ b/engine/gl/glquake.h
@@ -407,9 +407,11 @@ void R_SaveRTLights_f(void);
// gl_heightmap.c
//
#ifdef TERRAIN
-void GL_DrawHeightmapModel (batch_t **batch, entity_t *e);
-qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer);
-void HeightMap_Purge(model_t *mod);
+void Terr_DrawTerrainModel (batch_t **batch, entity_t *e);
+qboolean Terr_LoadTerrainModel (model_t *mod, void *buffer);
+void Terr_PurgeTerrainModel(model_t *mod, qboolean lightmapsonly);
+void *Mod_LoadTerrainInfo(model_t *mod, char *loadname); //call this after loading a bsp
+qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contentmask, trace_t *trace);
#endif
//doom
diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h
index 568ceb526..bd84123c3 100644
--- a/engine/gl/r_bishaders.h
+++ b/engine/gl/r_bishaders.h
@@ -1101,3 +1101,49 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
},
#endif
+#ifdef GLQUAKE
+{QR_OPENGL, 110, "terrain",
+"!!permu FOG\n"
+"#include \"sys/fog.h\"\n"
+"varying vec2 tc;\n"
+"varying vec2 lm;\n"
+
+"#ifdef VERTEX_SHADER\n"
+"attribute vec2 v_texcoord;\n"
+"attribute vec2 v_lmcoord;\n"
+"void main (void)\n"
+"{\n"
+"tc = v_texcoord.st;\n"
+"lm = v_lmcoord.st;\n"
+"gl_Position = ftetransform();\n"
+"}\n"
+"#endif\n"
+
+
+
+
+"#ifdef FRAGMENT_SHADER\n"
+//four texture passes
+"uniform sampler2D s_t0;\n"
+"uniform sampler2D s_t1;\n"
+"uniform sampler2D s_t2;\n"
+"uniform sampler2D s_t3;\n"
+
+//mix values
+"uniform sampler2D s_t4;\n"
+
+
+"void main (void)\n"
+"{\n"
+"vec4 m = texture2D(s_t4, lm);\n"
+
+"gl_FragColor = fog4(\n"
+"texture2D(s_t0, tc)*m.r\n"
+"+ texture2D(s_t1, tc)*m.g\n"
+"+ texture2D(s_t2, tc)*m.b\n"
+"+ texture2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b))\n"
+");\n"
+"}\n"
+"#endif\n"
+},
+#endif
diff --git a/engine/partcfgs/high.cfg b/engine/partcfgs/high.cfg
index f1ba498d9..f829d4c18 100644
--- a/engine/partcfgs/high.cfg
+++ b/engine/partcfgs/high.cfg
@@ -327,6 +327,8 @@ r_part tr_knightspike
friction 4
scalefactor 0.825
blend add
+ spawnmode spiral
+ spawnvel -50
}
/////////////////////////////////////////
@@ -361,46 +363,91 @@ r_trail "progs/v_spike.mdl" tr_vorespike
//{
//}
+r_part te_blood
+{
+ texture fte_bloodparticle
+ blend subtract
+ count 1
+ scale 32
+ alpha 0
+ die 1
+ randomvel 64
+ veladd 10
+ rotationspeed 90
+ rotationstart 0 360
+ rgb 64 128 128
+ rgbdelta -64 -128 -128
+ gravity 200
+ scalefactor 0.8
+// scaledelta -10
+}
+
+r_part pe_73
+{
+ assoc te_blood
+}
+
+r_part te_lightningblood
+{
+ texture fte_bloodparticle
+ blend subtract
+ count 1
+ scale 32
+ alpha 0
+ die 1
+ randomvel 64
+ veladd 10
+ rotationspeed 90
+ rotationstart 0 360
+ rgb 0 128 128
+ rgbdelta 0 -128 -128
+ gravity 200
+ scalefactor 0.8
+}
+
/////////////////////////////////////////
//zombie body-part blood trails
r_part tr_slightblood
{
- texture "particles/fteparticlefont.tga"
- tcoords 1 1 63 63 256 2 64
+ texture fte_bloodparticle
+ blend subtract
+// tcoords 1 1 63 63 256 2 64
step 16
scale 64
- alpha 0.6
+ alpha 0
die 1
randomvel 32
veladd 10
rotationspeed 90
rotationstart 0 360
- rgb 32 0 0
+ rgb 64 128 128
+ rgbdelta -64 -128 -128
gravity 200
scalefactor 0.8
scaledelta -10
- stains 5
+ stains -0.5
}
//////////////////////////////////////////
//regular ol' blood trails
r_part tr_blood
{
- texture "particles/fteparticlefont.tga"
- tcoords 1 1 63 63 256 2 64
- step 4
+ texture fte_bloodparticle
+ blend subtract
+ step 8
scale 64
- alpha 0.3
+ alpha 0
die 1
randomvel 32
veladd 10
rotationspeed 90
rotationstart 0 360
- rgb 64 0 0
+ rgb 32 128 128
+ rgbdelta -32 -128 -128
gravity 200
scalefactor 0.8
scaledelta -10
- stains 5
+ stains -0.5
}
//////////////////////////////////
@@ -432,6 +479,8 @@ r_part pe_defaulttrail
randomvel 2
friction 4
scalefactor 0.825
+ spawnmode spiral
+ spawnvel 25
blend add
}
diff --git a/engine/shaders/generatebuiltinsl.c b/engine/shaders/generatebuiltinsl.c
index 9e63c0d6d..e12815617 100644
--- a/engine/shaders/generatebuiltinsl.c
+++ b/engine/shaders/generatebuiltinsl.c
@@ -26,6 +26,7 @@ char shaders[][64] =
"postproc_panorama",
"rtlight",
"underwaterwarp",
+ "terrain",
""
};
diff --git a/engine/shaders/glsl/terrain.glsl b/engine/shaders/glsl/terrain.glsl
new file mode 100644
index 000000000..73c5f3aaf
--- /dev/null
+++ b/engine/shaders/glsl/terrain.glsl
@@ -0,0 +1,42 @@
+!!permu FOG
+#include "sys/fog.h"
+varying vec2 tc;
+varying vec2 lm;
+
+#ifdef VERTEX_SHADER
+attribute vec2 v_texcoord;
+attribute vec2 v_lmcoord;
+void main (void)
+{
+ tc = v_texcoord.st;
+ lm = v_lmcoord.st;
+ gl_Position = ftetransform();
+}
+#endif
+
+
+
+
+#ifdef FRAGMENT_SHADER
+//four texture passes
+uniform sampler2D s_t0;
+uniform sampler2D s_t1;
+uniform sampler2D s_t2;
+uniform sampler2D s_t3;
+
+//mix values
+uniform sampler2D s_t4;
+
+
+void main (void)
+{
+ vec4 m = texture2D(s_t4, lm);
+
+ gl_FragColor = fog4(
+ texture2D(s_t0, tc)*m.r
+ + texture2D(s_t1, tc)*m.g
+ + texture2D(s_t2, tc)*m.b
+ + texture2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b))
+ );
+}
+#endif
\ No newline at end of file
diff --git a/engine/sw/sw_rast.c b/engine/sw/sw_rast.c
index c5235a926..ea462b2c8 100644
--- a/engine/sw/sw_rast.c
+++ b/engine/sw/sw_rast.c
@@ -751,6 +751,7 @@ void SW_Draw_Init(void)
}
void SW_Draw_Shutdown(void)
{
+ R2D_Shutdown();
}
void SW_R_Init(void)
{