Initial commit
This commit is contained in:
commit
d6c7f1ae87
95 changed files with 31975 additions and 0 deletions
21
src/Makefile.am
Normal file
21
src/Makefile.am
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
bin_PROGRAMS = antigrav
|
||||
|
||||
INCLUDES = -W -Wall -DTIXML_USE_STL -Itinyxml/ -DDATADIR="\"$(datadir)/$(PACKAGE)\""
|
||||
SUBDIRS = tinyxml
|
||||
LDADD = tinyxml/libtinyxml.a
|
||||
|
||||
antigrav_SOURCES = main.cpp antigrav.h extensions.h \
|
||||
craft.cpp craft.h \
|
||||
level.cpp level.h \
|
||||
vector2.cpp vector2.h \
|
||||
font.cpp font.h \
|
||||
m3dmaterial.cpp m3dmaterial.h \
|
||||
m3dmesh.cpp m3dmesh.h \
|
||||
m3dtexture.cpp m3dtexture.h \
|
||||
terrain.cpp terrain.h \
|
||||
game.cpp game.h \
|
||||
player.cpp player.h \
|
||||
menu.cpp menu.h \
|
||||
ring.cpp ring.h \
|
||||
background.cpp background.h
|
||||
|
||||
572
src/Makefile.in
Normal file
572
src/Makefile.in
Normal file
|
|
@ -0,0 +1,572 @@
|
|||
# Makefile.in generated by automake 1.9.6 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ..
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
bin_PROGRAMS = antigrav$(EXEEXT)
|
||||
subdir = src
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.in
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_antigrav_OBJECTS = main.$(OBJEXT) craft.$(OBJEXT) level.$(OBJEXT) \
|
||||
vector2.$(OBJEXT) font.$(OBJEXT) m3dmaterial.$(OBJEXT) \
|
||||
m3dmesh.$(OBJEXT) m3dtexture.$(OBJEXT) terrain.$(OBJEXT) \
|
||||
game.$(OBJEXT) player.$(OBJEXT) menu.$(OBJEXT) ring.$(OBJEXT) \
|
||||
background.$(OBJEXT)
|
||||
antigrav_OBJECTS = $(am_antigrav_OBJECTS)
|
||||
antigrav_LDADD = $(LDADD)
|
||||
antigrav_DEPENDENCIES = tinyxml/libtinyxml.a
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
CXXLD = $(CXX)
|
||||
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
|
||||
-o $@
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(antigrav_SOURCES)
|
||||
DIST_SOURCES = $(antigrav_SOURCES)
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||
html-recursive info-recursive install-data-recursive \
|
||||
install-exec-recursive install-info-recursive \
|
||||
install-recursive installcheck-recursive installdirs-recursive \
|
||||
pdf-recursive ps-recursive uninstall-info-recursive \
|
||||
uninstall-recursive
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SDL_CFLAGS = @SDL_CFLAGS@
|
||||
SDL_CONFIG = @SDL_CONFIG@
|
||||
SDL_LIBS = @SDL_LIBS@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
INCLUDES = -W -Wall -DTIXML_USE_STL -Itinyxml/ -DDATADIR="\"$(datadir)/$(PACKAGE)\""
|
||||
SUBDIRS = tinyxml
|
||||
LDADD = tinyxml/libtinyxml.a
|
||||
antigrav_SOURCES = main.cpp antigrav.h extensions.h \
|
||||
craft.cpp craft.h \
|
||||
level.cpp level.h \
|
||||
vector2.cpp vector2.h \
|
||||
font.cpp font.h \
|
||||
m3dmaterial.cpp m3dmaterial.h \
|
||||
m3dmesh.cpp m3dmesh.h \
|
||||
m3dtexture.cpp m3dtexture.h \
|
||||
terrain.cpp terrain.h \
|
||||
game.cpp game.h \
|
||||
player.cpp player.h \
|
||||
menu.cpp menu.h \
|
||||
ring.cpp ring.h \
|
||||
background.cpp background.h
|
||||
|
||||
all: all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .cpp .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
|
||||
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
|
||||
if test -f $$p \
|
||||
; then \
|
||||
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
|
||||
else :; fi; \
|
||||
done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(bindir)/$$f"; \
|
||||
done
|
||||
|
||||
clean-binPROGRAMS:
|
||||
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||
antigrav$(EXEEXT): $(antigrav_OBJECTS) $(antigrav_DEPENDENCIES)
|
||||
@rm -f antigrav$(EXEEXT)
|
||||
$(CXXLINK) $(antigrav_LDFLAGS) $(antigrav_OBJECTS) $(antigrav_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/background.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/craft.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/font.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/game.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/level.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m3dmaterial.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m3dmesh.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m3dtexture.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menu.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ring.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/terrain.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vector2.Po@am__quote@
|
||||
|
||||
.cpp.o:
|
||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||
|
||||
.cpp.obj:
|
||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
uninstall-info-am:
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
# To change the values of `make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in `config.status', edit `config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
$(RECURSIVE_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
mostlyclean-recursive clean-recursive distclean-recursive \
|
||||
maintainer-clean-recursive:
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
case "$@" in \
|
||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||
*) list='$(SUBDIRS)' ;; \
|
||||
esac; \
|
||||
rev=''; for subdir in $$list; do \
|
||||
if test "$$subdir" = "."; then :; else \
|
||||
rev="$$subdir $$rev"; \
|
||||
fi; \
|
||||
done; \
|
||||
rev="$$rev ."; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
for subdir in $$rev; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done && test -z "$$fail"
|
||||
tags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
|
||||
done
|
||||
ctags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
|
||||
done
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||
include_option=--etags-include; \
|
||||
empty_fix=.; \
|
||||
else \
|
||||
include_option=--include; \
|
||||
empty_fix=; \
|
||||
fi; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test ! -f $$subdir/TAGS || \
|
||||
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkdir_p) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test -d "$(distdir)/$$subdir" \
|
||||
|| $(mkdir_p) "$(distdir)/$$subdir" \
|
||||
|| exit 1; \
|
||||
distdir=`$(am__cd) $(distdir) && pwd`; \
|
||||
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
|
||||
(cd $$subdir && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$$top_distdir" \
|
||||
distdir="$$distdir/$$subdir" \
|
||||
distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
all-am: Makefile $(PROGRAMS)
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(mkdir_p) "$$dir"; \
|
||||
done
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
install-data: install-data-recursive
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-recursive
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-recursive
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-recursive
|
||||
|
||||
info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-info: install-info-recursive
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-recursive
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS uninstall-info-am
|
||||
|
||||
uninstall-info: uninstall-info-recursive
|
||||
|
||||
.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \
|
||||
clean clean-binPROGRAMS clean-generic clean-recursive ctags \
|
||||
ctags-recursive distclean distclean-compile distclean-generic \
|
||||
distclean-recursive distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-binPROGRAMS \
|
||||
install-data install-data-am install-exec install-exec-am \
|
||||
install-info install-info-am install-man install-strip \
|
||||
installcheck installcheck-am installdirs installdirs-am \
|
||||
maintainer-clean maintainer-clean-generic \
|
||||
maintainer-clean-recursive mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic mostlyclean-recursive pdf pdf-am ps ps-am \
|
||||
tags tags-recursive uninstall uninstall-am \
|
||||
uninstall-binPROGRAMS uninstall-info-am
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
36
src/antigrav.h
Normal file
36
src/antigrav.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef _ANTIGRAV_H_
|
||||
#define _ANTIGRAV_H_
|
||||
|
||||
#define ABS(x) (((x) > 0)?(x):(-(x)))
|
||||
#define DEG(x) ((x) * 180.0 / M_PI)
|
||||
#define RAD(x) ((x) * M_PI / 180.0)
|
||||
#define MIN(x, y) ( ((x) < (y)) ? (x) : (y) )
|
||||
#define MAX(x, y) ( ((x) > (y)) ? (x) : (y) )
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#else
|
||||
#define DATADIR "./data"
|
||||
#endif
|
||||
|
||||
#include "font.h"
|
||||
|
||||
#include "tinyxml.h"
|
||||
#include "m3dmaterial.h"
|
||||
#include "m3dtexture.h"
|
||||
#include "m3dmesh.h"
|
||||
#include "terrain.h"
|
||||
|
||||
#include "vector2.h"
|
||||
#include "craft.h"
|
||||
#include "level.h"
|
||||
#include "player.h"
|
||||
#include "background.h"
|
||||
#include "game.h"
|
||||
#include "menu.h"
|
||||
#include "ring.h"
|
||||
|
||||
ALuint loadWavBuffer(const char *filename);
|
||||
|
||||
#endif
|
||||
|
||||
63
src/background.cpp
Normal file
63
src/background.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#include "SDL_opengl.h"
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "antigrav.h"
|
||||
|
||||
GLuint Background::planet;
|
||||
|
||||
int Background::init()
|
||||
{
|
||||
planet = m3dTexture::loadTexture("planet.png");
|
||||
if(planet==0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Background::Background()
|
||||
{
|
||||
float minx = -0.25 * Game::getInstance().getLevel().getWidth();
|
||||
float w = 1.5 * Game::getInstance().getLevel().getWidth();
|
||||
float miny = -5;
|
||||
float h = 65;
|
||||
float minz = 85;
|
||||
float d = 25;
|
||||
for(int s=0;s<STARS;++s) {
|
||||
starx[s] = minx + rand()/(double)RAND_MAX*w;
|
||||
stary[s] = miny + rand()/(double)RAND_MAX*h;
|
||||
starz[s] = minz + rand()/(double)RAND_MAX*d;
|
||||
}
|
||||
}
|
||||
|
||||
void Background::draw()
|
||||
{
|
||||
// Draw stars
|
||||
glPointSize(1.0);
|
||||
glBegin(GL_POINTS);
|
||||
for(int s=0;s<STARS;++s)
|
||||
glVertex3f(starx[s],stary[s],-starz[s]);
|
||||
glEnd();
|
||||
|
||||
// Draw planet
|
||||
glPushMatrix();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glTranslatef(100,32,-192);
|
||||
glScalef(64,-64,1);
|
||||
glBindTexture(GL_TEXTURE_2D, planet);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glTexCoord2f(0,0);
|
||||
glVertex2f(0,0);
|
||||
|
||||
glTexCoord2f(1,0);
|
||||
glVertex2f(1,0);
|
||||
|
||||
glTexCoord2f(0,1);
|
||||
glVertex2f(0,1);
|
||||
|
||||
glTexCoord2f(1,1);
|
||||
glVertex2f(1,1);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
21
src/background.h
Normal file
21
src/background.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef BACKGROUND_H
|
||||
#define BACKGROUND_H
|
||||
|
||||
class Background {
|
||||
public:
|
||||
static int init();
|
||||
|
||||
Background();
|
||||
|
||||
void draw();
|
||||
private:
|
||||
static const int STARS = 200;
|
||||
float starx[STARS];
|
||||
float stary[STARS];
|
||||
float starz[STARS];
|
||||
|
||||
static GLuint planet;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
514
src/craft.cpp
Normal file
514
src/craft.cpp
Normal file
|
|
@ -0,0 +1,514 @@
|
|||
#include "SDL_opengl.h"
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#include "antigrav.h"
|
||||
|
||||
CraftState::CraftState() : pos(0.0, 0.0), angle(0.0) { }
|
||||
|
||||
CraftState::CraftState(const Vector2& p, float a)
|
||||
{
|
||||
pos = p;
|
||||
angle = a;
|
||||
}
|
||||
|
||||
const Vector2& CraftState::getPos() const { return pos; }
|
||||
float CraftState::getAngle() const { return angle; }
|
||||
|
||||
CraftState operator+(const CraftState& s1, const CraftState& s2)
|
||||
{
|
||||
return CraftState(s1.getPos() + s2.getPos(), s1.getAngle() + s2.getAngle());
|
||||
}
|
||||
|
||||
CraftState operator*(float f, const CraftState& s2)
|
||||
{
|
||||
return CraftState(f * s2.getPos(), f * s2.getAngle());
|
||||
}
|
||||
|
||||
void CraftState::setPos(const Vector2 &p) { pos = p; }
|
||||
void CraftState::setAngle(float a) { angle = a; }
|
||||
|
||||
float CraftState::getX() const { return pos.getX(); }
|
||||
float CraftState::getY() const { return pos.getY(); }
|
||||
|
||||
|
||||
const float Craft::TURN_RATE = 3.14;
|
||||
const float Craft::TURN_DAMP = 1.0;
|
||||
const float Craft::TURN_BACK = 2.0;
|
||||
|
||||
const float Craft::GRAVITY = -2.0;
|
||||
const float Craft::HOVER_FORCE = 2.0;
|
||||
const float Craft::BOOST = 2.0;
|
||||
const float Craft::DAMP = 0.25;
|
||||
|
||||
const float Craft::HEIGHT = 0.15;
|
||||
const float Craft::WIDTH = 0.5;
|
||||
const float Craft::MASS = 1.0;
|
||||
const float Craft::INERTIA = 1.0 / 12.0 * MASS * (HEIGHT * HEIGHT + WIDTH * WIDTH);
|
||||
|
||||
const float Craft::INVERTED_FORCE_MOD = 0.2;
|
||||
|
||||
const float Craft::BOOST_REFUEL = 0.3;
|
||||
const float Craft::BOOST_FUEL_USE = 1.0;
|
||||
|
||||
const float Craft::MAJOR_AXIS = 0.25;
|
||||
const float Craft::MINOR_AXIS = 0.075;
|
||||
|
||||
const float Craft::BOUNCYNESS = 0.5;
|
||||
const float Craft::LEVEL_BOUNCYNESS = 0.5;
|
||||
|
||||
m3dMesh Craft::mesh;
|
||||
|
||||
Craft::Craft()
|
||||
{
|
||||
// rectangle shaped bounds
|
||||
vertices[0] = Vector2(-.5 * WIDTH, -.5 * HEIGHT);
|
||||
vertices[1] = Vector2(.5 * WIDTH, -.5 * HEIGHT);
|
||||
vertices[2] = Vector2(.5 * WIDTH, .5 * HEIGHT);
|
||||
vertices[3] = Vector2(-.5 * WIDTH, .5 * HEIGHT);
|
||||
|
||||
// diamond shaped bounds
|
||||
/* vertices[0] = Vector2(0.0, -.5 * HEIGHT);
|
||||
vertices[1] = Vector2(.5 * WIDTH, 0.0);
|
||||
vertices[2] = Vector2(0.0, .5 * HEIGHT);
|
||||
vertices[3] = Vector2(-.5 * WIDTH, 0.0);*/
|
||||
|
||||
majorAxis = MAJOR_AXIS;
|
||||
minorAxis = MINOR_AXIS;
|
||||
|
||||
boostFuel = 1.0;
|
||||
ringTimer = 0;
|
||||
}
|
||||
|
||||
template <class T> void Craft::integrateRKN(float x0, T y0, T dy0, float dx, T *y, T *dy)
|
||||
{
|
||||
T k1, k2, k3, k4;
|
||||
T l;
|
||||
|
||||
k1 = 0.5 * dx * derive(x0, y0, dy0);
|
||||
l = 0.5 * dx * (dy0 + 0.5 * k1);
|
||||
k2 = 0.5 * dx * derive(x0 + 0.5 * dx, y0 + l, dy0 + k1);
|
||||
k3 = 0.5 * dx * derive(x0 + 0.5 * dx, y0 + l, dy0 + k2);
|
||||
l = dx * (dy0 + k3);
|
||||
k4 = 0.5 * dx * derive(x0 + dx, y0 + l, dy0 + 2.0 * k3);
|
||||
|
||||
*y = dx * (dy0 + (1.0/3.0) * (k1 + k2 + k3));
|
||||
*dy = dy0 + (1.0/3.0) * (k1 + 2.0 * k2 + 2.0 * k3 + k4);
|
||||
}
|
||||
|
||||
CraftState Craft::derive(float t, const CraftState &s, const CraftState &ds)
|
||||
{
|
||||
CraftState result;
|
||||
|
||||
(void)t;
|
||||
|
||||
beam[0] = Vector2(getPos());
|
||||
beam[1] = Vector2(s.getPos().getY() * tan(s.getAngle()), -s.getPos().getY());
|
||||
beam[0] = beam[0] + beam[1].unitVector() * 0.55 * HEIGHT;
|
||||
beam[1] = beam[1] + beam[0] - beam[1].unitVector() * 0.55 * HEIGHT;
|
||||
|
||||
Vector2 temp;
|
||||
if(Game::getInstance().getLevel().intersect(beam[0], beam[1], temp))
|
||||
{
|
||||
beam[1] = temp;
|
||||
}
|
||||
|
||||
bool inverted = false;
|
||||
if(s.getAngle() < -M_PI/2.0 || s.getAngle() > M_PI/2.0) inverted = true;
|
||||
|
||||
Vector2 l = beam[1] - beam[0];
|
||||
float d = l.length();
|
||||
|
||||
int numCraft = -1;
|
||||
for(int i = 0; i < Game::MAX_PLAYERS; i++)
|
||||
{
|
||||
Craft &craft = Game::getInstance().getPlayer(i).getCraft();
|
||||
Vector2 point;
|
||||
|
||||
if(craft.beamIntersect(beam[0], beam[1], point))
|
||||
{
|
||||
float clen = (point - beam[0]).length();
|
||||
if(clen < d)
|
||||
{
|
||||
beam[1] = point;
|
||||
d = clen;
|
||||
numCraft = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
l = beam[1] - beam[0];
|
||||
d = exp(-d + 1) * HOVER_FORCE;
|
||||
|
||||
if(inverted) d *= INVERTED_FORCE_MOD;
|
||||
|
||||
// Boost
|
||||
if(ctrl[CTRL_BOOST] && boostFuel > 0.0 && !inverted) d *= BOOST;
|
||||
|
||||
hoverForce = d;
|
||||
|
||||
Vector2 fce = l.unitVector() * d;
|
||||
if(numCraft != -1) Game::getInstance().getPlayer(numCraft).getCraft().addForce(fce);
|
||||
|
||||
// set velocity vector
|
||||
result.setPos(Vector2(0.0, GRAVITY) - l.unitVector() * d - DAMP * ds.getPos() + force);
|
||||
force = Vector2(0.0,0.0);
|
||||
|
||||
// Turning
|
||||
if(ctrl[CTRL_CCW]) result.setAngle(TURN_RATE);
|
||||
else if(ctrl[CTRL_CW]) result.setAngle(-TURN_RATE);
|
||||
else result.setAngle(-TURN_BACK * s.getAngle() - TURN_DAMP * ds.getAngle());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Craft::update(float dt)
|
||||
{
|
||||
bool boost = false;
|
||||
// boost
|
||||
if(ctrl[CTRL_BOOST])
|
||||
{
|
||||
boostFuel -= BOOST_FUEL_USE * dt;
|
||||
if(boostFuel < 0.0)
|
||||
boostFuel = 0.0;
|
||||
else
|
||||
boost = true;
|
||||
} else
|
||||
{
|
||||
boostFuel += BOOST_REFUEL * dt;
|
||||
if(boostFuel > 1.0) boostFuel = 1.0;
|
||||
}
|
||||
|
||||
ringTimer += dt;
|
||||
if(ringTimer > ((boost)?0.20:0.4)) {
|
||||
if(getAngle() > -M_PI/4.0 && getAngle() < M_PI/4.0 && (beam[1]-beam[0]).length()<3.0) {
|
||||
Vector2 vel((beam[1]-beam[0]).unitVector()*2);
|
||||
Ring::addRing(Ring(getX(),getY(),getAngle(),vel+getVel(),color));
|
||||
ringTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
integrateRKN<CraftState>(0.0f, state, dState, dt, &delta, &dState);
|
||||
}
|
||||
|
||||
void Craft::move()
|
||||
{
|
||||
state = state + delta;
|
||||
|
||||
while(state.getAngle() > M_PI) state.setAngle(state.getAngle() - 2.0 * M_PI);
|
||||
while(state.getAngle() < -M_PI) state.setAngle(state.getAngle() + 2.0 * M_PI);
|
||||
}
|
||||
|
||||
void Craft::setControl(int control, bool value)
|
||||
{
|
||||
ctrl[control] = value;
|
||||
}
|
||||
|
||||
void Craft::setColor(float r, float g, float b)
|
||||
{
|
||||
color[0] = r;
|
||||
color[1] = g;
|
||||
color[2] = b;
|
||||
}
|
||||
|
||||
void Craft::draw3d()
|
||||
{
|
||||
glPushMatrix();
|
||||
|
||||
glTranslatef(state.getPos().getX(), state.getPos().getY(), 0.0);
|
||||
glRotatef(DEG(state.getAngle()), 0.0, 0.0, 1.0);
|
||||
|
||||
// draw 3d mesh
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
mesh.draw();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
#if 0
|
||||
// draw beam
|
||||
if(state.getAngle() > -M_PI / 2.0 && state.getAngle() < M_PI / 2.0)
|
||||
{
|
||||
glDisable(GL_LIGHTING);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2fv(beam[0].getData());
|
||||
glVertex2fv(beam[1].getData());
|
||||
glEnd();
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Craft::draw2d()
|
||||
{
|
||||
glPushMatrix();
|
||||
|
||||
glTranslatef(state.getPos().getX(), state.getPos().getY(), 0.0);
|
||||
glRotatef(DEG(state.getAngle()), 0.0, 0.0, 1.0);
|
||||
|
||||
// draw bounding ellipse
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
glVertex2f(cos((float) i / 16.0 * 2.0 * M_PI) * majorAxis, sin((float) i / 16.0 * 2.0 * M_PI) * minorAxis);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
// draw bounding box
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
glVertex2fv(vertices[i].getData());
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
// draw beam
|
||||
glBegin(GL_LINES);
|
||||
glVertex2fv(beam[0].getData());
|
||||
glVertex2fv(beam[1].getData());
|
||||
glEnd();
|
||||
}
|
||||
|
||||
bool Craft::collide(Craft &other)
|
||||
{
|
||||
Vector2 normal, point;
|
||||
|
||||
if(!checkCollision(other, point, normal)) return false;
|
||||
handleCollision(other, point, normal);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Craft::checkCollision(const Craft &other, Vector2 &point, Vector2 &normal)
|
||||
{
|
||||
Vector2 myV[4]; // my vertices
|
||||
Vector2 otV[4]; // other's vertices
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
myV[i] = 0.99 * getVertex(i);
|
||||
myV[i].rotate(getAngle() + getDAngle());
|
||||
myV[i] = myV[i] + getPos() + getDPos();
|
||||
|
||||
otV[i] = other.getVertex(i);
|
||||
otV[i].rotate(other.getAngle() + other.getDAngle());
|
||||
otV[i] = otV[i] + other.getPos() + other.getDPos();
|
||||
}
|
||||
|
||||
Vector2 points[2];
|
||||
int num = 0;
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
for(int j = 0; j < 4; j++)
|
||||
{
|
||||
// check for contact
|
||||
if(!Level::segmentIsect(myV[i], myV[(i+1)%4], otV[j], otV[(j+1)%4], points[num])) continue;
|
||||
|
||||
num++;
|
||||
if(num < 2) continue; // we need 2 contact points
|
||||
|
||||
// collision has occured
|
||||
|
||||
// contact point
|
||||
point = 0.5 * (points[0] + points[1]);
|
||||
|
||||
// normal vector
|
||||
normal = (points[1] - points[0]).normalVector();
|
||||
normal.normalize();
|
||||
|
||||
// check if normal is facing away from this object
|
||||
if((point-getPos()).unitVector() * normal > 0.0)
|
||||
{
|
||||
// it is, flip it!
|
||||
normal = -normal;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
void Craft::addImpulse(const Vector2 &impulse, const Vector2 &point)
|
||||
{
|
||||
// Limit impulses to 5.0 units
|
||||
Vector2 imp = impulse;
|
||||
if(imp.length() > 5.0) imp = imp.unitVector() * 5.0;
|
||||
|
||||
// Add impulse
|
||||
dState.setPos(dState.getPos() + imp / MASS);
|
||||
dState.setAngle(dState.getAngle() + ((point - getPos()) ^ imp) / INERTIA);
|
||||
|
||||
// reset delta
|
||||
delta.setPos(Vector2(0.0, 0.0));
|
||||
delta.setAngle(0.0);
|
||||
}
|
||||
|
||||
void Craft::handleCollision(Craft &other, const Vector2& point, const Vector2& normal)
|
||||
{
|
||||
Vector2 v1, v2;
|
||||
|
||||
v1 = getVel() + (point - (getPos() + getDPos())).rotate(getOmega());
|
||||
v2 = other.getVel() + (point - (other.getPos() + other.getDPos())).rotate(other.getOmega());
|
||||
|
||||
Vector2 impulse = getImpulse(other, BOUNCYNESS, v1 - v2, point, normal);
|
||||
|
||||
if((v1 - v2) * impulse < 0.0)
|
||||
{
|
||||
addImpulse(impulse, point);
|
||||
other.addImpulse(-impulse, point);
|
||||
} else
|
||||
{
|
||||
}
|
||||
|
||||
// move the crafts away from each other
|
||||
v1 = getVel();
|
||||
v1.normalize();
|
||||
if((other.getPos() - getPos()).unitVector() * v1 > 0.0) v1 = -v1;
|
||||
setPos(getPos() + v1 * 0.03);
|
||||
|
||||
v1 = other.getVel();
|
||||
v1.normalize();
|
||||
if((getPos() - other.getPos()).unitVector() * v1 > 0.0) v1 = -v1;
|
||||
other.setPos(other.getPos() + v1 * 0.03);
|
||||
|
||||
// rotate the crafts away from each other
|
||||
if(((point - getPos()).rotate(getOmega())) * ((point - other.getPos()).rotate(other.getOmega())) > 0.0)
|
||||
{
|
||||
if(getOmega() > 0.0) setAngle(getAngle() - 0.05);
|
||||
else setAngle(getAngle() + 0.05);
|
||||
|
||||
if(other.getOmega() > 0.0) other.setAngle(other.getAngle() - 0.05);
|
||||
else other.setAngle(other.getAngle() + 0.05);
|
||||
} else
|
||||
{
|
||||
if(getOmega() > 0.0) setAngle(getAngle() + 0.05);
|
||||
else setAngle(getAngle() - 0.05);
|
||||
|
||||
if(other.getOmega() > 0.0) other.setAngle(other.getAngle() + 0.05);
|
||||
else other.setAngle(other.getAngle() - 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 Craft::getImpulse(Craft &other, float e, const Vector2 &v, const Vector2 &point, const Vector2 &normal)
|
||||
{
|
||||
float c1, c2;
|
||||
float a;
|
||||
|
||||
a = -(1.0 + e) * (v * normal);
|
||||
|
||||
c1 = (point - (getPos() + getDPos())) ^ normal;
|
||||
c1 *= c1;
|
||||
c2 = (point - (other.getPos() + other.getDPos()) ) ^ normal;
|
||||
c2 *= c2;
|
||||
|
||||
a /= (1.0 / MASS) + (1.0 / other.MASS) + (c1 / INERTIA) + (c2 / other.INERTIA);
|
||||
|
||||
return a * normal;
|
||||
}
|
||||
|
||||
bool Craft::levelCollide()
|
||||
{
|
||||
Vector2 point, normal, delta;
|
||||
if(!checkLevelCollision(point, normal, delta)) return false;
|
||||
|
||||
setPos(getPos() - 1.1 * delta);
|
||||
|
||||
|
||||
glBegin(GL_POINTS);
|
||||
glVertex2fv(point.getData());
|
||||
glEnd();
|
||||
|
||||
glColor3f(1,0,0);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2fv(point.getData());
|
||||
glVertex2fv((point + normal).getData());
|
||||
glEnd();
|
||||
glColor3f(1,1,1);
|
||||
|
||||
|
||||
Vector2 px = point - (getPos() + getDPos());
|
||||
Vector2 v = getVel() + px.rotate(getOmega());
|
||||
|
||||
float c1;
|
||||
float a;
|
||||
|
||||
a = -(1.0 + LEVEL_BOUNCYNESS) * (v * normal);
|
||||
c1 = px ^ normal;
|
||||
c1 *= c1;
|
||||
a /= (1.0 / MASS) + (c1 / INERTIA);
|
||||
|
||||
addImpulse(a * normal, point);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Craft::checkLevelCollision(Vector2 &point, Vector2 &normal, Vector2 &delta)
|
||||
{
|
||||
Level &level = Game::getInstance().getLevel();
|
||||
|
||||
return level.ellipseIntersect((getPos() + getDPos()), (getAngle() + getDAngle()), majorAxis, minorAxis, point, normal, delta);
|
||||
}
|
||||
|
||||
int Craft::init()
|
||||
{
|
||||
return mesh.loadFromXML("racer.xml");
|
||||
}
|
||||
|
||||
void Craft::setPos(const Vector2 &p) { state.setPos(p); }
|
||||
void Craft::setVel(const Vector2 &v) { dState.setPos(v); }
|
||||
void Craft::setAngle(float a) { state.setAngle(a); }
|
||||
void Craft::setOmega(float a) { dState.setAngle(a); }
|
||||
|
||||
float Craft::getX() const { return state.getX(); }
|
||||
float Craft::getY() const { return state.getY(); }
|
||||
const Vector2 &Craft::getPos() const { return state.getPos(); }
|
||||
|
||||
float Craft::getVX() const { return dState.getX(); }
|
||||
float Craft::getVY() const { return dState.getY(); }
|
||||
const Vector2 &Craft::getVel() const { return dState.getPos(); }
|
||||
|
||||
float Craft::getDX() const { return delta.getX(); }
|
||||
float Craft::getDY() const { return delta.getY(); }
|
||||
const Vector2 &Craft::getDPos() const { return delta.getPos(); }
|
||||
|
||||
float Craft::getAngle() const { return state.getAngle(); }
|
||||
float Craft::getOmega() const { return dState.getAngle(); }
|
||||
float Craft::getDAngle() const { return delta.getAngle(); }
|
||||
|
||||
const Vector2 &Craft::getVertex(int n) const { return vertices[n]; }
|
||||
|
||||
float Craft::getBoostFuel() const { return boostFuel; }
|
||||
|
||||
float Craft::getHoverForce() const { return hoverForce; }
|
||||
float Craft::getSpeed() const { return dState.getPos().length(); }
|
||||
|
||||
m3dMesh &Craft::getMesh() const { return mesh; }
|
||||
|
||||
bool Craft::beamIntersect(const Vector2& v1, const Vector2& v2, Vector2 &point) const
|
||||
{
|
||||
Vector2 dv(0.5 * WIDTH, 0.0);
|
||||
dv.rotate(getAngle());
|
||||
|
||||
Vector2 p;
|
||||
if(Level::segmentIsect(getPos() + dv, getPos() - dv, v1, v2, p))
|
||||
{
|
||||
point = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Craft::addForce(Vector2 &f)
|
||||
{
|
||||
force = force + f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
134
src/craft.h
Normal file
134
src/craft.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
#ifndef _CRAFT_H_
|
||||
#define _CRAFT_H_
|
||||
|
||||
class CraftState
|
||||
{
|
||||
public:
|
||||
CraftState();
|
||||
CraftState(const Vector2& pos, float angle);
|
||||
|
||||
const Vector2& getPos() const;
|
||||
float getAngle() const;
|
||||
|
||||
float getX() const;
|
||||
float getY() const;
|
||||
|
||||
void setPos(const Vector2 &p);
|
||||
void setAngle(float a);
|
||||
|
||||
private:
|
||||
Vector2 pos;
|
||||
float angle;
|
||||
};
|
||||
|
||||
extern CraftState operator+(const CraftState& s1, const CraftState& s2);
|
||||
extern CraftState operator*(float f, const CraftState& s2);
|
||||
|
||||
class Craft
|
||||
{
|
||||
public:
|
||||
static const int CTRL_CW = 0;
|
||||
static const int CTRL_CCW = 1;
|
||||
static const int CTRL_BOOST = 2;
|
||||
static const int NUM_CONTROLS = 3;
|
||||
|
||||
static const float TURN_RATE;
|
||||
static const float TURN_DAMP;
|
||||
static const float TURN_BACK;
|
||||
|
||||
static const float GRAVITY;
|
||||
static const float HOVER_FORCE;
|
||||
static const float BOOST;
|
||||
static const float DAMP;
|
||||
|
||||
static const float MAJOR_AXIS;
|
||||
static const float MINOR_AXIS;
|
||||
static const float WIDTH;
|
||||
static const float HEIGHT;
|
||||
static const float INERTIA;
|
||||
static const float MASS;
|
||||
|
||||
static const float INVERTED_FORCE_MOD;
|
||||
|
||||
static const float BOOST_REFUEL;
|
||||
static const float BOOST_FUEL_USE;
|
||||
|
||||
static const float BOUNCYNESS;
|
||||
static const float LEVEL_BOUNCYNESS;
|
||||
|
||||
Craft();
|
||||
|
||||
void update(float dt);
|
||||
void setControl(int control, bool value);
|
||||
|
||||
void setPos(const Vector2 &p);
|
||||
void setVel(const Vector2 &v);
|
||||
void setAngle(float a);
|
||||
void setOmega(float a);
|
||||
void setColor(float r, float g, float b);
|
||||
|
||||
float getX() const;
|
||||
float getY() const;
|
||||
const Vector2 &getPos() const;
|
||||
float getVX() const;
|
||||
float getVY() const;
|
||||
float getDX() const;
|
||||
float getDY() const;
|
||||
const Vector2 &getDPos() const;
|
||||
const Vector2 &getVel() const;
|
||||
float getAngle() const;
|
||||
float getOmega() const;
|
||||
float getDAngle() const;
|
||||
|
||||
bool beamIntersect(const Vector2& v1, const Vector2& v2, Vector2 &point) const;
|
||||
void addForce(Vector2 &f);
|
||||
|
||||
float getBoostFuel() const;
|
||||
float getHoverForce() const;
|
||||
float getSpeed() const;
|
||||
|
||||
const Vector2 &getVertex(int n) const;
|
||||
|
||||
bool collide(Craft &other);
|
||||
bool levelCollide();
|
||||
void move();
|
||||
|
||||
void draw2d();
|
||||
void draw3d();
|
||||
|
||||
static int init();
|
||||
|
||||
m3dMesh &getMesh() const;
|
||||
|
||||
private:
|
||||
CraftState state, dState, delta;
|
||||
Vector2 vertices[4];
|
||||
float majorAxis, minorAxis;
|
||||
|
||||
Vector2 beam[2];
|
||||
|
||||
Vector2 force;
|
||||
|
||||
bool ctrl[NUM_CONTROLS];
|
||||
|
||||
Vector2 getImpulse(Craft &other, float e, const Vector2 &v, const Vector2 &point, const Vector2 &normal);
|
||||
bool checkCollision(const Craft &other, Vector2 &point, Vector2 &normal);
|
||||
void handleCollision(Craft &other, const Vector2& point, const Vector2& normal);
|
||||
void addImpulse(const Vector2 &impulse, const Vector2 &point);
|
||||
|
||||
bool checkLevelCollision(Vector2 &point, Vector2 &normal, Vector2 &delta);
|
||||
|
||||
template <class T> void integrateRKN(float x0, T y0, T dy0, float dx, T *y, T *dy);
|
||||
CraftState derive(float t, const CraftState &s, const CraftState &ds);
|
||||
|
||||
static m3dMesh mesh;
|
||||
|
||||
float boostFuel;
|
||||
float hoverForce;
|
||||
float ringTimer;
|
||||
float color[3];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
20
src/extensions.h
Normal file
20
src/extensions.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef _EXTENSIONS_H_
|
||||
#define _EXTENSIONS_H_
|
||||
|
||||
#if 0
|
||||
#define HAVE_MULTITEX
|
||||
#ifdef WIN32
|
||||
#define MAPIENTRY __stdcall
|
||||
#else
|
||||
#define MAPIENTRY
|
||||
#endif
|
||||
|
||||
typedef void (MAPIENTRY *MFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
|
||||
typedef void (MAPIENTRY *MFNGLACTIVETEXTUREARBPROC) (GLenum texture);
|
||||
|
||||
extern MFNGLMULTITEXCOORD2FVPROC mglMultiTexCoord2fv;
|
||||
extern MFNGLACTIVETEXTUREARBPROC mglActiveTextureARB;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
166
src/font.cpp
Normal file
166
src/font.cpp
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <GL/gl.h>
|
||||
#include "font.h"
|
||||
|
||||
const char *Font::chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!-.:";
|
||||
|
||||
const unsigned char Font::fontData[] = {
|
||||
0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0x00, 0xFC, 0xC6, 0xC6, 0xFC, 0xC6, 0xC6, 0xFC,
|
||||
0x00, 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00, 0xF8, 0xCC, 0xC6, 0xC6, 0xC6, 0xCC, 0xF8,
|
||||
0x00, 0xFE, 0xC0, 0xC0, 0xFC, 0xC0, 0xC0, 0xFE, 0x00, 0xFE, 0xC0, 0xC0, 0xFC, 0xC0, 0xC0, 0xC0,
|
||||
0x00, 0x3E, 0x60, 0xC0, 0xCE, 0xC6, 0x66, 0x3E, 0x00, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6,
|
||||
0x00, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00, 0x1E, 0x06, 0x06, 0x06, 0xC6, 0xC6, 0x7C,
|
||||
0x00, 0xC6, 0xCC, 0xD8, 0xF0, 0xF8, 0xDC, 0xCE, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E,
|
||||
0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6,
|
||||
0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0xFC, 0xC6, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0,
|
||||
0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xDE, 0xCC, 0x7A, 0x00, 0xFC, 0xC6, 0xC6, 0xCE, 0xF8, 0xDC, 0xCE,
|
||||
0x00, 0x78, 0xCC, 0xC0, 0x7C, 0x06, 0xC6, 0x7C, 0x00, 0xF8, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0xC6, 0xC6, 0xC6, 0xEE, 0x7C, 0x38, 0x10,
|
||||
0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0xFE, 0xEE, 0xC6, 0x00, 0xC6, 0xEE, 0x7C, 0x38, 0x7C, 0xEE, 0xC6,
|
||||
0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x30, 0x00, 0xFE, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xFE,
|
||||
0x00, 0x38, 0x4C, 0xC6, 0xC6, 0xC6, 0x64, 0x38, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC,
|
||||
0x00, 0x7C, 0xC6, 0x0E, 0x3C, 0x78, 0xE0, 0xFE, 0x00, 0x7E, 0x0C, 0x18, 0x3C, 0x06, 0xC6, 0x7C,
|
||||
0x00, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x00, 0xFC, 0xC0, 0xFC, 0x06, 0x06, 0xC6, 0x7C,
|
||||
0x00, 0x3C, 0x60, 0xC0, 0xFC, 0xC6, 0xC6, 0x7C, 0x00, 0xFE, 0xC6, 0x0C, 0x18, 0x30, 0x30, 0x30,
|
||||
0x00, 0x7C, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0x7C, 0x00, 0x7C, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78,
|
||||
0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00,
|
||||
0x00 };
|
||||
|
||||
Font Font::instance;
|
||||
|
||||
Font::Font()
|
||||
{
|
||||
}
|
||||
|
||||
Font &Font::getInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
int Font::init()
|
||||
{
|
||||
glGenTextures(NUM_CHARS, textures);
|
||||
if(glGetError() != GL_NO_ERROR) return -1;
|
||||
|
||||
int c, i, j;
|
||||
for(c = 0; c < NUM_CHARS; c++)
|
||||
{
|
||||
unsigned int data[64];
|
||||
|
||||
for(i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned char temp = fontData[c * 8 + i];
|
||||
unsigned char mask = 0x80;
|
||||
|
||||
for(j = 0; j < 8; j++)
|
||||
{
|
||||
data[i * 8 + j] =(temp&mask)?(0xFFFFFFFF):(0x00000000);
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textures[c]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
if(glGetError() != GL_NO_ERROR) return -1;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Font::deinit()
|
||||
{
|
||||
glDeleteTextures(NUM_CHARS, textures);
|
||||
}
|
||||
|
||||
void Font::drawChar(char c)
|
||||
{
|
||||
int i;
|
||||
if(c >= 'a' && c <= 'z') c += 'A' - 'a';
|
||||
for(i = 0; i <= NUM_CHARS; i++) if(chars[i] == c) break;
|
||||
if(i >= NUM_CHARS) return;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textures[i]);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glTexCoord2f(0.0, 0.0);
|
||||
glVertex2f(0.0, 0.0);
|
||||
glTexCoord2f(1.0, 0.0);
|
||||
glVertex2f(1.0, 0.0);
|
||||
glTexCoord2f(0.0, 1.0);
|
||||
glVertex2f(0.0, 1.0);
|
||||
glTexCoord2f(1.0, 1.0);
|
||||
glVertex2f(1.0, 1.0);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void Font::drawString(const char *str)
|
||||
{
|
||||
glPushMatrix();
|
||||
glPushMatrix();
|
||||
|
||||
while(*str != '\0')
|
||||
{
|
||||
if(*str == '\n')
|
||||
{
|
||||
glPopMatrix();
|
||||
glTranslatef(0.0, 1.0, 0.0);
|
||||
glPushMatrix();
|
||||
} else
|
||||
{
|
||||
drawChar(*str);
|
||||
glTranslatef(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
str++;
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void Font::printf(const char *fmt, ...)
|
||||
{
|
||||
/* based on the example code on 'man 3 vsnprintf' */
|
||||
/* Guess we need no more than 256 bytes. */
|
||||
int n, size = 256;
|
||||
char *p, *np;
|
||||
va_list ap;
|
||||
|
||||
if((p = (char*)malloc(size)) == NULL) return;
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* Try to print in the allocated space. */
|
||||
va_start(ap, fmt);
|
||||
n = vsnprintf(p, size, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* If that worked, break out of the loop */
|
||||
if(n > -1 && n < size) break;
|
||||
|
||||
/* Else try again with more space. */
|
||||
if(n > -1) /* glibc 2.1 */
|
||||
size = n + 1; /* precisely what is needed */
|
||||
else /* glibc 2.0 */
|
||||
size *= 2; /* twice the old size */
|
||||
if((np = (char*)realloc(p, size)) == NULL)
|
||||
{
|
||||
free(p);
|
||||
return;
|
||||
} else
|
||||
{
|
||||
p = np;
|
||||
}
|
||||
}
|
||||
|
||||
drawString(p);
|
||||
free(p);
|
||||
}
|
||||
29
src/font.h
Normal file
29
src/font.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef _FONT_H_
|
||||
#define _FONT_H_
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
class Font
|
||||
{
|
||||
public:
|
||||
int init();
|
||||
void deinit();
|
||||
void drawChar(char c);
|
||||
void drawString(const char *str);
|
||||
void printf(const char *fmt, ...);
|
||||
|
||||
|
||||
static Font &getInstance();
|
||||
private:
|
||||
static const int NUM_CHARS = 40;
|
||||
|
||||
Font();
|
||||
static Font instance;
|
||||
|
||||
static const unsigned char fontData[];
|
||||
static const char *chars;
|
||||
|
||||
GLuint textures[NUM_CHARS];
|
||||
};
|
||||
|
||||
#endif
|
||||
888
src/game.cpp
Normal file
888
src/game.cpp
Normal file
|
|
@ -0,0 +1,888 @@
|
|||
#include "SDL.h"
|
||||
#include "SDL_opengl.h"
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "antigrav.h"
|
||||
|
||||
Game Game::instance;
|
||||
|
||||
const int Game::CONTROLS[MAX_LOCAL_PLAYERS][NUM_CONTROLS] = {
|
||||
{SDLK_RIGHT, SDLK_LEFT, SDLK_UP},
|
||||
{SDLK_d, SDLK_a, SDLK_w},
|
||||
{SDLK_l, SDLK_j, SDLK_i},
|
||||
{SDLK_KP6, SDLK_KP4, SDLK_KP8}};
|
||||
|
||||
const char *Game::PLAYER_TEXTURES[MAX_PLAYERS] = {"", "racer1.png", "racer2.png", "racer3.png", "racer4.png", "racer5.png", "racer6.png", "racer7.png"};
|
||||
const float Game::PLAYER_COLORS[MAX_PLAYERS][3] = {{1,0,0},{0,0,1},{0,1,0},{1,1,0}, {0.65, 0, 1}, {0.20, 0.64, 0.69}, {0.89, 0.63, 0.18}, {0.59, 0.56, 0.88}};
|
||||
|
||||
GLuint Game::signal;
|
||||
GLuint Game::signalred;
|
||||
GLuint Game::signalgreen;
|
||||
ALuint Game::signalredbuffer;
|
||||
ALuint Game::signalgreenbuffer;
|
||||
|
||||
Game::Game()
|
||||
{
|
||||
enable3d = true;
|
||||
enable2d = false;
|
||||
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
players[i].setActive(false);
|
||||
players[i].setLocal(false);
|
||||
}
|
||||
}
|
||||
|
||||
Game::~Game()
|
||||
{
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
if(alIsSource(playerSources[i]))
|
||||
{
|
||||
alDeleteSources(1, &playerSources[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < GLOBAL_SOURCES; i++)
|
||||
{
|
||||
if(alIsSource(globalSources[i]))
|
||||
{
|
||||
alDeleteSources(1, &globalSources[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Game &Game::getInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
Level &Game::getLevel()
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
int Game::init()
|
||||
{
|
||||
// Get viewport
|
||||
glGetIntegerv(GL_VIEWPORT, masterViewport);
|
||||
screenWidth = masterViewport[2];
|
||||
screenHeight = masterViewport[3];
|
||||
|
||||
// Load resources
|
||||
if(Craft::init() != 0) return 1;
|
||||
if(level.init() != 0) return 1;
|
||||
if(Font::getInstance().init() != 0) return 1;
|
||||
if(Player::init() != 0) return 1;
|
||||
if(Ring::init() != 0) return 1;
|
||||
if(Background::init() != 0) return 1;
|
||||
|
||||
signal = m3dTexture::loadTexture("signal.png");
|
||||
if(signal==0)
|
||||
return -1;
|
||||
|
||||
signalred = m3dTexture::loadTexture("signalred.png");
|
||||
if(signalred==0)
|
||||
return -1;
|
||||
|
||||
signalgreen = m3dTexture::loadTexture("signalgreen.png");
|
||||
if(signalgreen==0)
|
||||
return -1;
|
||||
|
||||
/* signalredbuffer = alutCreateBufferWaveform(ALUT_WAVEFORM_SINE, 200.0, 0.0, 0.4);
|
||||
signalgreenbuffer = alutCreateBufferWaveform(ALUT_WAVEFORM_SINE, 300.0, 0.0, 0.7);*/
|
||||
signalredbuffer = loadWavBuffer("signalred.wav");
|
||||
if(signalredbuffer == AL_NONE) return -1;
|
||||
signalgreenbuffer = loadWavBuffer("signalgreen.wav");
|
||||
if(signalgreenbuffer == AL_NONE) return -1;
|
||||
|
||||
playerTex[0] = players[0].getCraft().getMesh().getTexture(0);
|
||||
for(int i = 1; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
if(playerTex[i].load(PLAYER_TEXTURES[i]) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
players[i].setTexture(&playerTex[i]);
|
||||
players[i].setColor(PLAYER_COLORS[i]);
|
||||
}
|
||||
|
||||
// set up player sources
|
||||
alGenSources(MAX_PLAYERS, playerSources);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Can't initialize OpenAL sources\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
players[i].setSource(playerSources[i]);
|
||||
}
|
||||
|
||||
// set up global sources
|
||||
alGenSources(GLOBAL_SOURCES, globalSources);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Can't initialize OpenAL sources\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set up permanent OpenGL state
|
||||
// lighting
|
||||
const GLfloat lightPos[] = {0,10,0,1};
|
||||
const GLfloat lightAmb[] = {.5,.5,.5,1};
|
||||
const GLfloat lightDif[] = {1,1,1,1};
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDif);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
|
||||
glEnable(GL_LIGHT0);
|
||||
|
||||
// Depth func
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
// Blend func
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sortStats(const void *s1, const void *s2) {
|
||||
float t1 = ((PlayerStat*)s1)->time;
|
||||
float t2 = ((PlayerStat*)s2)->time;
|
||||
if(t1<t2) return -1;
|
||||
if(t1>t2) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Game::gameLoop()
|
||||
{
|
||||
SDL_Event event;
|
||||
Uint32 startTime;
|
||||
float t;
|
||||
bool loop;
|
||||
|
||||
// <temporary>
|
||||
// generate level
|
||||
level.generate(time(NULL));
|
||||
// </temporary>
|
||||
|
||||
backg = Background();
|
||||
|
||||
// set up starting grid
|
||||
int grid = 0;
|
||||
activeplayers = 0;
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
playerFinishTime[i].plr = -1;
|
||||
if(!players[i].isActive()) continue;
|
||||
++activeplayers;
|
||||
|
||||
float xPos = 15.0 - grid * 0.75;
|
||||
float yPos = 0.75 + (grid & 1) * 0.5;
|
||||
grid++;
|
||||
|
||||
players[i].reset(xPos, level.getHeight(xPos) + yPos);
|
||||
|
||||
playerFinishTime[i].plr = i;
|
||||
playerFinishTime[i].time = -1;
|
||||
}
|
||||
|
||||
// Clear rings
|
||||
Ring::resetAll();
|
||||
|
||||
// set up viewports
|
||||
int temp = 0;
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
if(players[i].isActive() && players[i].isLocal()) temp++;
|
||||
}
|
||||
|
||||
initViewports(temp);
|
||||
|
||||
// set up audio distance model
|
||||
if(activeplayers > 1)
|
||||
{
|
||||
alDistanceModel(AL_NONE);
|
||||
Player::setEngineVolume(0.2);
|
||||
alDopplerFactor(0.0);
|
||||
} else
|
||||
{
|
||||
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
|
||||
Player::setEngineVolume(1.0);
|
||||
alDopplerFactor(0.25);
|
||||
}
|
||||
|
||||
// set up timer
|
||||
fps = 0.0;
|
||||
int numFrames = 0, skippedFrames = 0;
|
||||
Uint32 frameTime = 0, fpsTimer = 0;
|
||||
showFps = false;
|
||||
|
||||
// start main loop
|
||||
state = WAITFORSTART;
|
||||
stateTimer = 0;
|
||||
loop = true;
|
||||
startTime = SDL_GetTicks();
|
||||
while(loop)
|
||||
{
|
||||
|
||||
// Update timer and frame rate
|
||||
frameTime = SDL_GetTicks() - startTime;
|
||||
if(frameTime < MIN_FRAME_TIME && FRAME_LIMITER) { SDL_Delay(MIN_FRAME_TIME - frameTime); }
|
||||
frameTime = (SDL_GetTicks() - startTime);
|
||||
t = (frameTime) / 1000.0f;
|
||||
|
||||
fpsTimer += frameTime;
|
||||
if(numFrames++ >= 5)
|
||||
{
|
||||
if(fpsTimer == 0) fpsTimer = 1; // avoid division by zero on smoking fast machines
|
||||
fps = (float)(1000 * (numFrames - skippedFrames)) / fpsTimer;
|
||||
updateRate = (float)(1000 * numFrames) / fpsTimer;
|
||||
numFrames = 0;
|
||||
fpsTimer = 0;
|
||||
skippedFrames = 0;
|
||||
}
|
||||
|
||||
startTime = SDL_GetTicks();
|
||||
|
||||
// Handle events
|
||||
while(SDL_PollEvent(&event))
|
||||
{
|
||||
if(event.type == SDL_QUIT) loop = false;
|
||||
else if(event.type == SDL_KEYDOWN)
|
||||
{
|
||||
if(event.key.keysym.sym == SDLK_ESCAPE) loop = false;
|
||||
else if(event.key.keysym.sym == SDLK_F9) showFps = !showFps;
|
||||
|
||||
// update player controls
|
||||
updateControls(event.key.keysym.sym, true);
|
||||
if(state==WAITFORSTART) {
|
||||
state = START;
|
||||
stateTimer = 0;
|
||||
stateVal = 0;
|
||||
}
|
||||
|
||||
// debug-mode "secret" keys
|
||||
#ifdef DEBUG
|
||||
if(event.key.keysym.sym == SDLK_F10) m3dTexture::screenshot("antigrav-screenshot.png");
|
||||
else if(event.key.keysym.sym == SDLK_F11) enable3d = !enable3d;
|
||||
else if(event.key.keysym.sym == SDLK_F12) enable2d = !enable2d;
|
||||
#endif
|
||||
} else if(event.type == SDL_KEYUP)
|
||||
{
|
||||
// handle player controls
|
||||
updateControls(event.key.keysym.sym, false);
|
||||
}
|
||||
}
|
||||
|
||||
stateTimer += t;
|
||||
|
||||
switch(state) {
|
||||
case WAITFORSTART:
|
||||
break;
|
||||
case START:
|
||||
if(stateTimer > 4.0) {
|
||||
state = GAME;
|
||||
stateTimer = 0;
|
||||
}
|
||||
break;
|
||||
case GAME: {
|
||||
// Check if all players have finished
|
||||
int finp=0;
|
||||
for(int p=0;p<8;p++)
|
||||
if(players[p].isActive() && players[p].isFinished())
|
||||
finp++;
|
||||
if(finp==activeplayers) {
|
||||
state = FINISHED;
|
||||
stateTimer = 0;
|
||||
qsort(playerFinishTime,MAX_PLAYERS,sizeof(PlayerStat),
|
||||
sortStats);
|
||||
}
|
||||
// Update
|
||||
updateWorld(t);
|
||||
} break;
|
||||
|
||||
case FINISHED:
|
||||
// Update
|
||||
updateWorld(t);
|
||||
if(stateTimer>=5.0)
|
||||
loop = false;
|
||||
}
|
||||
|
||||
// skip frames to maintain solid frame rate
|
||||
if(frameTime > MAX_FRAME_TIME && FRAMESKIP)
|
||||
{
|
||||
skippedFrames++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Draw (all states)
|
||||
resetListener();
|
||||
drawFrame();
|
||||
updateListener();
|
||||
}
|
||||
|
||||
// Kill all audio
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
ALint state;
|
||||
alGetSourcei(playerSources[i], AL_SOURCE_STATE, &state);
|
||||
if(state == AL_PLAYING) alSourceStop(playerSources[i]);
|
||||
}
|
||||
|
||||
for(int i = 0; i < GLOBAL_SOURCES; i++)
|
||||
{
|
||||
ALint state;
|
||||
alGetSourcei(globalSources[i], AL_SOURCE_STATE, &state);
|
||||
if(state == AL_PLAYING) alSourceStop(globalSources[i]);
|
||||
}
|
||||
|
||||
return state!=FINISHED;
|
||||
}
|
||||
|
||||
// returns true if key handled, false if not
|
||||
bool Game::updateControls(int keysym, bool down)
|
||||
{
|
||||
int pl = -1;
|
||||
int ctrl = -1;
|
||||
if(state!=GAME) return false;
|
||||
|
||||
for(int i = 0; i < MAX_LOCAL_PLAYERS; i++)
|
||||
{
|
||||
for(int j = 0; j < NUM_CONTROLS; j++)
|
||||
{
|
||||
if(keysym == CONTROLS[i][j])
|
||||
{
|
||||
pl = i;
|
||||
ctrl = j;
|
||||
break;
|
||||
}
|
||||
|
||||
if(pl != -1) break;
|
||||
}
|
||||
}
|
||||
|
||||
if(pl == -1 || ctrl == -1) return false;
|
||||
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
if(!players[i].isLocal()) continue;
|
||||
if(pl == 0)
|
||||
{
|
||||
if(!players[i].isFinished())
|
||||
players[i].getCraft().setControl(ctrl, down);
|
||||
else
|
||||
players[i].getCraft().setControl(ctrl,false);
|
||||
return true;
|
||||
}
|
||||
|
||||
pl--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Game::updateWorld(float t)
|
||||
{
|
||||
// update crafts
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
if(!players[i].isActive()) continue;
|
||||
if(players[i].update(t)) {
|
||||
// Player finished
|
||||
playerFinishTime[i].time = stateTimer;
|
||||
}
|
||||
}
|
||||
|
||||
// Update rings
|
||||
Ring::updateAll(t);
|
||||
|
||||
// handle craft to craft collisions
|
||||
for(int i = 0; i < MAX_PLAYERS - 1; i++)
|
||||
{
|
||||
if(!players[i].isActive()) continue;
|
||||
Craft &craft1 = players[i].getCraft();
|
||||
|
||||
for(int j = i + 1; j < MAX_PLAYERS; j++)
|
||||
{
|
||||
if(!players[j].isActive()) continue;
|
||||
Craft &craft2 = players[j].getCraft();
|
||||
|
||||
if(!craft1.collide(craft2)) craft2.collide(craft1);
|
||||
}
|
||||
}
|
||||
|
||||
// handle craft to level collisions and move crafts
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
if(!players[i].isActive()) continue;
|
||||
|
||||
players[i].getCraft().levelCollide();
|
||||
players[i].getCraft().move();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Game::initViewports(int num)
|
||||
{
|
||||
numViewports = num;
|
||||
if(numViewports > MAX_VIEWPORTS) numViewports = MAX_VIEWPORTS;
|
||||
|
||||
if(numViewports == 1)
|
||||
{
|
||||
viewports[0][2] = screenWidth;
|
||||
viewports[0][3] = screenWidth / 16 * 9;
|
||||
viewports[0][0] = 0;
|
||||
viewports[0][1] = (screenHeight - viewports[0][3]) / 2;
|
||||
|
||||
for(int i = 0; i < 4; i++) masterViewport[i] = viewports[0][i];
|
||||
return;
|
||||
} else if(numViewports == 2)
|
||||
{
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
viewports[i][0] = 0;
|
||||
viewports[i][1] = (1 - i) * screenHeight / 2;
|
||||
viewports[i][2] = screenWidth;
|
||||
viewports[i][3] = screenHeight / 2;
|
||||
}
|
||||
} else
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
viewports[i][0] = (i & 1) * screenWidth / 2;
|
||||
viewports[i][1] = (1 - i/2) * screenHeight / 2;
|
||||
viewports[i][2] = screenWidth / 2;
|
||||
viewports[i][3] = screenHeight / 2;
|
||||
}
|
||||
}
|
||||
|
||||
masterViewport[0] = 0;
|
||||
masterViewport[1] = 0;
|
||||
masterViewport[2] = screenWidth;
|
||||
masterViewport[3] = screenHeight;
|
||||
}
|
||||
|
||||
void Game::drawFrame()
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
int vp = numViewports - 1;
|
||||
for(int i = MAX_PLAYERS-1; i >= 0; i--)
|
||||
{
|
||||
if(!players[i].isActive() || !players[i].isLocal()) continue;
|
||||
|
||||
drawViewport(i, viewports[vp--]);
|
||||
if(vp < 0) break;
|
||||
}
|
||||
|
||||
drawHud();
|
||||
|
||||
SDL_GL_SwapBuffers();
|
||||
}
|
||||
|
||||
void Game::draw3d(const float *eye, const float *at, float fovDiag)
|
||||
{
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
backg.draw();
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
level.draw3d(eye, at, fovDiag);
|
||||
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
if(!players[i].isActive()) continue;
|
||||
|
||||
players[i].getCraft().getMesh().setTexture(0, players[i].getTexture());
|
||||
players[i].getCraft().draw3d();
|
||||
}
|
||||
|
||||
Ring::drawAll();
|
||||
}
|
||||
|
||||
void Game::draw2d()
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
level.draw2d();
|
||||
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
if(!players[i].isActive()) continue;
|
||||
|
||||
players[i].getCraft().draw2d();
|
||||
}
|
||||
}
|
||||
|
||||
void Game::drawViewport(int current, const GLint *viewport)
|
||||
{
|
||||
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
// set up projection and calculate diagoonal fov
|
||||
const double fovY = RAD(45.0);
|
||||
const double aspect = (GLdouble)viewport[2]/viewport[3];
|
||||
gluPerspective(DEG(fovY), aspect, 0.1, 200.0);
|
||||
|
||||
double tfovY2 = tan(fovY / 2.0);
|
||||
double tfovX2 = tfovY2 * aspect;
|
||||
|
||||
float fovDiag = (float)atan(sqrt( tfovX2 * tfovX2 + tfovY2 * tfovY2 ));
|
||||
|
||||
// Set up transformation
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
Craft &craft = players[current].getCraft();
|
||||
|
||||
// Set camera position
|
||||
float eyeX, eyeY, eyeZ;
|
||||
float centerX, centerY, centerZ;
|
||||
eyeX = craft.getX();
|
||||
if(eyeX < 10.0) eyeX = 10.0;
|
||||
if(eyeX > level.getWidth() - 10.0) eyeX = level.getWidth() - 10.0;
|
||||
|
||||
eyeY = 6.0;
|
||||
eyeZ = 7.0;
|
||||
|
||||
centerX = eyeX;
|
||||
centerY = 4.0;
|
||||
centerZ = 0.0;
|
||||
|
||||
gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, centerX - eyeX, eyeZ - centerZ, centerY - eyeY);
|
||||
|
||||
// Update listener values
|
||||
listenerPos[0] += eyeX;
|
||||
listenerPos[1] += eyeY;
|
||||
listenerPos[2] += eyeZ;
|
||||
|
||||
listenerVel[0] += craft.getVX();
|
||||
|
||||
listenerOri[0] += centerX - eyeX;
|
||||
listenerOri[1] += centerY - eyeY;
|
||||
listenerOri[2] += centerZ - eyeZ;
|
||||
|
||||
listenerOri[3] += centerX - eyeX;
|
||||
listenerOri[4] += eyeZ - centerZ;
|
||||
listenerOri[5] += centerY - eyeY;
|
||||
|
||||
listenerWeight += 1.0;
|
||||
|
||||
// Draw
|
||||
const float at[3] = {centerX - eyeX, centerY - eyeY, centerZ - eyeZ};
|
||||
const float eye[3] = {eyeX, eyeY, eyeZ};
|
||||
|
||||
if(enable3d) draw3d(eye, at, fovDiag);
|
||||
if(enable2d) draw2d();
|
||||
|
||||
players[current].drawHud(viewport, activeplayers, current);
|
||||
}
|
||||
|
||||
void Game::drawHud()
|
||||
{
|
||||
glViewport(masterViewport[0], masterViewport[1], masterViewport[2], masterViewport[3]);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
float width, height;
|
||||
width = masterViewport[2] / 8.0;
|
||||
height = width * masterViewport[3] / masterViewport[2];
|
||||
glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
// Draw signal lights
|
||||
if(state == START || (state==GAME&&stateTimer<1.0)) {
|
||||
float y=0.0, w=0.0;
|
||||
|
||||
if(state==START) {
|
||||
glBindTexture(GL_TEXTURE_2D, signal);
|
||||
if(stateTimer < 1.0) {
|
||||
y = -10+stateTimer*10;
|
||||
} else {
|
||||
w = int(stateTimer)/3.0;
|
||||
if(stateVal != int(stateTimer)) {
|
||||
stateVal = int(stateTimer);
|
||||
ALuint source = getSource();
|
||||
if(alIsSource(source)) {
|
||||
float vec[3] = {0,0,0};
|
||||
alSourcefv(source, AL_VELOCITY, vec);
|
||||
float pos[3] = {listenerPos[0],listenerPos[1],listenerPos[2]-1};
|
||||
alSourcefv(source, AL_POSITION, pos);
|
||||
alSourcei(source, AL_LOOPING, AL_FALSE);
|
||||
alSourcei(source, AL_BUFFER, signalredbuffer);
|
||||
alSourcePlay(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, signalgreen);
|
||||
y = stateTimer*-10.0;
|
||||
if(stateVal!=-1) {
|
||||
stateVal=-1;
|
||||
ALuint source = getSource();
|
||||
if(alIsSource(source)) {
|
||||
float vec[3] = {0,0,0};
|
||||
alSourcefv(source, AL_VELOCITY, vec);
|
||||
float pos[3] = {listenerPos[0],listenerPos[1],listenerPos[2]-1};
|
||||
alSourcefv(source, AL_POSITION, pos);
|
||||
alSourcei(source, AL_LOOPING, AL_FALSE);
|
||||
alSourcei(source, AL_BUFFER, signalgreenbuffer);
|
||||
alSourcePlay(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unlit or green signals
|
||||
glPushMatrix();
|
||||
glTranslatef(width/2.0 - 10.0,y,0);
|
||||
glScalef(10,10,1);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glTexCoord2f(w, 0.0);
|
||||
glVertex2f(2*w, 0);
|
||||
|
||||
glTexCoord2f(1, 0.0);
|
||||
glVertex2f(2, 0);
|
||||
|
||||
glTexCoord2f(w, 1.0);
|
||||
glVertex2f(2*w, 1);
|
||||
|
||||
glTexCoord2f(1, 1.0);
|
||||
glVertex2f(2, 1);
|
||||
glEnd();
|
||||
|
||||
if(w>0.0) {
|
||||
// Red signals
|
||||
glBindTexture(GL_TEXTURE_2D, signalred);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glTexCoord2f(0, 0.0);
|
||||
glVertex2f(0, 0);
|
||||
|
||||
glTexCoord2f(w, 0.0);
|
||||
glVertex2f(2*w, 0);
|
||||
|
||||
glTexCoord2f(0, 1.0);
|
||||
glVertex2f(0, 1);
|
||||
|
||||
glTexCoord2f(w, 1.0);
|
||||
glVertex2f(2*w, 1);
|
||||
glEnd();
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// draw radar
|
||||
if(state == GAME && stateTimer > 1.0)
|
||||
{
|
||||
float alpha = (stateTimer - 1.0);
|
||||
if(alpha > 1.0) alpha = 1.0;
|
||||
drawRadar(width, height, alpha);
|
||||
}
|
||||
|
||||
// draw fps counter
|
||||
if(showFps)
|
||||
{
|
||||
glPushMatrix();
|
||||
glTranslatef(width - 10.0, 0.0, 0.0);
|
||||
Font::getInstance().printf(" fps: %d\nrate: %d",
|
||||
(int)fps, (int)updateRate);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// Draw end game statistics
|
||||
if(state == FINISHED)
|
||||
drawStatistics(width,height);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void Game::drawRadar(float width, float height, float alpha)
|
||||
{
|
||||
(void)height;
|
||||
|
||||
// draw radar
|
||||
glPushMatrix();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
const float maxHeight = 10.0;
|
||||
glTranslatef(width/6.0, 4.5, 0.0);
|
||||
glScalef((2.0/3.0 * width) / level.getWidth(), -4.0 / maxHeight, 1.0);
|
||||
|
||||
glColor4f(0.3, 0.3, 0.3, alpha);
|
||||
glBegin(GL_TRIANGLE_STRIP); // gray background
|
||||
glVertex2f(0.0, 0.0);
|
||||
glVertex2f(level.getWidth(), 0.0);
|
||||
glVertex2f(0.0, maxHeight);
|
||||
glVertex2f(level.getWidth(), maxHeight);
|
||||
glEnd();
|
||||
|
||||
glColor4f(1.0, 1.0, 1.0, alpha); // white frame
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2f(0.0, 0.0);
|
||||
glVertex2f(level.getWidth(), 0.0);
|
||||
glVertex2f(level.getWidth(), maxHeight);
|
||||
glVertex2f(0.0, maxHeight);
|
||||
glEnd();
|
||||
|
||||
level.drawRadar();
|
||||
|
||||
glPointSize(5.0);
|
||||
glBegin(GL_POINTS);
|
||||
for(int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
if(!players[i].isActive()) continue;
|
||||
|
||||
float x = players[i].getCraft().getX();
|
||||
float y = players[i].getCraft().getY();
|
||||
if(x>0 && x<level.getWidth() && y>0 && y<maxHeight) {
|
||||
players[i].bindColor(alpha);
|
||||
glVertex2fv(players[i].getCraft().getPos().getData());
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glPopMatrix();
|
||||
|
||||
glColor4f(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
void Game::drawStatistics(float width, float height)
|
||||
{
|
||||
glPushMatrix();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
float boxw = width * (2.0/3.0);
|
||||
float boxh = height * (2.0/3.0);
|
||||
|
||||
glTranslatef(width/2.0-boxw/2.0, height/2.0-boxh/2.0, 0.0);
|
||||
|
||||
glColor4f(0.3, 0.3, 0.3, 0.5);
|
||||
glBegin(GL_TRIANGLE_STRIP); // gray background
|
||||
glVertex2f(0.0, 0.0);
|
||||
glVertex2f(boxw, 0.0);
|
||||
glVertex2f(0.0, boxh);
|
||||
glVertex2f(boxw, boxh);
|
||||
glEnd();
|
||||
|
||||
glColor4f(1.0, 1.0, 1.0, 0.5); // white frame
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2f(0.0, 0.0);
|
||||
glVertex2f(boxw, 0.0);
|
||||
glVertex2f(boxw, boxh);
|
||||
glVertex2f(0.0, boxh);
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
Font &font = Font::getInstance();
|
||||
glColor4f(1,1,1,1);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(boxw/2-9,1,0);
|
||||
|
||||
glScalef(2,2,1);
|
||||
font.drawString("Kilpa ohi");
|
||||
glPopMatrix();
|
||||
|
||||
glTranslatef(10,8,0);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(0,1.5);
|
||||
glVertex2f(boxw-12,1.5);
|
||||
glVertex2f(38,0);
|
||||
glVertex2f(38,boxh-10);
|
||||
glEnd();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
font.drawString("Pelaaja");
|
||||
glTranslatef(40,0,0);
|
||||
font.drawString("Aika");
|
||||
glTranslatef(-40,4,0);
|
||||
|
||||
for(int p=0;p<MAX_PLAYERS;p++) {
|
||||
if(playerFinishTime[p].plr!=-1) {
|
||||
font.drawString(getPlayer(playerFinishTime[p].plr).getName());
|
||||
glTranslatef(40,0,0);
|
||||
font.printf("%.3f sek.",playerFinishTime[p].time);
|
||||
glTranslatef(-40,2,0);
|
||||
}
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glColor4f(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
Player &Game::getPlayer(int n)
|
||||
{
|
||||
return players[n];
|
||||
}
|
||||
|
||||
void Game::resetListener()
|
||||
{
|
||||
listenerWeight = 0.0;
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
listenerPos[i] = 0.0;
|
||||
listenerVel[i] = 0.0;
|
||||
listenerOri[i] = 0.0;
|
||||
listenerOri[i + 3] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::updateListener()
|
||||
{
|
||||
// Division by zero sanity check
|
||||
if(listenerWeight == 0.0) return;
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
listenerPos[i] /= listenerWeight;
|
||||
listenerVel[i] /= listenerWeight;
|
||||
listenerOri[i] /= listenerWeight;
|
||||
listenerOri[i + 3] /= listenerWeight;
|
||||
}
|
||||
|
||||
// Update OpenAL listener
|
||||
alListenerfv(AL_POSITION, listenerPos);
|
||||
alListenerfv(AL_VELOCITY, listenerVel);
|
||||
alListenerfv(AL_ORIENTATION, listenerOri);
|
||||
}
|
||||
|
||||
ALuint Game::getSource()
|
||||
{
|
||||
for(int i = 0; i < GLOBAL_SOURCES; i++)
|
||||
{
|
||||
ALint state;
|
||||
alGetSourcei(globalSources[i], AL_SOURCE_STATE, &state);
|
||||
if(state != AL_PLAYING) return globalSources[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
104
src/game.h
Normal file
104
src/game.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#ifndef _GAME_H_
|
||||
#define _GAME_H_
|
||||
|
||||
class Craft;
|
||||
class Level;
|
||||
|
||||
struct PlayerStat {
|
||||
int plr;
|
||||
float time;
|
||||
};
|
||||
|
||||
class Game {
|
||||
public:
|
||||
~Game();
|
||||
|
||||
static const int MAX_PLAYERS = 8;
|
||||
static const int MAX_LOCAL_PLAYERS = 4;
|
||||
static const int MAX_VIEWPORTS = MAX_LOCAL_PLAYERS;
|
||||
static const int NUM_CONTROLS = Craft::NUM_CONTROLS;
|
||||
|
||||
static const int MAX_FPS = 100;
|
||||
static const int MIN_FPS = 40;
|
||||
static const unsigned int MIN_FRAME_TIME = 1000 / MAX_FPS;
|
||||
static const unsigned int MAX_FRAME_TIME = 1000 / MIN_FPS;
|
||||
static const bool FRAMESKIP = false;
|
||||
static const bool FRAME_LIMITER = false;
|
||||
|
||||
static const char *PLAYER_TEXTURES[MAX_PLAYERS];
|
||||
static const float PLAYER_COLORS[MAX_PLAYERS][3];
|
||||
static const int CONTROLS[MAX_LOCAL_PLAYERS][NUM_CONTROLS];
|
||||
|
||||
int init();
|
||||
|
||||
int gameLoop();
|
||||
|
||||
Level &getLevel();
|
||||
static Game &getInstance();
|
||||
|
||||
void initViewports(int num);
|
||||
|
||||
Player &getPlayer(int n);
|
||||
|
||||
ALuint getSource();
|
||||
|
||||
private:
|
||||
static const int GLOBAL_SOURCES = 8;
|
||||
|
||||
Game();
|
||||
|
||||
void drawFrame();
|
||||
void drawViewport(int current, const GLint *viewport);
|
||||
void draw2d();
|
||||
void draw3d(const float *eye, const float *at, float fovDiag);
|
||||
void drawHud();
|
||||
void drawRadar(float width, float height, float alpha = 1.0);
|
||||
void drawStatistics(float width, float height);
|
||||
|
||||
bool updateControls(int keysym, bool down);
|
||||
void updateWorld(float t);
|
||||
|
||||
void resetListener();
|
||||
void updateListener();
|
||||
|
||||
Player players[MAX_PLAYERS];
|
||||
Level level;
|
||||
|
||||
m3dTexture playerTex[MAX_PLAYERS];
|
||||
|
||||
PlayerStat playerFinishTime[MAX_PLAYERS];
|
||||
|
||||
GLint viewports[MAX_VIEWPORTS][4];
|
||||
int numViewports;
|
||||
|
||||
GLint masterViewport[4];
|
||||
int screenWidth, screenHeight;
|
||||
|
||||
bool showFps;
|
||||
float fps, updateRate;
|
||||
|
||||
ALuint playerSources[MAX_PLAYERS];
|
||||
ALuint globalSources[GLOBAL_SOURCES];
|
||||
|
||||
float listenerWeight;
|
||||
float listenerPos[3];
|
||||
float listenerVel[3];
|
||||
float listenerOri[6];
|
||||
|
||||
bool enable3d, enable2d;
|
||||
static Game instance;
|
||||
|
||||
int activeplayers;
|
||||
|
||||
enum {WAITFORSTART,START,GAME,FINISHED} state;
|
||||
float stateTimer;
|
||||
int stateVal;
|
||||
|
||||
Background backg;
|
||||
|
||||
static GLuint signal,signalred,signalgreen;
|
||||
static ALuint signalredbuffer,signalgreenbuffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
264
src/level.cpp
Normal file
264
src/level.cpp
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
#include "SDL_opengl.h"
|
||||
#include <AL/al.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "antigrav.h"
|
||||
|
||||
const float Level::VERTEX_DIST = Terrain::VERTEX_DIST;
|
||||
|
||||
Level::Level()
|
||||
{
|
||||
for(int i = 0; i < MAX_VERTICES; i++) vertices[i] = Vector2(i * VERTEX_DIST, 0.0);
|
||||
|
||||
for(int i = 5; i < MAX_VERTICES - 5; i++)
|
||||
{
|
||||
vertices[i] = Vector2(i * VERTEX_DIST, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
void Level::draw3d(const float *eye, const float *at, float fovDiag)
|
||||
{
|
||||
glPushMatrix();
|
||||
glTranslatef(0.0, 0.0, -(float)ZERO_DEPTH/2.0);
|
||||
terrain.drawLists(eye, at, fovDiag, -(float)ZERO_DEPTH/2.0);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
terrain.drawRoad(ZERO_DEPTH);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void Level::draw2d()
|
||||
{
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for(int i = 0; i < MAX_VERTICES; i++) glVertex2fv(vertices[i].getData());
|
||||
glEnd();
|
||||
}
|
||||
|
||||
bool Level::intersect(const Vector2& v1, const Vector2 &v2, Vector2 &point) const
|
||||
{
|
||||
float x1, x2;
|
||||
int min, max;
|
||||
|
||||
x1 = v1.getX();
|
||||
x2 = v2.getX();
|
||||
|
||||
min = (int)(MIN(x1,x2) / VERTEX_DIST) - 1;
|
||||
if(min < 0) min = 0;
|
||||
|
||||
max = (int)(MAX(x1,x2) / VERTEX_DIST) + 2;
|
||||
if(max >= MAX_VERTICES) max = MAX_VERTICES - 1;
|
||||
|
||||
bool isect = false;
|
||||
for(int i = min; i < max; i++)
|
||||
{
|
||||
Vector2 temp;
|
||||
|
||||
if(segmentIsect(v1, v2, vertices[i], vertices[i+1], temp))
|
||||
{
|
||||
if(isect)
|
||||
{
|
||||
if((temp - v1).length() < (point-v1).length()) point = temp;
|
||||
} else
|
||||
{
|
||||
point = temp;
|
||||
}
|
||||
isect = true;
|
||||
}
|
||||
}
|
||||
|
||||
return isect;
|
||||
}
|
||||
|
||||
float Level::getHeight(float x) const
|
||||
{
|
||||
Vector2 point;
|
||||
const Vector2 v1(x, 1000.0);
|
||||
const Vector2 v2(x, -1000.0);
|
||||
|
||||
if(!intersect(v1,v2,point)) return 0.0;
|
||||
return point.getY();
|
||||
}
|
||||
|
||||
bool Level::segmentIsect(float x11, float y11, float x12, float y12, float x21, float y21, float x22, float y22, float *x, float *y)
|
||||
{
|
||||
float s1x, s1y, s2x, s2y, s, t;
|
||||
|
||||
s1x = x12 - x11;
|
||||
s1y = y12 - y11;
|
||||
|
||||
s2x = x22 - x21;
|
||||
s2y = y22 - y21;
|
||||
|
||||
s = (-s1y*(x11-x21) + s1x*(y11-y21))/(-s2x*s1y + s1x*s2y);
|
||||
t = (s2x*(y11-y21) - s2y*(x11-x21))/(-s2x*s1y + s1x*s2y);
|
||||
|
||||
if(s >= 0 && s <= 1 && t >= 0 && t <= 1)
|
||||
{
|
||||
*x = x11 + t * s1x;
|
||||
*y = y11 + t * s1y;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Level::segmentIsect(const Vector2& v11, const Vector2 &v12, const Vector2 &v21, const Vector2 &v22, Vector2 &point)
|
||||
{
|
||||
Vector2 s1, s2;
|
||||
float s, t;
|
||||
|
||||
s1 = v12 - v11;
|
||||
s2 = v22 - v21;
|
||||
|
||||
s = (s1 ^ (v11 - v21)) / (s1 ^ s2);
|
||||
t = (s2 ^ (v11 - v21)) / (s1 ^ s2);
|
||||
|
||||
if(s < 0.0 || s > 1.0 || t < 0.0 || t > 1.0) return false;
|
||||
|
||||
point = v11 + t * s1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int Level::init()
|
||||
{
|
||||
if(terrain.init(MAX_VERTICES, 32) != 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Level::generate(int seed)
|
||||
{
|
||||
Terrain::srandom(seed);
|
||||
generate();
|
||||
}
|
||||
|
||||
void Level::generate()
|
||||
{
|
||||
terrain.generate();
|
||||
terrain.normalize();
|
||||
terrain.descent(30);
|
||||
|
||||
for(int i = 0; i < MAX_VERTICES; i++)
|
||||
{
|
||||
float h = terrain.getHeight(i, ZERO_DEPTH-1);
|
||||
terrain.setHeight(i, ZERO_DEPTH, h);
|
||||
terrain.setHeight(i, ZERO_DEPTH+1, h);
|
||||
}
|
||||
|
||||
terrain.computeNormals();
|
||||
|
||||
for(int i = 0; i < MAX_VERTICES; i++)
|
||||
{
|
||||
vertices[i] = Vector2(i * VERTEX_DIST, terrain.getHeight(i, ZERO_DEPTH) * Terrain::HEIGHT_SCALE);
|
||||
}
|
||||
|
||||
terrain.createLists();
|
||||
}
|
||||
|
||||
bool Level::ellipseSegmentIsect(const Vector2& center, float angle, float major, float minor, const Vector2 &start, const Vector2 &end, Vector2& point, Vector2& normal, Vector2& delta)
|
||||
{
|
||||
Vector2 v1, v2;
|
||||
|
||||
v1 = start - center;
|
||||
v1.rotate(-angle);
|
||||
v1 = Vector2(v1.getX() / major, v1.getY() / minor);
|
||||
|
||||
v2 = end - center;
|
||||
v2.rotate(-angle);
|
||||
v2 = Vector2(v2.getX() / major, v2.getY() / minor);
|
||||
|
||||
Vector2 d = v2 - v1;
|
||||
float ld = d.length();
|
||||
|
||||
float t = (-v1) * d / (ld * ld);
|
||||
|
||||
if(t > 0.0 && t < 1.0)
|
||||
{
|
||||
point = v1 + t * d;
|
||||
if(point.length() > 1.0) return false;
|
||||
|
||||
delta = point;
|
||||
point.normalize();
|
||||
delta = point - delta;
|
||||
} else
|
||||
{
|
||||
if(v1.length() > 1.0 && v2.length() > 1.0) return false;
|
||||
|
||||
float a, b, c, discr;
|
||||
|
||||
a = d * d;
|
||||
b = 2.0 * (v1 * d);
|
||||
c = (v1 * v1) - 1.0;
|
||||
|
||||
discr = b * b - 4.0 * a * c;
|
||||
if(discr < 0.0) return false;
|
||||
|
||||
t = (-b - sqrt(discr)) / (2.0 * a);
|
||||
if(t < 0.0 || t > 1.0) t = (-b + sqrt(discr)) / (2.0 * a);
|
||||
if(t < 0.0 || t > 1.0) return false;
|
||||
|
||||
point = v1 + t * d;
|
||||
|
||||
if(v2.length() < 1.0) delta = (t - 1.0) * d;
|
||||
else delta = t * d;
|
||||
}
|
||||
|
||||
|
||||
// calculate normal
|
||||
normal = -point;
|
||||
|
||||
// transform back to world coordinates
|
||||
point = Vector2(point.getX() * major, point.getY() * minor);
|
||||
point.rotate(angle);
|
||||
point = point + center;
|
||||
|
||||
normal.rotate(angle);
|
||||
|
||||
delta = Vector2(delta.getX() * major, delta.getY() * minor);
|
||||
delta.rotate(angle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Level::ellipseIntersect(const Vector2& center, float angle, float major, float minor, Vector2& point, Vector2& normal, Vector2& delta)
|
||||
{
|
||||
float x1, x2;
|
||||
int min, max;
|
||||
|
||||
x1 = center.getX() - major;
|
||||
x2 = center.getX() + major;
|
||||
|
||||
min = (int)(MIN(x1,x2) / VERTEX_DIST) - 1;
|
||||
if(min < 0) min = 0;
|
||||
|
||||
max = (int)(MAX(x1,x2) / VERTEX_DIST) + 2;
|
||||
if(max >= MAX_VERTICES) max = MAX_VERTICES - 1;
|
||||
|
||||
for(int i = min; i < max; i++)
|
||||
{
|
||||
if(ellipseSegmentIsect(center, angle, major, minor, vertices[i], vertices[i+1], point, normal, delta)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float Level::getWidth()
|
||||
{
|
||||
return MAX_VERTICES * VERTEX_DIST;
|
||||
}
|
||||
|
||||
void Level::drawRadar()
|
||||
{
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
|
||||
for(int i = 0; i < MAX_VERTICES; i++)
|
||||
{
|
||||
glVertex2f(vertices[i].getX(), 0.0);
|
||||
glVertex2f(vertices[i].getX(), vertices[i].getY());
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
43
src/level.h
Normal file
43
src/level.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef _LEVEL_H_
|
||||
#define _LEVEL_H_
|
||||
|
||||
class Level
|
||||
{
|
||||
public:
|
||||
Level();
|
||||
|
||||
int init();
|
||||
|
||||
void generate(int seed);
|
||||
void generate();
|
||||
|
||||
float getWidth();
|
||||
|
||||
void draw3d(const float *eye, const float *at, float fovDiag);
|
||||
void draw2d();
|
||||
|
||||
void drawRadar();
|
||||
|
||||
bool intersect(const Vector2& v1, const Vector2 &v2, Vector2 &point) const;
|
||||
bool ellipseIntersect(const Vector2& center, float angle, float major, float minor, Vector2& point, Vector2& normal, Vector2 &delta);
|
||||
float getHeight(float x) const;
|
||||
|
||||
static Level &getInstance();
|
||||
|
||||
static bool segmentIsect(float x11, float y11, float x12, float y12, float x21, float y21, float x22, float y22, float *x, float *y);
|
||||
static bool segmentIsect(const Vector2& v11, const Vector2 &v12, const Vector2 &v21, const Vector2 &v22, Vector2 &point);
|
||||
|
||||
static bool ellipseSegmentIsect(const Vector2& center, float angle, float major, float minor, const Vector2 &start, const Vector2 &end, Vector2& point, Vector2& normal, Vector2 &delta);
|
||||
|
||||
private:
|
||||
|
||||
static const int ZERO_DEPTH = 24;
|
||||
static const int MAX_VERTICES = 512;
|
||||
static const float VERTEX_DIST;
|
||||
|
||||
Vector2 vertices[MAX_VERTICES];
|
||||
Terrain terrain;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
67
src/m3dmaterial.cpp
Normal file
67
src/m3dmaterial.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#include "SDL_opengl.h"
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "tinyxml.h"
|
||||
#include "m3dmaterial.h"
|
||||
#include "m3dtexture.h"
|
||||
#include "m3dmesh.h"
|
||||
|
||||
/// Create a new material
|
||||
/**
|
||||
Create a new material and make it dull gray
|
||||
*/
|
||||
m3dMaterial::m3dMaterial()
|
||||
{
|
||||
ambient[0] = 0.2;
|
||||
ambient[1] = 0.2;
|
||||
ambient[2] = 0.2;
|
||||
|
||||
diffuse[0] = 0.7;
|
||||
diffuse[1] = 0.7;
|
||||
diffuse[2] = 0.7;
|
||||
|
||||
specular[0] = 1.0;
|
||||
specular[1] = 1.0;
|
||||
specular[2] = 1.0;
|
||||
|
||||
shininess = 0.5;
|
||||
}
|
||||
|
||||
m3dMaterial::~m3dMaterial()
|
||||
{
|
||||
}
|
||||
|
||||
/// Load an object from XML
|
||||
/**
|
||||
@param root the XML element that represents this object
|
||||
@return -1 on failure, 0 on success
|
||||
*/
|
||||
int m3dMaterial::loadFromXML(const TiXmlElement *root)
|
||||
{
|
||||
if(root->QueryFloatAttribute("ambientR", &ambient[0]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("ambientG", &ambient[1]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("ambientB", &ambient[2]) != TIXML_SUCCESS) return -1;
|
||||
|
||||
if(root->QueryFloatAttribute("diffuseR", &diffuse[0]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("diffuseG", &diffuse[1]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("diffuseB", &diffuse[2]) != TIXML_SUCCESS) return -1;
|
||||
|
||||
if(root->QueryFloatAttribute("specularR", &specular[0]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("specularG", &specular[1]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("specularB", &specular[2]) != TIXML_SUCCESS) return -1;
|
||||
|
||||
if(root->QueryFloatAttribute("shininess", &shininess) != TIXML_SUCCESS) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void m3dMaterial::bind()
|
||||
{
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, shininess*128.0f);
|
||||
}
|
||||
|
||||
26
src/m3dmaterial.h
Normal file
26
src/m3dmaterial.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef _M3DMATERIAL_H_
|
||||
#define _M3DMATERIAL_H_
|
||||
|
||||
/// The base for all graphical objects
|
||||
/**
|
||||
|
||||
*/
|
||||
class m3dMaterial
|
||||
{
|
||||
public:
|
||||
m3dMaterial();
|
||||
~m3dMaterial();
|
||||
|
||||
int loadFromXML(const TiXmlElement *root);
|
||||
int saveToXML(TiXmlElement *root);
|
||||
|
||||
void bind();
|
||||
|
||||
protected:
|
||||
float ambient[3];
|
||||
float diffuse[3];
|
||||
float specular[3];
|
||||
float shininess;
|
||||
};
|
||||
|
||||
#endif
|
||||
319
src/m3dmesh.cpp
Normal file
319
src/m3dmesh.cpp
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
#define GL_GLEXT_PROTOTYPES
|
||||
#include "SDL_opengl.h"
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "tinyxml.h"
|
||||
#include "m3dmaterial.h"
|
||||
#include "m3dtexture.h"
|
||||
#include "m3dmesh.h"
|
||||
|
||||
#include "extensions.h"
|
||||
|
||||
/// Create a new empty mesh
|
||||
/**
|
||||
*/
|
||||
m3dMesh::m3dMesh()
|
||||
{
|
||||
verts = NULL;
|
||||
numVerts = 0;
|
||||
faces = NULL;
|
||||
numFaces = 0;
|
||||
materials = NULL;
|
||||
numMaterials = 0;
|
||||
textures = NULL;
|
||||
numTextures = 0;
|
||||
}
|
||||
|
||||
/// Destroy this mesh
|
||||
/**
|
||||
*/
|
||||
m3dMesh::~m3dMesh()
|
||||
{
|
||||
delete[] verts;
|
||||
delete[] faces;
|
||||
delete[] materials;
|
||||
delete[] textures;
|
||||
}
|
||||
|
||||
int m3dMesh::loadFromXML(const TiXmlElement *root)
|
||||
{
|
||||
if(string(root->Value()) != "Mesh")
|
||||
{
|
||||
fprintf(stderr, "Unknown node type: %s (required: %s)\n", root->Value(), "Mesh");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if(readTransformations(root) != 0) return -1;
|
||||
|
||||
if(root->QueryIntAttribute("numVertices", &numVerts) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryIntAttribute("numFaces", &numFaces) != TIXML_SUCCESS) return -1;
|
||||
|
||||
faces = new struct Face[numFaces];
|
||||
verts = new struct Vertex[numVerts];
|
||||
int f = 0, v = 0;
|
||||
|
||||
numMaterials = 0;
|
||||
|
||||
const TiXmlElement *element = root->FirstChildElement();
|
||||
string value;
|
||||
while(element)
|
||||
{
|
||||
value = element->Value();
|
||||
|
||||
if(value == "Vertex")
|
||||
{
|
||||
if(parseVertex(element, &verts[v]) != 0 || v >= numVerts)
|
||||
{
|
||||
fprintf(stderr, "Invalid vertex!\n");
|
||||
delete[] verts;
|
||||
delete[] faces;
|
||||
return -1;
|
||||
}
|
||||
|
||||
v++;
|
||||
} else if(value == "Face")
|
||||
{
|
||||
if(parseFace(element, &faces[f]) != 0 || f >= numFaces)
|
||||
{
|
||||
fprintf(stderr, "Invalid face!\n");
|
||||
delete[] verts;
|
||||
delete[] faces;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(faces[f].material > numMaterials-1) numMaterials = faces[f].material+1;
|
||||
if(faces[f].texture > numTextures-1) numTextures = faces[f].texture+1;
|
||||
f++;
|
||||
}
|
||||
|
||||
element = element->NextSiblingElement();
|
||||
}
|
||||
|
||||
materials = new m3dMaterial[numMaterials];
|
||||
int mat = 0;
|
||||
element = root->FirstChildElement("Material");
|
||||
while(element)
|
||||
{
|
||||
if(mat >= numMaterials)
|
||||
{
|
||||
fprintf(stderr, "Invalid mesh: incorrect number of materials!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
materials[mat].loadFromXML(element);
|
||||
mat++;
|
||||
|
||||
element = element->NextSiblingElement("Material");
|
||||
}
|
||||
|
||||
if(mat != numMaterials)
|
||||
{
|
||||
fprintf(stderr, "Invalid mesh: incorrect number of materials (wanted %d, got %d)!\n", numMaterials, mat);
|
||||
return -1;
|
||||
}
|
||||
|
||||
textures = new m3dTexture[numTextures];
|
||||
mat = 0;
|
||||
|
||||
element = root->FirstChildElement("Texture");
|
||||
while(element)
|
||||
{
|
||||
if(mat >= numTextures)
|
||||
{
|
||||
fprintf(stderr, "Invalid mesh: incorrect number of textures\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
textures[mat].loadFromXML(element);
|
||||
mat++;
|
||||
|
||||
element = element->NextSiblingElement("Texture");
|
||||
}
|
||||
|
||||
|
||||
if(mat != numTextures)
|
||||
{
|
||||
fprintf(stderr, "Invalid mesh: incorrect number of textures (wanted %d, got %d)!\n", numTextures, mat);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::sort(faces, faces+numFaces, FaceSort());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m3dMesh::parseVertex(const TiXmlElement *root, struct Vertex *vert)
|
||||
{
|
||||
if(string(root->Value()) != "Vertex")
|
||||
{
|
||||
fprintf(stderr, "Unknown node type: %s (required: Vertex)\n", root->Value());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(root->QueryFloatAttribute("x", &vert->co[0]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("y", &vert->co[1]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("z", &vert->co[2]) != TIXML_SUCCESS) return -1;
|
||||
|
||||
if(root->QueryFloatAttribute("nx", &vert->no[0]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("ny", &vert->no[1]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("nz", &vert->no[2]) != TIXML_SUCCESS) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m3dMesh::parseFace(const TiXmlElement *root, struct Face *face)
|
||||
{
|
||||
if(string(root->Value()) != "Face")
|
||||
{
|
||||
fprintf(stderr, "Unknown node type: %s (required: Face)\n", root->Value());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(root->QueryIntAttribute("smooth", &face->smooth) != TIXML_SUCCESS) return -1;
|
||||
|
||||
if(root->QueryFloatAttribute("nx", &face->no[0]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("ny", &face->no[1]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("nz", &face->no[2]) != TIXML_SUCCESS) return -1;
|
||||
|
||||
if(root->QueryIntAttribute("material", &face->material) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryIntAttribute("texture", &face->texture) != TIXML_SUCCESS) return -1;
|
||||
|
||||
const TiXmlElement *element = root->FirstChildElement("Vertex");
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
if(element == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(element->QueryIntAttribute("index", &face->verts[i]) != TIXML_SUCCESS) return -1;
|
||||
if(element->QueryFloatAttribute("u", &face->uv[i][0]) == TIXML_WRONG_TYPE) return -1;
|
||||
if(element->QueryFloatAttribute("v", &face->uv[i][1]) == TIXML_WRONG_TYPE) return -1;
|
||||
|
||||
element = element->NextSiblingElement("Vertex");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m3dMesh::loadFromXML(const char *filename)
|
||||
{
|
||||
TiXmlDocument doc;
|
||||
if(!doc.LoadFile(filename)) return -1;
|
||||
return loadFromXML(doc.RootElement());
|
||||
}
|
||||
|
||||
const m3dTexture &m3dMesh::getTexture(int n) const
|
||||
{
|
||||
return textures[n];
|
||||
}
|
||||
|
||||
void m3dMesh::setTexture(int n, const m3dTexture& tex)
|
||||
{
|
||||
textures[n] = tex;
|
||||
}
|
||||
|
||||
/// Draw the mesh
|
||||
/**
|
||||
Draws this mesh. No child objects are rendered, nor child lights are enabled.
|
||||
*/
|
||||
void m3dMesh::draw()
|
||||
{
|
||||
glPushMatrix();
|
||||
// transform();
|
||||
|
||||
int prevTexture;
|
||||
int prevMaterial;
|
||||
int numTexUnits;
|
||||
|
||||
if(faces[0].material != -1)
|
||||
{
|
||||
materials[faces[0].material].bind();
|
||||
}
|
||||
prevMaterial = faces[0].material;
|
||||
|
||||
if(faces[0].texture != -1)
|
||||
{
|
||||
textures[faces[0].texture].bind();
|
||||
numTexUnits = textures[faces[0].texture].getNumTexUnits();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
} else
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
numTexUnits = 0;
|
||||
}
|
||||
prevTexture = faces[0].texture;
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for(int i = 0; i < numFaces; i++)
|
||||
{
|
||||
struct Face *face;
|
||||
face = &faces[i];
|
||||
|
||||
if(prevMaterial != face->material || prevTexture != face->texture) glEnd();
|
||||
|
||||
if(prevMaterial != face->material)
|
||||
{
|
||||
if(face->material != -1)
|
||||
{
|
||||
materials[face->material].bind();
|
||||
} else
|
||||
{
|
||||
m3dMaterial().bind();
|
||||
}
|
||||
|
||||
prevMaterial = face->material;
|
||||
|
||||
if(prevTexture == face->texture) glBegin(GL_TRIANGLES);
|
||||
}
|
||||
|
||||
if(prevTexture != face->texture)
|
||||
{
|
||||
if(face->texture != -1)
|
||||
{
|
||||
textures[face->texture].bind();
|
||||
numTexUnits = textures[face->texture].getNumTexUnits();
|
||||
if(prevTexture == -1) glEnable(GL_TEXTURE_2D);
|
||||
} else
|
||||
{
|
||||
numTexUnits = 0;
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
prevTexture = face->texture;
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
}
|
||||
|
||||
if(!face->smooth)
|
||||
{
|
||||
glNormal3fv(face->no);
|
||||
}
|
||||
|
||||
for(int j = 0; j < 3; j++)
|
||||
{
|
||||
struct Vertex *vert;
|
||||
vert = &verts[face->verts[j]];
|
||||
|
||||
#ifdef HAVE_MULTITEX
|
||||
for(int t = 0; t < numTexUnits; t++)
|
||||
{
|
||||
mglMultiTexCoord2fv(GL_TEXTURE0_ARB + t, face->uv[j]);
|
||||
}
|
||||
#else
|
||||
glTexCoord2fv(face->uv[j]);
|
||||
#endif
|
||||
|
||||
if(face->smooth) glNormal3fv(vert->no);
|
||||
glVertex3fv(vert->co);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
72
src/m3dmesh.h
Normal file
72
src/m3dmesh.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef _M3DMESH_H_
|
||||
#define _M3DMESH_H_
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
float co[3];
|
||||
float no[3];
|
||||
};
|
||||
|
||||
struct Face
|
||||
{
|
||||
int verts[3];
|
||||
float no[3];
|
||||
float uv[3][2];
|
||||
int texture;
|
||||
int material;
|
||||
int smooth;
|
||||
};
|
||||
|
||||
struct FaceSort
|
||||
{
|
||||
int operator()(const struct Face &face1, const struct Face &face2)
|
||||
{
|
||||
if(face1.texture < face2.texture) return 1;
|
||||
else if(face1.texture > face2.texture) return 0;
|
||||
else return face1.material < face2.material;
|
||||
}
|
||||
};
|
||||
|
||||
class m3dMaterial;
|
||||
|
||||
/// A triangle mesh
|
||||
/**
|
||||
The m3dMesh is a simple class for loading and drawing triangle mesh
|
||||
models.
|
||||
*/
|
||||
class m3dMesh
|
||||
{
|
||||
public:
|
||||
m3dMesh();
|
||||
~m3dMesh();
|
||||
|
||||
int loadFromXML(const TiXmlElement *root);
|
||||
int loadFromXML(const char *filename);
|
||||
|
||||
const m3dTexture &getTexture(int n) const;
|
||||
void setTexture(int n, const m3dTexture &tex);
|
||||
|
||||
void draw();
|
||||
|
||||
private:
|
||||
struct Vertex *verts;
|
||||
struct Face *faces;
|
||||
int numVerts;
|
||||
int numFaces;
|
||||
|
||||
m3dTexture *textures;
|
||||
int numTextures;
|
||||
|
||||
m3dMaterial *materials;
|
||||
int numMaterials;
|
||||
|
||||
int parseVertex(const TiXmlElement *root, struct Vertex *vert);
|
||||
int parseFace(const TiXmlElement *root, struct Face *face);
|
||||
|
||||
void writeVertex(TiXmlElement *root, const struct Vertex *vert);
|
||||
void writeFace(TiXmlElement *root, const struct Face *face);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
491
src/m3dtexture.cpp
Normal file
491
src/m3dtexture.cpp
Normal file
|
|
@ -0,0 +1,491 @@
|
|||
#define GL_GLEXT_PROTOTYPES
|
||||
#include "SDL_opengl.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <png.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "tinyxml.h"
|
||||
#include "m3dmaterial.h"
|
||||
#include "m3dtexture.h"
|
||||
#include "m3dmesh.h"
|
||||
|
||||
#include "extensions.h"
|
||||
|
||||
/// Create a new null object
|
||||
/**
|
||||
Create a new object and reset rotation, scaling and transformation
|
||||
*/
|
||||
m3dTexture::m3dTexture()
|
||||
{
|
||||
texUnits = NULL;
|
||||
numTexUnits = 0;
|
||||
}
|
||||
|
||||
m3dTexture::~m3dTexture()
|
||||
{
|
||||
// for(int i = 0; i < numTexUnits; i++)
|
||||
// {
|
||||
// glDeleteTextures(1, &texUnits[i].handle);
|
||||
// }
|
||||
|
||||
delete[] texUnits;
|
||||
}
|
||||
|
||||
int m3dTexture::loadFromXML(const TiXmlElement *root)
|
||||
{
|
||||
// for(int i = 0; i < numTexUnits; i++)
|
||||
// {
|
||||
// glDeleteTextures(1, &texUnits[i].handle);
|
||||
// }
|
||||
|
||||
delete[] texUnits;
|
||||
|
||||
if(string(root->Value()) != "Texture")
|
||||
{
|
||||
fprintf(stderr, "Unknown node type: %s (required: %s)\n", root->Value(), "Texture");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(root->QueryIntAttribute("units", &numTexUnits) != TIXML_SUCCESS) return -1;
|
||||
|
||||
int maxTexUnits;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTexUnits);
|
||||
if(numTexUnits > maxTexUnits) numTexUnits = maxTexUnits;
|
||||
|
||||
texUnits = new struct TextureUnit[numTexUnits];
|
||||
|
||||
int n = 0;
|
||||
const TiXmlElement *element = root->FirstChildElement();
|
||||
const char *attr;
|
||||
string value;
|
||||
while(element)
|
||||
{
|
||||
value = element->Value();
|
||||
|
||||
if(value == "Image")
|
||||
{
|
||||
if(n >= numTexUnits)
|
||||
{
|
||||
fprintf(stderr, "Invalid: too many texture units!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
attr = element->Attribute("filename");
|
||||
if(attr == NULL)
|
||||
{
|
||||
fprintf(stderr, "Invalid: texture unit without filename!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
texUnits[n].filename = string(attr);
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
element = element->NextSiblingElement();
|
||||
}
|
||||
|
||||
if(n != numTexUnits)
|
||||
{
|
||||
fprintf(stderr, "Invalid texture: incorrect number of texture units (wanted %d, got %d)!\n", numTexUnits, n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(n = 0; n < numTexUnits; n++)
|
||||
{
|
||||
unsigned char *data = NULL;
|
||||
|
||||
glGenTextures(1, &(texUnits[n].handle));
|
||||
// ERROR CHECK!
|
||||
|
||||
if(loadPNG(texUnits[n].filename.c_str(), &data, &(texUnits[n].width), &(texUnits[n].height)) != 0)
|
||||
{
|
||||
fprintf(stderr, "Invalid: can't load texture %s\n", texUnits[n].filename.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texUnits[n].handle);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texUnits[n].width, texUnits[n].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// Advanced texture parameters here (anisotropy, mipmapping, different filters, etc)
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m3dTexture::load(const char *filename)
|
||||
{
|
||||
return load(1, &filename);
|
||||
}
|
||||
|
||||
int m3dTexture::load(int num, const char *filenames[])
|
||||
{
|
||||
/* for(int i = 0; i < numTexUnits; i++)
|
||||
{
|
||||
glDeleteTextures(1, &texUnits[i].handle);
|
||||
}*/
|
||||
|
||||
delete[] texUnits;
|
||||
|
||||
numTexUnits = num;
|
||||
texUnits = new struct TextureUnit[numTexUnits];
|
||||
|
||||
for(int n = 0; n < numTexUnits; n++)
|
||||
{
|
||||
texUnits[n].filename = std::string(filenames[n]);
|
||||
|
||||
unsigned char *data = NULL;
|
||||
|
||||
glGenTextures(1, &(texUnits[n].handle));
|
||||
// ERROR CHECK!
|
||||
|
||||
if(loadPNG(texUnits[n].filename.c_str(), &data, &(texUnits[n].width), &(texUnits[n].height)) != 0)
|
||||
{
|
||||
fprintf(stderr, "Invalid: can't load texture %s\n", texUnits[n].filename.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texUnits[n].handle);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texUnits[n].width, texUnits[n].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// Advanced texture parameters here (anisotropy, mipmapping, different filters, etc)
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void m3dTexture::bind() const
|
||||
{
|
||||
if(numTexUnits < 1) return;
|
||||
|
||||
#ifdef HAVE_MULTITEX
|
||||
for(int i = 0; i < numTexUnits; i++)
|
||||
{
|
||||
mglActiveTextureARB(GL_TEXTURE0_ARB + i);
|
||||
// glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texUnits[i].handle);
|
||||
}
|
||||
#else
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texUnits[0].handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
int m3dTexture::getNumTexUnits() const
|
||||
{
|
||||
return numTexUnits;
|
||||
}
|
||||
|
||||
void m3dTexture::pngReadCallbackSTDIO(png_structp pngPtr, png_bytep data, png_size_t length)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = (FILE*) png_get_io_ptr(pngPtr);
|
||||
fread(data, length, 1, f);
|
||||
}
|
||||
|
||||
/// Load a PNG image from a file
|
||||
/**
|
||||
Only 32-bit RGBA images supported
|
||||
|
||||
@param filename the filename to load from
|
||||
@param data a pointer to an uninitialized data area where the image data will be stored
|
||||
@param width a pointer where to store the image width
|
||||
@param height a pointer where to store the image width
|
||||
@return 0 on success, -1 on failure
|
||||
*/
|
||||
int m3dTexture::loadPNG(const char *filename, unsigned char **data, unsigned int *width, unsigned int *height)
|
||||
{
|
||||
FILE *f;
|
||||
int result;
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
if(f == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open file %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = loadPNG(data, width, height, f, m3dTexture::pngReadCallbackSTDIO);
|
||||
fclose(f);
|
||||
return result;
|
||||
}
|
||||
|
||||
int m3dTexture::loadPNG(unsigned char **data, unsigned int *width, unsigned int *height, void *handle, void (*pngReadCallback)(png_structp ctx, png_bytep area, png_size_t size))
|
||||
{
|
||||
png_structp pngPtr;
|
||||
png_infop pngInfoPtr;
|
||||
int bitDepth, colorType, interlaceType;
|
||||
// unsigned char header[4];
|
||||
volatile int ckey = -1;
|
||||
png_color_16 *transv;
|
||||
png_bytep *rowPointers;
|
||||
unsigned int row;
|
||||
|
||||
pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if(!pngPtr)
|
||||
{
|
||||
*data = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pngInfoPtr = png_create_info_struct(pngPtr);
|
||||
if(!pngInfoPtr)
|
||||
{
|
||||
png_destroy_read_struct(&pngPtr, NULL, NULL);
|
||||
*data = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(setjmp(pngPtr->jmpbuf))
|
||||
{
|
||||
perror("setjmp");
|
||||
png_destroy_read_struct(&pngPtr, &pngInfoPtr, NULL);
|
||||
*data = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
png_set_read_fn(pngPtr, handle, pngReadCallback);
|
||||
|
||||
png_read_info(pngPtr, pngInfoPtr);
|
||||
png_get_IHDR(pngPtr, pngInfoPtr, (png_uint_32*)width, (png_uint_32*)height, &bitDepth, &colorType, &interlaceType, NULL, NULL);
|
||||
|
||||
png_set_strip_16(pngPtr);
|
||||
|
||||
png_set_packing(pngPtr);
|
||||
|
||||
if(png_get_valid(pngPtr, pngInfoPtr, PNG_INFO_tRNS))
|
||||
{
|
||||
int num_trans;
|
||||
unsigned char *trans;
|
||||
png_get_tRNS(pngPtr, pngInfoPtr, &trans, &num_trans, &transv);
|
||||
ckey = 0;
|
||||
}
|
||||
|
||||
if(colorType != PNG_COLOR_TYPE_RGB_ALPHA || bitDepth != 8 || pngInfoPtr->channels != 4)
|
||||
{
|
||||
fprintf(stderr, "Only 32-bit RGBA png images are supported\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
png_read_update_info(pngPtr, pngInfoPtr);
|
||||
png_get_IHDR(pngPtr, pngInfoPtr, (png_uint_32*)width, (png_uint_32*)height, &bitDepth, &colorType, &interlaceType, NULL, NULL);
|
||||
|
||||
(*data) = new unsigned char[(*width) * (*height) * pngInfoPtr->channels];
|
||||
if((*data) == NULL)
|
||||
{
|
||||
fprintf(stderr, "loadPng(): Out of memory !\n");
|
||||
png_destroy_read_struct(&pngPtr, &pngInfoPtr, NULL);
|
||||
*data = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rowPointers = new png_bytep[*height];
|
||||
if(!rowPointers)
|
||||
{
|
||||
perror("malloc");
|
||||
png_destroy_read_struct(&pngPtr, &pngInfoPtr, NULL);
|
||||
delete[] (*data);
|
||||
*data = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(row = 0; (unsigned int) row < (*height); row++)
|
||||
{
|
||||
rowPointers[row] = (png_bytep)*data + (row * (*width) * pngInfoPtr->channels);
|
||||
}
|
||||
png_read_image(pngPtr, rowPointers);
|
||||
png_read_end(pngPtr, pngInfoPtr);
|
||||
|
||||
png_destroy_read_struct(&pngPtr, &pngInfoPtr, NULL);
|
||||
delete[] rowPointers;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m3dTexture::savePNG(const char *filename, const unsigned char *data, unsigned int width, unsigned int height)
|
||||
{
|
||||
FILE *f;
|
||||
int result;
|
||||
|
||||
f = fopen(filename, "wb");
|
||||
if(f == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open %s for writing!\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = savePNG(data, width, height, (void*)f, m3dTexture::pngWriteCallbackSTDIO, m3dTexture::pngFlushCallbackSTDIO);
|
||||
fclose(f);
|
||||
return result;
|
||||
}
|
||||
|
||||
void m3dTexture::pngWriteCallbackSTDIO(png_structp pngPtr, png_bytep data, png_size_t length)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = (FILE*) png_get_io_ptr(pngPtr);
|
||||
fwrite(data, length, 1, f);
|
||||
}
|
||||
|
||||
void m3dTexture::pngFlushCallbackSTDIO(png_structp pngPtr)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = (FILE*) png_get_io_ptr(pngPtr);
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
int m3dTexture::savePNG(const unsigned char *data, unsigned int width, unsigned int height, void *handle, void (*pngWriteCallback)(png_structp pngPtr, png_bytep data, png_size_t length), void (*pngFlushCallback)(png_structp pngPtr))
|
||||
{
|
||||
png_structp pngPtr;
|
||||
png_infop pngInfoPtr;
|
||||
png_bytep *rowPointers;
|
||||
int i;
|
||||
|
||||
pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
pngInfoPtr = png_create_info_struct(pngPtr);
|
||||
png_set_write_fn(pngPtr, handle, pngWriteCallback, pngFlushCallback);
|
||||
|
||||
pngInfoPtr->width = width;
|
||||
pngInfoPtr->height = height;
|
||||
pngInfoPtr->rowbytes = width * 4;
|
||||
pngInfoPtr->bit_depth = 8;
|
||||
pngInfoPtr->interlace_type = 0;
|
||||
pngInfoPtr->num_palette = 0;
|
||||
pngInfoPtr->valid = 0;
|
||||
|
||||
pngInfoPtr->sig_bit.red = 8;
|
||||
pngInfoPtr->sig_bit.green = 8;
|
||||
pngInfoPtr->sig_bit.blue = 8;
|
||||
pngInfoPtr->sig_bit.alpha = 8;
|
||||
|
||||
pngInfoPtr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
|
||||
png_write_info(pngPtr, pngInfoPtr);
|
||||
|
||||
rowPointers = new png_bytep[pngInfoPtr->height];
|
||||
|
||||
for(i = 0; (unsigned int) i < pngInfoPtr->height; i++)
|
||||
{
|
||||
rowPointers[i] = (unsigned char*)data + i * width * 4;
|
||||
}
|
||||
|
||||
png_write_image(pngPtr, rowPointers);
|
||||
png_write_end(pngPtr, pngInfoPtr);
|
||||
delete rowPointers;
|
||||
png_destroy_write_struct(&pngPtr, &pngInfoPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m3dTexture::screenshot(const char *filename)
|
||||
{
|
||||
unsigned char *data;
|
||||
unsigned int width, height;
|
||||
unsigned char *ptr1, *ptr2;
|
||||
unsigned int i, j;
|
||||
|
||||
unsigned char temp;
|
||||
GLint viewport[4];
|
||||
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
width = viewport[2];
|
||||
height = viewport[3];
|
||||
data = new unsigned char[width * height * 4];
|
||||
if(data == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
glReadBuffer(GL_COLOR_BUFFER_BIT);
|
||||
glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3], GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
ptr1 = data;
|
||||
for(i = 0; i < height/2; i++)
|
||||
{
|
||||
ptr2 = data + (height - i - 1) * width * 4;
|
||||
for(j = 0 ; j < width * 4; j++)
|
||||
{
|
||||
temp = *ptr1;
|
||||
*ptr1++ = *ptr2;
|
||||
*ptr2++ = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if(savePNG(filename, data, width, height) != 0)
|
||||
{
|
||||
delete data;
|
||||
return -1;
|
||||
}
|
||||
|
||||
delete data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
GLuint m3dTexture::loadTexture(const char *filename)
|
||||
{
|
||||
unsigned char *data;
|
||||
unsigned int width, height;
|
||||
GLuint tex;
|
||||
|
||||
glGenTextures(1, &tex);
|
||||
|
||||
if(m3dTexture::loadPNG(filename, &data, &width, &height) != 0)
|
||||
{
|
||||
fprintf(stderr, "Can't load texture %s\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
delete[] data;
|
||||
|
||||
if(glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
m3dTexture &m3dTexture::operator=(const m3dTexture &t)
|
||||
{
|
||||
if(&t == this) return *this;
|
||||
|
||||
// for(int i = 0; i < numTexUnits; i++)
|
||||
// {
|
||||
// glDeleteTextures(1, &texUnits[i].handle);
|
||||
// }
|
||||
|
||||
if(t.getNumTexUnits() != numTexUnits || texUnits == NULL)
|
||||
{
|
||||
delete[] texUnits;
|
||||
texUnits = new struct TextureUnit[t.getNumTexUnits()];
|
||||
}
|
||||
|
||||
numTexUnits = t.getNumTexUnits();
|
||||
|
||||
for(int i = 0; i < numTexUnits; i++)
|
||||
{
|
||||
// texUnits[i].filename = t.texUnits[i].filename;
|
||||
texUnits[i].handle = t.texUnits[i].handle;
|
||||
texUnits[i].width = t.texUnits[i].width;
|
||||
texUnits[i].height = t.texUnits[i].height;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
55
src/m3dtexture.h
Normal file
55
src/m3dtexture.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef _M3DTEXTURE_H_
|
||||
#define _M3DTEXTURE_H_
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <string>
|
||||
#include <png.h>
|
||||
|
||||
struct TextureUnit
|
||||
{
|
||||
std::string filename;
|
||||
GLuint handle;
|
||||
unsigned int width, height;
|
||||
};
|
||||
|
||||
/// A texture
|
||||
/**
|
||||
@todo All the actual texture stuff
|
||||
*/
|
||||
class m3dTexture
|
||||
{
|
||||
public:
|
||||
m3dTexture();
|
||||
~m3dTexture();
|
||||
|
||||
#ifdef TINYXML_INCLUDED
|
||||
int loadFromXML(const TiXmlElement *root);
|
||||
#endif
|
||||
|
||||
int load(const char *filename);
|
||||
int load(int num, const char *filenames[]);
|
||||
|
||||
void bind() const;
|
||||
int getNumTexUnits() const;
|
||||
|
||||
m3dTexture &operator=(const m3dTexture &t);
|
||||
|
||||
static int loadPNG(const char *filename, unsigned char **data, unsigned int *width, unsigned int *height);
|
||||
static int savePNG(const char *filename, const unsigned char *data, unsigned int width, unsigned int height);
|
||||
static int screenshot(const char *filename);
|
||||
|
||||
static GLuint loadTexture(const char *filename);
|
||||
|
||||
private:
|
||||
struct TextureUnit *texUnits;
|
||||
int numTexUnits;
|
||||
|
||||
static void pngReadCallbackSTDIO(png_structp pngPtr, png_bytep data, png_size_t length);
|
||||
static void pngWriteCallbackSTDIO(png_structp pngPtr, png_bytep data, png_size_t length);
|
||||
static void pngFlushCallbackSTDIO(png_structp pngPtr);
|
||||
|
||||
static int loadPNG(unsigned char **data, unsigned int *width, unsigned int *height, void *handle, void (*pngReadCallback)(png_structp ctx, png_bytep area, png_size_t size));
|
||||
static int savePNG(const unsigned char *data, unsigned int width, unsigned int height, void *handle, void (*pngWriteCallback)(png_structp pngPtr, png_bytep data, png_size_t length), void (*pngFlushCallback)(png_structp pngPtr));
|
||||
};
|
||||
|
||||
#endif
|
||||
227
src/main.cpp
Normal file
227
src/main.cpp
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_opengl.h"
|
||||
#include <AL/alut.h>
|
||||
#include <AL/al.h>
|
||||
#include <unistd.h>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include "antigrav.h"
|
||||
#include "extensions.h"
|
||||
|
||||
void mainLoop(void);
|
||||
|
||||
#ifdef HAVE_MULTITEX
|
||||
MFNGLMULTITEXCOORD2FVPROC mglMultiTexCoord2fv = NULL;
|
||||
MFNGLACTIVETEXTUREARBPROC mglActiveTextureARB = NULL;
|
||||
#endif
|
||||
|
||||
bool opt_fullscreen = true;
|
||||
bool opt_fsaa = false;
|
||||
int opt_width = 1024;
|
||||
const char *help_msg =
|
||||
"Usage: antigrav [options]\n\
|
||||
Options:\n\
|
||||
-h, --help\t\tprint this help, then exit\n\
|
||||
-f, --fsaa\t\tenable full screen antialiasing\n\
|
||||
-w, --windowed\trun in windowed mode\n\
|
||||
-r, --resolution=RES\tset resolution to RES, 1024 for 1024x768, 800 for 800x600, etc\n";
|
||||
|
||||
int parse_args(int argc, char *argv[])
|
||||
{
|
||||
|
||||
while(true)
|
||||
{
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"fsaa", no_argument, 0, 'f'},
|
||||
{"windowed", no_argument, 0, 'w'},
|
||||
{"resolution", required_argument, 0, 'r'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int c = getopt_long(argc, argv, "hfwr:", long_options, &option_index);
|
||||
if(c == -1)
|
||||
break;
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case 'h':
|
||||
printf(help_msg);
|
||||
return 1;
|
||||
break;
|
||||
case 'f':
|
||||
opt_fsaa = true;
|
||||
break;
|
||||
case 'w':
|
||||
opt_fullscreen = false;
|
||||
break;
|
||||
case 'r':
|
||||
opt_width = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
puts(help_msg);
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
SDL_Quit();
|
||||
alutExit();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SDL_Surface *screen;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
if(parse_args(argc, argv)) return 0;
|
||||
|
||||
atexit(cleanup);
|
||||
|
||||
if(SDL_Init(SDL_INIT_VIDEO) != 0)
|
||||
{
|
||||
fprintf(stderr, "Can't initialize SDL: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
// SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||
// SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
||||
// SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||
// SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
||||
if(opt_fsaa)
|
||||
{
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
|
||||
}
|
||||
|
||||
Uint32 flags = SDL_OPENGL;
|
||||
if(opt_fullscreen) flags |= SDL_FULLSCREEN;
|
||||
|
||||
int width = opt_width;
|
||||
int height = width * 3 / 4;
|
||||
|
||||
screen = SDL_SetVideoMode(width, height, 0, flags);
|
||||
if(screen == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't set video mode: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MULTITEX
|
||||
mglActiveTextureARB = (MFNGLACTIVETEXTUREARBPROC)SDL_GL_GetProcAddress("glActiveTextureARB");
|
||||
mglMultiTexCoord2fv = (MFNGLMULTITEXCOORD2FVPROC)SDL_GL_GetProcAddress("glMultiTexCoord2fv");
|
||||
if(mglActiveTextureARB == NULL || mglMultiTexCoord2fv == NULL)
|
||||
{
|
||||
fprintf(stderr, "Multitexturing extensions not available!\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(alutInit(&argc, argv) != AL_TRUE)
|
||||
{
|
||||
fprintf(stderr, "Can't initialize OpenAL: %s\n", alutGetErrorString(alutGetError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(chdir(DATADIR) != 0)
|
||||
{
|
||||
if(chdir("../data") != 0)
|
||||
{
|
||||
fprintf(stderr, "Can't find data directory in %s or %s\n", DATADIR, "../data");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_WM_SetCaption("antigravitaattori", "antigravitaattori");
|
||||
|
||||
// disable mouse cursor
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
Game &game = Game::getInstance();
|
||||
if(game.init()) return 1;
|
||||
if(Menu::init()) return 1;
|
||||
|
||||
Menu menu;
|
||||
while(1) {
|
||||
if(menu.show())
|
||||
return 0;
|
||||
if(game.gameLoop())
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ALuint loadWavBuffer(const char *filename)
|
||||
{
|
||||
ALuint buffer;
|
||||
alGenBuffers(1, &buffer);
|
||||
if(!alIsBuffer(buffer)) return AL_NONE;
|
||||
|
||||
SDL_AudioSpec wav_spec;
|
||||
Uint8 *wav_buffer;
|
||||
Uint32 wav_length;
|
||||
if(SDL_LoadWAV(filename, &wav_spec, &wav_buffer, &wav_length) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open %s : %s\n", filename, SDL_GetError());
|
||||
return AL_NONE;
|
||||
}
|
||||
|
||||
|
||||
// AL_FORMAT_MONO8, AL_FORMAT_MONO16, AL_FORMAT_STEREO8, and AL_FORMAT_STEREO16.
|
||||
int format;
|
||||
|
||||
if(wav_spec.channels == 1)
|
||||
{
|
||||
if(wav_spec.format == AUDIO_U8) format = AL_FORMAT_MONO8;
|
||||
else if(wav_spec.format == AUDIO_S16SYS) format = AL_FORMAT_MONO16;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Can't open %s : unknown audio format\n", filename);
|
||||
SDL_FreeWAV(wav_buffer);
|
||||
return AL_NONE;
|
||||
}
|
||||
} else if(wav_spec.channels == 2)
|
||||
{
|
||||
if(wav_spec.format == AUDIO_U8) format = AL_FORMAT_STEREO8;
|
||||
else if(wav_spec.format == AUDIO_S16SYS) format = AL_FORMAT_STEREO16;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Can't open %s : unknown audio format\n", filename);
|
||||
SDL_FreeWAV(wav_buffer);
|
||||
return AL_NONE;
|
||||
}
|
||||
} else
|
||||
{
|
||||
fprintf(stderr, "Can't open %s : unknown audio format\n", filename);
|
||||
SDL_FreeWAV(wav_buffer);
|
||||
return AL_NONE;
|
||||
}
|
||||
|
||||
alBufferData(buffer, format, wav_buffer, wav_length, wav_spec.freq);
|
||||
SDL_FreeWAV(wav_buffer);
|
||||
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Can't open %s : OpenAL error\n", filename);
|
||||
return AL_NONE;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
229
src/menu.cpp
Normal file
229
src/menu.cpp
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
#include "SDL.h"
|
||||
#include "SDL_opengl.h"
|
||||
#include <AL/al.h>
|
||||
|
||||
#include "antigrav.h"
|
||||
|
||||
const float Menu::ANIMLEN = 0.25;
|
||||
GLuint Menu::keys[4];
|
||||
|
||||
Menu::Menu()
|
||||
{
|
||||
int vp[4];
|
||||
glGetIntegerv(GL_VIEWPORT, vp);
|
||||
width = vp[2];
|
||||
height = vp[3];
|
||||
}
|
||||
|
||||
int Menu::init()
|
||||
{
|
||||
char name[10];
|
||||
for(int p=0;p<4;p++) {
|
||||
sprintf(name,"keys%d.png",p+1);
|
||||
keys[p] = m3dTexture::loadTexture(name);
|
||||
if(!keys[p])
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Menu::show()
|
||||
{
|
||||
SDL_Event event;
|
||||
int rval=-1;
|
||||
|
||||
Game &game = Game::getInstance();
|
||||
for(int p=0;p<4;p++) {
|
||||
char name[20];
|
||||
sprintf(name,"Pelaaja %d",p+1);
|
||||
game.getPlayer(p).setLocal(true);
|
||||
game.getPlayer(p).setActive(false);
|
||||
game.getPlayer(p).setName(name);
|
||||
game.getPlayer(p+4).setLocal(false);
|
||||
game.getPlayer(p+4).setActive(false);
|
||||
anim[p]=0;
|
||||
}
|
||||
startanim = 0;
|
||||
canstart = false;
|
||||
|
||||
Uint32 startTime = SDL_GetTicks();
|
||||
while(rval==-1) {
|
||||
// Update timer and frame rate
|
||||
Uint32 frameTime = SDL_GetTicks() - startTime;
|
||||
if(frameTime < Game::MIN_FRAME_TIME && Game::FRAME_LIMITER) {
|
||||
SDL_Delay(Game::MIN_FRAME_TIME - frameTime);
|
||||
}
|
||||
frameTime = (SDL_GetTicks() - startTime);
|
||||
float t = (frameTime) / 1000.0f;
|
||||
startTime = SDL_GetTicks();
|
||||
|
||||
for(int p=0;p<4;++p) {
|
||||
bool active = game.getPlayer(p).isActive();
|
||||
if(active && anim[p]<ANIMLEN) {
|
||||
anim[p] += t;
|
||||
if(anim[p]>ANIMLEN) anim[p]=ANIMLEN;
|
||||
} else if(!active && anim[p]>0) {
|
||||
anim[p] -= t;
|
||||
if(anim[p]<0) anim[p]=0;
|
||||
}
|
||||
}
|
||||
if(canstart && startanim < ANIMLEN) {
|
||||
startanim += t;
|
||||
if(startanim>ANIMLEN)
|
||||
startanim=ANIMLEN;
|
||||
} else if(!canstart && startanim > 0) {
|
||||
startanim -= t;
|
||||
if(startanim<0)
|
||||
startanim=0;
|
||||
}
|
||||
|
||||
update();
|
||||
while(SDL_PollEvent(&event)) {
|
||||
if(event.type == SDL_QUIT) rval=1;
|
||||
else if(event.type == SDL_KEYDOWN) {
|
||||
if(event.key.keysym.sym == SDLK_ESCAPE) rval=1;
|
||||
else if(event.key.keysym.sym == SDLK_RETURN) {
|
||||
// Start game if at least one player is active
|
||||
if(canstart)
|
||||
rval=0;
|
||||
} else {
|
||||
// Toggle player activity
|
||||
for(int p=0;p<Game::MAX_LOCAL_PLAYERS;++p) {
|
||||
for(int c=0;c<Game::NUM_CONTROLS;++c) {
|
||||
if(event.key.keysym.sym == game.CONTROLS[p][c]) {
|
||||
togglePlayer(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
void Menu::togglePlayer(int p)
|
||||
{
|
||||
Game &game = Game::getInstance();
|
||||
Player &plr = game.getPlayer(p);
|
||||
plr.setActive(!plr.isActive());
|
||||
int act=0;
|
||||
for(int plr=0;plr<4;plr++) {
|
||||
if(game.getPlayer(plr).isActive())
|
||||
++act;
|
||||
}
|
||||
canstart = act>0;
|
||||
}
|
||||
|
||||
void Menu::drawPlayer(int p)
|
||||
{
|
||||
Player &plr = Game::getInstance().getPlayer(p);
|
||||
|
||||
glViewport((width/2)*(p%2), (height/2)*!(p/2), width/2, height/2);
|
||||
|
||||
// Draw the ship
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(45.0, (GLdouble)width/height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
gluLookAt(1,2,3, 0,0,0, 0,1,0);
|
||||
float scale = anim[p]/ANIMLEN+1;
|
||||
float rot = anim[p]/ANIMLEN*360;
|
||||
glScalef(scale,scale,scale);
|
||||
glRotatef(rot,1,1,0);
|
||||
|
||||
plr.getCraft().getMesh().setTexture(0,plr.getTexture());
|
||||
plr.getCraft().getMesh().draw();
|
||||
|
||||
// Draw keys
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
glOrtho(0.0, width/16.0, height/16.0, 0.0, -1.0, 1.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, keys[p]);
|
||||
glPushMatrix();
|
||||
glTranslatef(((p%2)?((width/16.0)):24)-12.0,
|
||||
((p/2)?(height/16.0):22)-11, 0);
|
||||
glScalef(16,16,1);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glTexCoord2f(0,0);
|
||||
glVertex2f(-0.5,-0.5);
|
||||
glTexCoord2f(1,0);
|
||||
glVertex2f(0.5,-0.5);
|
||||
glTexCoord2f(0,1);
|
||||
glVertex2f(-0.5,0.5);
|
||||
glTexCoord2f(1,1);
|
||||
glVertex2f(0.5,0.5);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
|
||||
// Draw text
|
||||
Font &font = Font::getInstance();
|
||||
glScalef(2.0,2.0,1);
|
||||
glPushMatrix();
|
||||
glTranslatef(((p%2)?(width/32.0)-2:strlen(plr.getName())+2) -
|
||||
strlen(plr.getName()),1,0);
|
||||
font.drawString(plr.getName());
|
||||
|
||||
glPopMatrix();
|
||||
if(anim[p]<ANIMLEN) {
|
||||
glTranslatef((width/32.0)/2.0 - 12/2 , height/32.0-4.0, 0.0);
|
||||
glColor4f(1,1,1,1-anim[p]/ANIMLEN);
|
||||
font.drawString("Paina nappia");
|
||||
}
|
||||
glColor4f(1,1,1,1);
|
||||
}
|
||||
|
||||
void Menu::update()
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
// Draw players
|
||||
for(int p=0;p<4;p++) {
|
||||
drawPlayer(p);
|
||||
}
|
||||
|
||||
// Draw startup text
|
||||
if(startanim>0) {
|
||||
glViewport(0, 0, width, height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0, width/16.0, height/16.0, 0.0, -1.0, 1.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
Font &font = Font::getInstance();
|
||||
glTranslatef((width/16.0)/2.0 - 13/2.0,(height/16.0)/2.0-1,0);
|
||||
glColor4f(1,1,1,startanim/ANIMLEN);
|
||||
font.drawString("Enter aloittaa");
|
||||
glColor4f(1,1,1,1);
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
|
||||
// Draw other stuff
|
||||
SDL_GL_SwapBuffers();
|
||||
}
|
||||
|
||||
24
src/menu.h
Normal file
24
src/menu.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef _MENU_H_
|
||||
#define _MENU_H_
|
||||
|
||||
class Menu {
|
||||
public:
|
||||
Menu();
|
||||
static int init();
|
||||
|
||||
int show();
|
||||
private:
|
||||
void togglePlayer(int p);
|
||||
void drawPlayer(int p);
|
||||
void update();
|
||||
|
||||
int width, height;
|
||||
float anim[4];
|
||||
float startanim;
|
||||
bool canstart;
|
||||
static const float ANIMLEN;
|
||||
static GLuint keys[4];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
277
src/player.cpp
Normal file
277
src/player.cpp
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
#include "SDL_opengl.h"
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include "antigrav.h"
|
||||
|
||||
GLuint Player::gauges;
|
||||
GLuint Player::needle;
|
||||
GLuint Player::fuel;
|
||||
|
||||
ALuint Player::buffer;
|
||||
|
||||
float Player::engineVolume = 1.0;
|
||||
|
||||
Player::Player()
|
||||
: finished(false)
|
||||
{
|
||||
}
|
||||
|
||||
int Player::init()
|
||||
{
|
||||
if(!gauges) {
|
||||
gauges = m3dTexture::loadTexture("gauges.png");
|
||||
if(gauges==0)
|
||||
return -1;
|
||||
}
|
||||
if(!needle) {
|
||||
needle = m3dTexture::loadTexture("needle.png");
|
||||
if(needle==0)
|
||||
return -1;
|
||||
}
|
||||
if(!fuel) {
|
||||
fuel = m3dTexture::loadTexture("fuel.png");
|
||||
if(fuel==0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// <temporary>
|
||||
// buffer = alutCreateBufferWaveform(ALUT_WAVEFORM_SAWTOOTH, 100.0, 0.0, 1.0);
|
||||
// buffer = alutCreateBufferFromFile("hover.wav");
|
||||
buffer = loadWavBuffer("hover.wav");
|
||||
if(buffer == AL_NONE) return -1;
|
||||
// </temporary>
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Player::reset(float craftx, float crafty)
|
||||
{
|
||||
craft.setPos(Vector2(craftx,crafty));
|
||||
craft.setVel(Vector2(0,0));
|
||||
craft.setAngle(0);
|
||||
craft.setOmega(0);
|
||||
finished = false;
|
||||
}
|
||||
|
||||
void Player::setName(const char *n)
|
||||
{
|
||||
strncpy(name,n,sizeof name);
|
||||
}
|
||||
|
||||
void Player::setTexture(m3dTexture *tex)
|
||||
{
|
||||
texture = tex;
|
||||
}
|
||||
|
||||
void Player::setActive(bool a)
|
||||
{
|
||||
active = a;
|
||||
}
|
||||
|
||||
void Player::setLocal(bool l)
|
||||
{
|
||||
local = l;
|
||||
}
|
||||
|
||||
Craft &Player::getCraft() { return craft; }
|
||||
bool Player::isActive() const { return active; }
|
||||
bool Player::isLocal() const { return local; }
|
||||
const char *Player::getName() const { return name; }
|
||||
|
||||
bool Player::isFinished() const { return finished; }
|
||||
|
||||
bool Player::update(float dt)
|
||||
{
|
||||
bool rval = false;
|
||||
craft.update(dt);
|
||||
|
||||
if(craft.getX() >= Terrain::FINISH_LINE * Terrain::VERTEX_DIST && finished==false)
|
||||
{
|
||||
finished = true;
|
||||
rval = true;
|
||||
}
|
||||
|
||||
// update force meter
|
||||
const float maxForceRise = 1.0;
|
||||
const float maxForceFade = 0.5;
|
||||
|
||||
float force = craft.getHoverForce() / 5.0;
|
||||
if(force>1.0) force=1.0;
|
||||
|
||||
if(force > forceMeter)
|
||||
{
|
||||
if(force - forceMeter < maxForceRise * dt) forceMeter = force;
|
||||
else forceMeter += maxForceRise * dt;
|
||||
} else
|
||||
{
|
||||
if(forceMeter - force < maxForceFade * dt) forceMeter = force;
|
||||
else forceMeter -= maxForceFade * dt;
|
||||
}
|
||||
|
||||
|
||||
// update sound source
|
||||
ALint state;
|
||||
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
||||
if(state != AL_PLAYING) alSourcePlay(source);
|
||||
|
||||
float vec[3];
|
||||
|
||||
vec[0] = craft.getX();
|
||||
vec[1] = craft.getY();
|
||||
vec[2] = 0.0;
|
||||
alSourcefv(source, AL_POSITION, vec);
|
||||
|
||||
vec[0] = craft.getVX();
|
||||
vec[1] = craft.getVY();
|
||||
vec[2] = 0.0;
|
||||
alSourcefv(source, AL_VELOCITY, vec);
|
||||
|
||||
const float minGain = 0.5;
|
||||
const float maxGain = 3.0;
|
||||
|
||||
alSourcef(source, AL_GAIN, (minGain + forceMeter * (maxGain - minGain)) * engineVolume);
|
||||
|
||||
const float pitchChange = 1.5;
|
||||
float speed = craft.getSpeed() / 7.0;
|
||||
if(speed > 1.0) speed = 1.0;
|
||||
|
||||
alSourcef(source, AL_PITCH, 1.0 + (speed - 0.5) * pitchChange);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static void drawRect(float width=1.0,float height=1.0)
|
||||
{
|
||||
float w2 = width/2.0;
|
||||
float h2 = height/2.0;
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glTexCoord2f(0.0, 0.0);
|
||||
glVertex2f(-w2, -h2);
|
||||
|
||||
glTexCoord2f(1.0, 0.0);
|
||||
glVertex2f(w2, -h2);
|
||||
|
||||
glTexCoord2f(0.0, 1.0);
|
||||
glVertex2f(-w2, h2);
|
||||
|
||||
glTexCoord2f(1.0, 1.0);
|
||||
glVertex2f(w2, h2);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void Player::drawHud(const GLint *viewport, int activePlayers, int num)
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
float width, height;
|
||||
width = viewport[2] / 8.0;
|
||||
height = width * viewport[3] / viewport[2];
|
||||
glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glColor3f(1,1,1);
|
||||
// Draw gauges
|
||||
if(activePlayers < 3 || (num % 2) != 0)
|
||||
{
|
||||
glTranslatef(width - 20.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
|
||||
glTranslatef(16,8,0);
|
||||
glScalef(15.0, 15.0, 1.0);
|
||||
glBindTexture(GL_TEXTURE_2D, gauges);
|
||||
drawRect(2.0);
|
||||
|
||||
// Draw speed gauge needle
|
||||
glBindTexture(GL_TEXTURE_2D,needle);
|
||||
float speed = craft.getSpeed() / 5.0;
|
||||
if(speed>1.0) speed = 1.0;
|
||||
glPushMatrix();
|
||||
glTranslatef(-0.5,0,0);
|
||||
glScalef(0.8,0.8,1.0);
|
||||
glRotatef((speed - 0.5) * (150.0*2), 0, 0, 1);
|
||||
drawRect();
|
||||
glPopMatrix();
|
||||
|
||||
// Draw force gauge needle
|
||||
glPushMatrix();
|
||||
|
||||
glTranslatef(-0.10,-0.25,0);
|
||||
glScalef(0.4,0.4,1);
|
||||
glRotatef(50 + (forceMeter - 0.5) * (90.0*2), 0, 0, 1);
|
||||
drawRect();
|
||||
glPopMatrix();
|
||||
|
||||
// Draw fuel gauge bars (-55 <-> 100, 22 degree increments)
|
||||
glTranslatef(-0.5,0,0);
|
||||
float bars = -55 + craft.getBoostFuel()*(100+55);
|
||||
if(bars > -55+22) {
|
||||
glBindTexture(GL_TEXTURE_2D,fuel);
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glTexCoord2f(0.25,0.5);
|
||||
glVertex3f(0,0,0);
|
||||
for(float b=-55;b<bars;b+=22) {
|
||||
float c = cos(b / 180.0 * M_PI);
|
||||
float s = sin(b / 180.0 * M_PI);
|
||||
glTexCoord2f(0.25-c/4.0, 0.5-s/2.0);
|
||||
glVertex3f(c/-2.0,s/-2.0,0);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
const m3dTexture &Player::getTexture() const
|
||||
{
|
||||
return *texture;
|
||||
}
|
||||
|
||||
void Player::setColor(float r, float g, float b)
|
||||
{
|
||||
color[0] = r;
|
||||
color[1] = g;
|
||||
color[2] = b;
|
||||
craft.setColor(r,g,b);
|
||||
}
|
||||
|
||||
void Player::setColor(const float *col)
|
||||
{
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
color[i] = col[i];
|
||||
}
|
||||
craft.setColor(col[0],col[1],col[2]);
|
||||
}
|
||||
|
||||
void Player::setSource(ALuint src)
|
||||
{
|
||||
source = src;
|
||||
|
||||
alSourcei(source, AL_LOOPING, AL_TRUE);
|
||||
alSourcei(source, AL_BUFFER, buffer);
|
||||
}
|
||||
|
||||
const float *Player::getColor() const { return color; }
|
||||
void Player::bindColor() const { glColor3fv(color); }
|
||||
|
||||
void Player::bindColor(float alpha) const
|
||||
{
|
||||
glColor4f(color[0], color[1], color[2], alpha);
|
||||
}
|
||||
|
||||
ALuint Player::getSource() const { return source; }
|
||||
|
||||
void Player::setEngineVolume(float vol) { engineVolume = vol; }
|
||||
62
src/player.h
Normal file
62
src/player.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef _PLAYER_H_
|
||||
#define _PLAYER_H_
|
||||
|
||||
class Player
|
||||
{
|
||||
public:
|
||||
Player();
|
||||
|
||||
static int init();
|
||||
|
||||
void reset(float craftx, float crafty);
|
||||
void setName(const char *name);
|
||||
void setTexture(m3dTexture *texture);
|
||||
void setActive(bool active);
|
||||
void setLocal(bool l);
|
||||
|
||||
void setColor(float r, float g, float b);
|
||||
void setColor(const float *col);
|
||||
const float *getColor() const;
|
||||
void bindColor() const;
|
||||
void bindColor(float alpha) const;
|
||||
|
||||
const m3dTexture &getTexture() const;
|
||||
|
||||
Craft &getCraft();
|
||||
|
||||
bool update(float dt);
|
||||
|
||||
bool isActive() const;
|
||||
bool isLocal() const;
|
||||
bool isFinished() const;
|
||||
const char *getName() const;
|
||||
|
||||
void drawHud(const GLint *viewport, int activePlayers, int num);
|
||||
|
||||
void setSource(ALuint src);
|
||||
ALuint getSource() const;
|
||||
|
||||
static void setEngineVolume(float vol);
|
||||
private:
|
||||
char name[20];
|
||||
m3dTexture *texture;
|
||||
float color[3];
|
||||
|
||||
float forceMeter;
|
||||
|
||||
Craft craft;
|
||||
|
||||
bool active;
|
||||
bool local;
|
||||
bool finished;
|
||||
|
||||
static GLuint gauges,needle,fuel;
|
||||
static ALuint buffer;
|
||||
|
||||
static float engineVolume;
|
||||
|
||||
ALuint source;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
112
src/ring.cpp
Normal file
112
src/ring.cpp
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#include "SDL_opengl.h"
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "antigrav.h"
|
||||
|
||||
m3dMesh Ring::mesh;
|
||||
|
||||
const float Ring::MAXLIFE = 1.0;
|
||||
Ring *Ring::rings;
|
||||
int Ring::numRings;
|
||||
|
||||
int Ring::init()
|
||||
{
|
||||
if(mesh.loadFromXML("ring.xml"))
|
||||
return 1;
|
||||
|
||||
rings = new Ring[MAXRINGS];
|
||||
if(!rings)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Ring::Ring()
|
||||
: life(0)
|
||||
{
|
||||
}
|
||||
|
||||
Ring::Ring(float x, float y, float ang, const Vector2& vel, const float col[3])
|
||||
{
|
||||
posx = x;
|
||||
posy = y;
|
||||
velx = vel.getX();
|
||||
vely = vel.getY();
|
||||
life = MAXLIFE;
|
||||
angle = DEG(ang);
|
||||
|
||||
color[0] = col[0];
|
||||
color[1] = col[1];
|
||||
color[2] = col[2];
|
||||
color[3] = 1;
|
||||
}
|
||||
|
||||
void Ring::update(float t)
|
||||
{
|
||||
if(isAlive()) {
|
||||
posx += velx * t;
|
||||
posy += vely * t;
|
||||
life -= t;
|
||||
if(life<0)
|
||||
color[3]=0;
|
||||
else
|
||||
color[3] = life/MAXLIFE;
|
||||
}
|
||||
}
|
||||
|
||||
void Ring::draw()
|
||||
{
|
||||
glPushMatrix();
|
||||
glColor4fv(color);
|
||||
glTranslatef(posx,posy,0);
|
||||
glRotatef(angle,0,0,1);
|
||||
glScalef(7,7,7);
|
||||
mesh.draw();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
bool Ring::isAlive() const
|
||||
{
|
||||
return life>0;
|
||||
}
|
||||
|
||||
void Ring::updateAll(float t)
|
||||
{
|
||||
for(int i=0;i<MAXRINGS;++i) {
|
||||
if(rings[i].isAlive()) {
|
||||
rings[i].update(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Ring::drawAll() {
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_LIGHTING);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
||||
for(int i=0;i<MAXRINGS;++i) {
|
||||
if(rings[i].isAlive()) {
|
||||
rings[i].draw();
|
||||
}
|
||||
}
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_LIGHTING);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void Ring::addRing(const Ring& ring)
|
||||
{
|
||||
for(int i=0;i<MAXRINGS;++i) {
|
||||
if(rings[i].isAlive()==false) {
|
||||
rings[i] = ring;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Ring::resetAll()
|
||||
{
|
||||
for(int i=0;i<MAXRINGS;++i)
|
||||
rings[i] = Ring();
|
||||
}
|
||||
|
||||
34
src/ring.h
Normal file
34
src/ring.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef _RING_H_
|
||||
#define _RING_H_
|
||||
|
||||
class Ring {
|
||||
public:
|
||||
static int init();
|
||||
|
||||
Ring();
|
||||
Ring(float x, float y, float ang, const Vector2& vel, const float col[3]);
|
||||
void update(float t);
|
||||
void draw();
|
||||
bool isAlive() const;
|
||||
|
||||
static void resetAll();
|
||||
static void updateAll(float t);
|
||||
static void drawAll();
|
||||
static void addRing(const Ring& ring);
|
||||
|
||||
private:
|
||||
static m3dMesh mesh;
|
||||
float posx,posy,angle;
|
||||
float velx,vely;
|
||||
float life;
|
||||
float color[4];
|
||||
|
||||
static const float MAXLIFE;
|
||||
static const int MAXRINGS = 100;
|
||||
|
||||
static Ring *rings;
|
||||
static int numRings;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
528
src/terrain.cpp
Normal file
528
src/terrain.cpp
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
#include "SDL.h"
|
||||
#include "SDL_opengl.h"
|
||||
#include <cmath>
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#include "antigrav.h"
|
||||
|
||||
const float Terrain::VERTEX_DIST = 0.5;
|
||||
const float Terrain::HEIGHT_SCALE = 5.0;
|
||||
int Terrain::seed = 1;
|
||||
|
||||
Terrain::Terrain()
|
||||
{
|
||||
width = 0;
|
||||
height = 0;
|
||||
data = NULL;
|
||||
normals = NULL;
|
||||
roadTex = 0;
|
||||
goalTex = 0;
|
||||
roadTex2 = 0;
|
||||
listBase = 0;
|
||||
}
|
||||
|
||||
Terrain::~Terrain()
|
||||
{
|
||||
delete[] normals;
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
int Terrain::init(int w, int h)
|
||||
{
|
||||
if(roadTex == 0) roadTex = m3dTexture::loadTexture("road.png");
|
||||
if(roadTex == 0) return -1;
|
||||
if(goalTex == 0) goalTex = m3dTexture::loadTexture("goal.png");
|
||||
if(goalTex == 0) return -1;
|
||||
if(roadTex2 == 0) roadTex2 = m3dTexture::loadTexture("road2.png");
|
||||
if(roadTex2 == 0) return -1;
|
||||
if(texture == 0) texture = m3dTexture::loadTexture("stone.png");
|
||||
if(texture == 0) return -1;
|
||||
|
||||
if(listBase == 0) listBase = glGenLists(64);
|
||||
if(listBase == 0) return -1;
|
||||
|
||||
if(normals) delete[] normals;
|
||||
if(data) delete[] data;
|
||||
|
||||
if(w <= h)
|
||||
{
|
||||
if(!isPow2(w)) return -1;
|
||||
if(h % w != 0) return -1;
|
||||
} else
|
||||
{
|
||||
if(!isPow2(h)) return -1;
|
||||
if(w % h != 0) return -1;
|
||||
}
|
||||
|
||||
|
||||
data = new float[(w+1) * (h+1)];
|
||||
if(data == NULL) return -1;
|
||||
|
||||
for(int i = 0; i < (w+1)*(h+1); i++) data[i] = 0;
|
||||
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
normals = new float[(w+1) * (h+1) * 3];
|
||||
if(normals == NULL)
|
||||
{
|
||||
delete[] data;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Terrain::getHeight(int x, int y) const
|
||||
{
|
||||
if(data == NULL) return 0.0;
|
||||
if(x < 0 || x > width || y < 0 || y > height) return 0.0;
|
||||
|
||||
return data[(y * (width + 1)) + x];
|
||||
}
|
||||
|
||||
void Terrain::setHeight(int x, int y, float h)
|
||||
{
|
||||
if(x < 0 || x > width || y < 0 || y > height) return;
|
||||
data[y * (width + 1) + x] = h;
|
||||
}
|
||||
|
||||
void Terrain::generate()
|
||||
{
|
||||
float scale, ratio;
|
||||
float avg;
|
||||
int s, i, j;
|
||||
int x, y, dim;
|
||||
int xBlocks, yBlocks;
|
||||
int blockSize;
|
||||
int n;
|
||||
|
||||
if(width <= height)
|
||||
{
|
||||
n = Terrain::log2(width); // log2(min(width,height))
|
||||
xBlocks = 1;
|
||||
yBlocks = (height / width);
|
||||
blockSize = width;
|
||||
} else
|
||||
{
|
||||
n = Terrain::log2(height);
|
||||
yBlocks = 1;
|
||||
xBlocks = (width / height);
|
||||
blockSize = height;
|
||||
}
|
||||
|
||||
// seed the array
|
||||
for(i = 0; i <= yBlocks; i++)
|
||||
{
|
||||
for(j = 0; j <= xBlocks; j++)
|
||||
{
|
||||
setHeight(j * blockSize, i * blockSize, 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// roughness parameters
|
||||
const float h = 0.7;
|
||||
const float heightScale = 3.0;
|
||||
ratio = powf(2.0,-h);
|
||||
scale = heightScale * ratio;
|
||||
|
||||
|
||||
dim = 1 << n;
|
||||
for(s = 0; s < n; s++)
|
||||
{
|
||||
scale *= ratio;
|
||||
// if(s == n-1) scale = 0.0; // interpolate last step
|
||||
|
||||
// diamond step
|
||||
for(i = 0; i < (1 << s) * yBlocks; i++)
|
||||
{
|
||||
for(j = 0; j < (1 << s) * xBlocks; j++)
|
||||
{
|
||||
x = j * dim;
|
||||
y = i * dim;
|
||||
avg = 0;
|
||||
avg += getHeight(x, y);
|
||||
avg += getHeight(x + dim, y);
|
||||
avg += getHeight(x + dim, y + dim);
|
||||
avg += getHeight(x, y + dim);
|
||||
avg /= 4;
|
||||
setHeight(x + (dim >> 1), y + (dim >> 1), avg + scale * (random() - 0.5f));
|
||||
}
|
||||
}
|
||||
|
||||
// square step
|
||||
for(i = 0; i <= (1 << s) * yBlocks; i++)
|
||||
{
|
||||
for(j = 0; j <= (1 << s) * xBlocks; j++)
|
||||
{
|
||||
x = j * dim;
|
||||
y = i * dim;
|
||||
|
||||
if(j < (1 << s) * xBlocks)
|
||||
{
|
||||
avg = 0;
|
||||
avg += getHeight(x, y);
|
||||
avg += getHeight(x + dim, y);
|
||||
avg /= 2.0;
|
||||
setHeight(x + (dim >> 1), y, avg + scale * (random() -0.5f));
|
||||
}
|
||||
|
||||
if(i < (1 << s) * yBlocks)
|
||||
{
|
||||
avg = 0;
|
||||
avg += getHeight(x, y);
|
||||
avg += getHeight(x, y + dim);
|
||||
avg /= 2.0;
|
||||
setHeight(x, y + (dim >> 1), avg + scale * (random() -0.5f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dim >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Terrain::normalize()
|
||||
{
|
||||
float min = 1e10, max = -1e10;
|
||||
int i, j;
|
||||
|
||||
for(i = 0; i <= height; i++)
|
||||
{
|
||||
for(j = 0; j <= width; j++)
|
||||
{
|
||||
float h = getHeight(j ,i);
|
||||
if(h < min) min = h;
|
||||
if(h > max) max = h;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i <= height; i++)
|
||||
{
|
||||
for(j = 0; j <= width; j++)
|
||||
{
|
||||
setHeight(j, i, (getHeight(j ,i) - min) / (max - min));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Terrain::isPow2(int x)
|
||||
{
|
||||
return x && !( (x-1) & x );
|
||||
}
|
||||
|
||||
int Terrain::log2(int x)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
while(x != 0 && !(x & 1))
|
||||
{
|
||||
n++;
|
||||
x >>= 1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void Terrain::srandom(int s)
|
||||
{
|
||||
seed = s;
|
||||
}
|
||||
|
||||
float Terrain::random()
|
||||
{
|
||||
const int a = 48271;
|
||||
const int m = 2147483647;
|
||||
const int q = (m / a);
|
||||
const int r = (m % a);
|
||||
|
||||
int hi = seed / q;
|
||||
int lo = seed % q;
|
||||
int test = a * lo - r * hi;
|
||||
|
||||
if(test > 0) seed = test;
|
||||
else seed = test + m;
|
||||
|
||||
return (float)seed / m;
|
||||
}
|
||||
|
||||
void Terrain::vertex(int x, int y)
|
||||
{
|
||||
glNormal3fv(&normals[(y * (width + 1) + x) * 3]);
|
||||
glVertex3f(x * VERTEX_DIST, getHeight(x, y) * HEIGHT_SCALE, y * VERTEX_DIST);
|
||||
}
|
||||
|
||||
|
||||
void Terrain::draw()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for(i = 0; i < height - 1; i++)
|
||||
{
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
|
||||
for(j = 0; j < width; j++)
|
||||
{
|
||||
vertex(j, i);
|
||||
vertex(j, i+1);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
void Terrain::xproduct(const float *v1, const float *v2, float *result) const
|
||||
{
|
||||
result[0] = v1[1] * v2[2] - v2[1] * v1[2];
|
||||
result[1] = v1[0] * v2[2] - v2[0] * v1[2];
|
||||
result[2] = v1[0] * v2[1] - v2[0] * v1[1];
|
||||
}
|
||||
|
||||
float Terrain::dotproduct(const float *v1 , const float *v2) const
|
||||
{
|
||||
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
||||
}
|
||||
|
||||
void Terrain::vectorsub(const float *v1, const float *v2, float *result) const
|
||||
{
|
||||
result[0] = v1[0] - v2[0];
|
||||
result[1] = v1[1] - v2[1];
|
||||
result[2] = v1[2] - v2[2];
|
||||
|
||||
}
|
||||
void Terrain::vectorsub(float *v1, const float *v2) const
|
||||
{
|
||||
v1[0] -= v2[0];
|
||||
v1[1] -= v2[1];
|
||||
v1[2] -= v2[2];
|
||||
}
|
||||
|
||||
void Terrain::vectoradd(const float *v1, const float *v2, float *result) const
|
||||
{
|
||||
result[0] = v1[0] - v2[0];
|
||||
result[1] = v1[1] - v2[1];
|
||||
result[2] = v1[2] - v2[2];
|
||||
}
|
||||
|
||||
void Terrain::vectoradd(float *v1, const float *v2) const
|
||||
{
|
||||
v1[0] += v2[0];
|
||||
v1[1] += v2[1];
|
||||
v1[2] += v2[2];
|
||||
}
|
||||
|
||||
void Terrain::vectormul(float a, const float *v, float *result) const
|
||||
{
|
||||
result[0] = a * v[0];
|
||||
result[1] = a * v[1];
|
||||
result[2] = a * v[2];
|
||||
}
|
||||
|
||||
void Terrain::vectormul(float a, float *v) const
|
||||
{
|
||||
v[0] *= a;
|
||||
v[1] *= a;
|
||||
v[2] *= a;
|
||||
}
|
||||
|
||||
void Terrain::vectornorm(float *v) const
|
||||
{
|
||||
float l = sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||
v[0] /= l;
|
||||
v[1] /= l;
|
||||
v[2] /= l;
|
||||
}
|
||||
|
||||
float Terrain::vectorlen(const float *v) const
|
||||
{
|
||||
return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||
}
|
||||
|
||||
void Terrain::computeNormals()
|
||||
{
|
||||
const int delta[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
|
||||
|
||||
float *normal;
|
||||
float temp[3];
|
||||
float v0[3], v1[3], v2[3];
|
||||
float weight;
|
||||
int i, j, k;
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
for(i = 0; i <= height; i++)
|
||||
{
|
||||
for(j = 0; j <= width; j++)
|
||||
{
|
||||
normal = &normals[(i * (width + 1) + j) * 3];
|
||||
normal[0] = 0.0;
|
||||
normal[1] = 0.0;
|
||||
normal[2] = 0.0;
|
||||
|
||||
|
||||
v0[0] = j * VERTEX_DIST;
|
||||
v0[1] = getHeight(j, i) * HEIGHT_SCALE;
|
||||
v0[2] = i * VERTEX_DIST;
|
||||
|
||||
weight = 0.0;
|
||||
for(k = 0; k < 4; k++)
|
||||
{
|
||||
x1 = j + delta[k][0];
|
||||
y1 = i + delta[k][1];
|
||||
x2 = j + delta[(k+1)%4][0];
|
||||
y2 = i + delta[(k+1)%4][1];
|
||||
|
||||
if(x1 < 0 || x1 > width || y1 < 0 || y1 > height) continue;
|
||||
if(x2 < 0 || x2 > width || y2 < 0 || y2 > height) continue;
|
||||
|
||||
v1[0] = x1 * VERTEX_DIST;
|
||||
v1[1] = getHeight(x1, y1) * HEIGHT_SCALE;
|
||||
v1[2] = y1 * VERTEX_DIST;
|
||||
vectorsub(v1, v0);
|
||||
|
||||
v2[0] = x2 * VERTEX_DIST;
|
||||
v2[1] = getHeight(x2, y2) * HEIGHT_SCALE;
|
||||
v2[2] = y2 * VERTEX_DIST;
|
||||
vectorsub(v2, v0);
|
||||
|
||||
xproduct(v2, v1, temp);
|
||||
vectornorm(temp);
|
||||
|
||||
vectoradd(normal, temp);
|
||||
|
||||
weight += 1.0;
|
||||
}
|
||||
|
||||
vectormul(1.0 / weight, normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Terrain::descent(int start)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for(j = 0; j <= width; j++)
|
||||
{
|
||||
float maximum = getHeight(j, start);
|
||||
// float minimum = 0.5 * maximum;
|
||||
float minimum = 0.0;
|
||||
|
||||
for(i = start + 1; i <= height; i++)
|
||||
{
|
||||
float x = (float)(i - start - 1) / (height - start - 1);
|
||||
x = 1 - x * x * x;
|
||||
float h = minimum + getHeight(j, i) * x * (maximum - minimum);
|
||||
setHeight(j, i, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Terrain::drawRoad(int n)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, roadTex);
|
||||
for(int i = 0; i < width - 1; i++)
|
||||
{
|
||||
if(i == FINISH_LINE) glBindTexture(GL_TEXTURE_2D, goalTex);
|
||||
if(i == FINISH_LINE+1) glBindTexture(GL_TEXTURE_2D, roadTex2);
|
||||
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for(int j = 0; j <= 2; j++)
|
||||
{
|
||||
glTexCoord2f(0.0, j * 0.5);
|
||||
vertex(i, j + n - 1);
|
||||
glTexCoord2f(1.0, j * 0.5);
|
||||
vertex(i + 1, j + n - 1);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
void Terrain::createList(GLuint list, int x0, int y0, int w, int h)
|
||||
{
|
||||
glNewList(list, GL_COMPILE);
|
||||
|
||||
for(int i = 0; i < w; i++)
|
||||
{
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for(int j = 0; j <= h; j++)
|
||||
{
|
||||
glTexCoord2f((float)i / w, (float)j / h);
|
||||
vertex(x0 + i, y0 + j);
|
||||
glTexCoord2f((float)(i + 1) / w, (float)j / h);
|
||||
vertex(x0 + i + 1, y0 + j);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glEndList();
|
||||
}
|
||||
|
||||
void Terrain::createLists()
|
||||
{
|
||||
for(int i = 0; i < 32; i++)
|
||||
{
|
||||
for(int j =0 ; j < 2; j++)
|
||||
{
|
||||
createList(listBase + j * 32 + i, i * 16, j * 16, 16, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Terrain::drawLists(const float *eye, const float *at, float fovDiag, float dz)
|
||||
{
|
||||
float vec[3];
|
||||
|
||||
vec[0] = at[0];
|
||||
vec[1] = at[1];
|
||||
vec[2] = at[2];
|
||||
vectornorm(vec);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
int drawn = 0;
|
||||
|
||||
for(int i = 0; i < 32; i++)
|
||||
{
|
||||
for(int j = 0; j < 2; j++)
|
||||
{
|
||||
float pos[3] = {i * 16 * VERTEX_DIST - eye[0], 5.0 - eye[1], j * 16 * VERTEX_DIST + dz - eye[2]};
|
||||
float len;
|
||||
bool inside = false;
|
||||
|
||||
len = vectorlen(pos);
|
||||
if(acosf(dotproduct(pos, vec) / len) < fovDiag) inside = true;
|
||||
|
||||
if(!inside)
|
||||
{
|
||||
pos[0] = (i + 1) * 16 * VERTEX_DIST - eye[0];
|
||||
len = vectorlen(pos);
|
||||
if(acosf(dotproduct(pos, vec) / len) < fovDiag) inside = true;
|
||||
}
|
||||
|
||||
if(!inside)
|
||||
{
|
||||
pos[2] = (j + 1) * 16 * VERTEX_DIST + dz - eye[2];
|
||||
len = vectorlen(pos);
|
||||
if(acosf(dotproduct(pos, vec) / len) < fovDiag) inside = true;
|
||||
}
|
||||
|
||||
if(!inside)
|
||||
{
|
||||
pos[0] = i * 16 * VERTEX_DIST - eye[0];
|
||||
len = vectorlen(pos);
|
||||
if(acosf(dotproduct(pos, vec) / len) < fovDiag) inside = true;
|
||||
}
|
||||
|
||||
if(inside)
|
||||
{
|
||||
glCallList(listBase + j * 32 + i);
|
||||
drawn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
65
src/terrain.h
Normal file
65
src/terrain.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#ifndef _TERRAIN_H_
|
||||
#define _TERRAIN_H_
|
||||
|
||||
class Terrain
|
||||
{
|
||||
public:
|
||||
static const float VERTEX_DIST;
|
||||
static const float HEIGHT_SCALE;
|
||||
|
||||
static const int FINISH_LINE = 492;
|
||||
|
||||
Terrain();
|
||||
~Terrain();
|
||||
|
||||
void draw();
|
||||
void drawLists(const float *eye, const float *at, float fovDiag, float dz);
|
||||
void drawRoad(int n);
|
||||
|
||||
float getHeight(int x, int y) const;
|
||||
void setHeight(int x, int y, float h);
|
||||
|
||||
void generate();
|
||||
void normalize();
|
||||
void computeNormals();
|
||||
void descent(int start);
|
||||
void createLists();
|
||||
|
||||
int init(int w, int h);
|
||||
|
||||
static float random();
|
||||
static void srandom(int s);
|
||||
|
||||
static bool isPow2(int x);
|
||||
static int log2(int x);
|
||||
|
||||
private:
|
||||
static int seed;
|
||||
|
||||
void xproduct(const float *v1, const float *v2, float *result) const;
|
||||
float dotproduct(const float *v1 , const float *v2) const;
|
||||
void vectorsub(const float *v1, const float *v2, float *result) const;
|
||||
void vectorsub(float *v1, const float *v2) const;
|
||||
void vectoradd(const float *v1, const float *v2, float *result) const;
|
||||
void vectoradd(float *v1, const float *v2) const;
|
||||
void vectormul(float a, const float *v, float *result) const;
|
||||
void vectormul(float a, float *v) const;
|
||||
void vectornorm(float *v) const;
|
||||
float vectorlen(const float *v) const;
|
||||
|
||||
void vertex(int x, int y);
|
||||
|
||||
void createList(GLuint list, int x0, int y0, int w, int h);
|
||||
|
||||
float *data;
|
||||
float *normals;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
GLuint roadTex, goalTex, roadTex2;
|
||||
GLuint texture;
|
||||
GLuint listBase;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
8
src/tinyxml/Makefile.am
Normal file
8
src/tinyxml/Makefile.am
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
INCLUDES = -W -Wall -DTIXML_USE_STL
|
||||
|
||||
noinst_LIBRARIES = libtinyxml.a
|
||||
|
||||
libtinyxml_a_SOURCES = tinyxml.cpp tinyxml.h \
|
||||
tinyxmlerror.cpp \
|
||||
tinyxmlparser.cpp \
|
||||
tinystr.cpp tinystr.h
|
||||
413
src/tinyxml/Makefile.in
Normal file
413
src/tinyxml/Makefile.in
Normal file
|
|
@ -0,0 +1,413 @@
|
|||
# Makefile.in generated by automake 1.9.6 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ../..
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
subdir = src/tinyxml
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.in
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
AR = ar
|
||||
ARFLAGS = cru
|
||||
libtinyxml_a_AR = $(AR) $(ARFLAGS)
|
||||
libtinyxml_a_LIBADD =
|
||||
am_libtinyxml_a_OBJECTS = tinyxml.$(OBJEXT) tinyxmlerror.$(OBJEXT) \
|
||||
tinyxmlparser.$(OBJEXT) tinystr.$(OBJEXT)
|
||||
libtinyxml_a_OBJECTS = $(am_libtinyxml_a_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
CXXLD = $(CXX)
|
||||
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
|
||||
-o $@
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(libtinyxml_a_SOURCES)
|
||||
DIST_SOURCES = $(libtinyxml_a_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SDL_CFLAGS = @SDL_CFLAGS@
|
||||
SDL_CONFIG = @SDL_CONFIG@
|
||||
SDL_LIBS = @SDL_LIBS@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
INCLUDES = -W -Wall -DTIXML_USE_STL
|
||||
noinst_LIBRARIES = libtinyxml.a
|
||||
libtinyxml_a_SOURCES = tinyxml.cpp tinyxml.h \
|
||||
tinyxmlerror.cpp \
|
||||
tinyxmlparser.cpp \
|
||||
tinystr.cpp tinystr.h
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .cpp .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/tinyxml/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/tinyxml/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
libtinyxml.a: $(libtinyxml_a_OBJECTS) $(libtinyxml_a_DEPENDENCIES)
|
||||
-rm -f libtinyxml.a
|
||||
$(libtinyxml_a_AR) libtinyxml.a $(libtinyxml_a_OBJECTS) $(libtinyxml_a_LIBADD)
|
||||
$(RANLIB) libtinyxml.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinystr.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxml.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxmlerror.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxmlparser.Po@am__quote@
|
||||
|
||||
.cpp.o:
|
||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||
|
||||
.cpp.obj:
|
||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
uninstall-info-am:
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkdir_p) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LIBRARIES)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-info-am
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-noinstLIBRARIES ctags distclean distclean-compile \
|
||||
distclean-generic distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-exec install-exec-am install-info \
|
||||
install-info-am install-man install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
|
||||
uninstall-am uninstall-info-am
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
115
src/tinyxml/tinystr.cpp
Normal file
115
src/tinyxml/tinystr.cpp
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original file by Yves Berquin.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE WAS ALTERED BY Tyge Løvset, 7. April 2005.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
#include "tinystr.h"
|
||||
|
||||
// Error value for find primitive
|
||||
const TiXmlString::size_type TiXmlString::npos = static_cast< size_type >(-1);
|
||||
|
||||
// Null rep.
|
||||
TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, '\0' };
|
||||
|
||||
|
||||
void TiXmlString::reserve (size_type cap)
|
||||
{
|
||||
if (cap > capacity())
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.init(length(), cap);
|
||||
memcpy(tmp.start(), data(), length());
|
||||
swap(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TiXmlString& TiXmlString::assign(const char* str, size_type len)
|
||||
{
|
||||
size_type cap = capacity();
|
||||
if (len > cap || cap > 3*(len + 8))
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.init(len);
|
||||
memcpy(tmp.start(), str, len);
|
||||
swap(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(start(), str, len);
|
||||
set_size(len);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TiXmlString& TiXmlString::append(const char* str, size_type len)
|
||||
{
|
||||
size_type newsize = length() + len;
|
||||
if (newsize > capacity())
|
||||
{
|
||||
reserve (newsize + capacity());
|
||||
}
|
||||
memmove(finish(), str, len);
|
||||
set_size(newsize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.reserve(a.length() + b.length());
|
||||
tmp += a;
|
||||
tmp += b;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const char* b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
|
||||
tmp.reserve(a.length() + b_len);
|
||||
tmp += a;
|
||||
tmp.append(b, b_len);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
TiXmlString operator + (const char* a, const TiXmlString & b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
|
||||
tmp.reserve(a_len + b.length());
|
||||
tmp.append(a, a_len);
|
||||
tmp += b;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
#endif // TIXML_USE_STL
|
||||
319
src/tinyxml/tinystr.h
Normal file
319
src/tinyxml/tinystr.h
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original file by Yves Berquin.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005.
|
||||
*
|
||||
* - completely rewritten. compact, clean, and fast implementation.
|
||||
* - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems)
|
||||
* - fixed reserve() to work as per specification.
|
||||
* - fixed buggy compares operator==(), operator<(), and operator>()
|
||||
* - fixed operator+=() to take a const ref argument, following spec.
|
||||
* - added "copy" constructor with length, and most compare operators.
|
||||
* - added swap(), clear(), size(), capacity(), operator+().
|
||||
*/
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
#ifndef TIXML_STRING_INCLUDED
|
||||
#define TIXML_STRING_INCLUDED
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
/* The support for explicit isn't that universal, and it isn't really
|
||||
required - it is used to check that the TiXmlString class isn't incorrectly
|
||||
used. Be nice to old compilers and macro it here:
|
||||
*/
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
|
||||
// Microsoft visual studio, version 6 and higher.
|
||||
#define TIXML_EXPLICIT explicit
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 3 )
|
||||
// GCC version 3 and higher.s
|
||||
#define TIXML_EXPLICIT explicit
|
||||
#else
|
||||
#define TIXML_EXPLICIT
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
TiXmlString is an emulation of a subset of the std::string template.
|
||||
Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
|
||||
Only the member functions relevant to the TinyXML project have been implemented.
|
||||
The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
|
||||
a string and there's no more room, we allocate a buffer twice as big as we need.
|
||||
*/
|
||||
class TiXmlString
|
||||
{
|
||||
public :
|
||||
// The size type used
|
||||
typedef size_t size_type;
|
||||
|
||||
// Error value for find primitive
|
||||
static const size_type npos; // = -1;
|
||||
|
||||
|
||||
// TiXmlString empty constructor
|
||||
TiXmlString () : rep_(&nullrep_)
|
||||
{
|
||||
}
|
||||
|
||||
// TiXmlString copy constructor
|
||||
TiXmlString ( const TiXmlString & copy)
|
||||
{
|
||||
init(copy.length());
|
||||
memcpy(start(), copy.data(), length());
|
||||
}
|
||||
|
||||
// TiXmlString constructor, based on a string
|
||||
TIXML_EXPLICIT TiXmlString ( const char * copy)
|
||||
{
|
||||
init( static_cast<size_type>( strlen(copy) ));
|
||||
memcpy(start(), copy, length());
|
||||
}
|
||||
|
||||
// TiXmlString constructor, based on a string
|
||||
TIXML_EXPLICIT TiXmlString ( const char * str, size_type len)
|
||||
{
|
||||
init(len);
|
||||
memcpy(start(), str, len);
|
||||
}
|
||||
|
||||
// TiXmlString destructor
|
||||
~TiXmlString ()
|
||||
{
|
||||
quit();
|
||||
}
|
||||
|
||||
// = operator
|
||||
TiXmlString& operator = (const char * copy)
|
||||
{
|
||||
return assign( copy, (size_type)strlen(copy));
|
||||
}
|
||||
|
||||
// = operator
|
||||
TiXmlString& operator = (const TiXmlString & copy)
|
||||
{
|
||||
return assign(copy.start(), copy.length());
|
||||
}
|
||||
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (const char * suffix)
|
||||
{
|
||||
return append(suffix, static_cast<size_type>( strlen(suffix) ));
|
||||
}
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (char single)
|
||||
{
|
||||
return append(&single, 1);
|
||||
}
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (const TiXmlString & suffix)
|
||||
{
|
||||
return append(suffix.data(), suffix.length());
|
||||
}
|
||||
|
||||
|
||||
// Convert a TiXmlString into a null-terminated char *
|
||||
const char * c_str () const { return rep_->str; }
|
||||
|
||||
// Convert a TiXmlString into a char * (need not be null terminated).
|
||||
const char * data () const { return rep_->str; }
|
||||
|
||||
// Return the length of a TiXmlString
|
||||
size_type length () const { return rep_->size; }
|
||||
|
||||
// Alias for length()
|
||||
size_type size () const { return rep_->size; }
|
||||
|
||||
// Checks if a TiXmlString is empty
|
||||
bool empty () const { return rep_->size == 0; }
|
||||
|
||||
// Return capacity of string
|
||||
size_type capacity () const { return rep_->capacity; }
|
||||
|
||||
|
||||
// single char extraction
|
||||
const char& at (size_type index) const
|
||||
{
|
||||
assert( index < length() );
|
||||
return rep_->str[ index ];
|
||||
}
|
||||
|
||||
// [] operator
|
||||
char& operator [] (size_type index) const
|
||||
{
|
||||
assert( index < length() );
|
||||
return rep_->str[ index ];
|
||||
}
|
||||
|
||||
// find a char in a string. Return TiXmlString::npos if not found
|
||||
size_type find (char lookup) const
|
||||
{
|
||||
return find(lookup, 0);
|
||||
}
|
||||
|
||||
// find a char in a string from an offset. Return TiXmlString::npos if not found
|
||||
size_type find (char tofind, size_type offset) const
|
||||
{
|
||||
if (offset >= length()) return npos;
|
||||
|
||||
for (const char* p = c_str() + offset; *p != '\0'; ++p)
|
||||
{
|
||||
if (*p == tofind) return static_cast< size_type >( p - c_str() );
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
//Lee:
|
||||
//The original was just too strange, though correct:
|
||||
// TiXmlString().swap(*this);
|
||||
//Instead use the quit & re-init:
|
||||
quit();
|
||||
init(0,0);
|
||||
}
|
||||
|
||||
/* Function to reserve a big amount of data when we know we'll need it. Be aware that this
|
||||
function DOES NOT clear the content of the TiXmlString if any exists.
|
||||
*/
|
||||
void reserve (size_type cap);
|
||||
|
||||
TiXmlString& assign (const char* str, size_type len);
|
||||
|
||||
TiXmlString& append (const char* str, size_type len);
|
||||
|
||||
void swap (TiXmlString& other)
|
||||
{
|
||||
Rep* r = rep_;
|
||||
rep_ = other.rep_;
|
||||
other.rep_ = r;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void init(size_type sz) { init(sz, sz); }
|
||||
void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
|
||||
char* start() const { return rep_->str; }
|
||||
char* finish() const { return rep_->str + rep_->size; }
|
||||
|
||||
struct Rep
|
||||
{
|
||||
size_type size, capacity;
|
||||
char str[1];
|
||||
};
|
||||
|
||||
void init(size_type sz, size_type cap)
|
||||
{
|
||||
if (cap)
|
||||
{
|
||||
// Lee: the original form:
|
||||
// rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
|
||||
// doesn't work in some cases of new being overloaded. Switching
|
||||
// to the normal allocation, although use an 'int' for systems
|
||||
// that are overly picky about structure alignment.
|
||||
const size_type bytesNeeded = sizeof(Rep) + cap;
|
||||
const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int );
|
||||
rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
|
||||
|
||||
rep_->str[ rep_->size = sz ] = '\0';
|
||||
rep_->capacity = cap;
|
||||
}
|
||||
else
|
||||
{
|
||||
rep_ = &nullrep_;
|
||||
}
|
||||
}
|
||||
|
||||
void quit()
|
||||
{
|
||||
if (rep_ != &nullrep_)
|
||||
{
|
||||
// The rep_ is really an array of ints. (see the allocator, above).
|
||||
// Cast it back before delete, so the compiler won't incorrectly call destructors.
|
||||
delete [] ( reinterpret_cast<int*>( rep_ ) );
|
||||
}
|
||||
}
|
||||
|
||||
Rep * rep_;
|
||||
static Rep nullrep_;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
inline bool operator == (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
return ( a.length() == b.length() ) // optimization on some platforms
|
||||
&& ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare
|
||||
}
|
||||
inline bool operator < (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
return strcmp(a.c_str(), b.c_str()) < 0;
|
||||
}
|
||||
|
||||
inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
|
||||
inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; }
|
||||
inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
|
||||
inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
|
||||
|
||||
inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
|
||||
inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
|
||||
inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
|
||||
inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
|
||||
TiXmlString operator + (const TiXmlString & a, const char* b);
|
||||
TiXmlString operator + (const char* a, const TiXmlString & b);
|
||||
|
||||
|
||||
/*
|
||||
TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
|
||||
Only the operators that we need for TinyXML have been developped.
|
||||
*/
|
||||
class TiXmlOutStream : public TiXmlString
|
||||
{
|
||||
public :
|
||||
|
||||
// TiXmlOutStream << operator.
|
||||
TiXmlOutStream & operator << (const TiXmlString & in)
|
||||
{
|
||||
*this += in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TiXmlOutStream << operator.
|
||||
TiXmlOutStream & operator << (const char * in)
|
||||
{
|
||||
*this += in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
#endif // TIXML_STRING_INCLUDED
|
||||
#endif // TIXML_USE_STL
|
||||
1799
src/tinyxml/tinyxml.cpp
Normal file
1799
src/tinyxml/tinyxml.cpp
Normal file
File diff suppressed because it is too large
Load diff
1520
src/tinyxml/tinyxml.h
Normal file
1520
src/tinyxml/tinyxml.h
Normal file
File diff suppressed because it is too large
Load diff
52
src/tinyxml/tinyxmlerror.cpp
Normal file
52
src/tinyxml/tinyxmlerror.cpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
#include "tinyxml.h"
|
||||
|
||||
// The goal of the seperate error file is to make the first
|
||||
// step towards localization. tinyxml (currently) only supports
|
||||
// english error messages, but the could now be translated.
|
||||
//
|
||||
// It also cleans up the code a bit.
|
||||
//
|
||||
|
||||
const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
|
||||
{
|
||||
"No error",
|
||||
"Error",
|
||||
"Failed to open file",
|
||||
"Memory allocation failed.",
|
||||
"Error parsing Element.",
|
||||
"Failed to read Element name",
|
||||
"Error reading Element value.",
|
||||
"Error reading Attributes.",
|
||||
"Error: empty tag.",
|
||||
"Error reading end tag.",
|
||||
"Error parsing Unknown.",
|
||||
"Error parsing Comment.",
|
||||
"Error parsing Declaration.",
|
||||
"Error document empty.",
|
||||
"Error null (0) or unexpected EOF found in input stream.",
|
||||
"Error parsing CDATA.",
|
||||
};
|
||||
1580
src/tinyxml/tinyxmlparser.cpp
Normal file
1580
src/tinyxml/tinyxmlparser.cpp
Normal file
File diff suppressed because it is too large
Load diff
198
src/vector2.cpp
Normal file
198
src/vector2.cpp
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
#include <math.h>
|
||||
|
||||
#include "vector2.h"
|
||||
|
||||
/* Constructors */
|
||||
/// Create a zero vector
|
||||
/**
|
||||
This is the default constructor for the Vector class. Equivalent to Vector(0, 0)
|
||||
@see Vector(float,float)
|
||||
*/
|
||||
Vector2::Vector2()
|
||||
{
|
||||
data[0] = 0;
|
||||
data[1] = 0;
|
||||
}
|
||||
|
||||
/// Create a new vector
|
||||
/**
|
||||
Create a new Vector (xx, yy).
|
||||
@param xx The x-component of the vector
|
||||
@param yy The y-component of the vector
|
||||
*/
|
||||
Vector2::Vector2(float xx, float yy)
|
||||
{
|
||||
data[0] = xx;
|
||||
data[1] = yy;
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
/// Set the x-component of this vector
|
||||
/**
|
||||
@param xx the new x-component of this vector.
|
||||
*/
|
||||
void Vector2::setX(float xx)
|
||||
{
|
||||
data[0] = xx;
|
||||
}
|
||||
|
||||
/// Set the y-component of this vector
|
||||
/**
|
||||
@param yy the new x-component of this vector.
|
||||
*/
|
||||
void Vector2::setY(float yy)
|
||||
{
|
||||
data[1] = yy;
|
||||
}
|
||||
|
||||
/// Get the x-component of this vector
|
||||
/**
|
||||
@return The x-component of this vector
|
||||
*/
|
||||
float Vector2::getX() const
|
||||
{
|
||||
return data[0];
|
||||
}
|
||||
|
||||
/// Get the y-component of this vector
|
||||
/**
|
||||
@return The y-component of this vector
|
||||
*/
|
||||
float Vector2::getY() const
|
||||
{
|
||||
return data[1];
|
||||
}
|
||||
|
||||
/// Calculate length of this vector
|
||||
/**
|
||||
Calculates the length of this vector. The length is defined as
|
||||
sqrt(x<sup>2</sup>+y<sup>2</sup>).
|
||||
@return The lenght of this vector
|
||||
*/
|
||||
float Vector2::length() const
|
||||
{
|
||||
return sqrt(data[0] * data[0] + data[1] * data[1]);
|
||||
}
|
||||
|
||||
/// Calculate the angle of this vector
|
||||
/**
|
||||
Calculate the angle of this vector. The angle is defined as atan2(y, x);
|
||||
@return The angle of this vector in radians.
|
||||
*/
|
||||
float Vector2::angle() const
|
||||
{
|
||||
return atan2(data[1], data[0]);
|
||||
}
|
||||
|
||||
/// Rotate this vector
|
||||
/**
|
||||
Rotate this vector theta radians counter clockwise. The rotation operator is defined
|
||||
as x' = Ax, where A is the orthogonal rotation matrix.
|
||||
@param theta The angle to rotate in radians. Positive means counterclockwise.
|
||||
@return a reference to this vector
|
||||
*/
|
||||
Vector2& Vector2::rotate(float theta)
|
||||
{
|
||||
float c = cos(theta);
|
||||
float s = sin(theta);
|
||||
float tx = c * data[0] - s* data[1];
|
||||
data[1] = s * data[0] + c * data[1];
|
||||
data[0] = tx;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Normalize this vector
|
||||
/**
|
||||
This function normalizes this vector, when a vector is normalized, it preserves
|
||||
it direction, but is scaled to have a length of 1.0.
|
||||
*/
|
||||
Vector2& Vector2::normalize()
|
||||
{
|
||||
float len = sqrt(data[0] * data[0] + data[1] * data[1]);
|
||||
data[0] /= len;
|
||||
data[1] /= len;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2 Vector2::operator+(const Vector2 &vec) const
|
||||
{
|
||||
return Vector2(getX() + vec.getX(), getY() + vec.getY());
|
||||
}
|
||||
|
||||
Vector2 Vector2::operator-(const Vector2 &vec) const
|
||||
{
|
||||
return Vector2(getX() - vec.getX(), getY() - vec.getY());
|
||||
}
|
||||
|
||||
/// Get the unit vector of this vector
|
||||
/**
|
||||
The unit vector is a vector with the same direction as this one, but a length of 1.0.
|
||||
@return A new Vector2 which is the unit vector of this vector.
|
||||
*/
|
||||
Vector2 Vector2::unitVector() const
|
||||
{
|
||||
Vector2 temp(data[0], data[1]);
|
||||
temp.normalize();
|
||||
return temp;
|
||||
}
|
||||
|
||||
/// Get the normal vector of this vector
|
||||
/**
|
||||
The normal vector is a vector with equal length to this vector, but is normal to
|
||||
this vector (ie. the two vectors form a 90 degree angle).
|
||||
@return A vector that is normal to this vector and equal in length.
|
||||
*/
|
||||
Vector2 Vector2::normalVector() const
|
||||
{
|
||||
return Vector2(-data[1], data[0]);
|
||||
}
|
||||
|
||||
Vector2 &Vector2::operator=(const Vector2 &other)
|
||||
{
|
||||
data[0] = other.getX();
|
||||
data[1] = other.getY();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Operators */
|
||||
|
||||
const Vector2 Vector2::operator-() const
|
||||
{
|
||||
return Vector2(-data[0], -data[1]);
|
||||
}
|
||||
|
||||
|
||||
Vector2 operator*(float a, const Vector2 &vec)
|
||||
{
|
||||
Vector2 temp(vec.getX() * a, vec.getY() * a);
|
||||
return temp;
|
||||
}
|
||||
|
||||
Vector2 operator*(const Vector2 &vec, float a)
|
||||
{
|
||||
Vector2 temp(vec.getX() * a, vec.getY() * a);
|
||||
return temp;
|
||||
}
|
||||
|
||||
Vector2 operator/(const Vector2 &vec, float a)
|
||||
{
|
||||
Vector2 temp(vec.getX() / a, vec.getY() / a);
|
||||
return temp;
|
||||
}
|
||||
|
||||
/* Dot product */
|
||||
float operator*(const Vector2 &vec1, const Vector2 &vec2)
|
||||
{
|
||||
return vec1.getX() * vec2.getX() + vec1.getY() * vec2.getY();
|
||||
}
|
||||
|
||||
/* Cross product */
|
||||
float operator^(const Vector2 &vec1, const Vector2 &vec2)
|
||||
{
|
||||
return vec1.getX() * vec2.getY() - vec2.getX() * vec1.getY();
|
||||
}
|
||||
|
||||
const float *Vector2::getData() const { return data; }
|
||||
|
||||
54
src/vector2.h
Normal file
54
src/vector2.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef _VECTOR_H_
|
||||
#define _VECTOR_H_
|
||||
|
||||
/// A mathematical 2D Vector
|
||||
/**
|
||||
The Vector class is the basis of all mathematics used in the physical
|
||||
simulation. The Vector class is a mathematical representation of a 2D-vector.
|
||||
The vector has two components, x and y. The vector class is overloaded with the
|
||||
following operators: + (vector addition), - (vector substraction/negation), ^
|
||||
(vector <b>cross</b> product) and * (vector <b>dot</b> product). Operators
|
||||
for scalar multiplication and division are also defined.
|
||||
*/
|
||||
class Vector2
|
||||
{
|
||||
public:
|
||||
Vector2();
|
||||
Vector2(float xx, float yy);
|
||||
|
||||
void setX(float xx);
|
||||
void setY(float yy);
|
||||
|
||||
float getX() const;
|
||||
float getY() const;
|
||||
float length() const;
|
||||
float angle() const;
|
||||
Vector2 &rotate(float theta);
|
||||
|
||||
Vector2 &normalize();
|
||||
|
||||
Vector2 unitVector() const;
|
||||
Vector2 normalVector() const;
|
||||
|
||||
Vector2 operator+(const Vector2 &vec) const;
|
||||
Vector2 operator-(const Vector2 &vec) const;
|
||||
|
||||
Vector2 &operator=(const Vector2 &other);
|
||||
|
||||
const float *getData() const;
|
||||
|
||||
/* Vector negation */
|
||||
const Vector2 operator-() const;
|
||||
|
||||
private:
|
||||
float data[2];
|
||||
};
|
||||
|
||||
/* Operators */
|
||||
extern float operator*(const Vector2 &vec1, const Vector2 &vec2);
|
||||
extern float operator^(const Vector2 &vec1, const Vector2 &vec2);
|
||||
extern Vector2 operator/(const Vector2 &vec, float a);
|
||||
extern Vector2 operator*(const Vector2 &vec, float a);
|
||||
extern Vector2 operator*(float a, const Vector2 &vec);
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue