• R/O
  • SSH
  • HTTPS

marathon: コミット


コミットメタ情報

リビジョン493 (tree)
日時2011-07-05 22:57:56
作者logue

ログメッセージ

AlephOne r4449とマージ
converter.cppに2バイトコード判定処理を移動した。
少しだけゴミが減った。

変更サマリ

差分

--- marathon/trunk/configure (revision 492)
+++ marathon/trunk/configure (revision 493)
@@ -1,6 +1,6 @@
11 #! /bin/sh
22 # Guess values for system-dependent variables and create Makefiles.
3-# Generated by GNU Autoconf 2.66 for Aleph One/SDL 20110417.
3+# Generated by GNU Autoconf 2.68 for Aleph One/SDL 20110626.
44 #
55 # Report bugs to <http://sourceforge.net/bugs/?group_id=1997>.
66 #
@@ -91,6 +91,7 @@
9191 IFS=" "" $as_nl"
9292
9393 # Find who we are. Look in the path if we contain no directory separator.
94+as_myself=
9495 case $0 in #((
9596 *[\\/]* ) as_myself=$0 ;;
9697 *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -216,11 +217,18 @@
216217 # We cannot yet assume a decent shell, so we have to provide a
217218 # neutralization value for shells without unset; and this also
218219 # works around shells that cannot unset nonexistent variables.
220+ # Preserve -v and -x to the replacement shell.
219221 BASH_ENV=/dev/null
220222 ENV=/dev/null
221223 (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
222224 export CONFIG_SHELL
223- exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
225+ case $- in # ((((
226+ *v*x* | *x*v* ) as_opts=-vx ;;
227+ *v* ) as_opts=-v ;;
228+ *x* ) as_opts=-x ;;
229+ * ) as_opts= ;;
230+ esac
231+ exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
224232 fi
225233
226234 if test x$as_have_required = xno; then :
@@ -550,10 +558,10 @@
550558 MAKEFLAGS=
551559
552560 # Identity of this package.
553-PACKAGE_NAME='Aleph One/SDL'
554-PACKAGE_TARNAME='AlephOne'
555-PACKAGE_VERSION='20110417'
556-PACKAGE_STRING='Aleph One/SDL 20110417'
561+PACKAGE_NAME='Aleph One JP/SDL'
562+PACKAGE_TARNAME='AlephOneJP'
563+PACKAGE_VERSION='20110705'
564+PACKAGE_STRING='Aleph One JP/SDL 20110705'
557565 PACKAGE_BUGREPORT='http://sourceforge.net/bugs/?group_id=1997'
558566 PACKAGE_URL=''
559567
@@ -824,8 +832,9 @@
824832 fi
825833
826834 case $ac_option in
827- *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
828- *) ac_optarg=yes ;;
835+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
836+ *=) ac_optarg= ;;
837+ *) ac_optarg=yes ;;
829838 esac
830839
831840 # Accept the important Cygnus configure options, so we can diagnose typos.
@@ -1165,7 +1174,7 @@
11651174 $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
11661175 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
11671176 $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
1168- : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
1177+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
11691178 ;;
11701179
11711180 esac
@@ -1303,7 +1312,7 @@
13031312 # Omit some internal or obsolete options to make the list less imposing.
13041313 # This message is too long to be a string in the A/UX 3.1 sh.
13051314 cat <<_ACEOF
1306-\`configure' configures Aleph One/SDL 20110417 to adapt to many kinds of systems.
1315+\`configure' configures Aleph One/SDL 20110626 to adapt to many kinds of systems.
13071316
13081317 Usage: $0 [OPTION]... [VAR=VALUE]...
13091318
@@ -1374,7 +1383,7 @@
13741383
13751384 if test -n "$ac_init_help"; then
13761385 case $ac_init_help in
1377- short | recursive ) echo "Configuration of Aleph One/SDL 20110417:";;
1386+ short | recursive ) echo "Configuration of Aleph One/SDL 20110626:";;
13781387 esac
13791388 cat <<\_ACEOF
13801389
@@ -1495,8 +1504,8 @@
14951504 test -n "$ac_init_help" && exit $ac_status
14961505 if $ac_init_version; then
14971506 cat <<\_ACEOF
1498-Aleph One/SDL configure 20110417
1499-generated by GNU Autoconf 2.66
1507+Aleph One/SDL configure 20110626
1508+generated by GNU Autoconf 2.68
15001509
15011510 Copyright (C) 2010 Free Software Foundation, Inc.
15021511 This configure script is free software; the Free Software Foundation
@@ -1542,7 +1551,7 @@
15421551
15431552 ac_retval=1
15441553 fi
1545- eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
1554+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
15461555 as_fn_set_status $ac_retval
15471556
15481557 } # ac_fn_c_try_compile
@@ -1568,7 +1577,7 @@
15681577 mv -f conftest.er1 conftest.err
15691578 fi
15701579 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1571- test $ac_status = 0; } >/dev/null && {
1580+ test $ac_status = 0; } > conftest.i && {
15721581 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
15731582 test ! -s conftest.err
15741583 }; then :
@@ -1579,7 +1588,7 @@
15791588
15801589 ac_retval=1
15811590 fi
1582- eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
1591+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
15831592 as_fn_set_status $ac_retval
15841593
15851594 } # ac_fn_c_try_cpp
@@ -1617,7 +1626,7 @@
16171626
16181627 ac_retval=1
16191628 fi
1620- eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
1629+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
16211630 as_fn_set_status $ac_retval
16221631
16231632 } # ac_fn_cxx_try_compile
@@ -1643,7 +1652,7 @@
16431652 mv -f conftest.er1 conftest.err
16441653 fi
16451654 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1646- test $ac_status = 0; } >/dev/null && {
1655+ test $ac_status = 0; } > conftest.i && {
16471656 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
16481657 test ! -s conftest.err
16491658 }; then :
@@ -1654,7 +1663,7 @@
16541663
16551664 ac_retval=1
16561665 fi
1657- eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
1666+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
16581667 as_fn_set_status $ac_retval
16591668
16601669 } # ac_fn_cxx_try_cpp
@@ -1667,10 +1676,10 @@
16671676 ac_fn_c_check_header_mongrel ()
16681677 {
16691678 as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1670- if eval "test \"\${$3+set}\"" = set; then :
1679+ if eval \${$3+:} false; then :
16711680 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
16721681 $as_echo_n "checking for $2... " >&6; }
1673-if eval "test \"\${$3+set}\"" = set; then :
1682+if eval \${$3+:} false; then :
16741683 $as_echo_n "(cached) " >&6
16751684 fi
16761685 eval ac_res=\$$3
@@ -1706,7 +1715,7 @@
17061715 else
17071716 ac_header_preproc=no
17081717 fi
1709-rm -f conftest.err conftest.$ac_ext
1718+rm -f conftest.err conftest.i conftest.$ac_ext
17101719 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
17111720 $as_echo "$ac_header_preproc" >&6; }
17121721
@@ -1737,7 +1746,7 @@
17371746 esac
17381747 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
17391748 $as_echo_n "checking for $2... " >&6; }
1740-if eval "test \"\${$3+set}\"" = set; then :
1749+if eval \${$3+:} false; then :
17411750 $as_echo_n "(cached) " >&6
17421751 else
17431752 eval "$3=\$ac_header_compiler"
@@ -1746,7 +1755,7 @@
17461755 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
17471756 $as_echo "$ac_res" >&6; }
17481757 fi
1749- eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
1758+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
17501759
17511760 } # ac_fn_c_check_header_mongrel
17521761
@@ -1787,7 +1796,7 @@
17871796 ac_retval=$ac_status
17881797 fi
17891798 rm -rf conftest.dSYM conftest_ipa8_conftest.oo
1790- eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
1799+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
17911800 as_fn_set_status $ac_retval
17921801
17931802 } # ac_fn_c_try_run
@@ -1801,7 +1810,7 @@
18011810 as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
18021811 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
18031812 $as_echo_n "checking for $2... " >&6; }
1804-if eval "test \"\${$3+set}\"" = set; then :
1813+if eval \${$3+:} false; then :
18051814 $as_echo_n "(cached) " >&6
18061815 else
18071816 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -1819,7 +1828,7 @@
18191828 eval ac_res=\$$3
18201829 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
18211830 $as_echo "$ac_res" >&6; }
1822- eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
1831+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
18231832
18241833 } # ac_fn_c_check_header_compile
18251834
@@ -1864,7 +1873,7 @@
18641873 # interfere with the next link command; also delete a directory that is
18651874 # left behind by Apple's compiler. We do this before executing the actions.
18661875 rm -rf conftest.dSYM conftest_ipa8_conftest.oo
1867- eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
1876+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
18681877 as_fn_set_status $ac_retval
18691878
18701879 } # ac_fn_c_try_link
@@ -1877,7 +1886,7 @@
18771886 as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
18781887 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
18791888 $as_echo_n "checking for $2... " >&6; }
1880-if eval "test \"\${$3+set}\"" = set; then :
1889+if eval \${$3+:} false; then :
18811890 $as_echo_n "(cached) " >&6
18821891 else
18831892 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -1932,7 +1941,7 @@
19321941 eval ac_res=\$$3
19331942 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
19341943 $as_echo "$ac_res" >&6; }
1935- eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
1944+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
19361945
19371946 } # ac_fn_c_check_func
19381947
@@ -1944,10 +1953,10 @@
19441953 ac_fn_cxx_check_header_mongrel ()
19451954 {
19461955 as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1947- if eval "test \"\${$3+set}\"" = set; then :
1956+ if eval \${$3+:} false; then :
19481957 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
19491958 $as_echo_n "checking for $2... " >&6; }
1950-if eval "test \"\${$3+set}\"" = set; then :
1959+if eval \${$3+:} false; then :
19511960 $as_echo_n "(cached) " >&6
19521961 fi
19531962 eval ac_res=\$$3
@@ -1983,7 +1992,7 @@
19831992 else
19841993 ac_header_preproc=no
19851994 fi
1986-rm -f conftest.err conftest.$ac_ext
1995+rm -f conftest.err conftest.i conftest.$ac_ext
19871996 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
19881997 $as_echo "$ac_header_preproc" >&6; }
19891998
@@ -2014,7 +2023,7 @@
20142023 esac
20152024 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
20162025 $as_echo_n "checking for $2... " >&6; }
2017-if eval "test \"\${$3+set}\"" = set; then :
2026+if eval \${$3+:} false; then :
20182027 $as_echo_n "(cached) " >&6
20192028 else
20202029 eval "$3=\$ac_header_compiler"
@@ -2023,7 +2032,7 @@
20232032 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
20242033 $as_echo "$ac_res" >&6; }
20252034 fi
2026- eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
2035+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
20272036
20282037 } # ac_fn_cxx_check_header_mongrel
20292038 cat >config.log <<_ACEOF
@@ -2030,8 +2039,8 @@
20302039 This file contains any messages produced by compilers while
20312040 running configure, to aid debugging if configure makes a mistake.
20322041
2033-It was created by Aleph One/SDL $as_me 20110417, which was
2034-generated by GNU Autoconf 2.66. Invocation command line was
2042+It was created by Aleph One/SDL $as_me 20110626, which was
2043+generated by GNU Autoconf 2.68. Invocation command line was
20352044
20362045 $ $0 $@
20372046
@@ -2416,7 +2425,7 @@
24162425
24172426 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
24182427 $as_echo_n "checking build system type... " >&6; }
2419-if test "${ac_cv_build+set}" = set; then :
2428+if ${ac_cv_build+:} false; then :
24202429 $as_echo_n "(cached) " >&6
24212430 else
24222431 ac_build_alias=$build_alias
@@ -2450,7 +2459,7 @@
24502459
24512460 { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
24522461 $as_echo_n "checking host system type... " >&6; }
2453-if test "${ac_cv_host+set}" = set; then :
2462+if ${ac_cv_host+:} false; then :
24542463 $as_echo_n "(cached) " >&6
24552464 else
24562465 if test "x$host_alias" = x; then
@@ -2483,7 +2492,7 @@
24832492
24842493 { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
24852494 $as_echo_n "checking target system type... " >&6; }
2486-if test "${ac_cv_target+set}" = set; then :
2495+if ${ac_cv_target+:} false; then :
24872496 $as_echo_n "(cached) " >&6
24882497 else
24892498 if test "x$target_alias" = x; then
@@ -2540,7 +2549,7 @@
25402549 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
25412550 $as_echo_n "checking for a BSD-compatible install... " >&6; }
25422551 if test -z "$INSTALL"; then
2543-if test "${ac_cv_path_install+set}" = set; then :
2552+if ${ac_cv_path_install+:} false; then :
25442553 $as_echo_n "(cached) " >&6
25452554 else
25462555 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -2717,7 +2726,7 @@
27172726 set dummy ${ac_tool_prefix}strip; ac_word=$2
27182727 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
27192728 $as_echo_n "checking for $ac_word... " >&6; }
2720-if test "${ac_cv_prog_STRIP+set}" = set; then :
2729+if ${ac_cv_prog_STRIP+:} false; then :
27212730 $as_echo_n "(cached) " >&6
27222731 else
27232732 if test -n "$STRIP"; then
@@ -2757,7 +2766,7 @@
27572766 set dummy strip; ac_word=$2
27582767 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
27592768 $as_echo_n "checking for $ac_word... " >&6; }
2760-if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
2769+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
27612770 $as_echo_n "(cached) " >&6
27622771 else
27632772 if test -n "$ac_ct_STRIP"; then
@@ -2810,7 +2819,7 @@
28102819 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
28112820 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
28122821 if test -z "$MKDIR_P"; then
2813- if test "${ac_cv_path_mkdir+set}" = set; then :
2822+ if ${ac_cv_path_mkdir+:} false; then :
28142823 $as_echo_n "(cached) " >&6
28152824 else
28162825 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -2861,7 +2870,7 @@
28612870 set dummy $ac_prog; ac_word=$2
28622871 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
28632872 $as_echo_n "checking for $ac_word... " >&6; }
2864-if test "${ac_cv_prog_AWK+set}" = set; then :
2873+if ${ac_cv_prog_AWK+:} false; then :
28652874 $as_echo_n "(cached) " >&6
28662875 else
28672876 if test -n "$AWK"; then
@@ -2901,7 +2910,7 @@
29012910 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
29022911 set x ${MAKE-make}
29032912 ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
2904-if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\"" = set; then :
2913+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
29052914 $as_echo_n "(cached) " >&6
29062915 else
29072916 cat >conftest.make <<\_ACEOF
@@ -2959,7 +2968,7 @@
29592968
29602969 # Define the identity of the package.
29612970 PACKAGE='AlephOne'
2962- VERSION='20110417'
2971+ VERSION='20110626'
29632972
29642973
29652974 cat >>confdefs.h <<_ACEOF
@@ -3090,7 +3099,7 @@
30903099 set dummy ${ac_tool_prefix}gcc; ac_word=$2
30913100 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
30923101 $as_echo_n "checking for $ac_word... " >&6; }
3093-if test "${ac_cv_prog_CC+set}" = set; then :
3102+if ${ac_cv_prog_CC+:} false; then :
30943103 $as_echo_n "(cached) " >&6
30953104 else
30963105 if test -n "$CC"; then
@@ -3130,7 +3139,7 @@
31303139 set dummy gcc; ac_word=$2
31313140 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
31323141 $as_echo_n "checking for $ac_word... " >&6; }
3133-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
3142+if ${ac_cv_prog_ac_ct_CC+:} false; then :
31343143 $as_echo_n "(cached) " >&6
31353144 else
31363145 if test -n "$ac_ct_CC"; then
@@ -3183,7 +3192,7 @@
31833192 set dummy ${ac_tool_prefix}cc; ac_word=$2
31843193 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
31853194 $as_echo_n "checking for $ac_word... " >&6; }
3186-if test "${ac_cv_prog_CC+set}" = set; then :
3195+if ${ac_cv_prog_CC+:} false; then :
31873196 $as_echo_n "(cached) " >&6
31883197 else
31893198 if test -n "$CC"; then
@@ -3223,7 +3232,7 @@
32233232 set dummy cc; ac_word=$2
32243233 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
32253234 $as_echo_n "checking for $ac_word... " >&6; }
3226-if test "${ac_cv_prog_CC+set}" = set; then :
3235+if ${ac_cv_prog_CC+:} false; then :
32273236 $as_echo_n "(cached) " >&6
32283237 else
32293238 if test -n "$CC"; then
@@ -3282,7 +3291,7 @@
32823291 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
32833292 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
32843293 $as_echo_n "checking for $ac_word... " >&6; }
3285-if test "${ac_cv_prog_CC+set}" = set; then :
3294+if ${ac_cv_prog_CC+:} false; then :
32863295 $as_echo_n "(cached) " >&6
32873296 else
32883297 if test -n "$CC"; then
@@ -3326,7 +3335,7 @@
33263335 set dummy $ac_prog; ac_word=$2
33273336 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
33283337 $as_echo_n "checking for $ac_word... " >&6; }
3329-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
3338+if ${ac_cv_prog_ac_ct_CC+:} false; then :
33303339 $as_echo_n "(cached) " >&6
33313340 else
33323341 if test -n "$ac_ct_CC"; then
@@ -3609,7 +3618,7 @@
36093618 ac_clean_files=$ac_clean_files_save
36103619 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
36113620 $as_echo_n "checking for suffix of object files... " >&6; }
3612-if test "${ac_cv_objext+set}" = set; then :
3621+if ${ac_cv_objext+:} false; then :
36133622 $as_echo_n "(cached) " >&6
36143623 else
36153624 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3660,7 +3669,7 @@
36603669 ac_objext=$OBJEXT
36613670 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
36623671 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
3663-if test "${ac_cv_c_compiler_gnu+set}" = set; then :
3672+if ${ac_cv_c_compiler_gnu+:} false; then :
36643673 $as_echo_n "(cached) " >&6
36653674 else
36663675 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3697,7 +3706,7 @@
36973706 ac_save_CFLAGS=$CFLAGS
36983707 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
36993708 $as_echo_n "checking whether $CC accepts -g... " >&6; }
3700-if test "${ac_cv_prog_cc_g+set}" = set; then :
3709+if ${ac_cv_prog_cc_g+:} false; then :
37013710 $as_echo_n "(cached) " >&6
37023711 else
37033712 ac_save_c_werror_flag=$ac_c_werror_flag
@@ -3775,7 +3784,7 @@
37753784 fi
37763785 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
37773786 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
3778-if test "${ac_cv_prog_cc_c89+set}" = set; then :
3787+if ${ac_cv_prog_cc_c89+:} false; then :
37793788 $as_echo_n "(cached) " >&6
37803789 else
37813790 ac_cv_prog_cc_c89=no
@@ -3936,7 +3945,7 @@
39363945
39373946 { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
39383947 $as_echo_n "checking dependency style of $depcc... " >&6; }
3939-if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then :
3948+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
39403949 $as_echo_n "(cached) " >&6
39413950 else
39423951 if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
@@ -4071,7 +4080,7 @@
40714080 CPP=
40724081 fi
40734082 if test -z "$CPP"; then
4074- if test "${ac_cv_prog_CPP+set}" = set; then :
4083+ if ${ac_cv_prog_CPP+:} false; then :
40754084 $as_echo_n "(cached) " >&6
40764085 else
40774086 # Double quotes because CPP needs to be expanded
@@ -4101,7 +4110,7 @@
41014110 # Broken: fails on valid input.
41024111 continue
41034112 fi
4104-rm -f conftest.err conftest.$ac_ext
4113+rm -f conftest.err conftest.i conftest.$ac_ext
41054114
41064115 # OK, works on sane cases. Now check whether nonexistent headers
41074116 # can be detected and how.
@@ -4117,11 +4126,11 @@
41174126 ac_preproc_ok=:
41184127 break
41194128 fi
4120-rm -f conftest.err conftest.$ac_ext
4129+rm -f conftest.err conftest.i conftest.$ac_ext
41214130
41224131 done
41234132 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
4124-rm -f conftest.err conftest.$ac_ext
4133+rm -f conftest.i conftest.err conftest.$ac_ext
41254134 if $ac_preproc_ok; then :
41264135 break
41274136 fi
@@ -4160,7 +4169,7 @@
41604169 # Broken: fails on valid input.
41614170 continue
41624171 fi
4163-rm -f conftest.err conftest.$ac_ext
4172+rm -f conftest.err conftest.i conftest.$ac_ext
41644173
41654174 # OK, works on sane cases. Now check whether nonexistent headers
41664175 # can be detected and how.
@@ -4176,11 +4185,11 @@
41764185 ac_preproc_ok=:
41774186 break
41784187 fi
4179-rm -f conftest.err conftest.$ac_ext
4188+rm -f conftest.err conftest.i conftest.$ac_ext
41804189
41814190 done
41824191 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
4183-rm -f conftest.err conftest.$ac_ext
4192+rm -f conftest.i conftest.err conftest.$ac_ext
41844193 if $ac_preproc_ok; then :
41854194
41864195 else
@@ -4212,7 +4221,7 @@
42124221 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
42134222 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
42144223 $as_echo_n "checking for $ac_word... " >&6; }
4215-if test "${ac_cv_prog_CXX+set}" = set; then :
4224+if ${ac_cv_prog_CXX+:} false; then :
42164225 $as_echo_n "(cached) " >&6
42174226 else
42184227 if test -n "$CXX"; then
@@ -4256,7 +4265,7 @@
42564265 set dummy $ac_prog; ac_word=$2
42574266 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
42584267 $as_echo_n "checking for $ac_word... " >&6; }
4259-if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
4268+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
42604269 $as_echo_n "(cached) " >&6
42614270 else
42624271 if test -n "$ac_ct_CXX"; then
@@ -4334,7 +4343,7 @@
43344343
43354344 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
43364345 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
4337-if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
4346+if ${ac_cv_cxx_compiler_gnu+:} false; then :
43384347 $as_echo_n "(cached) " >&6
43394348 else
43404349 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4371,7 +4380,7 @@
43714380 ac_save_CXXFLAGS=$CXXFLAGS
43724381 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
43734382 $as_echo_n "checking whether $CXX accepts -g... " >&6; }
4374-if test "${ac_cv_prog_cxx_g+set}" = set; then :
4383+if ${ac_cv_prog_cxx_g+:} false; then :
43754384 $as_echo_n "(cached) " >&6
43764385 else
43774386 ac_save_cxx_werror_flag=$ac_cxx_werror_flag
@@ -4457,7 +4466,7 @@
44574466
44584467 { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
44594468 $as_echo_n "checking dependency style of $depcc... " >&6; }
4460-if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then :
4469+if ${am_cv_CXX_dependencies_compiler_type+:} false; then :
44614470 $as_echo_n "(cached) " >&6
44624471 else
44634472 if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
@@ -4588,7 +4597,7 @@
45884597 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
45894598 $as_echo_n "checking how to run the C++ preprocessor... " >&6; }
45904599 if test -z "$CXXCPP"; then
4591- if test "${ac_cv_prog_CXXCPP+set}" = set; then :
4600+ if ${ac_cv_prog_CXXCPP+:} false; then :
45924601 $as_echo_n "(cached) " >&6
45934602 else
45944603 # Double quotes because CXXCPP needs to be expanded
@@ -4618,7 +4627,7 @@
46184627 # Broken: fails on valid input.
46194628 continue
46204629 fi
4621-rm -f conftest.err conftest.$ac_ext
4630+rm -f conftest.err conftest.i conftest.$ac_ext
46224631
46234632 # OK, works on sane cases. Now check whether nonexistent headers
46244633 # can be detected and how.
@@ -4634,11 +4643,11 @@
46344643 ac_preproc_ok=:
46354644 break
46364645 fi
4637-rm -f conftest.err conftest.$ac_ext
4646+rm -f conftest.err conftest.i conftest.$ac_ext
46384647
46394648 done
46404649 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
4641-rm -f conftest.err conftest.$ac_ext
4650+rm -f conftest.i conftest.err conftest.$ac_ext
46424651 if $ac_preproc_ok; then :
46434652 break
46444653 fi
@@ -4677,7 +4686,7 @@
46774686 # Broken: fails on valid input.
46784687 continue
46794688 fi
4680-rm -f conftest.err conftest.$ac_ext
4689+rm -f conftest.err conftest.i conftest.$ac_ext
46814690
46824691 # OK, works on sane cases. Now check whether nonexistent headers
46834692 # can be detected and how.
@@ -4693,11 +4702,11 @@
46934702 ac_preproc_ok=:
46944703 break
46954704 fi
4696-rm -f conftest.err conftest.$ac_ext
4705+rm -f conftest.err conftest.i conftest.$ac_ext
46974706
46984707 done
46994708 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
4700-rm -f conftest.err conftest.$ac_ext
4709+rm -f conftest.i conftest.err conftest.$ac_ext
47014710 if $ac_preproc_ok; then :
47024711
47034712 else
@@ -4719,7 +4728,7 @@
47194728 set dummy ${ac_tool_prefix}ranlib; ac_word=$2
47204729 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
47214730 $as_echo_n "checking for $ac_word... " >&6; }
4722-if test "${ac_cv_prog_RANLIB+set}" = set; then :
4731+if ${ac_cv_prog_RANLIB+:} false; then :
47234732 $as_echo_n "(cached) " >&6
47244733 else
47254734 if test -n "$RANLIB"; then
@@ -4759,7 +4768,7 @@
47594768 set dummy ranlib; ac_word=$2
47604769 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
47614770 $as_echo_n "checking for $ac_word... " >&6; }
4762-if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
4771+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
47634772 $as_echo_n "(cached) " >&6
47644773 else
47654774 if test -n "$ac_ct_RANLIB"; then
@@ -4814,7 +4823,7 @@
48144823 set dummy ${ac_tool_prefix}windres; ac_word=$2
48154824 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
48164825 $as_echo_n "checking for $ac_word... " >&6; }
4817-if test "${ac_cv_prog_WINDRES+set}" = set; then :
4826+if ${ac_cv_prog_WINDRES+:} false; then :
48184827 $as_echo_n "(cached) " >&6
48194828 else
48204829 if test -n "$WINDRES"; then
@@ -4854,7 +4863,7 @@
48544863 set dummy windres; ac_word=$2
48554864 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
48564865 $as_echo_n "checking for $ac_word... " >&6; }
4857-if test "${ac_cv_prog_ac_ct_WINDRES+set}" = set; then :
4866+if ${ac_cv_prog_ac_ct_WINDRES+:} false; then :
48584867 $as_echo_n "(cached) " >&6
48594868 else
48604869 if test -n "$ac_ct_WINDRES"; then
@@ -4913,7 +4922,7 @@
49134922
49144923 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
49154924 $as_echo_n "checking for grep that handles long lines and -e... " >&6; }
4916-if test "${ac_cv_path_GREP+set}" = set; then :
4925+if ${ac_cv_path_GREP+:} false; then :
49174926 $as_echo_n "(cached) " >&6
49184927 else
49194928 if test -z "$GREP"; then
@@ -4976,7 +4985,7 @@
49764985
49774986 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
49784987 $as_echo_n "checking for egrep... " >&6; }
4979-if test "${ac_cv_path_EGREP+set}" = set; then :
4988+if ${ac_cv_path_EGREP+:} false; then :
49804989 $as_echo_n "(cached) " >&6
49814990 else
49824991 if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
@@ -5043,7 +5052,7 @@
50435052
50445053 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
50455054 $as_echo_n "checking for ANSI C header files... " >&6; }
5046-if test "${ac_cv_header_stdc+set}" = set; then :
5055+if ${ac_cv_header_stdc+:} false; then :
50475056 $as_echo_n "(cached) " >&6
50485057 else
50495058 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5173,7 +5182,7 @@
51735182 for ac_header in unistd.h
51745183 do :
51755184 ac_fn_c_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default"
5176-if test "x$ac_cv_header_unistd_h" = x""yes; then :
5185+if test "x$ac_cv_header_unistd_h" = xyes; then :
51775186 cat >>confdefs.h <<_ACEOF
51785187 #define HAVE_UNISTD_H 1
51795188 _ACEOF
@@ -5185,7 +5194,7 @@
51855194 for ac_header in pwd.h
51865195 do :
51875196 ac_fn_c_check_header_mongrel "$LINENO" "pwd.h" "ac_cv_header_pwd_h" "$ac_includes_default"
5188-if test "x$ac_cv_header_pwd_h" = x""yes; then :
5197+if test "x$ac_cv_header_pwd_h" = xyes; then :
51895198 cat >>confdefs.h <<_ACEOF
51905199 #define HAVE_PWD_H 1
51915200 _ACEOF
@@ -5196,7 +5205,7 @@
51965205
51975206
51985207 ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf"
5199-if test "x$ac_cv_func_snprintf" = x""yes; then :
5208+if test "x$ac_cv_func_snprintf" = xyes; then :
52005209
52015210
52025211 $as_echo "#define HAVE_SNPRINTF 1" >>confdefs.h
@@ -5205,7 +5214,7 @@
52055214 fi
52065215
52075216 ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf"
5208-if test "x$ac_cv_func_vsnprintf" = x""yes; then :
5217+if test "x$ac_cv_func_vsnprintf" = xyes; then :
52095218
52105219
52115220 $as_echo "#define HAVE_VSNPRINTF 1" >>confdefs.h
@@ -5215,7 +5224,7 @@
52155224
52165225
52175226 ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp"
5218-if test "x$ac_cv_func_mkstemp" = x""yes; then :
5227+if test "x$ac_cv_func_mkstemp" = xyes; then :
52195228
52205229
52215230 $as_echo "#define LUA_USE_MKSTEMP 1" >>confdefs.h
@@ -5269,7 +5278,7 @@
52695278 set dummy sdl-config; ac_word=$2
52705279 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
52715280 $as_echo_n "checking for $ac_word... " >&6; }
5272-if test "${ac_cv_path_SDL_CONFIG+set}" = set; then :
5281+if ${ac_cv_path_SDL_CONFIG+:} false; then :
52735282 $as_echo_n "(cached) " >&6
52745283 else
52755284 case $SDL_CONFIG in
@@ -5485,7 +5494,7 @@
54855494 for ac_header in SDL_image.h
54865495 do :
54875496 ac_fn_c_check_header_mongrel "$LINENO" "SDL_image.h" "ac_cv_header_SDL_image_h" "$ac_includes_default"
5488-if test "x$ac_cv_header_SDL_image_h" = x""yes; then :
5497+if test "x$ac_cv_header_SDL_image_h" = xyes; then :
54895498 cat >>confdefs.h <<_ACEOF
54905499 #define HAVE_SDL_IMAGE_H 1
54915500 _ACEOF
@@ -5492,7 +5501,7 @@
54925501
54935502 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IMG_Load in -lSDL_image" >&5
54945503 $as_echo_n "checking for IMG_Load in -lSDL_image... " >&6; }
5495-if test "${ac_cv_lib_SDL_image_IMG_Load+set}" = set; then :
5504+if ${ac_cv_lib_SDL_image_IMG_Load+:} false; then :
54965505 $as_echo_n "(cached) " >&6
54975506 else
54985507 ac_check_lib_save_LIBS=$LIBS
@@ -5526,7 +5535,7 @@
55265535 fi
55275536 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_SDL_image_IMG_Load" >&5
55285537 $as_echo "$ac_cv_lib_SDL_image_IMG_Load" >&6; }
5529-if test "x$ac_cv_lib_SDL_image_IMG_Load" = x""yes; then :
5538+if test "x$ac_cv_lib_SDL_image_IMG_Load" = xyes; then :
55305539
55315540 LIBS="-lSDL_image $LIBS"
55325541
@@ -5545,7 +5554,7 @@
55455554 for ac_header in SDL_ttf.h
55465555 do :
55475556 ac_fn_c_check_header_mongrel "$LINENO" "SDL_ttf.h" "ac_cv_header_SDL_ttf_h" "$ac_includes_default"
5548-if test "x$ac_cv_header_SDL_ttf_h" = x""yes; then :
5557+if test "x$ac_cv_header_SDL_ttf_h" = xyes; then :
55495558 cat >>confdefs.h <<_ACEOF
55505559 #define HAVE_SDL_TTF_H 1
55515560 _ACEOF
@@ -5552,7 +5561,7 @@
55525561
55535562 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TTF_Init in -lSDL_ttf" >&5
55545563 $as_echo_n "checking for TTF_Init in -lSDL_ttf... " >&6; }
5555-if test "${ac_cv_lib_SDL_ttf_TTF_Init+set}" = set; then :
5564+if ${ac_cv_lib_SDL_ttf_TTF_Init+:} false; then :
55565565 $as_echo_n "(cached) " >&6
55575566 else
55585567 ac_check_lib_save_LIBS=$LIBS
@@ -5586,7 +5595,7 @@
55865595 fi
55875596 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_SDL_ttf_TTF_Init" >&5
55885597 $as_echo "$ac_cv_lib_SDL_ttf_TTF_Init" >&6; }
5589-if test "x$ac_cv_lib_SDL_ttf_TTF_Init" = x""yes; then :
5598+if test "x$ac_cv_lib_SDL_ttf_TTF_Init" = xyes; then :
55905599
55915600 LIBS="-lSDL_ttf $LIBS"
55925601
@@ -5605,7 +5614,7 @@
56055614 for ac_header in SDL_net.h
56065615 do :
56075616 ac_fn_c_check_header_mongrel "$LINENO" "SDL_net.h" "ac_cv_header_SDL_net_h" "$ac_includes_default"
5608-if test "x$ac_cv_header_SDL_net_h" = x""yes; then :
5617+if test "x$ac_cv_header_SDL_net_h" = xyes; then :
56095618 cat >>confdefs.h <<_ACEOF
56105619 #define HAVE_SDL_NET_H 1
56115620 _ACEOF
@@ -5612,7 +5621,7 @@
56125621
56135622 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDLNet_Init in -lSDL_net" >&5
56145623 $as_echo_n "checking for SDLNet_Init in -lSDL_net... " >&6; }
5615-if test "${ac_cv_lib_SDL_net_SDLNet_Init+set}" = set; then :
5624+if ${ac_cv_lib_SDL_net_SDLNet_Init+:} false; then :
56165625 $as_echo_n "(cached) " >&6
56175626 else
56185627 ac_check_lib_save_LIBS=$LIBS
@@ -5646,7 +5655,7 @@
56465655 fi
56475656 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_SDL_net_SDLNet_Init" >&5
56485657 $as_echo "$ac_cv_lib_SDL_net_SDLNet_Init" >&6; }
5649-if test "x$ac_cv_lib_SDL_net_SDLNet_Init" = x""yes; then :
5658+if test "x$ac_cv_lib_SDL_net_SDLNet_Init" = xyes; then :
56505659
56515660 LIBS="-lSDL_net $LIBS"
56525661
@@ -5674,7 +5683,7 @@
56745683
56755684 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
56765685 $as_echo_n "checking for library containing gethostbyname... " >&6; }
5677-if test "${ac_cv_search_gethostbyname+set}" = set; then :
5686+if ${ac_cv_search_gethostbyname+:} false; then :
56785687 $as_echo_n "(cached) " >&6
56795688 else
56805689 ac_func_search_save_LIBS=$LIBS
@@ -5708,11 +5717,11 @@
57085717 fi
57095718 rm -f core conftest.err conftest.$ac_objext \
57105719 conftest$ac_exeext
5711- if test "${ac_cv_search_gethostbyname+set}" = set; then :
5720+ if ${ac_cv_search_gethostbyname+:} false; then :
57125721 break
57135722 fi
57145723 done
5715-if test "${ac_cv_search_gethostbyname+set}" = set; then :
5724+if ${ac_cv_search_gethostbyname+:} false; then :
57165725
57175726 else
57185727 ac_cv_search_gethostbyname=no
@@ -5730,7 +5739,7 @@
57305739
57315740 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
57325741 $as_echo_n "checking for library containing socket... " >&6; }
5733-if test "${ac_cv_search_socket+set}" = set; then :
5742+if ${ac_cv_search_socket+:} false; then :
57345743 $as_echo_n "(cached) " >&6
57355744 else
57365745 ac_func_search_save_LIBS=$LIBS
@@ -5764,11 +5773,11 @@
57645773 fi
57655774 rm -f core conftest.err conftest.$ac_objext \
57665775 conftest$ac_exeext
5767- if test "${ac_cv_search_socket+set}" = set; then :
5776+ if ${ac_cv_search_socket+:} false; then :
57685777 break
57695778 fi
57705779 done
5771-if test "${ac_cv_search_socket+set}" = set; then :
5780+if ${ac_cv_search_socket+:} false; then :
57725781
57735782 else
57745783 ac_cv_search_socket=no
@@ -5785,7 +5794,7 @@
57855794 else
57865795 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lnsl" >&5
57875796 $as_echo_n "checking for socket in -lnsl... " >&6; }
5788-if test "${ac_cv_lib_nsl_socket+set}" = set; then :
5797+if ${ac_cv_lib_nsl_socket+:} false; then :
57895798 $as_echo_n "(cached) " >&6
57905799 else
57915800 ac_check_lib_save_LIBS=$LIBS
@@ -5819,7 +5828,7 @@
58195828 fi
58205829 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_socket" >&5
58215830 $as_echo "$ac_cv_lib_nsl_socket" >&6; }
5822-if test "x$ac_cv_lib_nsl_socket" = x""yes; then :
5831+if test "x$ac_cv_lib_nsl_socket" = xyes; then :
58235832 LIBS="$LIBS -lsocket -lnsl"
58245833 fi
58255834
@@ -5828,7 +5837,7 @@
58285837
58295838
58305839 ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
5831-if test "x$ac_cv_header_zlib_h" = x""yes; then :
5840+if test "x$ac_cv_header_zlib_h" = xyes; then :
58325841
58335842 else
58345843 as_fn_error $? "Aleph One requires zlib" "$LINENO" 5
@@ -5837,7 +5846,7 @@
58375846
58385847 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for zlibVersion in -lz" >&5
58395848 $as_echo_n "checking for zlibVersion in -lz... " >&6; }
5840-if test "${ac_cv_lib_z_zlibVersion+set}" = set; then :
5849+if ${ac_cv_lib_z_zlibVersion+:} false; then :
58415850 $as_echo_n "(cached) " >&6
58425851 else
58435852 ac_check_lib_save_LIBS=$LIBS
@@ -5871,7 +5880,7 @@
58715880 fi
58725881 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_zlibVersion" >&5
58735882 $as_echo "$ac_cv_lib_z_zlibVersion" >&6; }
5874-if test "x$ac_cv_lib_z_zlibVersion" = x""yes; then :
5883+if test "x$ac_cv_lib_z_zlibVersion" = xyes; then :
58755884 LIBS="-lz $LIBS"
58765885 else
58775886 as_fn_error $? "Aleph One requires zlib" "$LINENO" 5
@@ -5892,7 +5901,7 @@
58925901 set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
58935902 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
58945903 $as_echo_n "checking for $ac_word... " >&6; }
5895-if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
5904+if ${ac_cv_path_PKG_CONFIG+:} false; then :
58965905 $as_echo_n "(cached) " >&6
58975906 else
58985907 case $PKG_CONFIG in
@@ -5935,7 +5944,7 @@
59355944 set dummy pkg-config; ac_word=$2
59365945 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
59375946 $as_echo_n "checking for $ac_word... " >&6; }
5938-if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then :
5947+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
59395948 $as_echo_n "(cached) " >&6
59405949 else
59415950 case $ac_pt_PKG_CONFIG in
@@ -6226,7 +6235,7 @@
62266235
62276236
62286237 ac_fn_cxx_check_header_mongrel "$LINENO" "boost/bind.hpp" "ac_cv_header_boost_bind_hpp" "$ac_includes_default"
6229-if test "x$ac_cv_header_boost_bind_hpp" = x""yes; then :
6238+if test "x$ac_cv_header_boost_bind_hpp" = xyes; then :
62306239
62316240 else
62326241 as_fn_error $? "You need boost/bind.hpp from the boost library to run Aleph One" "$LINENO" 5
@@ -6247,7 +6256,7 @@
62476256 ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
62486257
62496258 ac_fn_cxx_check_header_mongrel "$LINENO" "boost/function.hpp" "ac_cv_header_boost_function_hpp" "$ac_includes_default"
6250-if test "x$ac_cv_header_boost_function_hpp" = x""yes; then :
6259+if test "x$ac_cv_header_boost_function_hpp" = xyes; then :
62516260
62526261 else
62536262 as_fn_error $? "You need boost/function.hpp from the boost library to run Aleph One" "$LINENO" 5
@@ -6265,7 +6274,7 @@
62656274 for ac_header in smpeg/smpeg.h
62666275 do :
62676276 ac_fn_c_check_header_mongrel "$LINENO" "smpeg/smpeg.h" "ac_cv_header_smpeg_smpeg_h" "$ac_includes_default"
6268-if test "x$ac_cv_header_smpeg_smpeg_h" = x""yes; then :
6277+if test "x$ac_cv_header_smpeg_smpeg_h" = xyes; then :
62696278 cat >>confdefs.h <<_ACEOF
62706279 #define HAVE_SMPEG_SMPEG_H 1
62716280 _ACEOF
@@ -6272,7 +6281,7 @@
62726281
62736282 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SMPEG_new in -lsmpeg" >&5
62746283 $as_echo_n "checking for SMPEG_new in -lsmpeg... " >&6; }
6275-if test "${ac_cv_lib_smpeg_SMPEG_new+set}" = set; then :
6284+if ${ac_cv_lib_smpeg_SMPEG_new+:} false; then :
62766285 $as_echo_n "(cached) " >&6
62776286 else
62786287 ac_check_lib_save_LIBS=$LIBS
@@ -6306,7 +6315,7 @@
63066315 fi
63076316 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_smpeg_SMPEG_new" >&5
63086317 $as_echo "$ac_cv_lib_smpeg_SMPEG_new" >&6; }
6309-if test "x$ac_cv_lib_smpeg_SMPEG_new" = x""yes; then :
6318+if test "x$ac_cv_lib_smpeg_SMPEG_new" = xyes; then :
63106319
63116320 LIBS="-lsmpeg $LIBS"
63126321
@@ -6326,7 +6335,7 @@
63266335 for ac_header in mad.h
63276336 do :
63286337 ac_fn_c_check_header_mongrel "$LINENO" "mad.h" "ac_cv_header_mad_h" "$ac_includes_default"
6329-if test "x$ac_cv_header_mad_h" = x""yes; then :
6338+if test "x$ac_cv_header_mad_h" = xyes; then :
63306339 cat >>confdefs.h <<_ACEOF
63316340 #define HAVE_MAD_H 1
63326341 _ACEOF
@@ -6333,7 +6342,7 @@
63336342
63346343 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mad_stream_init in -lmad" >&5
63356344 $as_echo_n "checking for mad_stream_init in -lmad... " >&6; }
6336-if test "${ac_cv_lib_mad_mad_stream_init+set}" = set; then :
6345+if ${ac_cv_lib_mad_mad_stream_init+:} false; then :
63376346 $as_echo_n "(cached) " >&6
63386347 else
63396348 ac_check_lib_save_LIBS=$LIBS
@@ -6367,7 +6376,7 @@
63676376 fi
63686377 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mad_mad_stream_init" >&5
63696378 $as_echo "$ac_cv_lib_mad_mad_stream_init" >&6; }
6370-if test "x$ac_cv_lib_mad_mad_stream_init" = x""yes; then :
6379+if test "x$ac_cv_lib_mad_mad_stream_init" = xyes; then :
63716380
63726381 LIBS="-lmad $LIBS"
63736382
@@ -6387,7 +6396,7 @@
63876396 for ac_header in sndfile.h
63886397 do :
63896398 ac_fn_c_check_header_mongrel "$LINENO" "sndfile.h" "ac_cv_header_sndfile_h" "$ac_includes_default"
6390-if test "x$ac_cv_header_sndfile_h" = x""yes; then :
6399+if test "x$ac_cv_header_sndfile_h" = xyes; then :
63916400 cat >>confdefs.h <<_ACEOF
63926401 #define HAVE_SNDFILE_H 1
63936402 _ACEOF
@@ -6394,7 +6403,7 @@
63946403
63956404 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sf_open in -lsndfile" >&5
63966405 $as_echo_n "checking for sf_open in -lsndfile... " >&6; }
6397-if test "${ac_cv_lib_sndfile_sf_open+set}" = set; then :
6406+if ${ac_cv_lib_sndfile_sf_open+:} false; then :
63986407 $as_echo_n "(cached) " >&6
63996408 else
64006409 ac_check_lib_save_LIBS=$LIBS
@@ -6428,7 +6437,7 @@
64286437 fi
64296438 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sndfile_sf_open" >&5
64306439 $as_echo "$ac_cv_lib_sndfile_sf_open" >&6; }
6431-if test "x$ac_cv_lib_sndfile_sf_open" = x""yes; then :
6440+if test "x$ac_cv_lib_sndfile_sf_open" = xyes; then :
64326441
64336442 LIBS="-lsndfile $LIBS"
64346443
@@ -6554,7 +6563,7 @@
65546563 for ac_header in speex/speex.h
65556564 do :
65566565 ac_fn_c_check_header_mongrel "$LINENO" "speex/speex.h" "ac_cv_header_speex_speex_h" "$ac_includes_default"
6557-if test "x$ac_cv_header_speex_speex_h" = x""yes; then :
6566+if test "x$ac_cv_header_speex_speex_h" = xyes; then :
65586567 cat >>confdefs.h <<_ACEOF
65596568 #define HAVE_SPEEX_SPEEX_H 1
65606569 _ACEOF
@@ -6561,7 +6570,7 @@
65616570
65626571 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for speex_decoder_init in -lspeex" >&5
65636572 $as_echo_n "checking for speex_decoder_init in -lspeex... " >&6; }
6564-if test "${ac_cv_lib_speex_speex_decoder_init+set}" = set; then :
6573+if ${ac_cv_lib_speex_speex_decoder_init+:} false; then :
65656574 $as_echo_n "(cached) " >&6
65666575 else
65676576 ac_check_lib_save_LIBS=$LIBS
@@ -6595,7 +6604,7 @@
65956604 fi
65966605 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_speex_speex_decoder_init" >&5
65976606 $as_echo "$ac_cv_lib_speex_speex_decoder_init" >&6; }
6598-if test "x$ac_cv_lib_speex_speex_decoder_init" = x""yes; then :
6607+if test "x$ac_cv_lib_speex_speex_decoder_init" = xyes; then :
65996608
66006609 LIBS="-lspeex $LIBS"
66016610
@@ -6606,7 +6615,7 @@
66066615
66076616 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for speex_preprocess_state_init in -lspeexdsp" >&5
66086617 $as_echo_n "checking for speex_preprocess_state_init in -lspeexdsp... " >&6; }
6609-if test "${ac_cv_lib_speexdsp_speex_preprocess_state_init+set}" = set; then :
6618+if ${ac_cv_lib_speexdsp_speex_preprocess_state_init+:} false; then :
66106619 $as_echo_n "(cached) " >&6
66116620 else
66126621 ac_check_lib_save_LIBS=$LIBS
@@ -6640,7 +6649,7 @@
66406649 fi
66416650 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_speexdsp_speex_preprocess_state_init" >&5
66426651 $as_echo "$ac_cv_lib_speexdsp_speex_preprocess_state_init" >&6; }
6643-if test "x$ac_cv_lib_speexdsp_speex_preprocess_state_init" = x""yes; then :
6652+if test "x$ac_cv_lib_speexdsp_speex_preprocess_state_init" = xyes; then :
66446653
66456654 LIBS="-lspeexdsp $LIBS"
66466655
@@ -6657,7 +6666,7 @@
66576666 for ac_header in alsa/asoundlib.h
66586667 do :
66596668 ac_fn_c_check_header_mongrel "$LINENO" "alsa/asoundlib.h" "ac_cv_header_alsa_asoundlib_h" "$ac_includes_default"
6660-if test "x$ac_cv_header_alsa_asoundlib_h" = x""yes; then :
6669+if test "x$ac_cv_header_alsa_asoundlib_h" = xyes; then :
66616670 cat >>confdefs.h <<_ACEOF
66626671 #define HAVE_ALSA_ASOUNDLIB_H 1
66636672 _ACEOF
@@ -6664,7 +6673,7 @@
66646673
66656674 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for snd_pcm_open in -lasound" >&5
66666675 $as_echo_n "checking for snd_pcm_open in -lasound... " >&6; }
6667-if test "${ac_cv_lib_asound_snd_pcm_open+set}" = set; then :
6676+if ${ac_cv_lib_asound_snd_pcm_open+:} false; then :
66686677 $as_echo_n "(cached) " >&6
66696678 else
66706679 ac_check_lib_save_LIBS=$LIBS
@@ -6698,7 +6707,7 @@
66986707 fi
66996708 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_asound_snd_pcm_open" >&5
67006709 $as_echo "$ac_cv_lib_asound_snd_pcm_open" >&6; }
6701-if test "x$ac_cv_lib_asound_snd_pcm_open" = x""yes; then :
6710+if test "x$ac_cv_lib_asound_snd_pcm_open" = xyes; then :
67026711
67036712 LIBS="-lasound $LIBS"
67046713
@@ -6767,7 +6776,7 @@
67676776
67686777 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gluScaleImage in -lGLU" >&5
67696778 $as_echo_n "checking for gluScaleImage in -lGLU... " >&6; }
6770-if test "${ac_cv_lib_GLU_gluScaleImage+set}" = set; then :
6779+if ${ac_cv_lib_GLU_gluScaleImage+:} false; then :
67716780 $as_echo_n "(cached) " >&6
67726781 else
67736782 ac_check_lib_save_LIBS=$LIBS
@@ -6801,7 +6810,7 @@
68016810 fi
68026811 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GLU_gluScaleImage" >&5
68036812 $as_echo "$ac_cv_lib_GLU_gluScaleImage" >&6; }
6804-if test "x$ac_cv_lib_GLU_gluScaleImage" = x""yes; then :
6813+if test "x$ac_cv_lib_GLU_gluScaleImage" = xyes; then :
68056814 SYS_GL_LIBS="$SYS_GL_LIBS -lGLU"
68066815 fi
68076816
@@ -6810,7 +6819,7 @@
68106819 do :
68116820 ac_fn_c_check_header_compile "$LINENO" "GL/glext.h" "ac_cv_header_GL_glext_h" "#include <GL/gl.h>
68126821 "
6813-if test "x$ac_cv_header_GL_glext_h" = x""yes; then :
6822+if test "x$ac_cv_header_GL_glext_h" = xyes; then :
68146823 cat >>confdefs.h <<_ACEOF
68156824 #define HAVE_GL_GLEXT_H 1
68166825 _ACEOF
@@ -6928,10 +6937,21 @@
69286937 :end' >>confcache
69296938 if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
69306939 if test -w "$cache_file"; then
6931- test "x$cache_file" != "x/dev/null" &&
6940+ if test "x$cache_file" != "x/dev/null"; then
69326941 { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
69336942 $as_echo "$as_me: updating cache $cache_file" >&6;}
6934- cat confcache >$cache_file
6943+ if test ! -f "$cache_file" || test -h "$cache_file"; then
6944+ cat confcache >"$cache_file"
6945+ else
6946+ case $cache_file in #(
6947+ */* | ?:*)
6948+ mv -f confcache "$cache_file"$$ &&
6949+ mv -f "$cache_file"$$ "$cache_file" ;; #(
6950+ *)
6951+ mv -f confcache "$cache_file" ;;
6952+ esac
6953+ fi
6954+ fi
69356955 else
69366956 { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
69376957 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
@@ -7003,7 +7023,7 @@
70037023 Usually this means the macro was only invoked conditionally." "$LINENO" 5
70047024 fi
70057025
7006-: ${CONFIG_STATUS=./config.status}
7026+: "${CONFIG_STATUS=./config.status}"
70077027 ac_write_fail=0
70087028 ac_clean_files_save=$ac_clean_files
70097029 ac_clean_files="$ac_clean_files $CONFIG_STATUS"
@@ -7104,6 +7124,7 @@
71047124 IFS=" "" $as_nl"
71057125
71067126 # Find who we are. Look in the path if we contain no directory separator.
7127+as_myself=
71077128 case $0 in #((
71087129 *[\\/]* ) as_myself=$0 ;;
71097130 *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -7410,8 +7431,8 @@
74107431 # report actual input values of CONFIG_FILES etc. instead of their
74117432 # values after options handling.
74127433 ac_log="
7413-This file was extended by Aleph One/SDL $as_me 20110417, which was
7414-generated by GNU Autoconf 2.66. Invocation command line was
7434+This file was extended by Aleph One/SDL $as_me 20110626, which was
7435+generated by GNU Autoconf 2.68. Invocation command line was
74157436
74167437 CONFIG_FILES = $CONFIG_FILES
74177438 CONFIG_HEADERS = $CONFIG_HEADERS
@@ -7476,8 +7497,8 @@
74767497 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
74777498 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
74787499 ac_cs_version="\\
7479-Aleph One/SDL config.status 20110417
7480-configured by $0, generated by GNU Autoconf 2.66,
7500+Aleph One/SDL config.status 20110626
7501+configured by $0, generated by GNU Autoconf 2.68,
74817502 with options \\"\$ac_cs_config\\"
74827503
74837504 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -7498,11 +7519,16 @@
74987519 while test $# != 0
74997520 do
75007521 case $1 in
7501- --*=*)
7522+ --*=?*)
75027523 ac_option=`expr "X$1" : 'X\([^=]*\)='`
75037524 ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
75047525 ac_shift=:
75057526 ;;
7527+ --*=)
7528+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
7529+ ac_optarg=
7530+ ac_shift=:
7531+ ;;
75067532 *)
75077533 ac_option=$1
75087534 ac_optarg=$2
@@ -7524,6 +7550,7 @@
75247550 $ac_shift
75257551 case $ac_optarg in
75267552 *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
7553+ '') as_fn_error $? "missing file argument" ;;
75277554 esac
75287555 as_fn_append CONFIG_FILES " '$ac_optarg'"
75297556 ac_need_defaults=false;;
@@ -7647,9 +7674,10 @@
76477674 # after its creation but before its name has been assigned to `$tmp'.
76487675 $debug ||
76497676 {
7650- tmp=
7677+ tmp= ac_tmp=
76517678 trap 'exit_status=$?
7652- { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
7679+ : "${ac_tmp:=$tmp}"
7680+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
76537681 ' 0
76547682 trap 'as_fn_exit 1' 1 2 13 15
76557683 }
@@ -7657,12 +7685,13 @@
76577685
76587686 {
76597687 tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
7660- test -n "$tmp" && test -d "$tmp"
7688+ test -d "$tmp"
76617689 } ||
76627690 {
76637691 tmp=./conf$$-$RANDOM
76647692 (umask 077 && mkdir "$tmp")
76657693 } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
7694+ac_tmp=$tmp
76667695
76677696 # Set up the scripts for CONFIG_FILES section.
76687697 # No need to generate them if there are no CONFIG_FILES.
@@ -7684,7 +7713,7 @@
76847713 ac_cs_awk_cr=$ac_cr
76857714 fi
76867715
7687-echo 'BEGIN {' >"$tmp/subs1.awk" &&
7716+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
76887717 _ACEOF
76897718
76907719
@@ -7712,7 +7741,7 @@
77127741 rm -f conf$$subs.sh
77137742
77147743 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
7715-cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
7744+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
77167745 _ACEOF
77177746 sed -n '
77187747 h
@@ -7760,7 +7789,7 @@
77607789 rm -f conf$$subs.awk
77617790 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
77627791 _ACAWK
7763-cat >>"\$tmp/subs1.awk" <<_ACAWK &&
7792+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
77647793 for (key in S) S_is_set[key] = 1
77657794 FS = ""
77667795
@@ -7792,7 +7821,7 @@
77927821 sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
77937822 else
77947823 cat
7795-fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
7824+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
77967825 || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
77977826 _ACEOF
77987827
@@ -7826,7 +7855,7 @@
78267855 # No need to generate them if there are no CONFIG_HEADERS.
78277856 # This happens for instance with `./config.status Makefile'.
78287857 if test -n "$CONFIG_HEADERS"; then
7829-cat >"$tmp/defines.awk" <<\_ACAWK ||
7858+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
78307859 BEGIN {
78317860 _ACEOF
78327861
@@ -7838,8 +7867,8 @@
78387867 # handling of long lines.
78397868 ac_delim='%!_!# '
78407869 for ac_last_try in false false :; do
7841- ac_t=`sed -n "/$ac_delim/p" confdefs.h`
7842- if test -z "$ac_t"; then
7870+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
7871+ if test -z "$ac_tt"; then
78437872 break
78447873 elif $ac_last_try; then
78457874 as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
@@ -7959,7 +7988,7 @@
79597988 for ac_f
79607989 do
79617990 case $ac_f in
7962- -) ac_f="$tmp/stdin";;
7991+ -) ac_f="$ac_tmp/stdin";;
79637992 *) # Look for the file first in the build tree, then in the source tree
79647993 # (if the path is not absolute). The absolute path cannot be DOS-style,
79657994 # because $ac_f cannot contain `:'.
@@ -7994,7 +8023,7 @@
79948023 esac
79958024
79968025 case $ac_tag in
7997- *:-:* | *:-) cat >"$tmp/stdin" \
8026+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
79988027 || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
79998028 esac
80008029 ;;
@@ -8131,21 +8160,22 @@
81318160 s&@MKDIR_P@&$ac_MKDIR_P&;t t
81328161 $ac_datarootdir_hack
81338162 "
8134-eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
8135- || as_fn_error $? "could not create $ac_file" "$LINENO" 5
8163+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
8164+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
81368165
81378166 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
8138- { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
8139- { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
8167+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
8168+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
8169+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
81408170 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
81418171 which seems to be undefined. Please make sure it is defined" >&5
81428172 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
81438173 which seems to be undefined. Please make sure it is defined" >&2;}
81448174
8145- rm -f "$tmp/stdin"
8175+ rm -f "$ac_tmp/stdin"
81468176 case $ac_file in
8147- -) cat "$tmp/out" && rm -f "$tmp/out";;
8148- *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
8177+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
8178+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
81498179 esac \
81508180 || as_fn_error $? "could not create $ac_file" "$LINENO" 5
81518181 ;;
@@ -8156,20 +8186,20 @@
81568186 if test x"$ac_file" != x-; then
81578187 {
81588188 $as_echo "/* $configure_input */" \
8159- && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
8160- } >"$tmp/config.h" \
8189+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
8190+ } >"$ac_tmp/config.h" \
81618191 || as_fn_error $? "could not create $ac_file" "$LINENO" 5
8162- if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
8192+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
81638193 { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
81648194 $as_echo "$as_me: $ac_file is unchanged" >&6;}
81658195 else
81668196 rm -f "$ac_file"
8167- mv "$tmp/config.h" "$ac_file" \
8197+ mv "$ac_tmp/config.h" "$ac_file" \
81688198 || as_fn_error $? "could not create $ac_file" "$LINENO" 5
81698199 fi
81708200 else
81718201 $as_echo "/* $configure_input */" \
8172- && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
8202+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
81738203 || as_fn_error $? "could not create -" "$LINENO" 5
81748204 fi
81758205 # Compute "$ac_file"'s index in $config_headers.
--- marathon/trunk/Source_Files/GameWorld/physics.cpp (revision 492)
+++ marathon/trunk/Source_Files/GameWorld/physics.cpp (revision 493)
@@ -1,1008 +1,1028 @@
1-/*
2-PHYSICS.C
3-
4- Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5- and the "Aleph One" developers.
6-
7- This program is free software; you can redistribute it and/or modify
8- it under the terms of the GNU General Public License as published by
9- the Free Software Foundation; either version 2 of the License, or
10- (at your option) any later version.
11-
12- This program is distributed in the hope that it will be useful,
13- but WITHOUT ANY WARRANTY; without even the implied warranty of
14- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15- GNU General Public License for more details.
16-
17- This license is contained in the file "COPYING",
18- which is included with this source code; it is available online at
19- http://www.gnu.org/licenses/gpl.html
20-
21-Wednesday, May 11, 1994 9:32:16 AM
22-
23-Saturday, May 21, 1994 11:36:31 PM
24- missing effects due to map (i.e., gravity and collision detection). last day in san
25- jose after WWDC.
26-Sunday, May 22, 1994 11:14:55 AM
27- there are two viable methods of running a synchronized network game. the first is doom's,
28- where each player shares with each other player only his control information for that tick
29- (this imposes a maximum frame rate, as the state-of-the-world will be advanced at the same
30- time on all machines). the second is the continuous lag-tolerant model where each player
31- shares absolute information with each other player as often as possible and local machines
32- do their best at guessing what everyone else in the game is doing until they get better
33- information. whichever choice is made will change the physics drastically. we're going to
34- take the latter approach, and cache the KeyMap at interrupt time to be batch-processed
35- later at frame time.
36-
37-Feb. 4, 2000 (Loren Petrich):
38- Changed halt() to assert(false) for better debugging
39-
40-Feb 6, 2000 (Loren Petrich):
41- Added access to size of physics-definition structure
42-
43-Feb 20, 2000 (Loren Petrich):
44- Fixed chase-cam behavior: DROP_DEAD_HEIGHT is effectively zero for it.
45- Also, set up-and-down bob to zero when it is active.
46-
47-Aug 31, 2000 (Loren Petrich):
48- Added stuff for unpacking and packing
49-
50-May 16, 2002 (Woody Zenfell):
51- Letting user decide whether to auto-recenter when running
52-
53- June 14, 2003 (Woody Zenfell):
54- update_player_physics_variables() can now operate in a reduced-impact mode
55- that changes less of the game state. Useful for partial-game-state
56- save-and-restore code (as used by prediction mechanism).
57-*/
58-
59-/*
60-running backwards shouldnユt mean doom in a fistfight
61-
62-//who decides on the physics model, anyway? static_world-> or player->
63-//falling through gridlines and crapping on elevators has to do with variables->flags being wrong after the player dies
64-//absolute (or nearly-absolute) positioning information for yaw, pitch and velocity
65-//the physics model is too soft (more noticable at high frame rates)
66-//we can continually boot ourselves out of nearly-orthogonal walls by tiny amounts, resulting in a slide
67-//itユs fairly obvious that players can still end up in walls
68-//the recenter key should work faster
69-*/
70-
71-#ifdef DEBUG
72-//#define DIVERGENCE_CHECK
73-#endif
74-
75-#include "cseries.h"
76-#include "render.h"
77-#include "map.h"
78-#include "player.h"
79-#include "interface.h"
80-#include "monsters.h"
81-
82-#include "media.h"
83-
84-// LP addition:
85-#include "ChaseCam.h"
86-#include "Packing.h"
87-
88-#include <string.h>
89-
90-#ifdef env68k
91-#pragma segment player
92-#endif
93-
94-/* ---------- constants */
95-
96-#define COEFFICIENT_OF_ABSORBTION 2
97-#define SMALL_ENOUGH_VELOCITY (constants->climbing_acceleration)
98-#define CLOSE_ENOUGH_TO_FLOOR WORLD_TO_FIXED(WORLD_ONE/16)
99-
100-#define AIRBORNE_HEIGHT WORLD_TO_FIXED(WORLD_ONE/16)
101-
102-#define DROP_DEAD_HEIGHT WORLD_TO_FIXED(WORLD_ONE_HALF)
103-
104-#define FLAGS_WHICH_PREVENT_RECENTERING (_turning|_looking|_sidestepping|_looking_vertically|_look_dont_turn|_sidestep_dont_turn)
105-
106-/* ---------- private prototypes */
107-
108-/* needed for set_player_position -SB */
109-/*static*/ struct physics_constants *get_physics_constants_for_model(short physics_model, uint32 action_flags);
110-/*static*/ void instantiate_physics_variables(struct physics_constants *constants, struct physics_variables *variables, short player_index, bool first_time, bool take_action);
111-static void physics_update(struct physics_constants *constants, struct physics_variables *variables, struct player_data *player, uint32 action_flags);
112-
113-/* ---------- globals */
114-
115-/* import constants, structures and globals for physics models */
116-#include "physics_models.h"
117-
118-/* ---------- code */
119-
120-#ifdef DIVERGENCE_CHECK
121-#define SAVED_POINT_COUNT 8192
122-static world_point3d *saved_points;
123-static angle *saved_thetas;
124-static short saved_point_count, saved_point_iterations= 0;
125-static bool saved_divergence_warning;
126-#endif
127-
128-static struct physics_constants physics_models[NUMBER_OF_PHYSICS_MODELS];
129-
130-/* every other field in the player structure should be valid when this call is made */
131-void initialize_player_physics_variables(
132- short player_index)
133-{
134- struct player_data *player= get_player_data(player_index);
135- struct monster_data *monster= get_monster_data(player->monster_index);
136- struct object_data *object= get_object_data(monster->object_index);
137- struct physics_variables *variables= &player->variables;
138- struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, 0);
139-
140-//#ifdef DEBUG
141- obj_set(*variables, 0x80);
142-//#endif
143-
144- variables->head_direction= 0;
145- variables->adjusted_yaw= variables->direction= INTEGER_TO_FIXED(object->facing);
146- variables->adjusted_pitch= variables->elevation= 0;
147- variables->angular_velocity= variables->vertical_angular_velocity= 0;
148- variables->velocity= 0, variables->perpendicular_velocity= 0;
149- variables->position.x= WORLD_TO_FIXED(object->location.x);
150- variables->position.y= WORLD_TO_FIXED(object->location.y);
151- variables->position.z= WORLD_TO_FIXED(object->location.z);
152- variables->last_position= variables->position;
153- variables->last_direction= variables->direction;
154- /* .floor_height, .ceiling_height and .media_height will be calculated by instantiate, below */
155-
156- variables->external_angular_velocity= 0;
157- variables->external_velocity.i= variables->external_velocity.j= variables->external_velocity.k= 0;
158- variables->actual_height= constants->height;
159-
160- variables->step_phase= 0;
161- variables->step_amplitude= 0;
162-
163- variables->action= _player_stationary;
164- variables->old_flags= variables->flags= 0; /* not recentering, not above ground, not below ground (i.e., on floor) */
165-
166- /* setup shadow variables in player_data structure */
167- instantiate_physics_variables(get_physics_constants_for_model(static_world->physics_model, 0),
168- &player->variables, player_index, true, true);
169-
170-#ifdef DIVERGENCE_CHECK
171- if (!saved_point_iterations)
172- {
173- saved_points= new world_point3d[SAVED_POINT_COUNT];
174- saved_thetas= new angle[SAVED_POINT_COUNT];
175- }
176- saved_point_count= 0;
177- saved_point_iterations+= 1;
178- saved_divergence_warning= false;
179-#endif
180-}
181-
182-void update_player_physics_variables(
183- short player_index,
184- uint32 action_flags,
185- bool predictive)
186-{
187- struct player_data *player= get_player_data(player_index);
188- struct physics_variables *variables= &player->variables;
189- struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, action_flags);
190-
191- physics_update(constants, variables, player, action_flags);
192- instantiate_physics_variables(constants, variables, player_index, false, !predictive);
193-
194-#ifdef DIVERGENCE_CHECK
195- if (saved_point_count<SAVED_POINT_COUNT)
196- {
197- struct object_data *object= get_object_data(get_monster_data(player->monster_index)->object_index);
198- world_point3d p= object->location;
199- world_point3d *q= saved_points+saved_point_count;
200- angle *facing= saved_thetas+saved_point_count;
201-
202- if (saved_point_iterations==1)
203- {
204- saved_points[saved_point_count]= p;
205- *facing= object->facing;
206- }
207- else
208- {
209- if (p.x!=q->x||p.y!=q->y||p.z!=q->z||*facing!=object->facing&&!saved_divergence_warning)
210- {
211- dprintf("divergence @ tick %d: (%d,%d,%d,%d)!=(%d,%d,%d,%d)", saved_point_count,
212- q->x, q->y, q->z, *facing, p.x, p.y, p.z, object->facing);
213- saved_divergence_warning= true;
214- }
215- }
216-
217- saved_point_count+= 1;
218- }
219-#endif
220-}
221-
222-void adjust_player_for_polygon_height_change(
223- short monster_index,
224- short polygon_index,
225- world_distance new_floor_height,
226- world_distance new_ceiling_height)
227-{
228- short player_index= monster_index_to_player_index(monster_index);
229- struct player_data *player= get_player_data(player_index);
230- struct physics_variables *variables= &player->variables;
231- struct polygon_data *polygon= get_polygon_data(polygon_index);
232- world_distance old_floor_height= polygon->floor_height;
233-
234- (void) (new_ceiling_height);
235-
236- if (player->supporting_polygon_index==polygon_index)
237- {
238- if (FIXED_TO_WORLD(variables->position.z)<=old_floor_height) /* must be <= */
239- {
240- variables->floor_height= variables->position.z= WORLD_TO_FIXED(new_floor_height);
241- if (PLAYER_IS_DEAD(player)) variables->external_velocity.k= 0;
242- }
243- }
244-}
245-
246-void accelerate_player(
247- short monster_index,
248- world_distance vertical_velocity,
249- angle direction,
250- world_distance velocity)
251-{
252- short player_index= monster_index_to_player_index(monster_index);
253- struct player_data *player= get_player_data(player_index);
254- struct physics_variables *variables= &player->variables;
255- struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, 0);
256-
257- variables->external_velocity.k+= WORLD_TO_FIXED(vertical_velocity);
258- variables->external_velocity.k= PIN(variables->external_velocity.k, -constants->terminal_velocity, constants->terminal_velocity);
259-
260- variables->external_velocity.i+= (cosine_table[direction]*velocity)>>(TRIG_SHIFT+WORLD_FRACTIONAL_BITS-FIXED_FRACTIONAL_BITS);
261- variables->external_velocity.j+= (sine_table[direction]*velocity)>>(TRIG_SHIFT+WORLD_FRACTIONAL_BITS-FIXED_FRACTIONAL_BITS);
262-}
263-
264-void get_absolute_pitch_range(
265- _fixed *minimum,
266- _fixed *maximum)
267-{
268- struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, 0);
269-
270- *minimum= -constants->maximum_elevation;
271- *maximum= constants->maximum_elevation;
272-}
273-
274-/* deltas of zero are ignored; all deltas must be in [-FIXED_ONE,FIXED_ONE] which will be scaled
275- to the maximum for that value */
276-uint32 mask_in_absolute_positioning_information(
277- uint32 action_flags,
278- _fixed delta_yaw,
279- _fixed delta_pitch,
280- _fixed delta_position)
281-{
282- struct physics_variables *variables= &local_player->variables;
283- short encoded_delta;
284-
285- if ((delta_yaw||variables->angular_velocity) && !(action_flags&_override_absolute_yaw))
286- {
287-// if (delta_yaw<0 && delta_yaw>((-1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_YAW_BITS))) delta_yaw= 0;
288- if (delta_yaw>0 && delta_yaw<((1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_YAW_BITS))) delta_yaw= (1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_YAW_BITS);
289- encoded_delta= (delta_yaw>>(FIXED_FRACTIONAL_BITS-ABSOLUTE_YAW_BITS))+MAXIMUM_ABSOLUTE_YAW/2;
290- encoded_delta= PIN(encoded_delta, 0, MAXIMUM_ABSOLUTE_YAW-1);
291- action_flags= SET_ABSOLUTE_YAW(action_flags, encoded_delta)|_absolute_yaw_mode;
292- }
293-
294- if ((delta_pitch||variables->vertical_angular_velocity) && !(action_flags&_override_absolute_pitch))
295- {
296-// if (delta_pitch<0 && delta_pitch>((-1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_PITCH_BITS))) delta_pitch= 0;
297- if (delta_pitch>0 && delta_pitch<((1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_PITCH_BITS))) delta_pitch= (1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_PITCH_BITS);
298- encoded_delta= (delta_pitch>>(FIXED_FRACTIONAL_BITS-ABSOLUTE_PITCH_BITS))+MAXIMUM_ABSOLUTE_PITCH/2;
299- encoded_delta= PIN(encoded_delta, 0, MAXIMUM_ABSOLUTE_PITCH-1);
300- action_flags= SET_ABSOLUTE_PITCH(action_flags, encoded_delta)|_absolute_pitch_mode;
301- }
302-
303- if (delta_position && !(action_flags&_override_absolute_position))
304- {
305- encoded_delta= (delta_position>>(FIXED_FRACTIONAL_BITS-ABSOLUTE_POSITION_BITS))+MAXIMUM_ABSOLUTE_POSITION/2;
306- encoded_delta= PIN(encoded_delta, 0, MAXIMUM_ABSOLUTE_POSITION-1);
307- action_flags= SET_ABSOLUTE_POSITION(action_flags, encoded_delta)|_absolute_position_mode;
308- }
309-
310- return action_flags;
311-}
312-
313-/* will be obsolete when cybermaxx changes to new-style */
314-void instantiate_absolute_positioning_information(
315- short player_index,
316- _fixed facing,
317- _fixed elevation)
318-{
319- struct player_data *player= get_player_data(player_index);
320- struct physics_variables *variables= &player->variables;
321- struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, 0);
322-
323- assert(elevation>=-INTEGER_TO_FIXED(QUARTER_CIRCLE)&&elevation<=INTEGER_TO_FIXED(QUARTER_CIRCLE));
324- assert(facing>=0&&facing<INTEGER_TO_FIXED(FULL_CIRCLE));
325-
326- variables->elevation= PIN(elevation, -constants->maximum_elevation, constants->maximum_elevation);
327- variables->vertical_angular_velocity= 0;
328-
329- variables->direction= facing;
330-
331- instantiate_physics_variables(constants, variables, player_index, false, true);
332-}
333-
334-void get_binocular_vision_origins(
335- short player_index,
336- world_point3d *left,
337- short *left_polygon_index,
338- angle *left_angle,
339- world_point3d *right,
340- short *right_polygon_index,
341- angle *right_angle)
342-{
343- struct player_data *player= get_player_data(player_index);
344- struct physics_variables *variables= &player->variables;
345- struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, 0);
346- angle theta;
347-
348- theta= NORMALIZE_ANGLE(player->facing+QUARTER_CIRCLE);
349- right->x= FIXED_TO_WORLD(variables->position.x + ((constants->half_camera_separation*cosine_table[theta])>>TRIG_SHIFT));
350- right->y= FIXED_TO_WORLD(variables->position.y + ((constants->half_camera_separation*sine_table[theta])>>TRIG_SHIFT));
351- right->z= player->camera_location.z;
352- *right_polygon_index= find_new_object_polygon((world_point2d *)&player->camera_location, (world_point2d *)right, player->camera_polygon_index);
353- *right_angle= NORMALIZE_ANGLE(player->facing-1);
354-
355- theta= NORMALIZE_ANGLE(player->facing-QUARTER_CIRCLE);
356- left->x= FIXED_TO_WORLD(variables->position.x + ((constants->half_camera_separation*cosine_table[theta])>>TRIG_SHIFT));
357- left->y= FIXED_TO_WORLD(variables->position.y + ((constants->half_camera_separation*sine_table[theta])>>TRIG_SHIFT));
358- left->z= player->camera_location.z;
359- *left_polygon_index= find_new_object_polygon((world_point2d *)&player->camera_location, (world_point2d *)left, player->camera_polygon_index);
360- *left_angle= NORMALIZE_ANGLE(player->facing+1);
361-}
362-
363-void kill_player_physics_variables(
364- short player_index)
365-{
366-}
367-
368-/* return a number in [-FIXED_ONE,FIXED_ONE] (arguably) */
369-_fixed get_player_forward_velocity_scale(
370- short player_index)
371-{
372- struct player_data *player= get_player_data(player_index);
373- struct physics_variables *variables= &player->variables;
374- struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, _run_dont_walk);
375- _fixed dx= variables->position.x - variables->last_position.x;
376- _fixed dy= variables->position.y - variables->last_position.y;
377-
378- return INTEGER_TO_FIXED(((dx*cosine_table[FIXED_INTEGERAL_PART(variables->direction)] +
379- dy*sine_table[FIXED_INTEGERAL_PART(variables->direction)])>>TRIG_SHIFT))/constants->maximum_forward_velocity;
380-}
381-
382-
383-
384-/* ---------- private code */
385-
386-/*static*/ struct physics_constants *get_physics_constants_for_model(
387- short physics_model,
388- uint32 action_flags)
389-{
390- struct physics_constants *constants;
391-
392- switch (physics_model)
393- {
394- case _editor_model:
395- case _earth_gravity_model: constants= physics_models + ((action_flags&_run_dont_walk) ? _model_game_running : _model_game_walking); break;
396- case _low_gravity_model:
397- assert(false);
398- break;
399- default:
400- assert(false);
401- break;
402- }
403-
404- return constants;
405-}
406-
407-/*static*/ void instantiate_physics_variables(
408- struct physics_constants *constants,
409- struct physics_variables *variables,
410- short player_index,
411- bool first_time,
412- bool take_action)
413-{
414- struct player_data *player= get_player_data(player_index);
415- struct monster_data *monster= get_monster_data(player->monster_index);
416- struct object_data *legs= get_object_data(monster->object_index);
417- struct object_data *torso= get_object_data(legs->parasitic_object);
418- short old_polygon_index= legs->polygon;
419- world_point3d new_location;
420- world_distance adjusted_floor_height, adjusted_ceiling_height, object_floor;
421- bool clipped;
422- _fixed step_height;
423- angle facing, elevation;
424- _fixed fixed_facing;
425-
426- /* convert to world coordinates before doing collision detection */
427- new_location.x= FIXED_TO_WORLD(variables->position.x);
428- new_location.y= FIXED_TO_WORLD(variables->position.y);
429- new_location.z= FIXED_TO_WORLD(variables->position.z);
430-
431- /* check for 2d collisions with walls and knock the player back out of the wall (because of
432- the way the physics updates work, we donユt worry about collisions with the floor or
433- ceiling). ONLY MODIFY THE PLAYERユS FIXED_POINT3D POSITION IF WE HAD A COLLISION */
434- if (PLAYER_IS_DEAD(player)) new_location.z+= FIXED_TO_WORLD(DROP_DEAD_HEIGHT);
435- if (take_action && !first_time && player->last_supporting_polygon_index!=player->supporting_polygon_index) changed_polygon(player->last_supporting_polygon_index, player->supporting_polygon_index, player_index);
436- player->last_supporting_polygon_index= first_time ? NONE : player->supporting_polygon_index;
437- clipped= keep_line_segment_out_of_walls(legs->polygon, &legs->location, &new_location,
438- WORLD_ONE/3, FIXED_TO_WORLD(variables->actual_height), &adjusted_floor_height, &adjusted_ceiling_height,
439- &player->supporting_polygon_index);
440- if (PLAYER_IS_DEAD(player)) new_location.z-= FIXED_TO_WORLD(DROP_DEAD_HEIGHT);
441-
442- /* check for 2d collisions with solid objects and knock the player back out of the object.
443- ONLY MODIFY THE PLAYERユS FIXED_POINT3D POSITION IF WE HAD A COLLISION. */
444- object_floor= INT16_MIN;
445- {
446- short obstruction_index= legal_player_move(player->monster_index, &new_location, &object_floor);
447-
448- if (obstruction_index!=NONE)
449- {
450- struct object_data *object= get_object_data(obstruction_index);
451-
452- switch (GET_OBJECT_OWNER(object))
453- {
454- case _object_is_monster:
455- if(take_action)
456- bump_monster(player->monster_index, object->permutation);
457- case _object_is_scenery:
458- new_location.x= legs->location.x, new_location.y= legs->location.y;
459- clipped= true;
460- break;
461-
462- default:
463- assert(false);
464- break;
465- }
466- }
467- }
468-
469- /* translate_map_object will handle crossing polygon boundaries */
470- if (translate_map_object(monster->object_index, &new_location, NONE))
471- {
472- if (old_polygon_index==legs->polygon) clipped= true; /* oops; trans_map_obj destructively changed our position */
473- if(take_action)
474- monster_moved(player->monster_index, old_polygon_index);
475- }
476-
477- /* if our move got clipped, copy the new coordinate back into the physics variables */
478- if (clipped)
479- {
480- variables->position.x= WORLD_TO_FIXED(new_location.x);
481- variables->position.y= WORLD_TO_FIXED(new_location.y);
482- variables->position.z= WORLD_TO_FIXED(new_location.z);
483- }
484-
485- /* shadow position in player structure, build camera location */
486- step_height= (constants->step_amplitude*sine_table[variables->step_phase>>(FIXED_FRACTIONAL_BITS-ANGULAR_BITS+1)])>>TRIG_SHIFT;
487- step_height= (step_height*variables->step_amplitude)>>FIXED_FRACTIONAL_BITS;
488-
489- player->camera_location= new_location;
490- if (PLAYER_IS_DEAD(player) && new_location.z<adjusted_floor_height) new_location.z= adjusted_floor_height;
491- player->location= new_location;
492- player->camera_location.z+= FIXED_TO_WORLD(step_height+variables->actual_height-constants->camera_height);
493- player->step_height = FIXED_TO_WORLD(step_height);
494- player->camera_polygon_index= legs->polygon;
495-
496- /* shadow facing in player structure and object structure */
497- fixed_facing= variables->direction+variables->head_direction;
498- facing= FIXED_INTEGERAL_PART(fixed_facing), facing= NORMALIZE_ANGLE(facing);
499- elevation= FIXED_INTEGERAL_PART(variables->elevation), elevation= NORMALIZE_ANGLE(elevation);
500- legs->location.z= player->location.z;
501- legs->facing= NORMALIZE_ANGLE(FIXED_INTEGERAL_PART(variables->direction)), torso->facing= player->facing= facing;
502- player->elevation= elevation;
503-
504- /* initialize floor_height and ceiling_height for next call to physics_update() */
505- variables->floor_height= WORLD_TO_FIXED(MAX(adjusted_floor_height, object_floor));
506- variables->ceiling_height= WORLD_TO_FIXED(adjusted_ceiling_height);
507- {
508- short media_index= get_polygon_data(legs->polygon)->media_index;
509- // LP change: idiot-proofing
510- media_data *media = get_media_data(media_index);
511- world_distance media_height= (media_index==NONE || !media) ? INT16_MIN : media->height;
512-
513- if (player->location.z<media_height) variables->flags|= _FEET_BELOW_MEDIA_BIT; else variables->flags&= (uint16)~_FEET_BELOW_MEDIA_BIT;
514- if (player->camera_location.z<media_height) variables->flags|= _HEAD_BELOW_MEDIA_BIT; else variables->flags&= (uint16)~_HEAD_BELOW_MEDIA_BIT;
515- }
516-
517- // so our sounds come from the right place
518- monster->sound_location= player->camera_location;
519- monster->sound_polygon_index= player->camera_polygon_index;
520-}
521-
522-/* separate physics_constant structures are passed in for running/walking modes */
523-// ZZZ note: 'player' is only used in this routine for PLAYER_IS_DEAD(player) - as such,
524-// perhaps this should take an "is_dead" flag as a parameter instead of the player structure.
525-static void physics_update(
526- struct physics_constants *constants,
527- struct physics_variables *variables,
528- struct player_data *player,
529- uint32 action_flags)
530-{
531- fixed_point3d new_position;
532- short sine, cosine;
533- _fixed delta_z;
534- _fixed delta; /* used as a scratch ヤchangeユ variable */
535-
536- if (PLAYER_IS_DEAD(player)) /* dead players immediately loose all bodily control */
537- {
538- int32 dot_product;
539-
540- cosine= cosine_table[FIXED_INTEGERAL_PART(variables->direction)], sine= sine_table[FIXED_INTEGERAL_PART(variables->direction)];
541- dot_product= ((((variables->velocity*cosine)>>TRIG_SHIFT) + variables->external_velocity.i)*cosine +
542- (((variables->velocity*sine)>>TRIG_SHIFT) + variables->external_velocity.j)*sine)>>TRIG_SHIFT;
543-
544- if (dot_product>0 && dot_product<(constants->maximum_forward_velocity>>4)) dot_product= 0;
545- switch (SGN(dot_product))
546- {
547- case -1: action_flags= _looking_up; break;
548- case 1: action_flags= _looking_down; break;
549- case 0: action_flags= 0; break;
550- default:
551- assert(false);
552- break;
553- }
554-
555- variables->floor_height-= DROP_DEAD_HEIGHT;
556- }
557- delta_z= variables->position.z-variables->floor_height;
558-
559- /* process modifier keys (sidestepping and looking) into normal actions */
560- if ((action_flags&_turning) && (action_flags&_sidestep_dont_turn) && !(action_flags&_absolute_yaw_mode))
561- {
562- if (action_flags&_turning_left) action_flags|= _sidestepping_left;
563- if (action_flags&_turning_right) action_flags|= _sidestepping_right;
564- action_flags&= ~_turning;
565- }
566- if ((action_flags&_moving) && (action_flags&_look_dont_turn) && !(action_flags&_absolute_position_mode))
567- {
568- if (action_flags&_moving_forward) action_flags|= _looking_up;
569- if (action_flags&_moving_backward) action_flags|= _looking_down;
570- action_flags&= ~_moving;
571- action_flags&= ~_absolute_pitch_mode;
572- }
573-
574- /* handle turning left or right; if weユve exceeded our maximum velocity lock out user actions
575- until we return to a legal range */
576- if (action_flags&_absolute_yaw_mode)
577- {
578- variables->angular_velocity= (GET_ABSOLUTE_YAW(action_flags)-MAXIMUM_ABSOLUTE_YAW/2)<<(FIXED_FRACTIONAL_BITS); // !!!!!!!!!!
579- }
580- else
581- {
582- if (variables->angular_velocity<-constants->maximum_angular_velocity||variables->angular_velocity>constants->maximum_angular_velocity) action_flags&= ~_turning;
583- switch (action_flags&_turning)
584- {
585- case _turning_left:
586- delta= variables->angular_velocity>0 ? constants->angular_acceleration+constants->angular_deceleration : constants->angular_acceleration;
587- variables->angular_velocity= FLOOR(variables->angular_velocity-delta, -constants->maximum_angular_velocity);
588- break;
589- case _turning_right:
590- delta= variables->angular_velocity<0 ? constants->angular_acceleration+constants->angular_deceleration : constants->angular_acceleration;
591- variables->angular_velocity= CEILING(variables->angular_velocity+delta, constants->maximum_angular_velocity);
592- break;
593-
594- default: /* slow down */
595- variables->angular_velocity= (variables->angular_velocity>=0) ?
596- FLOOR(variables->angular_velocity-constants->angular_deceleration, 0) :
597- CEILING(variables->angular_velocity+constants->angular_deceleration, 0);
598- break;
599- }
600-
601- /* handling looking left/right */
602- switch (action_flags&_looking)
603- {
604- case _looking_left:
605- variables->head_direction= FLOOR(variables->head_direction-constants->fast_angular_velocity, -constants->fast_angular_maximum);
606- break;
607- case _looking_right:
608- variables->head_direction= CEILING(variables->head_direction+constants->fast_angular_velocity, constants->fast_angular_maximum);
609- break;
610- case _looking: /* do nothing if both keys are down */
611- break;
612-
613- default: /* recenter head */
614- variables->head_direction= (variables->head_direction>=0) ?
615- FLOOR(variables->head_direction-constants->fast_angular_velocity, 0) :
616- CEILING(variables->head_direction+constants->fast_angular_velocity, 0);
617- }
618- }
619-
620- if (action_flags&_absolute_pitch_mode)
621- {
622- variables->vertical_angular_velocity= (GET_ABSOLUTE_PITCH(action_flags)-MAXIMUM_ABSOLUTE_PITCH/2)<<(FIXED_FRACTIONAL_BITS);
623- }
624- else
625- {
626- /* if the user touched the recenter key, set the recenter flag and override all up/down
627- keypresses with our own */
628- if (action_flags&_looking_center) variables->flags|= _RECENTERING_BIT;
629- if (variables->flags&_RECENTERING_BIT)
630- {
631- action_flags&= ~_looking_vertically;
632- action_flags|= variables->elevation<0 ? _looking_up : _looking_down;
633- }
634-
635- /* handle looking up and down; if weユre moving at our terminal velocity forward or backward,
636- without any side-to-side motion, recenter our head vertically */
637-
638- // ZZZ: only do auto-recentering if the user wants it
639- if(!PLAYER_DOESNT_AUTO_RECENTER(player)) {
640- if (!(action_flags&FLAGS_WHICH_PREVENT_RECENTERING)) /* canユt recenter if any of these are true */
641- {
642- if (((action_flags&_moving_forward) && (variables->velocity==constants->maximum_forward_velocity)) ||
643- ((action_flags&_moving_backward) && (variables->velocity==-constants->maximum_backward_velocity)))
644- {
645- if (variables->elevation<0)
646- {
647- variables->elevation= CEILING(variables->elevation+constants->angular_recentering_velocity, 0);
648- }
649- else
650- {
651- variables->elevation= FLOOR(variables->elevation-constants->angular_recentering_velocity, 0);
652- }
653- }
654- }
655- }
656-
657- switch (action_flags&_looking_vertically)
658- {
659- case _looking_down:
660- delta= variables->vertical_angular_velocity>0 ? constants->angular_acceleration+constants->angular_deceleration : constants->angular_acceleration;
661- variables->vertical_angular_velocity= FLOOR(variables->vertical_angular_velocity-delta, PLAYER_IS_DEAD(player) ? -(constants->maximum_angular_velocity>>3) : -constants->maximum_angular_velocity);
662- break;
663- case _looking_up:
664- delta= variables->vertical_angular_velocity<0 ? constants->angular_acceleration+constants->angular_deceleration : constants->angular_acceleration;
665- variables->vertical_angular_velocity= CEILING(variables->vertical_angular_velocity+delta, PLAYER_IS_DEAD(player) ? (constants->maximum_angular_velocity>>3) : constants->maximum_angular_velocity);
666- break;
667-
668- default: /* if no key is being held down, decelerate; if the player is moving try and return to phi==0 */
669- variables->vertical_angular_velocity= (variables->vertical_angular_velocity>=0) ?
670- FLOOR(variables->vertical_angular_velocity-constants->angular_deceleration, 0) :
671- CEILING(variables->vertical_angular_velocity+constants->angular_deceleration, 0);
672- break;
673- }
674- }
675-
676- /* if weユre on the ground (or rising up from it), allow movement; if weユre flying through
677- the air, donユt let the player adjust his velocity in any way */
678- if (delta_z<=0 || (variables->flags&_HEAD_BELOW_MEDIA_BIT))
679- {
680- if (action_flags&_absolute_position_mode)
681- {
682- short encoded_delta= GET_ABSOLUTE_POSITION(action_flags)-MAXIMUM_ABSOLUTE_POSITION/2;
683-
684- if (encoded_delta<0)
685- {
686- variables->velocity= (encoded_delta*constants->maximum_backward_velocity)>>(ABSOLUTE_POSITION_BITS-1);
687- }
688- else
689- {
690- variables->velocity= (encoded_delta*constants->maximum_forward_velocity)>>(ABSOLUTE_POSITION_BITS-1);
691- }
692- }
693- else
694- {
695- /* handle moving forward or backward; if weユve exceeded our maximum velocity lock out user actions
696- until we return to a legal range */
697- if (variables->velocity<-constants->maximum_backward_velocity||variables->velocity>constants->maximum_forward_velocity) action_flags&= ~_moving;
698- switch (action_flags&_moving)
699- {
700- case _moving_forward:
701- delta= variables->velocity<0 ? constants->deceleration+constants->acceleration : constants->acceleration;
702- variables->velocity= CEILING(variables->velocity+delta, constants->maximum_forward_velocity);
703- break;
704- case _moving_backward:
705- delta= variables->velocity>0 ? constants->deceleration+constants->acceleration : constants->acceleration;
706- variables->velocity= FLOOR(variables->velocity-delta, -constants->maximum_backward_velocity);
707- break;
708-
709- default: /* slow down */
710- variables->velocity= (variables->velocity>=0) ?
711- FLOOR(variables->velocity-constants->deceleration, 0) :
712- CEILING(variables->velocity+constants->deceleration, 0);
713- break;
714- }
715- }
716-
717- /* handle sidestepping left or right; if weユve exceeded our maximum velocity lock out user actions
718- until we return to a legal range */
719- if (variables->perpendicular_velocity<-constants->maximum_perpendicular_velocity||variables->perpendicular_velocity>constants->maximum_perpendicular_velocity) action_flags&= ~_sidestepping;
720- switch (action_flags&_sidestepping)
721- {
722- case _sidestepping_left:
723- delta= variables->perpendicular_velocity>0 ? constants->acceleration+constants->deceleration : constants->acceleration;
724- variables->perpendicular_velocity= FLOOR(variables->perpendicular_velocity-delta, -constants->maximum_perpendicular_velocity);
725- break;
726- case _sidestepping_right:
727- delta= variables->perpendicular_velocity<0 ? constants->acceleration+constants->deceleration : constants->acceleration;
728- variables->perpendicular_velocity= CEILING(variables->perpendicular_velocity+delta, constants->maximum_perpendicular_velocity);
729- break;
730-
731- default: /* slow down */
732- variables->perpendicular_velocity= (variables->perpendicular_velocity>=0) ?
733- FLOOR(variables->perpendicular_velocity-constants->deceleration, 0) :
734- CEILING(variables->perpendicular_velocity+constants->deceleration, 0);
735- break;
736- }
737- }
738-
739- /* change vertical_velocity based on difference between player height and surface height
740- (if we are standing on an object, like a body, take that into account, too: this
741- means a player could actually use bodies as ramps to reach ledges he couldn't
742- otherwise jump to). we should think about absorbing forward (or perpendicular)
743- velocity to compensate for an increase in vertical velocity, which would slow down
744- a player climbing stairs, etc. */
745- if (delta_z<0)
746- {
747- variables->external_velocity.k= CEILING(variables->external_velocity.k+constants->climbing_acceleration, constants->terminal_velocity);
748- }
749- if (delta_z>0)
750- {
751- _fixed gravity= constants->gravitational_acceleration;
752- _fixed terminal_velocity= constants->terminal_velocity;
753-
754- if (static_world->environment_flags&_environment_low_gravity) gravity>>= 1;
755- if (variables->flags&_FEET_BELOW_MEDIA_BIT) gravity>>= 1, terminal_velocity>>= 1;
756-
757- variables->external_velocity.k= FLOOR(variables->external_velocity.k-gravity, -terminal_velocity);
758- }
759-
760- if ((action_flags&_swim) && (variables->flags&_HEAD_BELOW_MEDIA_BIT) && variables->external_velocity.k<10*constants->climbing_acceleration)
761- {
762- variables->external_velocity.k+= constants->climbing_acceleration;
763- }
764-
765- /* change the playerユs elevation based on his vertical angular velocity; if weユre recentering and
766- have recentered clear the recentering bit */
767- variables->elevation+= variables->vertical_angular_velocity;
768- variables->elevation= PIN(variables->elevation, -constants->maximum_elevation, constants->maximum_elevation);
769- if ((variables->flags&_RECENTERING_BIT) && !(action_flags&_absolute_pitch_mode))
770- {
771- if ((variables->elevation<=0&&(action_flags&_looking_down))||(variables->elevation>=0&&(action_flags&_looking_up)))
772- {
773- variables->elevation= variables->vertical_angular_velocity= 0;
774- variables->flags&= (uint16)~_RECENTERING_BIT;
775- }
776- }
777-
778- /* change the playerユs heading based on his angular velocities */
779- variables->last_direction= variables->direction;
780- variables->direction+= variables->angular_velocity;
781- if (variables->direction<0) variables->direction+= INTEGER_TO_FIXED(FULL_CIRCLE);
782- if (variables->direction>=INTEGER_TO_FIXED(FULL_CIRCLE)) variables->direction-= INTEGER_TO_FIXED(FULL_CIRCLE);
783-
784- /* change the playerユs x,y position based on his direction and velocities (parallel and perpendicular) */
785- new_position= variables->position;
786- cosine= cosine_table[FIXED_INTEGERAL_PART(variables->direction)], sine= sine_table[FIXED_INTEGERAL_PART(variables->direction)];
787- new_position.x+= (variables->velocity*cosine-variables->perpendicular_velocity*sine)>>TRIG_SHIFT;
788- new_position.y+= (variables->velocity*sine+variables->perpendicular_velocity*cosine)>>TRIG_SHIFT;
789-
790- /* set above/below floor flags, remember old flags */
791- variables->old_flags= variables->flags;
792- if (new_position.z<variables->floor_height) variables->flags|= _BELOW_GROUND_BIT; else variables->flags&= (uint16)~_BELOW_GROUND_BIT;
793- if (new_position.z>variables->floor_height) variables->flags|= _ABOVE_GROUND_BIT; else variables->flags&= (uint16)~_ABOVE_GROUND_BIT;
794-
795- /* if we just landed on the ground, or we just came up through the ground, absorb some of
796- the playerユs external_velocity.k (and in the case of hitting the ground, reflect it) */
797- if (variables->external_velocity.k>0 && (variables->old_flags&_BELOW_GROUND_BIT) && !(variables->flags&_BELOW_GROUND_BIT))
798- {
799- variables->external_velocity.k/= 2*COEFFICIENT_OF_ABSORBTION; /* slow down */
800- }
801- if (variables->external_velocity.k>0 && new_position.z+variables->actual_height>=variables->ceiling_height)
802- {
803- variables->external_velocity.k/= -COEFFICIENT_OF_ABSORBTION, new_position.z= variables->ceiling_height-variables->actual_height; // &&variables->position.z+variables->actual_height<variables->ceiling_height
804- }
805- if (variables->external_velocity.k<0&&!(variables->old_flags&_BELOW_GROUND_BIT)&&!(variables->flags&_ABOVE_GROUND_BIT))
806- {
807- variables->external_velocity.k/= -COEFFICIENT_OF_ABSORBTION;
808- }
809- if (ABS(variables->external_velocity.k)<SMALL_ENOUGH_VELOCITY &&
810- ABS(variables->floor_height-new_position.z)<CLOSE_ENOUGH_TO_FLOOR)
811- {
812- variables->external_velocity.k= 0, new_position.z= variables->floor_height;
813- variables->flags&= ~(_BELOW_GROUND_BIT|_ABOVE_GROUND_BIT);
814- }
815-
816- /* change the playerユs z position based on his vertical velocity (if we hit the ground coming down
817- then bounce and absorb most of the blow */
818- new_position.x+= variables->external_velocity.i;
819- new_position.y+= variables->external_velocity.j;
820- new_position.z+= variables->external_velocity.k;
821-
822- {
823- short dx= variables->external_velocity.i, dy= variables->external_velocity.j;
824- _fixed delta= (delta_z<=0) ? constants->external_deceleration : (constants->external_deceleration>>2);
825- int32 magnitude= isqrt(dx*dx + dy*dy);
826-
827- if (magnitude && magnitude>ABS(delta))
828- {
829- variables->external_velocity.i-= (dx*delta)/magnitude;
830- variables->external_velocity.j-= (dy*delta)/magnitude;
831- }
832- else
833- {
834- variables->external_velocity.i= variables->external_velocity.j= 0;
835- }
836- }
837-
838- /* lower the playerユs externally-induced angular velocity */
839- variables->external_angular_velocity= (variables->external_angular_velocity>=0) ?
840- FLOOR(variables->external_angular_velocity-constants->external_angular_deceleration, 0) :
841- CEILING(variables->external_angular_velocity+constants->external_angular_deceleration, 0);
842-
843- /* instantiate new position, save old position */
844- variables->last_position= variables->position;
845- variables->position= new_position;
846-
847- /* if the player is moving, adjust step_phase by step_delta (if the player isnユt moving
848- continue to adjust step_phase until it is zero) if the player is in the air, donユt
849- update phase until he lands. */
850- variables->flags&= (uint16)~_STEP_PERIOD_BIT;
851- if (constants->maximum_forward_velocity)
852- variables->step_amplitude= (MAX(ABS(variables->velocity), ABS(variables->perpendicular_velocity))*FIXED_ONE)/constants->maximum_forward_velocity;
853- else // CB: "Missed Island" physics would produce a division by 0
854- variables->step_amplitude= MAX(ABS(variables->velocity), ABS(variables->perpendicular_velocity))*FIXED_ONE;
855- if (delta_z>=0)
856- {
857- if (variables->velocity||variables->perpendicular_velocity)
858- {
859-// fixed old_step_phase= variables->step_phase;
860-
861- if ((variables->step_phase+= constants->step_delta)>=FIXED_ONE)
862- {
863- variables->step_phase-= FIXED_ONE;
864- variables->flags|= _STEP_PERIOD_BIT;
865- }
866-// else
867-// {
868-// if (variables->step_phase>=FIXED_ONE_HALF && old_step_phase<FIXED_ONE_HALF)
869-// {
870-// variables->flags|= _STEP_PERIOD_BIT;
871-// }
872-// }
873- }
874- else
875- {
876- if (variables->step_phase)
877- {
878- if (variables->step_phase>FIXED_ONE_HALF)
879- {
880- if ((variables->step_phase+= constants->step_delta)>=FIXED_ONE) variables->step_phase= 0;
881- }
882- else
883- {
884- if ((variables->step_phase-= constants->step_delta)<0) variables->step_phase= 0;
885- }
886- }
887- }
888- }
889-
890- if (delta_z >= (PLAYER_IS_DEAD(player) ? (AIRBORNE_HEIGHT+DROP_DEAD_HEIGHT) : AIRBORNE_HEIGHT))
891- {
892- variables->action= _player_airborne;
893- }
894- else
895- {
896- if (variables->angular_velocity||variables->velocity||variables->perpendicular_velocity)
897- {
898- variables->action= (action_flags&_run_dont_walk) ? _player_running : _player_walking;
899- }
900- else
901- {
902- variables->action= (variables->external_velocity.i||variables->external_velocity.j||variables->external_velocity.k) ? _player_sliding : _player_stationary;
903- }
904- }
905-}
906-
907-
908-uint8 *unpack_physics_constants(uint8 *Stream, size_t Count)
909-{
910- return unpack_physics_constants(Stream,physics_models,Count);
911-}
912-
913-uint8 *unpack_physics_constants(uint8 *Stream, physics_constants *Objects, size_t Count)
914-{
915- uint8* S = Stream;
916- physics_constants* ObjPtr = Objects;
917-
918- for (size_t k = 0; k < Count; k++, ObjPtr++)
919- {
920- StreamToValue(S,ObjPtr->maximum_forward_velocity);
921- StreamToValue(S,ObjPtr->maximum_backward_velocity);
922- StreamToValue(S,ObjPtr->maximum_perpendicular_velocity);
923- StreamToValue(S,ObjPtr->acceleration);
924- StreamToValue(S,ObjPtr->deceleration);
925- StreamToValue(S,ObjPtr->airborne_deceleration);
926- StreamToValue(S,ObjPtr->gravitational_acceleration);
927- StreamToValue(S,ObjPtr->climbing_acceleration);
928- StreamToValue(S,ObjPtr->terminal_velocity);
929- StreamToValue(S,ObjPtr->external_deceleration);
930-
931- StreamToValue(S,ObjPtr->angular_acceleration);
932- StreamToValue(S,ObjPtr->angular_deceleration);
933- StreamToValue(S,ObjPtr->maximum_angular_velocity);
934- StreamToValue(S,ObjPtr->angular_recentering_velocity);
935- StreamToValue(S,ObjPtr->fast_angular_velocity);
936- StreamToValue(S,ObjPtr->fast_angular_maximum);
937- StreamToValue(S,ObjPtr->maximum_elevation);
938- StreamToValue(S,ObjPtr->external_angular_deceleration);
939-
940- StreamToValue(S,ObjPtr->step_delta);
941- StreamToValue(S,ObjPtr->step_amplitude);
942- StreamToValue(S,ObjPtr->radius);
943- StreamToValue(S,ObjPtr->height);
944- StreamToValue(S,ObjPtr->dead_height);
945- StreamToValue(S,ObjPtr->camera_height);
946- StreamToValue(S,ObjPtr->splash_height);
947-
948- StreamToValue(S,ObjPtr->half_camera_separation);
949- }
950-
951- assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_physics_constants));
952- return S;
953-}
954-
955-uint8 *pack_physics_constants(uint8 *Stream, size_t Count)
956-{
957- return pack_physics_constants(Stream,physics_models,Count);
958-}
959-
960-uint8 *pack_physics_constants(uint8 *Stream, physics_constants *Objects, size_t Count)
961-{
962- uint8* S = Stream;
963- physics_constants* ObjPtr = Objects;
964-
965- for (size_t k = 0; k < Count; k++, ObjPtr++)
966- {
967- ValueToStream(S,ObjPtr->maximum_forward_velocity);
968- ValueToStream(S,ObjPtr->maximum_backward_velocity);
969- ValueToStream(S,ObjPtr->maximum_perpendicular_velocity);
970- ValueToStream(S,ObjPtr->acceleration);
971- ValueToStream(S,ObjPtr->deceleration);
972- ValueToStream(S,ObjPtr->airborne_deceleration);
973- ValueToStream(S,ObjPtr->gravitational_acceleration);
974- ValueToStream(S,ObjPtr->climbing_acceleration);
975- ValueToStream(S,ObjPtr->terminal_velocity);
976- ValueToStream(S,ObjPtr->external_deceleration);
977-
978- ValueToStream(S,ObjPtr->angular_acceleration);
979- ValueToStream(S,ObjPtr->angular_deceleration);
980- ValueToStream(S,ObjPtr->maximum_angular_velocity);
981- ValueToStream(S,ObjPtr->angular_recentering_velocity);
982- ValueToStream(S,ObjPtr->fast_angular_velocity);
983- ValueToStream(S,ObjPtr->fast_angular_maximum);
984- ValueToStream(S,ObjPtr->maximum_elevation);
985- ValueToStream(S,ObjPtr->external_angular_deceleration);
986-
987- ValueToStream(S,ObjPtr->step_delta);
988- ValueToStream(S,ObjPtr->step_amplitude);
989- ValueToStream(S,ObjPtr->radius);
990- ValueToStream(S,ObjPtr->height);
991- ValueToStream(S,ObjPtr->dead_height);
992- ValueToStream(S,ObjPtr->camera_height);
993- ValueToStream(S,ObjPtr->splash_height);
994-
995- ValueToStream(S,ObjPtr->half_camera_separation);
996- }
997-
998- assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_physics_constants));
999- return S;
1000-}
1001-
1002-void init_physics_constants()
1003-{
1004- memcpy(physics_models, original_physics_models, sizeof(physics_models));
1005-}
1006-
1007-// LP addition: get number of physics models (restricted sense)
1008-size_t get_number_of_physics_models() {return NUMBER_OF_PHYSICS_MODELS;}
1+/*
2+PHYSICS.C
3+
4+ Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5+ and the "Aleph One" developers.
6+
7+ This program is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 2 of the License, or
10+ (at your option) any later version.
11+
12+ This program is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ This license is contained in the file "COPYING",
18+ which is included with this source code; it is available online at
19+ http://www.gnu.org/licenses/gpl.html
20+
21+Wednesday, May 11, 1994 9:32:16 AM
22+
23+Saturday, May 21, 1994 11:36:31 PM
24+ missing effects due to map (i.e., gravity and collision detection). last day in san
25+ jose after WWDC.
26+Sunday, May 22, 1994 11:14:55 AM
27+ there are two viable methods of running a synchronized network game. the first is doom's,
28+ where each player shares with each other player only his control information for that tick
29+ (this imposes a maximum frame rate, as the state-of-the-world will be advanced at the same
30+ time on all machines). the second is the continuous lag-tolerant model where each player
31+ shares absolute information with each other player as often as possible and local machines
32+ do their best at guessing what everyone else in the game is doing until they get better
33+ information. whichever choice is made will change the physics drastically. we're going to
34+ take the latter approach, and cache the KeyMap at interrupt time to be batch-processed
35+ later at frame time.
36+
37+Feb. 4, 2000 (Loren Petrich):
38+ Changed halt() to assert(false) for better debugging
39+
40+Feb 6, 2000 (Loren Petrich):
41+ Added access to size of physics-definition structure
42+
43+Feb 20, 2000 (Loren Petrich):
44+ Fixed chase-cam behavior: DROP_DEAD_HEIGHT is effectively zero for it.
45+ Also, set up-and-down bob to zero when it is active.
46+
47+Aug 31, 2000 (Loren Petrich):
48+ Added stuff for unpacking and packing
49+
50+May 16, 2002 (Woody Zenfell):
51+ Letting user decide whether to auto-recenter when running
52+
53+ June 14, 2003 (Woody Zenfell):
54+ update_player_physics_variables() can now operate in a reduced-impact mode
55+ that changes less of the game state. Useful for partial-game-state
56+ save-and-restore code (as used by prediction mechanism).
57+*/
58+
59+/*
60+running backwards shouldnユt mean doom in a fistfight
61+
62+//who decides on the physics model, anyway? static_world-> or player->
63+//falling through gridlines and crapping on elevators has to do with variables->flags being wrong after the player dies
64+//absolute (or nearly-absolute) positioning information for yaw, pitch and velocity
65+//the physics model is too soft (more noticable at high frame rates)
66+//we can continually boot ourselves out of nearly-orthogonal walls by tiny amounts, resulting in a slide
67+//itユs fairly obvious that players can still end up in walls
68+//the recenter key should work faster
69+*/
70+
71+#ifdef DEBUG
72+//#define DIVERGENCE_CHECK
73+#endif
74+
75+#include "cseries.h"
76+#include "render.h"
77+#include "map.h"
78+#include "player.h"
79+#include "interface.h"
80+#include "monsters.h"
81+
82+#include "media.h"
83+
84+// LP addition:
85+#include "ChaseCam.h"
86+#include "Packing.h"
87+
88+#include <string.h>
89+
90+#ifdef env68k
91+#pragma segment player
92+#endif
93+
94+/* ---------- constants */
95+
96+#define COEFFICIENT_OF_ABSORBTION 2
97+#define SMALL_ENOUGH_VELOCITY (constants->climbing_acceleration)
98+#define CLOSE_ENOUGH_TO_FLOOR WORLD_TO_FIXED(WORLD_ONE/16)
99+
100+#define AIRBORNE_HEIGHT WORLD_TO_FIXED(WORLD_ONE/16)
101+
102+#define DROP_DEAD_HEIGHT WORLD_TO_FIXED(WORLD_ONE_HALF)
103+
104+#define FLAGS_WHICH_PREVENT_RECENTERING (_turning|_looking|_sidestepping|_looking_vertically|_look_dont_turn|_sidestep_dont_turn)
105+
106+/* ---------- private prototypes */
107+
108+/* needed for set_player_position -SB */
109+/*static*/ struct physics_constants *get_physics_constants_for_model(short physics_model, uint32 action_flags);
110+/*static*/ void instantiate_physics_variables(struct physics_constants *constants, struct physics_variables *variables, short player_index, bool first_time, bool take_action);
111+static void physics_update(struct physics_constants *constants, struct physics_variables *variables, struct player_data *player, uint32 action_flags);
112+
113+/* ---------- globals */
114+
115+/* import constants, structures and globals for physics models */
116+#include "physics_models.h"
117+
118+/* ---------- code */
119+
120+#ifdef DIVERGENCE_CHECK
121+#define SAVED_POINT_COUNT 8192
122+static world_point3d *saved_points;
123+static angle *saved_thetas;
124+static short saved_point_count, saved_point_iterations= 0;
125+static bool saved_divergence_warning;
126+#endif
127+
128+static struct physics_constants physics_models[NUMBER_OF_PHYSICS_MODELS];
129+
130+/* every other field in the player structure should be valid when this call is made */
131+void initialize_player_physics_variables(
132+ short player_index)
133+{
134+ struct player_data *player= get_player_data(player_index);
135+ struct monster_data *monster= get_monster_data(player->monster_index);
136+ struct object_data *object= get_object_data(monster->object_index);
137+ struct physics_variables *variables= &player->variables;
138+ struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, 0);
139+
140+//#ifdef DEBUG
141+ obj_set(*variables, 0x80);
142+//#endif
143+
144+ variables->head_direction= 0;
145+ variables->adjusted_yaw= variables->direction= INTEGER_TO_FIXED(object->facing);
146+ variables->adjusted_pitch= variables->elevation= 0;
147+ variables->angular_velocity= variables->vertical_angular_velocity= 0;
148+ variables->velocity= 0, variables->perpendicular_velocity= 0;
149+ variables->position.x= WORLD_TO_FIXED(object->location.x);
150+ variables->position.y= WORLD_TO_FIXED(object->location.y);
151+ variables->position.z= WORLD_TO_FIXED(object->location.z);
152+ variables->last_position= variables->position;
153+ variables->last_direction= variables->direction;
154+ /* .floor_height, .ceiling_height and .media_height will be calculated by instantiate, below */
155+
156+ variables->external_angular_velocity= 0;
157+ variables->external_velocity.i= variables->external_velocity.j= variables->external_velocity.k= 0;
158+ variables->actual_height= constants->height;
159+
160+ variables->step_phase= 0;
161+ variables->step_amplitude= 0;
162+
163+ variables->action= _player_stationary;
164+ variables->old_flags= variables->flags= 0; /* not recentering, not above ground, not below ground (i.e., on floor) */
165+
166+ /* setup shadow variables in player_data structure */
167+ instantiate_physics_variables(get_physics_constants_for_model(static_world->physics_model, 0),
168+ &player->variables, player_index, true, true);
169+
170+#ifdef DIVERGENCE_CHECK
171+ if (!saved_point_iterations)
172+ {
173+ saved_points= new world_point3d[SAVED_POINT_COUNT];
174+ saved_thetas= new angle[SAVED_POINT_COUNT];
175+ }
176+ saved_point_count= 0;
177+ saved_point_iterations+= 1;
178+ saved_divergence_warning= false;
179+#endif
180+}
181+
182+void update_player_physics_variables(
183+ short player_index,
184+ uint32 action_flags,
185+ bool predictive)
186+{
187+ struct player_data *player= get_player_data(player_index);
188+ struct physics_variables *variables= &player->variables;
189+ struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, action_flags);
190+
191+ physics_update(constants, variables, player, action_flags);
192+ instantiate_physics_variables(constants, variables, player_index, false, !predictive);
193+
194+#ifdef DIVERGENCE_CHECK
195+ if (saved_point_count<SAVED_POINT_COUNT)
196+ {
197+ struct object_data *object= get_object_data(get_monster_data(player->monster_index)->object_index);
198+ world_point3d p= object->location;
199+ world_point3d *q= saved_points+saved_point_count;
200+ angle *facing= saved_thetas+saved_point_count;
201+
202+ if (saved_point_iterations==1)
203+ {
204+ saved_points[saved_point_count]= p;
205+ *facing= object->facing;
206+ }
207+ else
208+ {
209+ if (p.x!=q->x||p.y!=q->y||p.z!=q->z||*facing!=object->facing&&!saved_divergence_warning)
210+ {
211+ dprintf("divergence @ tick %d: (%d,%d,%d,%d)!=(%d,%d,%d,%d)", saved_point_count,
212+ q->x, q->y, q->z, *facing, p.x, p.y, p.z, object->facing);
213+ saved_divergence_warning= true;
214+ }
215+ }
216+
217+ saved_point_count+= 1;
218+ }
219+#endif
220+}
221+
222+void adjust_player_for_polygon_height_change(
223+ short monster_index,
224+ short polygon_index,
225+ world_distance new_floor_height,
226+ world_distance new_ceiling_height)
227+{
228+ short player_index= monster_index_to_player_index(monster_index);
229+ struct player_data *player= get_player_data(player_index);
230+ struct physics_variables *variables= &player->variables;
231+ struct polygon_data *polygon= get_polygon_data(polygon_index);
232+ world_distance old_floor_height= polygon->floor_height;
233+
234+ (void) (new_ceiling_height);
235+
236+ if (player->supporting_polygon_index==polygon_index)
237+ {
238+ if (FIXED_TO_WORLD(variables->position.z)<=old_floor_height) /* must be <= */
239+ {
240+ variables->floor_height= variables->position.z= WORLD_TO_FIXED(new_floor_height);
241+ if (PLAYER_IS_DEAD(player)) variables->external_velocity.k= 0;
242+ }
243+ }
244+}
245+
246+void accelerate_player(
247+ short monster_index,
248+ world_distance vertical_velocity,
249+ angle direction,
250+ world_distance velocity)
251+{
252+ short player_index= monster_index_to_player_index(monster_index);
253+ struct player_data *player= get_player_data(player_index);
254+ struct physics_variables *variables= &player->variables;
255+ struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, 0);
256+
257+ variables->external_velocity.k+= WORLD_TO_FIXED(vertical_velocity);
258+ variables->external_velocity.k= PIN(variables->external_velocity.k, -constants->terminal_velocity, constants->terminal_velocity);
259+
260+ variables->external_velocity.i+= (cosine_table[direction]*velocity)>>(TRIG_SHIFT+WORLD_FRACTIONAL_BITS-FIXED_FRACTIONAL_BITS);
261+ variables->external_velocity.j+= (sine_table[direction]*velocity)>>(TRIG_SHIFT+WORLD_FRACTIONAL_BITS-FIXED_FRACTIONAL_BITS);
262+}
263+
264+void get_absolute_pitch_range(
265+ _fixed *minimum,
266+ _fixed *maximum)
267+{
268+ struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, 0);
269+
270+ *minimum= -constants->maximum_elevation;
271+ *maximum= constants->maximum_elevation;
272+}
273+
274+/* deltas of zero are ignored; all deltas must be in [-FIXED_ONE,FIXED_ONE] which will be scaled
275+ to the maximum for that value */
276+uint32 mask_in_absolute_positioning_information(
277+ uint32 action_flags,
278+ _fixed delta_yaw,
279+ _fixed delta_pitch,
280+ _fixed delta_position)
281+{
282+ struct physics_variables *variables= &local_player->variables;
283+ short encoded_delta;
284+
285+ if ((delta_yaw||variables->angular_velocity) && !(action_flags&_override_absolute_yaw))
286+ {
287+ // Bit-shifting is always done with positive_numbers,
288+ // for consistent rounding regardless of direction
289+ int sign_yaw = 1.0;
290+ if (delta_yaw < 0)
291+ {
292+ sign_yaw = -1.0;
293+ delta_yaw = -delta_yaw;
294+ }
295+// if (delta_yaw<0 && delta_yaw>((-1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_YAW_BITS))) delta_yaw= 0;
296+ if (delta_yaw>0 && delta_yaw<((1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_YAW_BITS))) delta_yaw= (1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_YAW_BITS);
297+ encoded_delta= sign_yaw*(delta_yaw>>(FIXED_FRACTIONAL_BITS-ABSOLUTE_YAW_BITS))+MAXIMUM_ABSOLUTE_YAW/2;
298+ encoded_delta= PIN(encoded_delta, 0, MAXIMUM_ABSOLUTE_YAW-1);
299+ action_flags= SET_ABSOLUTE_YAW(action_flags, encoded_delta)|_absolute_yaw_mode;
300+ }
301+
302+ if ((delta_pitch||variables->vertical_angular_velocity) && !(action_flags&_override_absolute_pitch))
303+ {
304+// if (delta_pitch<0 && delta_pitch>((-1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_PITCH_BITS))) delta_pitch= 0;
305+ int sign_pitch = 1.0;
306+ if (delta_pitch < 0)
307+ {
308+ sign_pitch = -1.0;
309+ delta_pitch = -delta_pitch;
310+ }
311+ if (delta_pitch>0 && delta_pitch<((1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_PITCH_BITS))) delta_pitch= (1)<<(FIXED_FRACTIONAL_BITS-ABSOLUTE_PITCH_BITS);
312+ encoded_delta= sign_pitch*(delta_pitch>>(FIXED_FRACTIONAL_BITS-ABSOLUTE_PITCH_BITS))+MAXIMUM_ABSOLUTE_PITCH/2;
313+ encoded_delta= PIN(encoded_delta, 0, MAXIMUM_ABSOLUTE_PITCH-1);
314+ action_flags= SET_ABSOLUTE_PITCH(action_flags, encoded_delta)|_absolute_pitch_mode;
315+ }
316+
317+ if (delta_position && !(action_flags&_override_absolute_position))
318+ {
319+ int sign_position = 1.0;
320+ if (delta_position < 0)
321+ {
322+ sign_position = -1.0;
323+ delta_position = -delta_position;
324+ }
325+ encoded_delta= sign_position*(delta_position>>(FIXED_FRACTIONAL_BITS-ABSOLUTE_POSITION_BITS))+MAXIMUM_ABSOLUTE_POSITION/2;
326+ encoded_delta= PIN(encoded_delta, 0, MAXIMUM_ABSOLUTE_POSITION-1);
327+ action_flags= SET_ABSOLUTE_POSITION(action_flags, encoded_delta)|_absolute_position_mode;
328+ }
329+
330+ return action_flags;
331+}
332+
333+/* will be obsolete when cybermaxx changes to new-style */
334+void instantiate_absolute_positioning_information(
335+ short player_index,
336+ _fixed facing,
337+ _fixed elevation)
338+{
339+ struct player_data *player= get_player_data(player_index);
340+ struct physics_variables *variables= &player->variables;
341+ struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, 0);
342+
343+ assert(elevation>=-INTEGER_TO_FIXED(QUARTER_CIRCLE)&&elevation<=INTEGER_TO_FIXED(QUARTER_CIRCLE));
344+ assert(facing>=0&&facing<INTEGER_TO_FIXED(FULL_CIRCLE));
345+
346+ variables->elevation= PIN(elevation, -constants->maximum_elevation, constants->maximum_elevation);
347+ variables->vertical_angular_velocity= 0;
348+
349+ variables->direction= facing;
350+
351+ instantiate_physics_variables(constants, variables, player_index, false, true);
352+}
353+
354+void get_binocular_vision_origins(
355+ short player_index,
356+ world_point3d *left,
357+ short *left_polygon_index,
358+ angle *left_angle,
359+ world_point3d *right,
360+ short *right_polygon_index,
361+ angle *right_angle)
362+{
363+ struct player_data *player= get_player_data(player_index);
364+ struct physics_variables *variables= &player->variables;
365+ struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, 0);
366+ angle theta;
367+
368+ theta= NORMALIZE_ANGLE(player->facing+QUARTER_CIRCLE);
369+ right->x= FIXED_TO_WORLD(variables->position.x + ((constants->half_camera_separation*cosine_table[theta])>>TRIG_SHIFT));
370+ right->y= FIXED_TO_WORLD(variables->position.y + ((constants->half_camera_separation*sine_table[theta])>>TRIG_SHIFT));
371+ right->z= player->camera_location.z;
372+ *right_polygon_index= find_new_object_polygon((world_point2d *)&player->camera_location, (world_point2d *)right, player->camera_polygon_index);
373+ *right_angle= NORMALIZE_ANGLE(player->facing-1);
374+
375+ theta= NORMALIZE_ANGLE(player->facing-QUARTER_CIRCLE);
376+ left->x= FIXED_TO_WORLD(variables->position.x + ((constants->half_camera_separation*cosine_table[theta])>>TRIG_SHIFT));
377+ left->y= FIXED_TO_WORLD(variables->position.y + ((constants->half_camera_separation*sine_table[theta])>>TRIG_SHIFT));
378+ left->z= player->camera_location.z;
379+ *left_polygon_index= find_new_object_polygon((world_point2d *)&player->camera_location, (world_point2d *)left, player->camera_polygon_index);
380+ *left_angle= NORMALIZE_ANGLE(player->facing+1);
381+}
382+
383+void kill_player_physics_variables(
384+ short player_index)
385+{
386+}
387+
388+/* return a number in [-FIXED_ONE,FIXED_ONE] (arguably) */
389+_fixed get_player_forward_velocity_scale(
390+ short player_index)
391+{
392+ struct player_data *player= get_player_data(player_index);
393+ struct physics_variables *variables= &player->variables;
394+ struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, _run_dont_walk);
395+ _fixed dx= variables->position.x - variables->last_position.x;
396+ _fixed dy= variables->position.y - variables->last_position.y;
397+
398+ return INTEGER_TO_FIXED(((dx*cosine_table[FIXED_INTEGERAL_PART(variables->direction)] +
399+ dy*sine_table[FIXED_INTEGERAL_PART(variables->direction)])>>TRIG_SHIFT))/constants->maximum_forward_velocity;
400+}
401+
402+
403+
404+/* ---------- private code */
405+
406+/*static*/ struct physics_constants *get_physics_constants_for_model(
407+ short physics_model,
408+ uint32 action_flags)
409+{
410+ struct physics_constants *constants;
411+
412+ switch (physics_model)
413+ {
414+ case _editor_model:
415+ case _earth_gravity_model: constants= physics_models + ((action_flags&_run_dont_walk) ? _model_game_running : _model_game_walking); break;
416+ case _low_gravity_model:
417+ assert(false);
418+ break;
419+ default:
420+ assert(false);
421+ break;
422+ }
423+
424+ return constants;
425+}
426+
427+/*static*/ void instantiate_physics_variables(
428+ struct physics_constants *constants,
429+ struct physics_variables *variables,
430+ short player_index,
431+ bool first_time,
432+ bool take_action)
433+{
434+ struct player_data *player= get_player_data(player_index);
435+ struct monster_data *monster= get_monster_data(player->monster_index);
436+ struct object_data *legs= get_object_data(monster->object_index);
437+ struct object_data *torso= get_object_data(legs->parasitic_object);
438+ short old_polygon_index= legs->polygon;
439+ world_point3d new_location;
440+ world_distance adjusted_floor_height, adjusted_ceiling_height, object_floor;
441+ bool clipped;
442+ _fixed step_height;
443+ angle facing, elevation;
444+ _fixed fixed_facing;
445+
446+ /* convert to world coordinates before doing collision detection */
447+ new_location.x= FIXED_TO_WORLD(variables->position.x);
448+ new_location.y= FIXED_TO_WORLD(variables->position.y);
449+ new_location.z= FIXED_TO_WORLD(variables->position.z);
450+
451+ /* check for 2d collisions with walls and knock the player back out of the wall (because of
452+ the way the physics updates work, we donユt worry about collisions with the floor or
453+ ceiling). ONLY MODIFY THE PLAYERユS FIXED_POINT3D POSITION IF WE HAD A COLLISION */
454+ if (PLAYER_IS_DEAD(player)) new_location.z+= FIXED_TO_WORLD(DROP_DEAD_HEIGHT);
455+ if (take_action && !first_time && player->last_supporting_polygon_index!=player->supporting_polygon_index) changed_polygon(player->last_supporting_polygon_index, player->supporting_polygon_index, player_index);
456+ player->last_supporting_polygon_index= first_time ? NONE : player->supporting_polygon_index;
457+ clipped= keep_line_segment_out_of_walls(legs->polygon, &legs->location, &new_location,
458+ WORLD_ONE/3, FIXED_TO_WORLD(variables->actual_height), &adjusted_floor_height, &adjusted_ceiling_height,
459+ &player->supporting_polygon_index);
460+ if (PLAYER_IS_DEAD(player)) new_location.z-= FIXED_TO_WORLD(DROP_DEAD_HEIGHT);
461+
462+ /* check for 2d collisions with solid objects and knock the player back out of the object.
463+ ONLY MODIFY THE PLAYERユS FIXED_POINT3D POSITION IF WE HAD A COLLISION. */
464+ object_floor= INT16_MIN;
465+ {
466+ short obstruction_index= legal_player_move(player->monster_index, &new_location, &object_floor);
467+
468+ if (obstruction_index!=NONE)
469+ {
470+ struct object_data *object= get_object_data(obstruction_index);
471+
472+ switch (GET_OBJECT_OWNER(object))
473+ {
474+ case _object_is_monster:
475+ if(take_action)
476+ bump_monster(player->monster_index, object->permutation);
477+ case _object_is_scenery:
478+ new_location.x= legs->location.x, new_location.y= legs->location.y;
479+ clipped= true;
480+ break;
481+
482+ default:
483+ assert(false);
484+ break;
485+ }
486+ }
487+ }
488+
489+ /* translate_map_object will handle crossing polygon boundaries */
490+ if (translate_map_object(monster->object_index, &new_location, NONE))
491+ {
492+ if (old_polygon_index==legs->polygon) clipped= true; /* oops; trans_map_obj destructively changed our position */
493+ if(take_action)
494+ monster_moved(player->monster_index, old_polygon_index);
495+ }
496+
497+ /* if our move got clipped, copy the new coordinate back into the physics variables */
498+ if (clipped)
499+ {
500+ variables->position.x= WORLD_TO_FIXED(new_location.x);
501+ variables->position.y= WORLD_TO_FIXED(new_location.y);
502+ variables->position.z= WORLD_TO_FIXED(new_location.z);
503+ }
504+
505+ /* shadow position in player structure, build camera location */
506+ step_height= (constants->step_amplitude*sine_table[variables->step_phase>>(FIXED_FRACTIONAL_BITS-ANGULAR_BITS+1)])>>TRIG_SHIFT;
507+ step_height= (step_height*variables->step_amplitude)>>FIXED_FRACTIONAL_BITS;
508+
509+ player->camera_location= new_location;
510+ if (PLAYER_IS_DEAD(player) && new_location.z<adjusted_floor_height) new_location.z= adjusted_floor_height;
511+ player->location= new_location;
512+ player->camera_location.z+= FIXED_TO_WORLD(step_height+variables->actual_height-constants->camera_height);
513+ player->step_height = FIXED_TO_WORLD(step_height);
514+ player->camera_polygon_index= legs->polygon;
515+
516+ /* shadow facing in player structure and object structure */
517+ fixed_facing= variables->direction+variables->head_direction;
518+ facing= FIXED_INTEGERAL_PART(fixed_facing), facing= NORMALIZE_ANGLE(facing);
519+ elevation= FIXED_INTEGERAL_PART(variables->elevation), elevation= NORMALIZE_ANGLE(elevation);
520+ legs->location.z= player->location.z;
521+ legs->facing= NORMALIZE_ANGLE(FIXED_INTEGERAL_PART(variables->direction)), torso->facing= player->facing= facing;
522+ player->elevation= elevation;
523+
524+ /* initialize floor_height and ceiling_height for next call to physics_update() */
525+ variables->floor_height= WORLD_TO_FIXED(MAX(adjusted_floor_height, object_floor));
526+ variables->ceiling_height= WORLD_TO_FIXED(adjusted_ceiling_height);
527+ {
528+ short media_index= get_polygon_data(legs->polygon)->media_index;
529+ // LP change: idiot-proofing
530+ media_data *media = get_media_data(media_index);
531+ world_distance media_height= (media_index==NONE || !media) ? INT16_MIN : media->height;
532+
533+ if (player->location.z<media_height) variables->flags|= _FEET_BELOW_MEDIA_BIT; else variables->flags&= (uint16)~_FEET_BELOW_MEDIA_BIT;
534+ if (player->camera_location.z<media_height) variables->flags|= _HEAD_BELOW_MEDIA_BIT; else variables->flags&= (uint16)~_HEAD_BELOW_MEDIA_BIT;
535+ }
536+
537+ // so our sounds come from the right place
538+ monster->sound_location= player->camera_location;
539+ monster->sound_polygon_index= player->camera_polygon_index;
540+}
541+
542+/* separate physics_constant structures are passed in for running/walking modes */
543+// ZZZ note: 'player' is only used in this routine for PLAYER_IS_DEAD(player) - as such,
544+// perhaps this should take an "is_dead" flag as a parameter instead of the player structure.
545+static void physics_update(
546+ struct physics_constants *constants,
547+ struct physics_variables *variables,
548+ struct player_data *player,
549+ uint32 action_flags)
550+{
551+ fixed_point3d new_position;
552+ short sine, cosine;
553+ _fixed delta_z;
554+ _fixed delta; /* used as a scratch ヤchangeユ variable */
555+
556+ if (PLAYER_IS_DEAD(player)) /* dead players immediately loose all bodily control */
557+ {
558+ int32 dot_product;
559+
560+ cosine= cosine_table[FIXED_INTEGERAL_PART(variables->direction)], sine= sine_table[FIXED_INTEGERAL_PART(variables->direction)];
561+ dot_product= ((((variables->velocity*cosine)>>TRIG_SHIFT) + variables->external_velocity.i)*cosine +
562+ (((variables->velocity*sine)>>TRIG_SHIFT) + variables->external_velocity.j)*sine)>>TRIG_SHIFT;
563+
564+ if (dot_product>0 && dot_product<(constants->maximum_forward_velocity>>4)) dot_product= 0;
565+ switch (SGN(dot_product))
566+ {
567+ case -1: action_flags= _looking_up; break;
568+ case 1: action_flags= _looking_down; break;
569+ case 0: action_flags= 0; break;
570+ default:
571+ assert(false);
572+ break;
573+ }
574+
575+ variables->floor_height-= DROP_DEAD_HEIGHT;
576+ }
577+ delta_z= variables->position.z-variables->floor_height;
578+
579+ /* process modifier keys (sidestepping and looking) into normal actions */
580+ if ((action_flags&_turning) && (action_flags&_sidestep_dont_turn) && !(action_flags&_absolute_yaw_mode))
581+ {
582+ if (action_flags&_turning_left) action_flags|= _sidestepping_left;
583+ if (action_flags&_turning_right) action_flags|= _sidestepping_right;
584+ action_flags&= ~_turning;
585+ }
586+ if ((action_flags&_moving) && (action_flags&_look_dont_turn) && !(action_flags&_absolute_position_mode))
587+ {
588+ if (action_flags&_moving_forward) action_flags|= _looking_up;
589+ if (action_flags&_moving_backward) action_flags|= _looking_down;
590+ action_flags&= ~_moving;
591+ action_flags&= ~_absolute_pitch_mode;
592+ }
593+
594+ /* handle turning left or right; if weユve exceeded our maximum velocity lock out user actions
595+ until we return to a legal range */
596+ if (action_flags&_absolute_yaw_mode)
597+ {
598+ variables->angular_velocity= (GET_ABSOLUTE_YAW(action_flags)-MAXIMUM_ABSOLUTE_YAW/2)<<(FIXED_FRACTIONAL_BITS); // !!!!!!!!!!
599+ }
600+ else
601+ {
602+ if (variables->angular_velocity<-constants->maximum_angular_velocity||variables->angular_velocity>constants->maximum_angular_velocity) action_flags&= ~_turning;
603+ switch (action_flags&_turning)
604+ {
605+ case _turning_left:
606+ delta= variables->angular_velocity>0 ? constants->angular_acceleration+constants->angular_deceleration : constants->angular_acceleration;
607+ variables->angular_velocity= FLOOR(variables->angular_velocity-delta, -constants->maximum_angular_velocity);
608+ break;
609+ case _turning_right:
610+ delta= variables->angular_velocity<0 ? constants->angular_acceleration+constants->angular_deceleration : constants->angular_acceleration;
611+ variables->angular_velocity= CEILING(variables->angular_velocity+delta, constants->maximum_angular_velocity);
612+ break;
613+
614+ default: /* slow down */
615+ variables->angular_velocity= (variables->angular_velocity>=0) ?
616+ FLOOR(variables->angular_velocity-constants->angular_deceleration, 0) :
617+ CEILING(variables->angular_velocity+constants->angular_deceleration, 0);
618+ break;
619+ }
620+
621+ /* handling looking left/right */
622+ switch (action_flags&_looking)
623+ {
624+ case _looking_left:
625+ variables->head_direction= FLOOR(variables->head_direction-constants->fast_angular_velocity, -constants->fast_angular_maximum);
626+ break;
627+ case _looking_right:
628+ variables->head_direction= CEILING(variables->head_direction+constants->fast_angular_velocity, constants->fast_angular_maximum);
629+ break;
630+ case _looking: /* do nothing if both keys are down */
631+ break;
632+
633+ default: /* recenter head */
634+ variables->head_direction= (variables->head_direction>=0) ?
635+ FLOOR(variables->head_direction-constants->fast_angular_velocity, 0) :
636+ CEILING(variables->head_direction+constants->fast_angular_velocity, 0);
637+ }
638+ }
639+
640+ if (action_flags&_absolute_pitch_mode)
641+ {
642+ variables->vertical_angular_velocity= (GET_ABSOLUTE_PITCH(action_flags)-MAXIMUM_ABSOLUTE_PITCH/2)<<(FIXED_FRACTIONAL_BITS);
643+ }
644+ else
645+ {
646+ /* if the user touched the recenter key, set the recenter flag and override all up/down
647+ keypresses with our own */
648+ if (action_flags&_looking_center) variables->flags|= _RECENTERING_BIT;
649+ if (variables->flags&_RECENTERING_BIT)
650+ {
651+ action_flags&= ~_looking_vertically;
652+ action_flags|= variables->elevation<0 ? _looking_up : _looking_down;
653+ }
654+
655+ /* handle looking up and down; if weユre moving at our terminal velocity forward or backward,
656+ without any side-to-side motion, recenter our head vertically */
657+
658+ // ZZZ: only do auto-recentering if the user wants it
659+ if(!PLAYER_DOESNT_AUTO_RECENTER(player)) {
660+ if (!(action_flags&FLAGS_WHICH_PREVENT_RECENTERING)) /* canユt recenter if any of these are true */
661+ {
662+ if (((action_flags&_moving_forward) && (variables->velocity==constants->maximum_forward_velocity)) ||
663+ ((action_flags&_moving_backward) && (variables->velocity==-constants->maximum_backward_velocity)))
664+ {
665+ if (variables->elevation<0)
666+ {
667+ variables->elevation= CEILING(variables->elevation+constants->angular_recentering_velocity, 0);
668+ }
669+ else
670+ {
671+ variables->elevation= FLOOR(variables->elevation-constants->angular_recentering_velocity, 0);
672+ }
673+ }
674+ }
675+ }
676+
677+ switch (action_flags&_looking_vertically)
678+ {
679+ case _looking_down:
680+ delta= variables->vertical_angular_velocity>0 ? constants->angular_acceleration+constants->angular_deceleration : constants->angular_acceleration;
681+ variables->vertical_angular_velocity= FLOOR(variables->vertical_angular_velocity-delta, PLAYER_IS_DEAD(player) ? -(constants->maximum_angular_velocity>>3) : -constants->maximum_angular_velocity);
682+ break;
683+ case _looking_up:
684+ delta= variables->vertical_angular_velocity<0 ? constants->angular_acceleration+constants->angular_deceleration : constants->angular_acceleration;
685+ variables->vertical_angular_velocity= CEILING(variables->vertical_angular_velocity+delta, PLAYER_IS_DEAD(player) ? (constants->maximum_angular_velocity>>3) : constants->maximum_angular_velocity);
686+ break;
687+
688+ default: /* if no key is being held down, decelerate; if the player is moving try and return to phi==0 */
689+ variables->vertical_angular_velocity= (variables->vertical_angular_velocity>=0) ?
690+ FLOOR(variables->vertical_angular_velocity-constants->angular_deceleration, 0) :
691+ CEILING(variables->vertical_angular_velocity+constants->angular_deceleration, 0);
692+ break;
693+ }
694+ }
695+
696+ /* if weユre on the ground (or rising up from it), allow movement; if weユre flying through
697+ the air, donユt let the player adjust his velocity in any way */
698+ if (delta_z<=0 || (variables->flags&_HEAD_BELOW_MEDIA_BIT))
699+ {
700+ if (action_flags&_absolute_position_mode)
701+ {
702+ short encoded_delta= GET_ABSOLUTE_POSITION(action_flags)-MAXIMUM_ABSOLUTE_POSITION/2;
703+
704+ if (encoded_delta<0)
705+ {
706+ variables->velocity= (encoded_delta*constants->maximum_backward_velocity)>>(ABSOLUTE_POSITION_BITS-1);
707+ }
708+ else
709+ {
710+ variables->velocity= (encoded_delta*constants->maximum_forward_velocity)>>(ABSOLUTE_POSITION_BITS-1);
711+ }
712+ }
713+ else
714+ {
715+ /* handle moving forward or backward; if weユve exceeded our maximum velocity lock out user actions
716+ until we return to a legal range */
717+ if (variables->velocity<-constants->maximum_backward_velocity||variables->velocity>constants->maximum_forward_velocity) action_flags&= ~_moving;
718+ switch (action_flags&_moving)
719+ {
720+ case _moving_forward:
721+ delta= variables->velocity<0 ? constants->deceleration+constants->acceleration : constants->acceleration;
722+ variables->velocity= CEILING(variables->velocity+delta, constants->maximum_forward_velocity);
723+ break;
724+ case _moving_backward:
725+ delta= variables->velocity>0 ? constants->deceleration+constants->acceleration : constants->acceleration;
726+ variables->velocity= FLOOR(variables->velocity-delta, -constants->maximum_backward_velocity);
727+ break;
728+
729+ default: /* slow down */
730+ variables->velocity= (variables->velocity>=0) ?
731+ FLOOR(variables->velocity-constants->deceleration, 0) :
732+ CEILING(variables->velocity+constants->deceleration, 0);
733+ break;
734+ }
735+ }
736+
737+ /* handle sidestepping left or right; if weユve exceeded our maximum velocity lock out user actions
738+ until we return to a legal range */
739+ if (variables->perpendicular_velocity<-constants->maximum_perpendicular_velocity||variables->perpendicular_velocity>constants->maximum_perpendicular_velocity) action_flags&= ~_sidestepping;
740+ switch (action_flags&_sidestepping)
741+ {
742+ case _sidestepping_left:
743+ delta= variables->perpendicular_velocity>0 ? constants->acceleration+constants->deceleration : constants->acceleration;
744+ variables->perpendicular_velocity= FLOOR(variables->perpendicular_velocity-delta, -constants->maximum_perpendicular_velocity);
745+ break;
746+ case _sidestepping_right:
747+ delta= variables->perpendicular_velocity<0 ? constants->acceleration+constants->deceleration : constants->acceleration;
748+ variables->perpendicular_velocity= CEILING(variables->perpendicular_velocity+delta, constants->maximum_perpendicular_velocity);
749+ break;
750+
751+ default: /* slow down */
752+ variables->perpendicular_velocity= (variables->perpendicular_velocity>=0) ?
753+ FLOOR(variables->perpendicular_velocity-constants->deceleration, 0) :
754+ CEILING(variables->perpendicular_velocity+constants->deceleration, 0);
755+ break;
756+ }
757+ }
758+
759+ /* change vertical_velocity based on difference between player height and surface height
760+ (if we are standing on an object, like a body, take that into account, too: this
761+ means a player could actually use bodies as ramps to reach ledges he couldn't
762+ otherwise jump to). we should think about absorbing forward (or perpendicular)
763+ velocity to compensate for an increase in vertical velocity, which would slow down
764+ a player climbing stairs, etc. */
765+ if (delta_z<0)
766+ {
767+ variables->external_velocity.k= CEILING(variables->external_velocity.k+constants->climbing_acceleration, constants->terminal_velocity);
768+ }
769+ if (delta_z>0)
770+ {
771+ _fixed gravity= constants->gravitational_acceleration;
772+ _fixed terminal_velocity= constants->terminal_velocity;
773+
774+ if (static_world->environment_flags&_environment_low_gravity) gravity>>= 1;
775+ if (variables->flags&_FEET_BELOW_MEDIA_BIT) gravity>>= 1, terminal_velocity>>= 1;
776+
777+ variables->external_velocity.k= FLOOR(variables->external_velocity.k-gravity, -terminal_velocity);
778+ }
779+
780+ if ((action_flags&_swim) && (variables->flags&_HEAD_BELOW_MEDIA_BIT) && variables->external_velocity.k<10*constants->climbing_acceleration)
781+ {
782+ variables->external_velocity.k+= constants->climbing_acceleration;
783+ }
784+
785+ /* change the playerユs elevation based on his vertical angular velocity; if weユre recentering and
786+ have recentered clear the recentering bit */
787+ variables->elevation+= variables->vertical_angular_velocity;
788+ variables->elevation= PIN(variables->elevation, -constants->maximum_elevation, constants->maximum_elevation);
789+ if ((variables->flags&_RECENTERING_BIT) && !(action_flags&_absolute_pitch_mode))
790+ {
791+ if ((variables->elevation<=0&&(action_flags&_looking_down))||(variables->elevation>=0&&(action_flags&_looking_up)))
792+ {
793+ variables->elevation= variables->vertical_angular_velocity= 0;
794+ variables->flags&= (uint16)~_RECENTERING_BIT;
795+ }
796+ }
797+
798+ /* change the playerユs heading based on his angular velocities */
799+ variables->last_direction= variables->direction;
800+ variables->direction+= variables->angular_velocity;
801+ if (variables->direction<0) variables->direction+= INTEGER_TO_FIXED(FULL_CIRCLE);
802+ if (variables->direction>=INTEGER_TO_FIXED(FULL_CIRCLE)) variables->direction-= INTEGER_TO_FIXED(FULL_CIRCLE);
803+
804+ /* change the playerユs x,y position based on his direction and velocities (parallel and perpendicular) */
805+ new_position= variables->position;
806+ cosine= cosine_table[FIXED_INTEGERAL_PART(variables->direction)], sine= sine_table[FIXED_INTEGERAL_PART(variables->direction)];
807+ new_position.x+= (variables->velocity*cosine-variables->perpendicular_velocity*sine)>>TRIG_SHIFT;
808+ new_position.y+= (variables->velocity*sine+variables->perpendicular_velocity*cosine)>>TRIG_SHIFT;
809+
810+ /* set above/below floor flags, remember old flags */
811+ variables->old_flags= variables->flags;
812+ if (new_position.z<variables->floor_height) variables->flags|= _BELOW_GROUND_BIT; else variables->flags&= (uint16)~_BELOW_GROUND_BIT;
813+ if (new_position.z>variables->floor_height) variables->flags|= _ABOVE_GROUND_BIT; else variables->flags&= (uint16)~_ABOVE_GROUND_BIT;
814+
815+ /* if we just landed on the ground, or we just came up through the ground, absorb some of
816+ the playerユs external_velocity.k (and in the case of hitting the ground, reflect it) */
817+ if (variables->external_velocity.k>0 && (variables->old_flags&_BELOW_GROUND_BIT) && !(variables->flags&_BELOW_GROUND_BIT))
818+ {
819+ variables->external_velocity.k/= 2*COEFFICIENT_OF_ABSORBTION; /* slow down */
820+ }
821+ if (variables->external_velocity.k>0 && new_position.z+variables->actual_height>=variables->ceiling_height)
822+ {
823+ variables->external_velocity.k/= -COEFFICIENT_OF_ABSORBTION, new_position.z= variables->ceiling_height-variables->actual_height; // &&variables->position.z+variables->actual_height<variables->ceiling_height
824+ }
825+ if (variables->external_velocity.k<0&&!(variables->old_flags&_BELOW_GROUND_BIT)&&!(variables->flags&_ABOVE_GROUND_BIT))
826+ {
827+ variables->external_velocity.k/= -COEFFICIENT_OF_ABSORBTION;
828+ }
829+ if (ABS(variables->external_velocity.k)<SMALL_ENOUGH_VELOCITY &&
830+ ABS(variables->floor_height-new_position.z)<CLOSE_ENOUGH_TO_FLOOR)
831+ {
832+ variables->external_velocity.k= 0, new_position.z= variables->floor_height;
833+ variables->flags&= ~(_BELOW_GROUND_BIT|_ABOVE_GROUND_BIT);
834+ }
835+
836+ /* change the playerユs z position based on his vertical velocity (if we hit the ground coming down
837+ then bounce and absorb most of the blow */
838+ new_position.x+= variables->external_velocity.i;
839+ new_position.y+= variables->external_velocity.j;
840+ new_position.z+= variables->external_velocity.k;
841+
842+ {
843+ short dx= variables->external_velocity.i, dy= variables->external_velocity.j;
844+ _fixed delta= (delta_z<=0) ? constants->external_deceleration : (constants->external_deceleration>>2);
845+ int32 magnitude= isqrt(dx*dx + dy*dy);
846+
847+ if (magnitude && magnitude>ABS(delta))
848+ {
849+ variables->external_velocity.i-= (dx*delta)/magnitude;
850+ variables->external_velocity.j-= (dy*delta)/magnitude;
851+ }
852+ else
853+ {
854+ variables->external_velocity.i= variables->external_velocity.j= 0;
855+ }
856+ }
857+
858+ /* lower the playerユs externally-induced angular velocity */
859+ variables->external_angular_velocity= (variables->external_angular_velocity>=0) ?
860+ FLOOR(variables->external_angular_velocity-constants->external_angular_deceleration, 0) :
861+ CEILING(variables->external_angular_velocity+constants->external_angular_deceleration, 0);
862+
863+ /* instantiate new position, save old position */
864+ variables->last_position= variables->position;
865+ variables->position= new_position;
866+
867+ /* if the player is moving, adjust step_phase by step_delta (if the player isnユt moving
868+ continue to adjust step_phase until it is zero) if the player is in the air, donユt
869+ update phase until he lands. */
870+ variables->flags&= (uint16)~_STEP_PERIOD_BIT;
871+ if (constants->maximum_forward_velocity)
872+ variables->step_amplitude= (MAX(ABS(variables->velocity), ABS(variables->perpendicular_velocity))*FIXED_ONE)/constants->maximum_forward_velocity;
873+ else // CB: "Missed Island" physics would produce a division by 0
874+ variables->step_amplitude= MAX(ABS(variables->velocity), ABS(variables->perpendicular_velocity))*FIXED_ONE;
875+ if (delta_z>=0)
876+ {
877+ if (variables->velocity||variables->perpendicular_velocity)
878+ {
879+// fixed old_step_phase= variables->step_phase;
880+
881+ if ((variables->step_phase+= constants->step_delta)>=FIXED_ONE)
882+ {
883+ variables->step_phase-= FIXED_ONE;
884+ variables->flags|= _STEP_PERIOD_BIT;
885+ }
886+// else
887+// {
888+// if (variables->step_phase>=FIXED_ONE_HALF && old_step_phase<FIXED_ONE_HALF)
889+// {
890+// variables->flags|= _STEP_PERIOD_BIT;
891+// }
892+// }
893+ }
894+ else
895+ {
896+ if (variables->step_phase)
897+ {
898+ if (variables->step_phase>FIXED_ONE_HALF)
899+ {
900+ if ((variables->step_phase+= constants->step_delta)>=FIXED_ONE) variables->step_phase= 0;
901+ }
902+ else
903+ {
904+ if ((variables->step_phase-= constants->step_delta)<0) variables->step_phase= 0;
905+ }
906+ }
907+ }
908+ }
909+
910+ if (delta_z >= (PLAYER_IS_DEAD(player) ? (AIRBORNE_HEIGHT+DROP_DEAD_HEIGHT) : AIRBORNE_HEIGHT))
911+ {
912+ variables->action= _player_airborne;
913+ }
914+ else
915+ {
916+ if (variables->angular_velocity||variables->velocity||variables->perpendicular_velocity)
917+ {
918+ variables->action= (action_flags&_run_dont_walk) ? _player_running : _player_walking;
919+ }
920+ else
921+ {
922+ variables->action= (variables->external_velocity.i||variables->external_velocity.j||variables->external_velocity.k) ? _player_sliding : _player_stationary;
923+ }
924+ }
925+}
926+
927+
928+uint8 *unpack_physics_constants(uint8 *Stream, size_t Count)
929+{
930+ return unpack_physics_constants(Stream,physics_models,Count);
931+}
932+
933+uint8 *unpack_physics_constants(uint8 *Stream, physics_constants *Objects, size_t Count)
934+{
935+ uint8* S = Stream;
936+ physics_constants* ObjPtr = Objects;
937+
938+ for (size_t k = 0; k < Count; k++, ObjPtr++)
939+ {
940+ StreamToValue(S,ObjPtr->maximum_forward_velocity);
941+ StreamToValue(S,ObjPtr->maximum_backward_velocity);
942+ StreamToValue(S,ObjPtr->maximum_perpendicular_velocity);
943+ StreamToValue(S,ObjPtr->acceleration);
944+ StreamToValue(S,ObjPtr->deceleration);
945+ StreamToValue(S,ObjPtr->airborne_deceleration);
946+ StreamToValue(S,ObjPtr->gravitational_acceleration);
947+ StreamToValue(S,ObjPtr->climbing_acceleration);
948+ StreamToValue(S,ObjPtr->terminal_velocity);
949+ StreamToValue(S,ObjPtr->external_deceleration);
950+
951+ StreamToValue(S,ObjPtr->angular_acceleration);
952+ StreamToValue(S,ObjPtr->angular_deceleration);
953+ StreamToValue(S,ObjPtr->maximum_angular_velocity);
954+ StreamToValue(S,ObjPtr->angular_recentering_velocity);
955+ StreamToValue(S,ObjPtr->fast_angular_velocity);
956+ StreamToValue(S,ObjPtr->fast_angular_maximum);
957+ StreamToValue(S,ObjPtr->maximum_elevation);
958+ StreamToValue(S,ObjPtr->external_angular_deceleration);
959+
960+ StreamToValue(S,ObjPtr->step_delta);
961+ StreamToValue(S,ObjPtr->step_amplitude);
962+ StreamToValue(S,ObjPtr->radius);
963+ StreamToValue(S,ObjPtr->height);
964+ StreamToValue(S,ObjPtr->dead_height);
965+ StreamToValue(S,ObjPtr->camera_height);
966+ StreamToValue(S,ObjPtr->splash_height);
967+
968+ StreamToValue(S,ObjPtr->half_camera_separation);
969+ }
970+
971+ assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_physics_constants));
972+ return S;
973+}
974+
975+uint8 *pack_physics_constants(uint8 *Stream, size_t Count)
976+{
977+ return pack_physics_constants(Stream,physics_models,Count);
978+}
979+
980+uint8 *pack_physics_constants(uint8 *Stream, physics_constants *Objects, size_t Count)
981+{
982+ uint8* S = Stream;
983+ physics_constants* ObjPtr = Objects;
984+
985+ for (size_t k = 0; k < Count; k++, ObjPtr++)
986+ {
987+ ValueToStream(S,ObjPtr->maximum_forward_velocity);
988+ ValueToStream(S,ObjPtr->maximum_backward_velocity);
989+ ValueToStream(S,ObjPtr->maximum_perpendicular_velocity);
990+ ValueToStream(S,ObjPtr->acceleration);
991+ ValueToStream(S,ObjPtr->deceleration);
992+ ValueToStream(S,ObjPtr->airborne_deceleration);
993+ ValueToStream(S,ObjPtr->gravitational_acceleration);
994+ ValueToStream(S,ObjPtr->climbing_acceleration);
995+ ValueToStream(S,ObjPtr->terminal_velocity);
996+ ValueToStream(S,ObjPtr->external_deceleration);
997+
998+ ValueToStream(S,ObjPtr->angular_acceleration);
999+ ValueToStream(S,ObjPtr->angular_deceleration);
1000+ ValueToStream(S,ObjPtr->maximum_angular_velocity);
1001+ ValueToStream(S,ObjPtr->angular_recentering_velocity);
1002+ ValueToStream(S,ObjPtr->fast_angular_velocity);
1003+ ValueToStream(S,ObjPtr->fast_angular_maximum);
1004+ ValueToStream(S,ObjPtr->maximum_elevation);
1005+ ValueToStream(S,ObjPtr->external_angular_deceleration);
1006+
1007+ ValueToStream(S,ObjPtr->step_delta);
1008+ ValueToStream(S,ObjPtr->step_amplitude);
1009+ ValueToStream(S,ObjPtr->radius);
1010+ ValueToStream(S,ObjPtr->height);
1011+ ValueToStream(S,ObjPtr->dead_height);
1012+ ValueToStream(S,ObjPtr->camera_height);
1013+ ValueToStream(S,ObjPtr->splash_height);
1014+
1015+ ValueToStream(S,ObjPtr->half_camera_separation);
1016+ }
1017+
1018+ assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_physics_constants));
1019+ return S;
1020+}
1021+
1022+void init_physics_constants()
1023+{
1024+ memcpy(physics_models, original_physics_models, sizeof(physics_models));
1025+}
1026+
1027+// LP addition: get number of physics models (restricted sense)
1028+size_t get_number_of_physics_models() {return NUMBER_OF_PHYSICS_MODELS;}
--- marathon/trunk/Source_Files/Lua/lua_player.cpp (revision 492)
+++ marathon/trunk/Source_Files/Lua/lua_player.cpp (revision 493)
@@ -459,7 +459,7 @@
459459
460460 return 0;
461461 }
462-#include "converter.h"
462+
463463 static int Lua_Overlay_Set_Text(lua_State *L)
464464 {
465465 if (Lua_Overlay::PlayerIndex(L, 1) == local_player_index)
@@ -467,7 +467,7 @@
467467 const char *text = 0;
468468 if (lua_isstring(L, 2))
469469 text = lua_tostring(L, 2);
470- const char* cv=sjis2utf8(text, strlen(text));
470+
471471 SetScriptHUDText(Lua_Overlay::Index(L, 1), text);
472472 }
473473
@@ -1571,9 +1571,7 @@
15711571 lua_pcall(L, 1, 1, 0);
15721572 if (lua_tostring(L, -1))
15731573 {
1574-// screen_printf("%s", lua_tostring(L, -1));
1575- const char* s = lua_tostring(L, -1);
1576- screen_printf("%s", sjis2utf8(s, strlen(s)));
1574+ screen_printf("%s", lua_tostring(L, -1));
15771575 }
15781576 lua_pop(L, 1);
15791577 }
--- marathon/trunk/Source_Files/RenderOther/computer_interface.cpp (revision 492)
+++ marathon/trunk/Source_Files/RenderOther/computer_interface.cpp (revision 493)
@@ -440,11 +440,7 @@
440440 _get_interface_color(text_face->color + _computer_interface_text_color, &color);
441441 current_pixel = SDL_MapRGB(/*world_pixels*/draw_surface->format, color.r, color.g, color.b);
442442 }
443-
444-// 2バイト文字か?
445-static int isJChar(unsigned char text) {
446- return (((text >= 0x81) && (text <= 0x9f)) || ((text >= 0xe0) && (text <= 0xfc)));
447-}
443+#include "converter.h"
448444 static bool calculate_line(char *base_text, short width, short start_index, short text_end_index, short *end_index)
449445 {
450446 bool done = false;
@@ -454,16 +450,15 @@
454450
455451 // terminal_font no longer a global, since it may change
456452 font_info *terminal_font = GetInterfaceFont(_computer_interface_font);
457-
453+ TTF_Font* font = ((ttf_font_info*)terminal_font)->font;
458454 while (running_width < width && base_text[index] && base_text[index] != MAC_LINE_END) {
459- if (isJChar(base_text[index]) == 1){
460- // 2byteなので2倍(いい加減だ)
455+ if (isJChar(base_text[index])){
461456 running_width += char_width(base_text[index], terminal_font, current_style)+char_width(base_text[index+1], terminal_font, current_style);
462- index++;
457+ index ++;
463458 }else{
464459 running_width += char_width(base_text[index], terminal_font, current_style);
465460 }
466- index++;
461+ index ++;
467462 }
468463
469464 // Now go backwards, looking for whitespace to split on
@@ -474,13 +469,12 @@
474469
475470 while (break_point>start_index) {
476471 // 末尾が2バイト文字だった場合
477- if (isJChar(base_text[break_point-2]) == 1){
472+ if (is2ndJChar(base_text[break_point-1])){
478473 break_point--;
479474 }
480- if (base_text[break_point] == ' ' || base_text[break_point] == ' '){
475+ if (base_text[break_point] == ' '){
481476 break; // Non printing
482477 }
483-
484478 break_point--; // this needs to be in front of the test
485479 }
486480
--- marathon/trunk/Source_Files/RenderOther/screen_drawing.cpp (revision 492)
+++ marathon/trunk/Source_Files/RenderOther/screen_drawing.cpp (revision 493)
@@ -515,6 +515,7 @@
515515 }
516516
517517 #ifdef HAVE_SDL_TTF
518+#include <iostream>
518519 int ttf_font_info::_draw_text(SDL_Surface *s, const char *text, size_t length, int x, int y, uint32 pixel, uint16 style, bool utf8) const
519520 {
520521 int clip_top, clip_bottom, clip_left, clip_right;
@@ -591,7 +592,7 @@
591592 {
592593 draw_text(draw_surface, text, strlen(text), x, y, pixel, font, style);
593594 }
594-
595+#include "converter.h"
595596 void _draw_screen_text(const char *text, screen_rectangle *destination, short flags, short font_id, short text_color)
596597 {
597598 int x, y;
@@ -617,7 +618,13 @@
617618 int last_non_printing_character = 0, text_width = 0;
618619 unsigned count = 0;
619620 while (count < strlen(text_to_draw) && text_width < RECTANGLE_WIDTH(destination)) {
620- text_width += char_width(text_to_draw[count], font, style);
621+ // computer_interface.cppと同じ処置
622+ if (isJChar(text_to_draw[count])){
623+ text_width += char_width(text_to_draw[count], font, style)+char_width(text_to_draw[count+1], font, style);
624+ count++;
625+ }else{
626+ text_width += char_width(text_to_draw[count], font, style);
627+ }
621628 if (text_to_draw[count] == ' ')
622629 last_non_printing_character = count;
623630 count++;
--- marathon/trunk/Source_Files/RenderMain/RenderRasterize_Shader.cpp (revision 492)
+++ marathon/trunk/Source_Files/RenderMain/RenderRasterize_Shader.cpp (revision 493)
@@ -49,7 +49,7 @@
4949
5050 glGenTextures(1, &texID);
5151 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texID);
52- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, Wanting_sRGB ? GL_SRGB : GL_RGB8, _w, _h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
52+ glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, Bloom_sRGB ? GL_SRGB : GL_RGB8, _w, _h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
5353 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texID, 0);
5454 assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT);
5555 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
@@ -86,11 +86,158 @@
8686 }
8787 };
8888
89+// Gamma Corrected Blender: draw to src_a, draw to src_b, blend, swap, repeat
90+// when finished, draw from dst
91+class GCB {
92+public:
93+ GLuint w;
94+ GLuint h;
95+ GLuint textureIDs[3];
96+
97+ GCB(GLuint _w, GLuint _h) : w(_w), h(_h), active_(false), src_a_(0), src_b_(1), dst_(2) {
98+ glGenFramebuffersEXT(1, &fbo_);
99+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
100+
101+ glGenRenderbuffersEXT(1, &depthBuffer_);
102+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer_);
103+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, w, h);
104+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer_);
105+
106+ glGenTextures(3, textureIDs);
107+ for (int i = 0; i < 3; ++i)
108+ {
109+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textureIDs[i]);
110+ glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB8, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
111+ }
112+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, textureIDs[src_a_], 0);
113+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
114+ }
115+
116+ void activate_src_a() {
117+ activate();
118+ bind_texture(src_a_);
119+ }
120+
121+ void activate_src_b() {
122+ activate();
123+ bind_texture(src_b_);
124+ }
125+
126+ void activate_dst() {
127+ activate();
128+ bind_texture(dst_);
129+ }
130+
131+ void deactivate() {
132+ glPopAttrib();
133+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
134+ active_ = false;
135+ }
136+
137+ // blends src_a with src_b into dst
138+ // automatically deactivates FBO
139+ void blend(FBO* multi) {
140+ // use gamma corrected shader here
141+ // activate_dst();
142+
143+ glMatrixMode(GL_PROJECTION);
144+ glPushMatrix();
145+ glLoadIdentity();
146+
147+ glMatrixMode(GL_MODELVIEW);
148+ glPushMatrix();
149+ glLoadIdentity();
150+
151+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
152+
153+ glOrtho(0, w, 0, h, 0.0, 1.0);
154+ glColor4f(1.0, 1.0, 1.0, 1.0);
155+
156+ glDisable(GL_DEPTH_TEST);
157+ glDisable(GL_BLEND);
158+
159+ // set up FBO passed in as texture #1
160+ glActiveTextureARB(GL_TEXTURE1_ARB);
161+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, multi->texID);
162+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
163+ glActiveTextureARB(GL_TEXTURE0_ARB);
164+
165+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
166+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
167+ GLint multi_coordinates[8] = { 0, 0, 0, multi->_h, multi->_w, multi->_h, multi->_w, 0 };
168+ glTexCoordPointer(2, GL_INT, 0, multi_coordinates);
169+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
170+
171+ draw_(src_a_);
172+
173+ // tear down multitexture stuff
174+ glActiveTextureARB(GL_TEXTURE1_ARB);
175+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
176+ glActiveTextureARB(GL_TEXTURE0_ARB);
177+
178+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
179+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
180+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
181+
182+ glEnable(GL_BLEND);
183+ glEnable(GL_DEPTH_TEST);
184+
185+ glPopMatrix();
186+ glMatrixMode(GL_PROJECTION);
187+ glPopMatrix();
188+
189+ deactivate();
190+ }
191+
192+ void swap() {
193+ std::swap(src_a_, dst_);
194+ }
195+
196+ void draw() {
197+ draw_(dst_);
198+ }
199+
200+private:
201+ void activate() {
202+ if (!active_)
203+ {
204+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
205+ glPushAttrib(GL_VIEWPORT_BIT);
206+ glViewport(0, 0, w, h);
207+ active_ = true;
208+ }
209+ }
210+
211+ void draw_(int id) {
212+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textureIDs[id]);
213+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
214+
215+ GLint coordinates[8] = { 0, 0, 0, h, w, h, w, 0 };
216+
217+ glVertexPointer(2, GL_INT, 0, coordinates);
218+ glTexCoordPointer(2, GL_INT, 0, coordinates);
219+
220+ glDrawArrays(GL_QUADS, 0, 4);
221+
222+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
223+ }
224+
225+ void bind_texture(int id) {
226+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, textureIDs[id], 0);
227+ }
228+
229+ bool active_;
230+ int src_a_, src_b_, dst_;
231+ GLuint fbo_;
232+ GLuint depthBuffer_;
233+};
234+
89235 class Blur {
90236
91237 private:
92238 FBO _horizontal;
93239 FBO _vertical;
240+ std::auto_ptr<GCB> _blend;
94241
95242 Shader *_shader_blur;
96243 Shader *_shader_bloom;
@@ -98,7 +245,12 @@
98245 public:
99246
100247 Blur(GLuint w, GLuint h, Shader* s_blur, Shader* s_bloom)
101- : _horizontal(w, h), _vertical(w, h), _shader_blur(s_blur), _shader_bloom(s_bloom) {}
248+ : _horizontal(w, h), _vertical(w, h), _shader_blur(s_blur), _shader_bloom(s_bloom) {
249+ if (!Bloom_sRGB)
250+ _blend.reset(new GCB(graphics_preferences->screen_mode.width, graphics_preferences->screen_mode.height));
251+ else
252+ _blend.reset();
253+ }
102254
103255 void resize(GLuint w, GLuint h) {
104256 _horizontal = FBO(w, h);
@@ -120,21 +272,22 @@
120272 glMatrixMode(GL_MODELVIEW);
121273 glLoadIdentity();
122274
275+ glDisable(GL_DEPTH_TEST);
276+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
277+
123278 glDisable(GL_BLEND);
124279 glOrtho(0, _vertical._w, 0, _vertical._h, 0.0, 1.0);
125280 glColor4f(1., 1., 1., 1.);
126281
282+ if (Bloom_sRGB)
283+ glEnable(GL_FRAMEBUFFER_SRGB_EXT);
284+
127285 int passes = _shader_bloom->passes();
128286 if (passes < 0)
129287 passes = 5;
130288
131- if (passes > 0) {
132- glEnable(GL_BLEND);
133- _shader_bloom->enable();
134- _shader_bloom->setFloat(Shader::U_Pass, 0);
135- _horizontal.draw();
136- Shader::disable();
137- }
289+ if (_blend.get())
290+ _blend->swap(); // swap src_a into dst
138291
139292 for (int i = 0; i < passes; i++) {
140293 glDisable(GL_BLEND);
@@ -157,12 +310,54 @@
157310 FBO::deactivate();
158311
159312 glEnable(GL_BLEND);
313+ if (_blend.get()) {
314+ _blend->swap();
315+ _blend->activate_dst();
316+ }
160317 _shader_bloom->enable();
161318 _shader_bloom->setFloat(Shader::U_Pass, i + 1);
162- _horizontal.draw();
319+ if (_blend.get())
320+ _blend->blend(&_horizontal);
321+ else
322+ _horizontal.draw();
163323 Shader::disable();
164324 }
325+
326+ if (Bloom_sRGB && !Using_sRGB)
327+ glDisable(GL_FRAMEBUFFER_SRGB_EXT);
328+
329+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
330+
331+ if (_blend.get())
332+ draw_blended();
165333 }
334+
335+ void prepare_render() {
336+ if (_blend.get()) {
337+ _blend->activate_src_a();
338+ glClear(GL_DEPTH_BUFFER_BIT);
339+ }
340+ }
341+
342+ void complete_render() {
343+ if (_blend.get())
344+ _blend->deactivate();
345+ }
346+
347+ void draw_blended() {
348+ glMatrixMode(GL_PROJECTION);
349+ glLoadIdentity();
350+ glMatrixMode(GL_MODELVIEW);
351+ glLoadIdentity();
352+ glDisable(GL_BLEND);
353+ glDisable(GL_DEPTH_TEST);
354+ glOrtho(0, _blend->w, 0, _blend->h, 0.0, 1.0);
355+ glColor4f(1., 1., 1., 1.);
356+ _blend->draw();
357+ glPopMatrix();
358+ glMatrixMode(GL_PROJECTION);
359+ glPopMatrix();
360+ }
166361 };
167362
168363
@@ -177,10 +372,10 @@
177372 Shader* s_blur = Shader::get(Shader::S_Blur);
178373 Shader* s_bloom = Shader::get(Shader::S_Bloom);
179374
180- blur = NULL;
375+ blur.reset();
181376 if(TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_Blur)) {
182377 if(s_blur && s_bloom) {
183- blur = new Blur(640., 640. * graphics_preferences->screen_mode.height / graphics_preferences->screen_mode.width, s_blur, s_bloom);
378+ blur.reset(new Blur(640., 640. * graphics_preferences->screen_mode.height / graphics_preferences->screen_mode.width, s_blur, s_bloom));
184379 }
185380 }
186381
@@ -226,18 +421,21 @@
226421 s->setFloat(Shader::U_UseFog, usefog ? 1.0 : 0.0);
227422 Shader::disable();
228423
424+ bool bloom = (TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_Blur) && blur.get());
425+ if (bloom)
426+ blur->prepare_render();
427+
229428 RenderRasterizerClass::render_tree(kDiffuse);
230429
231- if(TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_Blur) && blur) {
430+ if (bloom) {
431+ blur->complete_render();
432+
232433 blur->begin();
233434 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
234435 RenderRasterizerClass::render_tree(kGlow);
235436 blur->end();
236437
237- glDisable(GL_DEPTH_TEST);
238- glBlendFunc(GL_SRC_ALPHA,GL_ONE);
239438 blur->draw();
240- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
241439 }
242440
243441 glAlphaFunc(GL_GREATER, 0.5);
@@ -378,11 +576,17 @@
378576 return TMgr;
379577 }
380578
579+// Circle constants
580+const double TWO_PI = 8*atan(1.0);
581+const double Radian2Circle = 1/TWO_PI; // A circle is 2*pi radians
582+const double FullCircleReciprocal = 1/double(FULL_CIRCLE);
583+
381584 TextureManager RenderRasterize_Shader::setupWallTexture(const shape_descriptor& Texture, short transferMode, float wobble, float intensity, float offset, RenderStep renderStep) {
382585
383586 Shader *s = NULL;
384587
385588 TextureManager TMgr;
589+ LandscapeOptions *opts;
386590 TMgr.ShapeDesc = Texture;
387591 if (TMgr.ShapeDesc == UNONE) { return TMgr; }
388592 get_shape_bitmap_and_shading_table(Texture, &TMgr.Texture, &TMgr.ShadingTables,
@@ -410,11 +614,11 @@
410614 {
411615 TMgr.TextureType = OGL_Txtr_Landscape;
412616 TMgr.TransferMode = _big_landscaped_transfer;
413- TMgr.Landscape_AspRatExp = 0;
414- LandscapeOptions *opts = View_GetLandscapeOptions(Texture);
617+ opts = View_GetLandscapeOptions(Texture);
618+ TMgr.LandscapeVertRepeat = opts->VertRepeat;
619+ TMgr.Landscape_AspRatExp = opts->OGL_AspRatExp;
415620 s = Shader::get(renderStep == kGlow ? Shader::S_LandscapeBloom : Shader::S_Landscape);
416621 s->enable();
417- s->setFloat(Shader::U_Repeat, 1.0 + opts->HorizExp);
418622 }
419623 break;
420624 default:
@@ -451,6 +655,19 @@
451655 }
452656
453657 TMgr.SetupTextureMatrix();
658+
659+ if (TMgr.TextureType == OGL_Txtr_Landscape) {
660+ double TexScale = ABS(TMgr.U_Scale);
661+ double HorizScale = double(1 << opts->HorizExp);
662+ s->setFloat(Shader::U_ScaleX, HorizScale * (npotTextures ? 1.0 : TexScale) * Radian2Circle);
663+ s->setFloat(Shader::U_OffsetX, HorizScale * (0.25 + opts->Azimuth * FullCircleReciprocal));
664+
665+ short AdjustedVertExp = opts->VertExp + opts->OGL_AspRatExp;
666+ double VertScale = (AdjustedVertExp >= 0) ? double(1 << AdjustedVertExp)
667+ : 1/double(1 << (-AdjustedVertExp));
668+ s->setFloat(Shader::U_ScaleY, VertScale * TexScale * Radian2Circle);
669+ s->setFloat(Shader::U_OffsetY, (0.5 + TMgr.U_Offset) * TexScale);
670+ }
454671
455672 if (renderStep == kGlow) {
456673 if (TMgr.TextureType == OGL_Txtr_Landscape) {
@@ -926,7 +1143,7 @@
9261143
9271144 if(s == NULL) {
9281145 if(TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_BumpMap)) {
929- s = Shader::get(renderStep == kGlow ? Shader::S_SpecularBloom : Shader::S_Specular);
1146+ s = Shader::get(renderStep == kGlow ? Shader::S_BumpBloom : Shader::S_Bump);
9301147 } else {
9311148 s = Shader::get(renderStep == kGlow ? Shader::S_WallBloom : Shader::S_Wall);
9321149 }
--- marathon/trunk/Source_Files/RenderMain/OGL_Subst_Texture_Def.cpp (revision 492)
+++ marathon/trunk/Source_Files/RenderMain/OGL_Subst_Texture_Def.cpp (revision 493)
@@ -1,490 +1,495 @@
1-/*
2-
3- Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
4- and the "Aleph One" developers.
5-
6- This program is free software; you can redistribute it and/or modify
7- it under the terms of the GNU General Public License as published by
8- the Free Software Foundation; either version 2 of the License, or
9- (at your option) any later version.
10-
11- This program is distributed in the hope that it will be useful,
12- but WITHOUT ANY WARRANTY; without even the implied warranty of
13- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14- GNU General Public License for more details.
15-
16- This license is contained in the file "COPYING",
17- which is included with this source code; it is available online at
18- http://www.gnu.org/licenses/gpl.html
19-
20- OpenGL Substitute-Texture-Definition File
21- by Loren Petrich,
22- March 12, 2000
23-
24- This contains implementations of functions for handling
25- the OpenGL substitute textures for the walls and the sprites
26-*/
27-
28-#include "cseries.h"
29-#include "OGL_Subst_Texture_Def.h"
30-
31-#include <set>
32-#include <string>
33-#include <boost/unordered_map.hpp>
34-
35-#ifdef HAVE_OPENGL
36-
37-void OGL_TextureOptions::FindImagePosition()
38-{
39- Right = Left + short(ImageScale*NormalImg.GetWidth() + 0.5);
40- Bottom = Top + short(ImageScale*NormalImg.GetHeight() + 0.5);
41-}
42-
43-// Texture-options stuff;
44-// defaults for whatever might need them
45-static OGL_TextureOptions DefaultTextureOptions;
46-
47-typedef std::pair<short, short> TOKey;
48-typedef boost::unordered_map<TOKey, OGL_TextureOptions> TOHash;
49-static TOHash Collections[NUMBER_OF_COLLECTIONS];
50-
51-// Deletes a collection's texture-options sequences
52-void TODelete(short Collection)
53-{
54- Collections[Collection].clear();
55-}
56-
57-// Deletes all of them
58-static void TODelete_All()
59-{
60- for (int c = 0; c < NUMBER_OF_COLLECTIONS; c++) TODelete(c);
61-}
62-
63-int OGL_CountTextures(short Collection)
64-{
65- return Collections[Collection].size();
66-}
67-
68-extern void OGL_ProgressCallback(int);
69-
70-void OGL_LoadTextures(short Collection)
71-{
72-
73- for (TOHash::iterator it = Collections[Collection].begin(); it != Collections[Collection].end(); ++it)
74- {
75- it->second.Load();
76- // Find adjusted-frame image-data positioning;
77- // this is for doing sprites with textures with sizes different from the originals
78- it->second.FindImagePosition();
79-
80- OGL_ProgressCallback(1);
81-
82- }
83-}
84-
85-
86-void OGL_UnloadTextures(short Collection)
87-{
88- for (TOHash::iterator it = Collections[Collection].begin(); it != Collections[Collection].end(); ++it)
89- {
90- it->second.Unload();
91- }
92-}
93-
94-
95-OGL_TextureOptions *OGL_GetTextureOptions(short Collection, short CLUT, short Bitmap)
96-{
97- TOHash::iterator it = Collections[Collection].find(TOKey(CLUT, Bitmap));
98- if (it != Collections[Collection].end())
99- {
100- return &it->second;
101- }
102-
103- it = Collections[Collection].find(TOKey(ALL_CLUTS, Bitmap));
104- if (it != Collections[Collection].end())
105- {
106- return &it->second;
107- }
108-
109- return &DefaultTextureOptions;
110-}
111-
112-
113-class XML_TO_ClearParser: public XML_ElementParser
114-{
115- bool IsPresent;
116- short Collection;
117-
118-public:
119- bool Start();
120- bool HandleAttribute(const char *Tag, const char *Value);
121- bool AttributesDone();
122-
123- XML_TO_ClearParser(): XML_ElementParser("txtr_clear") {}
124-};
125-
126-bool XML_TO_ClearParser::Start()
127-{
128- IsPresent = false;
129- return true;
130-}
131-
132-bool XML_TO_ClearParser::HandleAttribute(const char *Tag, const char *Value)
133-{
134- if (StringsEqual(Tag,"coll"))
135- {
136- if (ReadBoundedInt16Value(Value,Collection,0,NUMBER_OF_COLLECTIONS-1))
137- {
138- IsPresent = true;
139- return true;
140- }
141- else return false;
142- }
143- UnrecognizedTag();
144- return false;
145-}
146-
147-bool XML_TO_ClearParser::AttributesDone()
148-{
149- if (IsPresent)
150- TODelete(Collection);
151- else
152- TODelete_All();
153-
154- return true;
155-}
156-
157-static XML_TO_ClearParser TO_ClearParser;
158-
159-
160-class XML_TextureOptionsParser: public XML_ElementParser
161-{
162- bool CollIsPresent, BitmapIsPresent;
163- short Collection, CLUT, Bitmap;
164-
165- std::set<std::string> Attributes;
166-
167- OGL_TextureOptions Data;
168-
169- bool _HandleAttribute(const char *Tag, const char *Value);
170-
171-public:
172- bool Start();
173- bool HandleAttribute(const char *Tag, const char *Value);
174- bool AttributesDone();
175- bool ResetValues();
176-
177- XML_TextureOptionsParser(): XML_ElementParser("texture") {}
178-};
179-
180-bool XML_TextureOptionsParser::Start()
181-{
182- Data = DefaultTextureOptions;
183- CollIsPresent = BitmapIsPresent = false;
184- CLUT = ALL_CLUTS;
185- Attributes.clear();
186-
187- return true;
188-}
189-
190-bool XML_TextureOptionsParser::_HandleAttribute(const char *Tag, const char *Value)
191-{
192- if (StringsEqual(Tag,"coll"))
193- {
194- if (ReadBoundedInt16Value(Value,Collection,0,NUMBER_OF_COLLECTIONS-1))
195- {
196- CollIsPresent = true;
197- return true;
198- }
199- else return false;
200- }
201- else if (StringsEqual(Tag,"clut"))
202- {
203- return ReadBoundedInt16Value(Value,CLUT,short(ALL_CLUTS),short(SILHOUETTE_BITMAP_SET));
204- }
205- else if (StringsEqual(Tag,"bitmap"))
206- {
207- if (ReadBoundedInt16Value(Value,Bitmap,0,MAXIMUM_SHAPES_PER_COLLECTION-1))
208- {
209- BitmapIsPresent = true;
210- return true;
211- }
212- else return false;
213- }
214- else if (StringsEqual(Tag,"opac_type"))
215- {
216- return ReadBoundedInt16Value(Value,Data.OpacityType,0,OGL_NUMBER_OF_OPACITY_TYPES-1);
217- }
218- else if (StringsEqual(Tag,"opac_scale"))
219- {
220- return ReadFloatValue(Value,Data.OpacityScale);
221- }
222- else if (StringsEqual(Tag,"opac_shift"))
223- {
224- return ReadFloatValue(Value,Data.OpacityShift);
225- }
226- else if (StringsEqual(Tag,"void_visible"))
227- {
228- return ReadBooleanValueAsBool(Value,Data.VoidVisible);
229- }
230- else if (StringsEqual(Tag,"normal_image"))
231- {
232- Data.NormalColors.SetNameWithPath(Value);
233- return true;
234- }
235- else if (StringsEqual(Tag,"offset_image"))
236- {
237- Data.OffsetMap.SetNameWithPath(Value);
238- return true;
239- }
240- else if (StringsEqual(Tag,"normal_mask"))
241- {
242- Data.NormalMask.SetNameWithPath(Value);
243- return true;
244- }
245- else if (StringsEqual(Tag,"glow_image"))
246- {
247- Data.GlowColors.SetNameWithPath(Value);
248- return true;
249- }
250- else if (StringsEqual(Tag,"glow_mask"))
251- {
252- Data.GlowMask.SetNameWithPath(Value);
253- return true;
254- }
255- else if (StringsEqual(Tag,"normal_blend"))
256- {
257- return ReadBoundedInt16Value(Value,Data.NormalBlend,0,OGL_NUMBER_OF_BLEND_TYPES-1);
258- }
259- else if (StringsEqual(Tag,"glow_blend"))
260- {
261- return ReadBoundedInt16Value(Value,Data.GlowBlend,0,OGL_NUMBER_OF_BLEND_TYPES-1);
262- }
263- else if (StringsEqual(Tag,"image_scale"))
264- {
265- return ReadFloatValue(Value,Data.ImageScale);
266- }
267- else if (StringsEqual(Tag,"x_offset"))
268- {
269- return ReadInt16Value(Value,Data.Left);
270- }
271- else if (StringsEqual(Tag,"y_offset"))
272- {
273- return ReadInt16Value(Value,Data.Top);
274- }
275- else if (StringsEqual(Tag,"actual_height"))
276- {
277- return ReadInt16Value(Value, Data.actual_height);
278- }
279- else if (StringsEqual(Tag, "actual_width"))
280- {
281- return ReadInt16Value(Value, Data.actual_width);
282- }
283- else if (StringsEqual(Tag, "type"))
284- {
285- return ReadInt16Value(Value, Data.Type);
286- }
287- else if (StringsEqual(Tag, "normal_premultiply"))
288- {
289- return ReadBooleanValueAsBool(Value, Data.NormalIsPremultiplied);
290- }
291- else if (StringsEqual(Tag, "glow_premultiply"))
292- {
293- return ReadBooleanValueAsBool(Value, Data.GlowIsPremultiplied);
294- }
295- else if (StringsEqual(Tag,"normal_bloom_scale"))
296- {
297- return ReadFloatValue(Value,Data.BloomScale);
298- }
299- else if (StringsEqual(Tag,"normal_bloom_shift"))
300- {
301- return ReadFloatValue(Value,Data.BloomShift);
302- }
303- else if (StringsEqual(Tag,"glow_bloom_scale"))
304- {
305- return ReadFloatValue(Value,Data.GlowBloomScale);
306- }
307- else if (StringsEqual(Tag,"glow_bloom_shift"))
308- {
309- return ReadFloatValue(Value,Data.GlowBloomShift);
310- }
311- else if (StringsEqual(Tag,"landscape_bloom"))
312- {
313- return ReadFloatValue(Value,Data.LandscapeBloom);
314- }
315- else if (StringsEqual(Tag,"minimum_glow_intensity"))
316- {
317- return ReadFloatValue(Value,Data.MinGlowIntensity);
318- }
319- UnrecognizedTag();
320- return false;
321-}
322-
323-bool XML_TextureOptionsParser::HandleAttribute(const char* Tag, const char* Value)
324-{
325- if (_HandleAttribute(Tag, Value))
326- {
327- Attributes.insert(Tag);
328- return true;
329- }
330- return false;
331-}
332-
333-bool XML_TextureOptionsParser::AttributesDone()
334-{
335- // Verify...
336- if (!CollIsPresent || !BitmapIsPresent)
337- {
338- AttribsMissing();
339- return false;
340- }
341-
342- TOHash::iterator it = Collections[Collection].find(TOKey(CLUT, Bitmap));
343- if (it == Collections[Collection].end())
344- {
345- Collections[Collection][TOKey(CLUT, Bitmap)] = Data;
346- return true;
347- }
348-
349- if (Attributes.count("opac_type"))
350- {
351- it->second.OpacityType = Data.OpacityType;
352- }
353-
354- if (Attributes.count("opac_scale"))
355- {
356- it->second.OpacityScale = Data.OpacityScale;
357- }
358-
359- if (Attributes.count("opac_shift"))
360- {
361- it->second.OpacityShift = Data.OpacityShift;
362- }
363-
364- if (Attributes.count("void_visible"))
365- {
366- it->second.VoidVisible = Data.VoidVisible;
367- }
368-
369- if (Attributes.count("normal_image"))
370- {
371- it->second.NormalColors = Data.NormalColors;
372- }
373-
374- if (Attributes.count("offset_image"))
375- {
376- it->second.OffsetMap = Data.OffsetMap;
377- }
378-
379- if (Attributes.count("normal_mask"))
380- {
381- it->second.NormalMask = Data.NormalMask;
382- }
383-
384- if (Attributes.count("glow_image"))
385- {
386- it->second.GlowColors = Data.GlowColors;
387- }
388-
389- if (Attributes.count("glow_mask"))
390- {
391- it->second.GlowMask = Data.GlowMask;
392- }
393-
394- if (Attributes.count("normal_blend"))
395- {
396- it->second.NormalBlend = Data.NormalBlend;
397- }
398-
399- if (Attributes.count("glow_blend"))
400- {
401- it->second.GlowBlend = Data.GlowBlend;
402- }
403-
404- if (Attributes.count("image_scale"))
405- {
406- it->second.ImageScale = Data.ImageScale;
407- }
408-
409- if (Attributes.count("x_offset"))
410- {
411- it->second.Left = Data.Left;
412- }
413-
414- if (Attributes.count("y_offset"))
415- {
416- it->second.Top = Data.Top;
417- }
418-
419- if (Attributes.count("actual_height"))
420- {
421- it->second.actual_height = Data.actual_height;
422- }
423-
424- if (Attributes.count("actual_width"))
425- {
426- it->second.actual_width = Data.actual_width;
427- }
428-
429- if (Attributes.count("type"))
430- {
431- it->second.Type = Data.Type;
432- }
433-
434- if (Attributes.count("normal_premultiply"))
435- {
436- it->second.NormalIsPremultiplied = Data.NormalIsPremultiplied;
437- }
438-
439- if (Attributes.count("glow_premultiply"))
440- {
441- it->second.GlowIsPremultiplied = Data.GlowIsPremultiplied;
442- }
443-
444- if (Attributes.count("normal_bloom_scale"))
445- {
446- it->second.BloomScale = Data.BloomScale;
447- }
448-
449- if (Attributes.count("normal_bloom_shift"))
450- {
451- it->second.BloomShift = Data.BloomShift;
452- }
453-
454- if (Attributes.count("glow_bloom_scale"))
455- {
456- it->second.GlowBloomScale = Data.GlowBloomScale;
457- }
458-
459- if (Attributes.count("glow_bloom_shift"))
460- {
461- it->second.GlowBloomShift = Data.GlowBloomShift;
462- }
463-
464- if (Attributes.count("landscape_bloom"))
465- {
466- it->second.LandscapeBloom = Data.LandscapeBloom;
467- }
468-
469- if (Attributes.count("minimum_glow_intensity"))
470- {
471- it->second.MinGlowIntensity = Data.MinGlowIntensity;
472- }
473-
474- return true;
475-}
476-
477-bool XML_TextureOptionsParser::ResetValues()
478-{
479- TODelete_All();
480- return true;
481-}
482-
483-static XML_TextureOptionsParser TextureOptionsParser;
484-
485-
486-// XML-parser support:
487-XML_ElementParser *TextureOptions_GetParser() {return &TextureOptionsParser;}
488-XML_ElementParser *TO_Clear_GetParser() {return &TO_ClearParser;}
489-
490-#endif
1+/*
2+
3+ Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
4+ and the "Aleph One" developers.
5+
6+ This program is free software; you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation; either version 2 of the License, or
9+ (at your option) any later version.
10+
11+ This program is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ This license is contained in the file "COPYING",
17+ which is included with this source code; it is available online at
18+ http://www.gnu.org/licenses/gpl.html
19+
20+ OpenGL Substitute-Texture-Definition File
21+ by Loren Petrich,
22+ March 12, 2000
23+
24+ This contains implementations of functions for handling
25+ the OpenGL substitute textures for the walls and the sprites
26+*/
27+
28+#include "cseries.h"
29+#include "OGL_Subst_Texture_Def.h"
30+#include "Logging.h"
31+
32+#include <set>
33+#include <string>
34+#include <boost/unordered_map.hpp>
35+
36+#ifdef HAVE_OPENGL
37+
38+// Texture-options stuff;
39+// defaults for whatever might need them
40+static OGL_TextureOptions DefaultTextureOptions;
41+
42+typedef std::pair<short, short> TOKey;
43+typedef boost::unordered_map<TOKey, OGL_TextureOptions> TOHash;
44+static TOHash Collections[NUMBER_OF_COLLECTIONS];
45+
46+// Deletes a collection's texture-options sequences
47+void TODelete(short Collection)
48+{
49+ Collections[Collection].clear();
50+}
51+
52+// Deletes all of them
53+static void TODelete_All()
54+{
55+ for (int c = 0; c < NUMBER_OF_COLLECTIONS; c++) TODelete(c);
56+}
57+
58+int OGL_CountTextures(short Collection)
59+{
60+ return Collections[Collection].size();
61+}
62+
63+extern void OGL_ProgressCallback(int);
64+
65+void OGL_LoadTextures(short Collection)
66+{
67+
68+ for (TOHash::iterator it = Collections[Collection].begin(); it != Collections[Collection].end(); ++it)
69+ {
70+ it->second.Load();
71+ OGL_ProgressCallback(1);
72+
73+ }
74+}
75+
76+
77+void OGL_UnloadTextures(short Collection)
78+{
79+ for (TOHash::iterator it = Collections[Collection].begin(); it != Collections[Collection].end(); ++it)
80+ {
81+ it->second.Unload();
82+ }
83+}
84+
85+
86+OGL_TextureOptions *OGL_GetTextureOptions(short Collection, short CLUT, short Bitmap)
87+{
88+ TOHash::iterator it = Collections[Collection].find(TOKey(CLUT, Bitmap));
89+ if (it != Collections[Collection].end())
90+ {
91+ return &it->second;
92+ }
93+
94+ it = Collections[Collection].find(TOKey(ALL_CLUTS, Bitmap));
95+ if (it != Collections[Collection].end())
96+ {
97+ return &it->second;
98+ }
99+
100+ return &DefaultTextureOptions;
101+}
102+
103+
104+class XML_TO_ClearParser: public XML_ElementParser
105+{
106+ bool IsPresent;
107+ short Collection;
108+
109+public:
110+ bool Start();
111+ bool HandleAttribute(const char *Tag, const char *Value);
112+ bool AttributesDone();
113+
114+ XML_TO_ClearParser(): XML_ElementParser("txtr_clear") {}
115+};
116+
117+bool XML_TO_ClearParser::Start()
118+{
119+ IsPresent = false;
120+ return true;
121+}
122+
123+bool XML_TO_ClearParser::HandleAttribute(const char *Tag, const char *Value)
124+{
125+ if (StringsEqual(Tag,"coll"))
126+ {
127+ if (ReadBoundedInt16Value(Value,Collection,0,NUMBER_OF_COLLECTIONS-1))
128+ {
129+ IsPresent = true;
130+ return true;
131+ }
132+ else return false;
133+ }
134+ UnrecognizedTag();
135+ return false;
136+}
137+
138+bool XML_TO_ClearParser::AttributesDone()
139+{
140+ if (IsPresent)
141+ TODelete(Collection);
142+ else
143+ TODelete_All();
144+
145+ return true;
146+}
147+
148+static XML_TO_ClearParser TO_ClearParser;
149+
150+
151+class XML_TextureOptionsParser: public XML_ElementParser
152+{
153+ bool CollIsPresent, BitmapIsPresent;
154+ short Collection, CLUT, Bitmap;
155+
156+ std::set<std::string> Attributes;
157+
158+ OGL_TextureOptions Data;
159+
160+ bool _HandleAttribute(const char *Tag, const char *Value);
161+
162+public:
163+ bool Start();
164+ bool HandleAttribute(const char *Tag, const char *Value);
165+ bool AttributesDone();
166+ bool ResetValues();
167+
168+ XML_TextureOptionsParser(): XML_ElementParser("texture") {}
169+};
170+
171+bool XML_TextureOptionsParser::Start()
172+{
173+ Data = DefaultTextureOptions;
174+ CollIsPresent = BitmapIsPresent = false;
175+ CLUT = ALL_CLUTS;
176+ Attributes.clear();
177+
178+ return true;
179+}
180+
181+bool XML_TextureOptionsParser::_HandleAttribute(const char *Tag, const char *Value)
182+{
183+ if (StringsEqual(Tag,"coll"))
184+ {
185+ if (ReadBoundedInt16Value(Value,Collection,0,NUMBER_OF_COLLECTIONS-1))
186+ {
187+ CollIsPresent = true;
188+ return true;
189+ }
190+ else return false;
191+ }
192+ else if (StringsEqual(Tag,"clut"))
193+ {
194+ return ReadBoundedInt16Value(Value,CLUT,short(ALL_CLUTS),short(SILHOUETTE_BITMAP_SET));
195+ }
196+ else if (StringsEqual(Tag,"bitmap"))
197+ {
198+ if (ReadBoundedInt16Value(Value,Bitmap,0,MAXIMUM_SHAPES_PER_COLLECTION-1))
199+ {
200+ BitmapIsPresent = true;
201+ return true;
202+ }
203+ else return false;
204+ }
205+ else if (StringsEqual(Tag,"opac_type"))
206+ {
207+ return ReadBoundedInt16Value(Value,Data.OpacityType,0,OGL_NUMBER_OF_OPACITY_TYPES-1);
208+ }
209+ else if (StringsEqual(Tag,"opac_scale"))
210+ {
211+ return ReadFloatValue(Value,Data.OpacityScale);
212+ }
213+ else if (StringsEqual(Tag,"opac_shift"))
214+ {
215+ return ReadFloatValue(Value,Data.OpacityShift);
216+ }
217+ else if (StringsEqual(Tag,"void_visible"))
218+ {
219+ return ReadBooleanValueAsBool(Value,Data.VoidVisible);
220+ }
221+ else if (StringsEqual(Tag,"normal_image"))
222+ {
223+ Data.NormalColors.SetNameWithPath(Value);
224+ return true;
225+ }
226+ else if (StringsEqual(Tag,"offset_image"))
227+ {
228+ Data.OffsetMap.SetNameWithPath(Value);
229+ return true;
230+ }
231+ else if (StringsEqual(Tag,"normal_mask"))
232+ {
233+ Data.NormalMask.SetNameWithPath(Value);
234+ return true;
235+ }
236+ else if (StringsEqual(Tag,"glow_image"))
237+ {
238+ Data.GlowColors.SetNameWithPath(Value);
239+ return true;
240+ }
241+ else if (StringsEqual(Tag,"glow_mask"))
242+ {
243+ Data.GlowMask.SetNameWithPath(Value);
244+ return true;
245+ }
246+ else if (StringsEqual(Tag,"normal_blend"))
247+ {
248+ return ReadBoundedInt16Value(Value,Data.NormalBlend,0,OGL_NUMBER_OF_BLEND_TYPES-1);
249+ }
250+ else if (StringsEqual(Tag,"glow_blend"))
251+ {
252+ return ReadBoundedInt16Value(Value,Data.GlowBlend,0,OGL_NUMBER_OF_BLEND_TYPES-1);
253+ }
254+ else if (StringsEqual(Tag, "image_scale"))
255+ {
256+ logWarning("Ignoring deprecated image_scale tag");
257+ return true;
258+ }
259+ else if (StringsEqual(Tag,"shape_width"))
260+ {
261+ return ReadInt16Value(Value,Data.shape_width);
262+ }
263+ else if (StringsEqual(Tag,"shape_height"))
264+ {
265+ return ReadInt16Value(Value,Data.shape_height);
266+ }
267+ else if (StringsEqual(Tag,"offset_x"))
268+ {
269+ return ReadInt16Value(Value,Data.offset_x);
270+ }
271+ else if (StringsEqual(Tag,"offset_y"))
272+ {
273+ return ReadInt16Value(Value,Data.offset_y);
274+ }
275+ else if (StringsEqual(Tag,"actual_height"))
276+ {
277+ return ReadInt16Value(Value, Data.actual_height);
278+ }
279+ else if (StringsEqual(Tag, "actual_width"))
280+ {
281+ return ReadInt16Value(Value, Data.actual_width);
282+ }
283+ else if (StringsEqual(Tag, "type"))
284+ {
285+ return ReadInt16Value(Value, Data.Type);
286+ }
287+ else if (StringsEqual(Tag, "normal_premultiply"))
288+ {
289+ return ReadBooleanValueAsBool(Value, Data.NormalIsPremultiplied);
290+ }
291+ else if (StringsEqual(Tag, "glow_premultiply"))
292+ {
293+ return ReadBooleanValueAsBool(Value, Data.GlowIsPremultiplied);
294+ }
295+ else if (StringsEqual(Tag,"normal_bloom_scale"))
296+ {
297+ return ReadFloatValue(Value,Data.BloomScale);
298+ }
299+ else if (StringsEqual(Tag,"normal_bloom_shift"))
300+ {
301+ return ReadFloatValue(Value,Data.BloomShift);
302+ }
303+ else if (StringsEqual(Tag,"glow_bloom_scale"))
304+ {
305+ return ReadFloatValue(Value,Data.GlowBloomScale);
306+ }
307+ else if (StringsEqual(Tag,"glow_bloom_shift"))
308+ {
309+ return ReadFloatValue(Value,Data.GlowBloomShift);
310+ }
311+ else if (StringsEqual(Tag,"landscape_bloom"))
312+ {
313+ return ReadFloatValue(Value,Data.LandscapeBloom);
314+ }
315+ else if (StringsEqual(Tag,"minimum_glow_intensity"))
316+ {
317+ return ReadFloatValue(Value,Data.MinGlowIntensity);
318+ }
319+ UnrecognizedTag();
320+ return false;
321+}
322+
323+bool XML_TextureOptionsParser::HandleAttribute(const char* Tag, const char* Value)
324+{
325+ if (_HandleAttribute(Tag, Value))
326+ {
327+ Attributes.insert(Tag);
328+ return true;
329+ }
330+ return false;
331+}
332+
333+bool XML_TextureOptionsParser::AttributesDone()
334+{
335+ // Verify...
336+ if (!CollIsPresent || !BitmapIsPresent)
337+ {
338+ AttribsMissing();
339+ return false;
340+ }
341+
342+ TOHash::iterator it = Collections[Collection].find(TOKey(CLUT, Bitmap));
343+ if (it == Collections[Collection].end())
344+ {
345+ Collections[Collection][TOKey(CLUT, Bitmap)] = Data;
346+ return true;
347+ }
348+
349+ if (Attributes.count("opac_type"))
350+ {
351+ it->second.OpacityType = Data.OpacityType;
352+ }
353+
354+ if (Attributes.count("opac_scale"))
355+ {
356+ it->second.OpacityScale = Data.OpacityScale;
357+ }
358+
359+ if (Attributes.count("opac_shift"))
360+ {
361+ it->second.OpacityShift = Data.OpacityShift;
362+ }
363+
364+ if (Attributes.count("void_visible"))
365+ {
366+ it->second.VoidVisible = Data.VoidVisible;
367+ }
368+
369+ if (Attributes.count("normal_image"))
370+ {
371+ it->second.NormalColors = Data.NormalColors;
372+ }
373+
374+ if (Attributes.count("offset_image"))
375+ {
376+ it->second.OffsetMap = Data.OffsetMap;
377+ }
378+
379+ if (Attributes.count("normal_mask"))
380+ {
381+ it->second.NormalMask = Data.NormalMask;
382+ }
383+
384+ if (Attributes.count("glow_image"))
385+ {
386+ it->second.GlowColors = Data.GlowColors;
387+ }
388+
389+ if (Attributes.count("glow_mask"))
390+ {
391+ it->second.GlowMask = Data.GlowMask;
392+ }
393+
394+ if (Attributes.count("normal_blend"))
395+ {
396+ it->second.NormalBlend = Data.NormalBlend;
397+ }
398+
399+ if (Attributes.count("glow_blend"))
400+ {
401+ it->second.GlowBlend = Data.GlowBlend;
402+ }
403+
404+ if (Attributes.count("shape_width"))
405+ {
406+ it->second.shape_width = Data.shape_width;
407+ }
408+
409+ if (Attributes.count("shape_height"))
410+ {
411+ it->second.shape_height = Data.shape_height;
412+ }
413+
414+ if (Attributes.count("offset_x"))
415+ {
416+ it->second.offset_x = Data.offset_x;
417+ }
418+
419+ if (Attributes.count("offset_y"))
420+ {
421+ it->second.offset_y = Data.offset_y;
422+ }
423+
424+ if (Attributes.count("actual_height"))
425+ {
426+ it->second.actual_height = Data.actual_height;
427+ }
428+
429+ if (Attributes.count("actual_width"))
430+ {
431+ it->second.actual_width = Data.actual_width;
432+ }
433+
434+ if (Attributes.count("type"))
435+ {
436+ it->second.Type = Data.Type;
437+ }
438+
439+ if (Attributes.count("normal_premultiply"))
440+ {
441+ it->second.NormalIsPremultiplied = Data.NormalIsPremultiplied;
442+ }
443+
444+ if (Attributes.count("glow_premultiply"))
445+ {
446+ it->second.GlowIsPremultiplied = Data.GlowIsPremultiplied;
447+ }
448+
449+ if (Attributes.count("normal_bloom_scale"))
450+ {
451+ it->second.BloomScale = Data.BloomScale;
452+ }
453+
454+ if (Attributes.count("normal_bloom_shift"))
455+ {
456+ it->second.BloomShift = Data.BloomShift;
457+ }
458+
459+ if (Attributes.count("glow_bloom_scale"))
460+ {
461+ it->second.GlowBloomScale = Data.GlowBloomScale;
462+ }
463+
464+ if (Attributes.count("glow_bloom_shift"))
465+ {
466+ it->second.GlowBloomShift = Data.GlowBloomShift;
467+ }
468+
469+ if (Attributes.count("landscape_bloom"))
470+ {
471+ it->second.LandscapeBloom = Data.LandscapeBloom;
472+ }
473+
474+ if (Attributes.count("minimum_glow_intensity"))
475+ {
476+ it->second.MinGlowIntensity = Data.MinGlowIntensity;
477+ }
478+
479+ return true;
480+}
481+
482+bool XML_TextureOptionsParser::ResetValues()
483+{
484+ TODelete_All();
485+ return true;
486+}
487+
488+static XML_TextureOptionsParser TextureOptionsParser;
489+
490+
491+// XML-parser support:
492+XML_ElementParser *TextureOptions_GetParser() {return &TextureOptionsParser;}
493+XML_ElementParser *TO_Clear_GetParser() {return &TO_ClearParser;}
494+
495+#endif
--- marathon/trunk/Source_Files/RenderMain/OGL_Setup.cpp (revision 492)
+++ marathon/trunk/Source_Files/RenderMain/OGL_Setup.cpp (revision 493)
@@ -96,6 +96,7 @@
9696
9797 bool Using_sRGB = false;
9898 bool Wanting_sRGB = false;
99+bool Bloom_sRGB = false;
99100 bool npotTextures = false; // non-power-of-two
100101
101102 // Initializer
--- marathon/trunk/Source_Files/RenderMain/OGL_Shader.cpp (revision 492)
+++ marathon/trunk/Source_Files/RenderMain/OGL_Shader.cpp (revision 493)
@@ -77,7 +77,9 @@
7777 "depth",
7878 "strictDepthMode",
7979 "glow",
80- "landscapeInverseMatrix"
80+ "landscapeInverseMatrix",
81+ "scalex",
82+ "scaley"
8183 };
8284
8385 const char* Shader::_shader_names[NUMBER_OF_SHADER_TYPES] =
@@ -95,9 +97,7 @@
9597 "wall",
9698 "wall_bloom",
9799 "bump",
98- "bump_bloom",
99- "specular",
100- "specular_bloom"
100+ "bump_bloom"
101101 };
102102
103103 class XML_ShaderParser: public XML_ElementParser {
@@ -190,6 +190,10 @@
190190 {
191191 source.push_back("#define GAMMA_CORRECTED_BLENDING\n");
192192 }
193+ if (Bloom_sRGB)
194+ {
195+ source.push_back("#define BLOOM_SRGB_FRAMEBUFFER\n");
196+ }
193197 source.push_back(str);
194198
195199 glShaderSourceARB(shader, source.size(), &source[0], NULL);
@@ -342,50 +346,68 @@
342346 "uniform float offsety;\n"
343347 "uniform float pass;\n"
344348 "varying vec4 vertexColor;\n"
345- "const float f0 = 0.07692307;\n"
346- "const float f1 = 0.15384615;\n"
347- "const float o1 = 1.5;\n"
348- "const float f2 = 0.15384615;\n"
349- "const float o2 = 3.5;\n"
350- "const float f3 = 0.15384615;\n"
351- "const float o3 = 5.5;\n"
349+ "const float f0 = 0.14012035;\n"
350+ "const float f1 = 0.24122258;\n"
351+ "const float o1 = 1.45387071;\n"
352+ "const float f2 = 0.13265595;\n"
353+ "const float o2 = 3.39370426;\n"
354+ "const float f3 = 0.04518872;\n"
355+ "const float o3 = 5.33659787;\n"
356+ "#ifdef BLOOM_SRGB_FRAMEBUFFER\n"
357+ "vec3 s2l(vec3 srgb) { return srgb; }\n"
358+ "vec3 l2s(vec3 linear) { return linear; }\n"
359+ "#else\n"
360+ "vec3 s2l(vec3 srgb) { return srgb * srgb; }\n"
361+ "vec3 l2s(vec3 linear) { return sqrt(linear); }\n"
362+ "#endif\n"
352363 "void main (void) {\n"
353364 " vec2 s = vec2(offsetx, offsety);\n"
354365 " // Thanks to Renaud Bedard - http://theinstructionlimit.com/?p=43\n"
355- " vec3 c = texture2DRect(texture0, gl_TexCoord[0].xy).rgb;\n"
366+ " vec3 c = s2l(texture2DRect(texture0, gl_TexCoord[0].xy).rgb);\n"
356367 " vec3 t = f0 * c;\n"
357- " t += f1 * texture2DRect(texture0, gl_TexCoord[0].xy - o1*s).rgb;\n"
358- " t += f1 * texture2DRect(texture0, gl_TexCoord[0].xy + o1*s).rgb;\n"
359- " t += f2 * texture2DRect(texture0, gl_TexCoord[0].xy - o2*s).rgb;\n"
360- " t += f2 * texture2DRect(texture0, gl_TexCoord[0].xy + o2*s).rgb;\n"
361- " t += f3 * texture2DRect(texture0, gl_TexCoord[0].xy - o3*s).rgb;\n"
362- " t += f3 * texture2DRect(texture0, gl_TexCoord[0].xy + o3*s).rgb;\n"
363- " if (pass < 1.5) { t = clamp(t, c, vec3(1.0, 1.0, 1.0)); }\n"
364- " gl_FragColor = vec4(t, 1.0) * vertexColor;\n"
368+ " t += f1 * s2l(texture2DRect(texture0, gl_TexCoord[0].xy - o1*s).rgb);\n"
369+ " t += f1 * s2l(texture2DRect(texture0, gl_TexCoord[0].xy + o1*s).rgb);\n"
370+ " t += f2 * s2l(texture2DRect(texture0, gl_TexCoord[0].xy - o2*s).rgb);\n"
371+ " t += f2 * s2l(texture2DRect(texture0, gl_TexCoord[0].xy + o2*s).rgb);\n"
372+ " t += f3 * s2l(texture2DRect(texture0, gl_TexCoord[0].xy - o3*s).rgb);\n"
373+ " t += f3 * s2l(texture2DRect(texture0, gl_TexCoord[0].xy + o3*s).rgb);\n"
374+ " gl_FragColor = vec4(l2s(t), 1.0) * vertexColor;\n"
375+ "}\n";
376+
377+ defaultVertexPrograms["bloom"] = ""
378+ "varying vec4 vertexColor;\n"
379+ "void main(void) {\n"
380+ " gl_TexCoord[0] = gl_MultiTexCoord0;\n"
381+ "#ifndef BLOOM_SRGB_FRAMEBUFFER\n"
382+ " gl_TexCoord[1] = gl_MultiTexCoord1;\n"
383+ "#endif\n"
384+ " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
385+ " vertexColor = gl_Color;\n"
365386 "}\n";
366-
367- defaultVertexPrograms["bloom"] = defaultVertexPrograms["blur"];
368387 defaultFragmentPrograms["bloom"] = ""
369388 "uniform sampler2DRect texture0;\n"
370389 "uniform float pass;\n"
371390 "varying vec4 vertexColor;\n"
391+ "#ifndef BLOOM_SRGB_FRAMEBUFFER\n"
392+ "uniform sampler2DRect texture1;\n"
393+ "vec3 s2l(vec3 srgb) { return srgb * srgb; }\n"
394+ "vec3 l2s(vec3 linear) { return sqrt(linear); }\n"
395+ "#endif\n"
372396 "void main (void) {\n"
373- " vec4 color = texture2DRect(texture0, gl_TexCoord[0].xy);\n"
374- "#ifdef GAMMA_CORRECTED_BLENDING\n"
375- " color = color * (1.0 - 0.1 * pass * pass);\n"
397+ " vec4 color0 = texture2DRect(texture0, gl_TexCoord[0].xy);\n"
398+ "#ifndef BLOOM_SRGB_FRAMEBUFFER\n"
399+ " vec4 color1 = texture2DRect(texture1, gl_TexCoord[1].xy);\n"
400+ " vec3 color = l2s(s2l(color0.rgb) + s2l(color1.rgb));\n"
376401 "#else\n"
377- " color = color * (1.0 - 0.05 * pass);\n"
402+ " vec3 color = color0.rgb;\n"
378403 "#endif\n"
379- " gl_FragColor = color * vertexColor;\n"
404+ " gl_FragColor = vec4(color, 1.0);\n"
380405 "}\n";
381406
382407 defaultVertexPrograms["landscape"] = ""
383408 "uniform mat4 landscapeInverseMatrix;\n"
384- "varying vec3 viewDir;\n"
385409 "varying vec3 faceDir;\n"
386410 "varying vec3 relDir;\n"
387- "varying float texScale;\n"
388- "varying float texOffset;\n"
389411 "varying vec4 vertexColor;\n"
390412 "void main(void) {\n"
391413 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
@@ -393,34 +415,28 @@
393415 " gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n"
394416 "#endif\n"
395417 " vec4 v = landscapeInverseMatrix * vec4(0.0, 0.0, 0.0, 1.0);\n"
396- " viewDir = (gl_Vertex - v).xyz;\n"
397418 " faceDir = ((gl_ModelViewMatrixInverse * vec4(0.0, 0.0, -1.0, 1.0)) - v).xyz;\n"
398419 " relDir = (gl_ModelViewMatrix * gl_Vertex).xyz;\n"
399- " texScale = gl_TextureMatrix[0][1][1];\n"
400- " texOffset = gl_TextureMatrix[0][3][1];\n"
401420 " vertexColor = gl_Color;\n"
402421 "}\n";
403422 defaultFragmentPrograms["landscape"] = ""
404423 "uniform sampler2D texture0;\n"
405- "uniform float repeat;\n"
406424 "uniform float usefog;\n"
407- "varying vec3 viewDir;\n"
425+ "uniform float scalex;\n"
426+ "uniform float scaley;\n"
427+ "uniform float offsetx;\n"
428+ "uniform float offsety;\n"
408429 "varying vec3 faceDir;\n"
409430 "varying vec3 relDir;\n"
410- "varying float texScale;\n"
411- "varying float texOffset;\n"
412431 "varying vec4 vertexColor;\n"
413- "const float pi = 3.141593;\n"
414432 "const float zoom = 1.2;\n"
415433 "const float pitch_adjust = 0.96;\n"
416434 "void main(void) {\n"
417435 " vec3 facev = normalize(faceDir);\n"
418436 " vec3 relv = normalize(relDir);\n"
419- " float offset = abs(texScale) > 1.01 ? 0.5 : 0.5 / abs(texScale) - sign(texOffset) + texOffset;\n"
420- " float scale = texScale * repeat / (2.0 * pi);\n"
421437 " float x = relv.x / (relv.z * zoom) + atan(facev.x, facev.y);\n"
422438 " float y = relv.y / (relv.z * zoom) - (facev.z * pitch_adjust);\n"
423- " vec4 color = texture2D(texture0, vec2(sign(scale) * (0.5 - x * scale), offset - y * scale));\n"
439+ " vec4 color = texture2D(texture0, vec2(offsetx - x * scalex, offsety - y * scaley));\n"
424440 " vec3 intensity = color.rgb;\n"
425441 " if (usefog > 0.0) {\n"
426442 " intensity = gl_Fog.color.rgb;\n"
@@ -430,26 +446,23 @@
430446 defaultVertexPrograms["landscape_bloom"] = defaultVertexPrograms["landscape"];
431447 defaultFragmentPrograms["landscape_bloom"] = ""
432448 "uniform sampler2D texture0;\n"
433- "uniform float repeat;\n"
434449 "uniform float usefog;\n"
450+ "uniform float scalex;\n"
451+ "uniform float scaley;\n"
452+ "uniform float offsetx;\n"
453+ "uniform float offsety;\n"
435454 "uniform float bloomScale;\n"
436- "varying vec3 viewDir;\n"
437455 "varying vec3 faceDir;\n"
438456 "varying vec3 relDir;\n"
439- "varying float texScale;\n"
440- "varying float texOffset;\n"
441457 "varying vec4 vertexColor;\n"
442- "const float pi = 3.141593;\n"
443- "const float zoom = 1.2;\n"
444- "const float pitch_adjust = 0.96;\n"
458+ "const float zoom = 1.205;\n"
459+ "const float pitch_adjust = 0.955;\n"
445460 "void main(void) {\n"
446461 " vec3 facev = normalize(faceDir);\n"
447462 " vec3 relv = normalize(relDir);\n"
448- " float offset = abs(texScale) > 1.01 ? 0.5 : 0.5 / abs(texScale) - sign(texOffset) + texOffset;\n"
449- " float scale = texScale * repeat / (2.0 * pi);\n"
450463 " float x = relv.x / (relv.z * zoom) + atan(facev.x, facev.y);\n"
451464 " float y = relv.y / (relv.z * zoom) - (facev.z * pitch_adjust);\n"
452- " vec4 color = texture2D(texture0, vec2(sign(scale) * (0.5 - x * scale), offset - y * scale));\n"
465+ " vec4 color = texture2D(texture0, vec2(offsetx - x * scalex, offsety - y * scaley));\n"
453466 " float intensity = clamp(bloomScale, 0.0, 1.0);\n"
454467 " if (usefog > 0.0) {\n"
455468 " intensity = 0.0;\n"
@@ -717,7 +730,7 @@
717730 " texCoords.x += h * viewv.x;\n"
718731 " texCoords.y -= h * viewv.y;\n"
719732 " }\n"
720- " vec3 norm = (texture2D(texture1, gl_TexCoord[0].xy).rgb - vec3(0.5, 0.5, 0.0)) * vec3(2.0, 2.0, 1.0);\n"
733+ " vec3 norm = (texture2D(texture1, texCoords.xy).rgb - 0.5) * 2.0;\n"
721734 " float diffuse = 0.5 + abs(dot(norm, viewv))*0.5;\n"
722735 " if (glow > 0.001) {\n"
723736 " diffuse = 1.0;\n"
@@ -756,7 +769,7 @@
756769 " texCoords.x += h * viewv.x;\n"
757770 " texCoords.y -= h * viewv.y;\n"
758771 " }\n"
759- " vec3 norm = (texture2D(texture1, gl_TexCoord[0].xy).rgb - vec3(0.5, 0.5, 0.0)) * vec3(2.0, 2.0, 1.0);\n"
772+ " vec3 norm = (texture2D(texture1, texCoords.xy).rgb - 0.5) * 2.0;\n"
760773 " float diffuse = 0.5 + abs(dot(norm, viewv))*0.5;\n"
761774 " if (glow > 0.001) {\n"
762775 " diffuse = 1.0;\n"
@@ -770,56 +783,5 @@
770783 " float fogFactor = clamp(exp2(FDxLOG2E * length(viewDir)), 0.0, 1.0);\n"
771784 " gl_FragColor = vec4(mix(vec3(0.0, 0.0, 0.0), color.rgb * intensity, fogFactor), vertexColor.a * color.a);\n"
772785 "}\n";
773- defaultVertexPrograms["specular"] = defaultVertexPrograms["bump"];
774- defaultFragmentPrograms["specular"] = ""
775- "uniform sampler2D texture0;\n"
776- "uniform sampler2D texture1;\n"
777- "uniform float glow;\n"
778- "uniform float flare;\n"
779- "varying vec3 viewXY;\n"
780- "varying vec3 viewDir;\n"
781- "varying vec4 vertexColor;\n"
782- "varying float FDxLOG2E;\n"
783- "void main (void) {\n"
784- " float mlFactor = clamp(0.5 + flare - (length(viewDir)/8192.0), 0.0, 1.0);\n"
785- " vec3 intensity;\n"
786- " if (vertexColor.r > mlFactor) {\n"
787- " intensity = vertexColor.rgb + (mlFactor * 0.5); }\n"
788- " else {\n"
789- " intensity = (vertexColor.rgb * 0.5) + mlFactor; }\n"
790- " vec3 viewv = normalize(viewDir);\n"
791- " vec3 norm = (texture2D(texture1, gl_TexCoord[0].xy).rgb - vec3(0.5, 0.5, 0.0)) * vec3(2.0, 2.0, 1.0);\n"
792- " float diffuse = 0.5 + abs(dot(norm, viewv))*0.5;\n"
793- " vec4 color = texture2D(texture0, gl_TexCoord[0].xy);\n"
794- " float diffuse_factor = texture2D(texture1, gl_TexCoord[0].xy).a - 0.5;\n"
795- " diffuse = pow(diffuse, 14.0 * diffuse_factor + 1.0);\n"
796- " float fogFactor = clamp(exp2(FDxLOG2E * length(viewDir)), 0.0, 1.0);\n"
797- " gl_FragColor = vec4(mix(vec3(0.0, 0.0, 0.0), color.rgb * diffuse, fogFactor), vertexColor.a * color.a);\n"
798- "}\n";
799- defaultVertexPrograms["specular_bloom"] = defaultVertexPrograms["bump"];
800- defaultFragmentPrograms["specular_bloom"] = ""
801- "uniform sampler2D texture0;\n"
802- "uniform sampler2D texture1;\n"
803- "uniform float glow;\n"
804- "uniform float flare;\n"
805- "uniform float bloomScale;\n"
806- "uniform float bloomShift;\n"
807- "varying vec3 viewXY;\n"
808- "varying vec3 viewDir;\n"
809- "varying vec4 vertexColor;\n"
810- "varying float FDxLOG2E;\n"
811- "void main (void) {\n"
812- " vec3 viewv = normalize(viewDir);\n"
813- " vec3 norm = (texture2D(texture1, gl_TexCoord[0].xy).rgb - vec3(0.5, 0.5, 0.0)) * vec3(2.0, 2.0, 1.0);\n"
814- " float diffuse = 0.5 + abs(dot(norm, viewv))*0.5;\n"
815- " if (glow > 0.001) {\n"
816- " diffuse = 1.0;\n"
817- " }\n"
818- " vec4 color = texture2D(texture0, gl_TexCoord[0].xy);\n"
819- " float diffuse_factor = 2.0 * (texture2D(texture1, gl_TexCoord[0].xy).a - 0.5);\n"
820- " diffuse = pow(diffuse, 256.0 * diffuse_factor) * diffuse_factor;\n"
821- " float fogFactor = clamp(exp2(FDxLOG2E * length(viewDir)), 0.0, 1.0);\n"
822- " gl_FragColor = vec4(mix(vec3(0.0, 0.0, 0.0), color.rgb * diffuse, fogFactor), vertexColor.a * color.a);\n"
823- "}\n";
824786 }
825787
--- marathon/trunk/Source_Files/RenderMain/OGL_Model_Def.cpp (revision 492)
+++ marathon/trunk/Source_Files/RenderMain/OGL_Model_Def.cpp (revision 493)
@@ -1,1016 +1,1032 @@
1-/*
2-
3- Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
4- and the "Aleph One" developers.
5-
6- This program is free software; you can redistribute it and/or modify
7- it under the terms of the GNU General Public License as published by
8- the Free Software Foundation; either version 2 of the License, or
9- (at your option) any later version.
10-
11- This program is distributed in the hope that it will be useful,
12- but WITHOUT ANY WARRANTY; without even the implied warranty of
13- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14- GNU General Public License for more details.
15-
16- This license is contained in the file "COPYING",
17- which is included with this source code; it is available online at
18- http://www.gnu.org/licenses/gpl.html
19-
20- OpenGL Model-Definition File
21- by Loren Petrich,
22- May 11, 2003
23-
24- This contains the definitions of all the OpenGL models and skins
25-*/
26-
27-#include "cseries.h"
28-#include "OGL_Model_Def.h"
29-#include "OGL_Setup.h"
30-
31-#ifdef HAVE_OPENGL
32-
33-#include <cmath>
34-
35-#include "Dim3_Loader.h"
36-#include "StudioLoader.h"
37-#include "WavefrontLoader.h"
38-#include "QD3D_Loader.h"
39-
40-
41-// Model-data stuff;
42-// defaults for whatever might need them
43-// Including skin stuff for convenience here
44-static OGL_ModelData DefaultModelData;
45-static OGL_SkinData DefaultSkinData;
46-
47-
48-// For mapping Marathon-physics sequences onto model sequences
49-struct SequenceMapEntry
50-{
51- int16 Sequence;
52- int16 ModelSequence;
53-};
54-
55-
56-// Store model-data stuff in a set of STL vectors
57-struct ModelDataEntry
58-{
59- // Which Marathon-engine sequence gets translated into this model,
60- // if static, or the neutral sequence, if dynamic
61- short Sequence;
62-
63- vector<SequenceMapEntry> SequenceMap;
64-
65- // Make a member for more convenient access
66- OGL_ModelData ModelData;
67-
68- ModelDataEntry(): Sequence(NONE) {}
69-};
70-
71-
72-// Separate model-data sequence lists for each collection ID,
73-// to speed up searching
74-static vector<ModelDataEntry> MdlList[NUMBER_OF_COLLECTIONS];
75-
76-// Will look up both the model index and its sequence
77-struct ModelHashEntry
78-{
79- int16 ModelIndex;
80- int16 ModelSeqTabIndex;
81-};
82-
83-// Model-data hash table for extra-fast searching:
84-static vector<ModelHashEntry> MdlHash[NUMBER_OF_COLLECTIONS];
85-
86-// Hash-table size and function
87-const int MdlHashSize = 1 << 8;
88-const int MdlHashMask = MdlHashSize - 1;
89-inline uint8 MdlHashFunc(short Sequence)
90-{
91- // E-Z
92- return (uint8)(Sequence & MdlHashMask);
93-}
94-
95-
96-// Deletes a collection's model-data sequences
97-static void MdlDelete(short Collection)
98-{
99- int c = Collection;
100- MdlList[c].clear();
101- MdlHash[c].clear();
102-}
103-
104-// Deletes all of them
105-static void MdlDeleteAll()
106-{
107- for (int c=0; c<NUMBER_OF_COLLECTIONS; c++) MdlDelete(c);
108-}
109-
110-
111-OGL_ModelData *OGL_GetModelData(short Collection, short Sequence, short& ModelSequence)
112-{
113- // Model is neutral unless specified otherwise
114- ModelSequence = NONE;
115-
116- // Initialize the hash table if necessary
117- if (MdlHash[Collection].empty())
118- {
119- MdlHash[Collection].resize(MdlHashSize);
120- objlist_set(&MdlHash[Collection][0],NONE,MdlHashSize);
121- }
122-
123- // Set up a *reference* to the appropriate hashtable entry;
124- // this makes setting this entry a bit more convenient
125- ModelHashEntry& HashVal = MdlHash[Collection][MdlHashFunc(Sequence)];
126-
127- // Check to see if the model-data entry is correct;
128- // if it is, then we're done.
129- if (HashVal.ModelIndex != NONE)
130- {
131- // First, check in the sequence-map table
132- vector<ModelDataEntry>::iterator MdlIter = MdlList[Collection].begin() + HashVal.ModelIndex;
133- size_t MSTIndex = static_cast<size_t>(HashVal.ModelSeqTabIndex); // Cast only safe b/c of following check
134- if (MSTIndex < MdlIter->SequenceMap.size())
135- {
136- vector<SequenceMapEntry>::iterator SMIter = MdlIter->SequenceMap.begin() + MSTIndex;
137- if (SMIter->Sequence == Sequence)
138- {
139- ModelSequence = SMIter->ModelSequence;
140- return MdlIter->ModelData.ModelPresent() ? &MdlIter->ModelData : NULL;
141- }
142- }
143-
144- // Now check the neutral sequence
145- if (MdlIter->Sequence == Sequence)
146- {
147- return MdlIter->ModelData.ModelPresent() ? &MdlIter->ModelData : NULL;
148- }
149- }
150-
151- // Fallback for the case of a hashtable miss;
152- // do a linear search and then update the hash entry appropriately.
153- vector<ModelDataEntry>& ML = MdlList[Collection];
154- int16 Indx = 0;
155- for (vector<ModelDataEntry>::iterator MdlIter = ML.begin(); MdlIter < ML.end(); MdlIter++, Indx++)
156- {
157- // First, search the sequence-map table
158- int16 SMIndx = 0;
159- vector<SequenceMapEntry>& SM = MdlIter->SequenceMap;
160- for (vector<SequenceMapEntry>::iterator SMIter = SM.begin(); SMIter < SM.end(); SMIter++, SMIndx++)
161- {
162- if (SMIter->Sequence == Sequence)
163- {
164- HashVal.ModelIndex = Indx;
165- HashVal.ModelSeqTabIndex = SMIndx;
166- ModelSequence = SMIter->ModelSequence;
167- return MdlIter->ModelData.ModelPresent() ? &MdlIter->ModelData : NULL;
168- }
169- }
170-
171- // Now check the neutral sequence
172- if (MdlIter->Sequence == Sequence)
173- {
174- HashVal.ModelIndex = Indx;
175- HashVal.ModelSeqTabIndex = NONE;
176- return MdlIter->ModelData.ModelPresent() ? &MdlIter->ModelData : NULL;
177- }
178- }
179-
180- // None found!
181- return NULL;
182-}
183-
184-int OGL_SkinData::GetMaxSize()
185-{
186- return Get_OGL_ConfigureData().ModelConfig.MaxSize;
187-}
188-
189-
190-// Any easy STL ways of doing this mapping of functions onto members of arrays?
191-
192-void OGL_SkinManager::Load()
193-{
194- for (vector<OGL_SkinData>::iterator SkinIter = SkinData.begin(); SkinIter < SkinData.end(); SkinIter++)
195- SkinIter->Load();
196-}
197-
198-
199-void OGL_SkinManager::Unload()
200-{
201- for (vector<OGL_SkinData>::iterator SkinIter = SkinData.begin(); SkinIter < SkinData.end(); SkinIter++)
202- SkinIter->Unload();
203-}
204-
205-
206-void OGL_SkinManager::Reset(bool Clear_OGL_Txtrs)
207-{
208- if (Clear_OGL_Txtrs)
209- {
210- for (int k=0; k<NUMBER_OF_OPENGL_BITMAP_SETS; k++)
211- for (int l=0; l<NUMBER_OF_TEXTURES; l++)
212- {
213- if (IDsInUse[k][l])
214- glDeleteTextures(1,&IDs[k][l]);
215- }
216- }
217-
218- // Mass clearing
219- objlist_clear(IDsInUse[0],NUMBER_OF_OPENGL_BITMAP_SETS*NUMBER_OF_TEXTURES);
220-}
221-
222-
223-OGL_SkinData *OGL_SkinManager::GetSkin(short CLUT)
224-{
225- for (unsigned k=0; k<SkinData.size(); k++)
226- {
227- OGL_SkinData& Skin = SkinData[k];
228- if (Skin.CLUT == CLUT || Skin.CLUT == ALL_CLUTS)
229- return &Skin;
230- }
231-
232- return NULL;
233-}
234-
235-
236-bool OGL_SkinManager::Use(short CLUT, short Which)
237-{
238- // References so they can be written into
239- GLuint& TxtrID = IDs[CLUT][Which];
240- bool& InUse = IDsInUse[CLUT][Which];
241- bool LoadSkin = false;
242- if (!InUse)
243- {
244- glGenTextures(1,&TxtrID);
245- InUse = true;
246- LoadSkin = true;
247- }
248- glBindTexture(GL_TEXTURE_2D,TxtrID);
249- return LoadSkin;
250-}
251-
252-
253-// Circle constants
254-const double TWO_PI = 8*atan(1.0);
255-const double Degree2Radian = TWO_PI/360; // A circle is 2*pi radians
256-
257-// Matrix manipulation (can't trust OpenGL to be active, so won't be using OpenGL matrix stuff)
258-
259-// Src -> Dest
260-static void MatCopy(const GLfloat SrcMat[3][3], GLfloat DestMat[3][3])
261-{
262- objlist_copy(DestMat[0],SrcMat[0],9);
263-}
264-
265-// Sets the arg to that matrix
266-static void MatIdentity(GLfloat Mat[3][3])
267-{
268- const GLfloat IMat[3][3] = {{1,0,0},{0,1,0},{0,0,1}};
269- MatCopy(IMat,Mat);
270-}
271-
272-// Src1, Src2 -> Dest (cannot be one of the sources)
273-static void MatMult(const GLfloat Mat1[3][3], const GLfloat Mat2[3][3], GLfloat DestMat[3][3])
274-{
275- for (int k=0; k<3; k++)
276- for (int l=0; l<3; l++)
277- {
278- GLfloat Sum = 0;
279- for (int m=0; m<3; m++)
280- Sum += Mat1[k][m]*Mat2[m][l];
281- DestMat[k][l] = Sum;
282- }
283-}
284-
285-// Alters the matrix in place
286-static void MatScalMult(GLfloat Mat[3][3], const GLfloat Scale)
287-{
288- for (int k=0; k<3; k++)
289- {
290- GLfloat *MatRow = Mat[k];
291- for (int l=0; l<3; l++)
292- MatRow[l] *= Scale;
293- }
294-}
295-
296-// Src -> Dest vector (cannot be the same location)
297-static void MatVecMult(const GLfloat Mat[3][3], const GLfloat *SrcVec, GLfloat *DestVec)
298-{
299- for (int k=0; k<3; k++)
300- {
301- const GLfloat *MatRow = Mat[k];
302- GLfloat Sum = 0;
303- for (int l=0; l<3; l++)
304- Sum += MatRow[l]*SrcVec[l];
305- DestVec[k] = Sum;
306- }
307-}
308-
309-
310-inline bool StringPresent(vector<char>& String)
311-{
312- return (String.size() > 1);
313-}
314-
315-
316-void OGL_ModelData::Load()
317-{
318- // Already loaded?
319- if (ModelPresent()) return;
320-
321- // Load the model
322- Model.Clear();
323-
324- if (ModelFile == FileSpecifier()) return;
325- if (!ModelFile.Exists()) return;
326-
327- bool Success = false;
328-
329- char *Type = &ModelType[0];
330- if (StringsEqual(Type,"wave",4))
331- {
332- // Alias|Wavefront, backward compatible version
333- Success = LoadModel_Wavefront(ModelFile, Model);
334- }
335- else if (StringsEqual(Type,"obj",3))
336- {
337- // Alias|Wavefront, but with coordinate system conversion.
338- Success = LoadModel_Wavefront_RightHand(ModelFile, Model);
339- }
340- else if (StringsEqual(Type,"3ds",3))
341- {
342- // 3D Studio Max, backward compatible version
343- Success = LoadModel_Studio(ModelFile, Model);
344- }
345- else if (StringsEqual(Type,"max",3))
346- {
347- // 3D Studio Max, but with coordinate system conversion.
348- Success = LoadModel_Studio_RightHand(ModelFile, Model);
349- }
350- else if (StringsEqual(Type,"dim3",4))
351- {
352- // Brian Barnes's "Dim3" model format (first pass: model geometry)
353- Success = LoadModel_Dim3(ModelFile, Model, LoadModelDim3_First);
354-
355- // Second and third passes: frames and sequences
356- try
357- {
358- if (ModelFile1 == FileSpecifier()) throw 0;
359- if (!ModelFile1.Exists()) throw 0;
360- if (!LoadModel_Dim3(ModelFile1, Model, LoadModelDim3_Rest)) throw 0;
361- }
362- catch(...)
363- {}
364- //
365- try
366- {
367- if (ModelFile2 == FileSpecifier()) throw 0;
368- if (!ModelFile2.Exists()) throw 0;
369- if (!LoadModel_Dim3(ModelFile2, Model, LoadModelDim3_Rest)) throw 0;
370- }
371- catch(...)
372- {}
373- }
374-#if HAVE_QUESA
375- else if (StringsEqual(Type,"qd3d") || StringsEqual(Type,"3dmf") || StringsEqual(Type,"quesa"))
376- {
377- // QuickDraw 3D / Quesa
378- Success = LoadModel_QD3D(ModelFile, Model);
379- }
380-#endif
381-
382- if (!Success)
383- {
384- Model.Clear();
385- return;
386- }
387-
388- // Calculate transformation matrix
389- GLfloat Angle, Cosine, Sine;
390- GLfloat RotMatrix[3][3], NewRotMatrix[3][3], IndivRotMatrix[3][3];
391- MatIdentity(RotMatrix);
392-
393- MatIdentity(IndivRotMatrix);
394- Angle = (float)Degree2Radian*XRot;
395- Cosine = (float)cos(Angle);
396- Sine = (float)sin(Angle);
397- IndivRotMatrix[1][1] = Cosine;
398- IndivRotMatrix[1][2] = - Sine;
399- IndivRotMatrix[2][1] = Sine;
400- IndivRotMatrix[2][2] = Cosine;
401- MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix);
402- MatCopy(NewRotMatrix,RotMatrix);
403-
404- MatIdentity(IndivRotMatrix);
405- Angle = (float)Degree2Radian*YRot;
406- Cosine = (float)cos(Angle);
407- Sine = (float)sin(Angle);
408- IndivRotMatrix[2][2] = Cosine;
409- IndivRotMatrix[2][0] = - Sine;
410- IndivRotMatrix[0][2] = Sine;
411- IndivRotMatrix[0][0] = Cosine;
412- MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix);
413- MatCopy(NewRotMatrix,RotMatrix);
414-
415- MatIdentity(IndivRotMatrix);
416- Angle = (float)Degree2Radian*ZRot;
417- Cosine = (float)cos(Angle);
418- Sine = (float)sin(Angle);
419- IndivRotMatrix[0][0] = Cosine;
420- IndivRotMatrix[0][1] = - Sine;
421- IndivRotMatrix[1][0] = Sine;
422- IndivRotMatrix[1][1] = Cosine;
423- MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix);
424- MatCopy(NewRotMatrix,RotMatrix);
425-
426- MatScalMult(NewRotMatrix,Scale); // For the position vertices
427- if (Scale < 0) MatScalMult(RotMatrix,-1); // For the normals
428-
429- // Is model animated or static?
430- // Test by trying to find neutral positions (useful for working with the normals later on)
431- if (Model.FindPositions_Neutral(false))
432- {
433- // Copy over the vector and normal transformation matrices:
434- for (int k=0; k<3; k++)
435- for (int l=0; l<3; l++)
436- {
437- Model.TransformPos.M[k][l] = NewRotMatrix[k][l];
438- Model.TransformNorm.M[k][l] = RotMatrix[k][l];
439- }
440-
441- Model.TransformPos.M[0][3] = XShift;
442- Model.TransformPos.M[1][3] = YShift;
443- Model.TransformPos.M[2][3] = ZShift;
444-
445- // Find the transformed bounding box:
446- bool RestOfCorners = false;
447- GLfloat NewBoundingBox[2][3];
448- // The indices i1, i2, and i3 are for selecting which of the box's two principal corners
449- // to get coordinates from
450- for (int i1=0; i1<2; i1++)
451- {
452- GLfloat X = Model.BoundingBox[i1][0];
453- for (int i2=0; i2<2; i2++)
454- {
455- GLfloat Y = Model.BoundingBox[i2][0];
456- for (int i3=0; i3<2; i3++)
457- {
458- GLfloat Z = Model.BoundingBox[i3][0];
459-
460- GLfloat Corner[3];
461- for (int ic=0; ic<3; ic++)
462- {
463- GLfloat *Row = Model.TransformPos.M[ic];
464- Corner[ic] = Row[0]*X + Row[1]*Y + Row[2]*Z + Row[3];
465- }
466-
467- if (RestOfCorners)
468- {
469- // Find minimum and maximum for each coordinate
470- for (int ic=0; ic<3; ic++)
471- {
472- NewBoundingBox[0][ic] = min(NewBoundingBox[0][ic],Corner[ic]);
473- NewBoundingBox[1][ic] = max(NewBoundingBox[1][ic],Corner[ic]);
474- }
475- }
476- else
477- {
478- // Simply copy it in:
479- for (int ic=0; ic<3; ic++)
480- NewBoundingBox[0][ic] = NewBoundingBox[1][ic] = Corner[ic];
481- RestOfCorners = true;
482- }
483- }
484- }
485- }
486-
487- for (int ic=0; ic<2; ic++)
488- objlist_copy(Model.BoundingBox[ic],NewBoundingBox[ic],3);
489- }
490- else
491- {
492- // Static model
493- size_t NumVerts = Model.Positions.size()/3;
494-
495- for (size_t k=0; k<NumVerts; k++)
496- {
497- GLfloat *Pos = Model.PosBase() + 3*k;
498- GLfloat NewPos[3];
499- MatVecMult(NewRotMatrix,Pos,NewPos); // Has the scaling
500- Pos[0] = NewPos[0] + XShift;
501- Pos[1] = NewPos[1] + YShift;
502- Pos[2] = NewPos[2] + ZShift;
503- }
504-
505- size_t NumNorms = Model.Normals.size()/3;
506- for (size_t k=0; k<NumNorms; k++)
507- {
508- GLfloat *Norms = Model.NormBase() + 3*k;
509- GLfloat NewNorms[3];
510- MatVecMult(RotMatrix,Norms,NewNorms); // Not scaled
511- objlist_copy(Norms,NewNorms,3);
512- }
513-
514- // So as to be consistent with the new points
515- Model.FindBoundingBox();
516- }
517-
518- Model.AdjustNormals(NormalType,NormalSplit);
519- Model.CalculateTangents();
520-
521- // Don't forget the skins
522- OGL_SkinManager::Load();
523-}
524-
525-
526-void OGL_ModelData::Unload()
527-{
528- Model.Clear();
529- OGL_ResetForceSpriteDepth();
530-
531- // Don't forget the skins
532- OGL_SkinManager::Unload();
533-}
534-
535-int OGL_CountModels(short Collection)
536-{
537- return MdlList[Collection].size();
538-}
539-
540-extern void OGL_ProgressCallback(int);
541-
542-static bool ForcingSpriteDepth = false;
543-void OGL_ResetForceSpriteDepth() { ForcingSpriteDepth = false; }
544-bool OGL_ForceSpriteDepth() { return ForcingSpriteDepth; }
545-
546-// for managing the model and image loading and unloading
547-void OGL_LoadModels(short Collection)
548-{
549- vector<ModelDataEntry>& ML = MdlList[Collection];
550- for (vector<ModelDataEntry>::iterator MdlIter = ML.begin(); MdlIter < ML.end(); MdlIter++)
551- {
552- MdlIter->ModelData.Load();
553- if (MdlIter->ModelData.ForceSpriteDepth)
554- {
555- ForcingSpriteDepth = true;
556- }
557- OGL_ProgressCallback(1);
558- }
559-}
560-
561-void OGL_UnloadModels(short Collection)
562-{
563- vector<ModelDataEntry>& ML = MdlList[Collection];
564- for (vector<ModelDataEntry>::iterator MdlIter = ML.begin(); MdlIter < ML.end(); MdlIter++)
565- {
566- MdlIter->ModelData.Unload();
567- }
568-}
569-
570-
571-// Reset model skins; used in OGL_ResetTextures() in OGL_Textures.cpp
572-void OGL_ResetModelSkins(bool Clear_OGL_Txtrs)
573-{
574- for (int ic=0; ic<MAXIMUM_COLLECTIONS; ic++)
575- {
576- vector<ModelDataEntry>& ML = MdlList[ic];
577- for (vector<ModelDataEntry>::iterator MdlIter = ML.begin(); MdlIter < ML.end(); MdlIter++)
578- {
579- MdlIter->ModelData.Reset(Clear_OGL_Txtrs);
580- }
581- }
582-}
583-
584-class XML_SkinDataParser: public XML_ElementParser
585-{
586- short CLUT;
587-
588- OGL_SkinData Data;
589-public:
590- bool Start();
591- bool HandleAttribute(const char *Tag, const char *Value);
592- bool AttributesDone();
593-
594- vector<OGL_SkinData> *SkinDataPtr;
595-
596- XML_SkinDataParser(): XML_ElementParser("skin"), SkinDataPtr(NULL) {}
597-};
598-
599-bool XML_SkinDataParser::Start()
600-{
601- Data = DefaultSkinData;
602-
603- return true;
604-}
605-
606-bool XML_SkinDataParser::HandleAttribute(const char *Tag, const char *Value)
607-{
608- if (StringsEqual(Tag,"clut"))
609- {
610- return ReadBoundedInt16Value(Value,Data.CLUT,short(ALL_CLUTS),short(SILHOUETTE_BITMAP_SET));
611- }
612- else if (StringsEqual(Tag,"opac_type"))
613- {
614- return ReadBoundedInt16Value(Value,Data.OpacityType,0,OGL_NUMBER_OF_OPACITY_TYPES-1);
615- }
616- else if (StringsEqual(Tag,"opac_scale"))
617- {
618- return ReadFloatValue(Value,Data.OpacityScale);
619- }
620- else if (StringsEqual(Tag,"opac_shift"))
621- {
622- return ReadFloatValue(Value,Data.OpacityShift);
623- }
624- else if (StringsEqual(Tag,"normal_image"))
625- {
626- Data.NormalColors.SetNameWithPath(Value);
627- return true;
628- }
629- else if (StringsEqual(Tag,"offset_image"))
630- {
631- Data.OffsetMap.SetNameWithPath(Value);
632- return true;
633- }
634- else if (StringsEqual(Tag,"normal_mask"))
635- {
636- Data.NormalMask.SetNameWithPath(Value);
637- return true;
638- }
639- else if (StringsEqual(Tag,"glow_image"))
640- {
641- Data.GlowColors.SetNameWithPath(Value);
642- return true;
643- }
644- else if (StringsEqual(Tag,"glow_mask"))
645- {
646- Data.GlowMask.SetNameWithPath(Value);
647- return true;
648- }
649- else if (StringsEqual(Tag,"normal_blend"))
650- {
651- return ReadBoundedInt16Value(Value,Data.NormalBlend,0,OGL_NUMBER_OF_BLEND_TYPES-1);
652- }
653- else if (StringsEqual(Tag,"glow_blend"))
654- {
655- return ReadBoundedInt16Value(Value,Data.GlowBlend,0,OGL_NUMBER_OF_BLEND_TYPES-1);
656- }
657- else if (StringsEqual(Tag,"normal_bloom_scale"))
658- {
659- return ReadFloatValue(Value,Data.BloomScale);
660- }
661- else if (StringsEqual(Tag,"normal_bloom_shift"))
662- {
663- return ReadFloatValue(Value,Data.BloomShift);
664- }
665- else if (StringsEqual(Tag,"glow_bloom_scale"))
666- {
667- return ReadFloatValue(Value,Data.GlowBloomScale);
668- }
669- else if (StringsEqual(Tag,"glow_bloom_shift"))
670- {
671- return ReadFloatValue(Value,Data.GlowBloomShift);
672- }
673- else if (StringsEqual(Tag,"minimum_glow_intensity"))
674- {
675- return ReadFloatValue(Value,Data.MinGlowIntensity);
676- }
677- UnrecognizedTag();
678- return false;
679-}
680-
681-bool XML_SkinDataParser::AttributesDone()
682-{
683- // Check to see if a frame is already accounted for
684- assert(SkinDataPtr);
685- vector<OGL_SkinData>& SkinData = *SkinDataPtr;
686- for (vector<OGL_SkinData>::iterator SDIter = SkinData.begin(); SDIter < SkinData.end(); SDIter++)
687- {
688- if (SDIter->CLUT == Data.CLUT)
689- {
690- // Replace the data
691- *SDIter = Data;
692- return true;
693- }
694- }
695-
696- // If not, then add a new frame entry
697- SkinData.push_back(Data);
698-
699- return true;
700-}
701-
702-static XML_SkinDataParser SkinDataParser;
703-
704-
705-// For mapping Marathon-engine sequences onto model sequences
706-class XML_SequenceMapParser: public XML_ElementParser
707-{
708- bool SeqIsPresent, ModelSeqIsPresent;
709- SequenceMapEntry Data;
710-
711-public:
712- bool Start();
713- bool HandleAttribute(const char *Tag, const char *Value);
714- bool AttributesDone();
715-
716- vector<SequenceMapEntry> *SeqMapPtr;
717-
718- XML_SequenceMapParser(): XML_ElementParser("seq_map") {}
719-};
720-
721-bool XML_SequenceMapParser::Start()
722-{
723- Data.Sequence = Data.ModelSequence = NONE;
724- SeqIsPresent = ModelSeqIsPresent = false;
725- return true;
726-}
727-
728-bool XML_SequenceMapParser::HandleAttribute(const char *Tag, const char *Value)
729-{
730- if (StringsEqual(Tag,"seq"))
731- {
732- if (ReadBoundedInt16Value(Value,Data.Sequence,0,MAXIMUM_SHAPES_PER_COLLECTION-1))
733- {
734- SeqIsPresent = true;
735- return true;
736- }
737- else return false;
738- }
739- else if (StringsEqual(Tag,"model_seq"))
740- {
741- if (ReadBoundedInt16Value(Value,Data.ModelSequence,NONE,MAXIMUM_SHAPES_PER_COLLECTION-1))
742- {
743- ModelSeqIsPresent = true;
744- return true;
745- }
746- else return false;
747- }
748- UnrecognizedTag();
749- return false;
750-}
751-
752-bool XML_SequenceMapParser::AttributesDone()
753-{
754- // Verify...
755- if (!SeqIsPresent || !ModelSeqIsPresent)
756- {
757- AttribsMissing();
758- return false;
759- }
760-
761- // Add the entry
762- vector<SequenceMapEntry>& SeqMap = *SeqMapPtr;
763- SeqMap.push_back(Data);
764- return true;
765-}
766-
767-static XML_SequenceMapParser SequenceMapParser;
768-
769-
770-class XML_MdlClearParser: public XML_ElementParser
771-{
772- bool IsPresent;
773- short Collection;
774-
775-public:
776- bool Start();
777- bool HandleAttribute(const char *Tag, const char *Value);
778- bool AttributesDone();
779-
780- XML_MdlClearParser(): XML_ElementParser("model_clear") {}
781-};
782-
783-bool XML_MdlClearParser::Start()
784-{
785- IsPresent = false;
786- return true;
787-}
788-
789-bool XML_MdlClearParser::HandleAttribute(const char *Tag, const char *Value)
790-{
791- if (StringsEqual(Tag,"coll"))
792- {
793- if (ReadBoundedInt16Value(Value,Collection,0,NUMBER_OF_COLLECTIONS-1))
794- {
795- IsPresent = true;
796- return true;
797- }
798- else return false;
799- }
800- UnrecognizedTag();
801- return false;
802-}
803-
804-bool XML_MdlClearParser::AttributesDone()
805-{
806- if (IsPresent)
807- MdlDelete(Collection);
808- else
809- MdlDeleteAll();
810-
811- return true;
812-}
813-
814-static XML_MdlClearParser Mdl_ClearParser;
815-
816-
817-class XML_ModelDataParser: public XML_ElementParser
818-{
819- bool CollIsPresent;
820- short Collection, Sequence;
821- vector<SequenceMapEntry> SequenceMap;
822-
823- OGL_ModelData Data;
824-
825-public:
826- bool Start();
827- bool HandleAttribute(const char *Tag, const char *Value);
828- bool AttributesDone();
829- bool ResetValues();
830- bool End();
831-
832- XML_ModelDataParser(): XML_ElementParser("model") {}
833-};
834-
835-bool XML_ModelDataParser::Start()
836-{
837- Data = DefaultModelData;
838- CollIsPresent = false;
839- Sequence = NONE;
840- SequenceMap.clear();
841-
842- // For doing the model skins
843- SkinDataParser.SkinDataPtr = &Data.SkinData;
844-
845- // For doing the sequence mapping
846- SequenceMapParser.SeqMapPtr = &SequenceMap;
847-
848- return true;
849-}
850-
851-bool XML_ModelDataParser::HandleAttribute(const char *Tag, const char *Value)
852-{
853- if (StringsEqual(Tag,"coll"))
854- {
855- if (ReadBoundedInt16Value(Value,Collection,0,NUMBER_OF_COLLECTIONS-1))
856- {
857- CollIsPresent = true;
858- return true;
859- }
860- else return false;
861- }
862- else if (StringsEqual(Tag,"seq"))
863- {
864- return (ReadBoundedInt16Value(Value,Sequence,0,MAXIMUM_SHAPES_PER_COLLECTION-1));
865- }
866- else if (StringsEqual(Tag,"scale"))
867- {
868- return ReadFloatValue(Value,Data.Scale);
869- }
870- else if (StringsEqual(Tag,"x_rot"))
871- {
872- return ReadFloatValue(Value,Data.XRot);
873- }
874- else if (StringsEqual(Tag,"y_rot"))
875- {
876- return ReadFloatValue(Value,Data.YRot);
877- }
878- else if (StringsEqual(Tag,"z_rot"))
879- {
880- return ReadFloatValue(Value,Data.ZRot);
881- }
882- else if (StringsEqual(Tag,"x_shift"))
883- {
884- return ReadFloatValue(Value,Data.XShift);
885- }
886- else if (StringsEqual(Tag,"y_shift"))
887- {
888- return ReadFloatValue(Value,Data.YShift);
889- }
890- else if (StringsEqual(Tag,"z_shift"))
891- {
892- return ReadFloatValue(Value,Data.ZShift);
893- }
894- else if (StringsEqual(Tag,"side"))
895- {
896- return ReadInt16Value(Value,Data.Sidedness);
897- }
898- else if (StringsEqual(Tag,"norm_type"))
899- {
900- return ReadBoundedInt16Value(Value,Data.NormalType,0,Model3D::NUMBER_OF_NORMAL_TYPES-1);
901- }
902- else if (StringsEqual(Tag,"norm_split"))
903- {
904- return ReadFloatValue(Value,Data.NormalSplit);
905- }
906- else if (StringsEqual(Tag,"light_type"))
907- {
908- return ReadBoundedInt16Value(Value,Data.LightType,0,NUMBER_OF_MODEL_LIGHT_TYPES-1);
909- }
910- else if (StringsEqual(Tag,"depth_type"))
911- {
912- return ReadInt16Value(Value,Data.DepthType);
913- }
914- else if (StringsEqual(Tag,"force_sprite_depth"))
915- {
916- return ReadBooleanValue(Value,Data.ForceSpriteDepth);
917- }
918- else if (StringsEqual(Tag,"file"))
919- {
920- Data.ModelFile.SetNameWithPath(Value);
921- return true;
922- }
923- else if (StringsEqual(Tag,"file1"))
924- {
925- Data.ModelFile1.SetNameWithPath(Value);
926- return true;
927- }
928- else if (StringsEqual(Tag,"file2"))
929- {
930- Data.ModelFile2.SetNameWithPath(Value);
931- return true;
932- }
933- else if (StringsEqual(Tag,"type"))
934- {
935- size_t nchars = strlen(Value)+1;
936- Data.ModelType.resize(nchars);
937- memcpy(&Data.ModelType[0],Value,nchars);
938- return true;
939- }
940- UnrecognizedTag();
941- return false;
942-}
943-
944-bool XML_ModelDataParser::AttributesDone()
945-{
946- // Verify...
947- if (!CollIsPresent)
948- {
949- AttribsMissing();
950- return false;
951- }
952- return true;
953-}
954-
955-bool XML_ModelDataParser::ResetValues()
956-{
957- MdlDeleteAll();
958- return true;
959-}
960-
961-bool XML_ModelDataParser::End()
962-{
963- // Do this at the end because the model data will then include the skin data
964-
965- // Check to see if a frame is already accounted for
966- vector<ModelDataEntry>& ML = MdlList[Collection];
967- for (vector<ModelDataEntry>::iterator MdlIter = ML.begin(); MdlIter < ML.end(); MdlIter++)
968- {
969- // Run a gauntlet of equality tests
970- if (MdlIter->Sequence != Sequence) continue;
971-
972- if (MdlIter->SequenceMap.size() != SequenceMap.size()) continue;
973-
974- // Ought to sort, then compare, for correct results
975- bool AllEqual = true;
976- for (size_t q=0; q<SequenceMap.size(); q++)
977- {
978- SequenceMapEntry& MS = MdlIter->SequenceMap[q];
979- SequenceMapEntry& S = SequenceMap[q];
980- if (MS.Sequence != S.Sequence || MS.ModelSequence != S.ModelSequence)
981- {
982- AllEqual = false;
983- break;
984- }
985- }
986- if (!AllEqual) continue;
987-
988- // Replace the data; it passed the tests
989- MdlIter->ModelData = Data;
990- return true;
991- }
992-
993- // If not, then add a new frame entry
994- ModelDataEntry DataEntry;
995- DataEntry.Sequence = Sequence;
996- DataEntry.SequenceMap.swap(SequenceMap); // Quick transfer of contents in desired direction
997- DataEntry.ModelData = Data;
998- ML.push_back(DataEntry);
999-
1000- return true;
1001-}
1002-
1003-static XML_ModelDataParser ModelDataParser;
1004-
1005-
1006-// XML-parser support:
1007-XML_ElementParser *ModelData_GetParser()
1008-{
1009- ModelDataParser.AddChild(&SkinDataParser);
1010- ModelDataParser.AddChild(&SequenceMapParser);
1011-
1012- return &ModelDataParser;
1013-}
1014-XML_ElementParser *Mdl_Clear_GetParser() {return &Mdl_ClearParser;}
1015-
1016-#endif
1+/*
2+
3+ Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
4+ and the "Aleph One" developers.
5+
6+ This program is free software; you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation; either version 2 of the License, or
9+ (at your option) any later version.
10+
11+ This program is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ This license is contained in the file "COPYING",
17+ which is included with this source code; it is available online at
18+ http://www.gnu.org/licenses/gpl.html
19+
20+ OpenGL Model-Definition File
21+ by Loren Petrich,
22+ May 11, 2003
23+
24+ This contains the definitions of all the OpenGL models and skins
25+*/
26+
27+#include "cseries.h"
28+#include "OGL_Model_Def.h"
29+#include "OGL_Setup.h"
30+
31+#ifdef HAVE_OPENGL
32+
33+#include <cmath>
34+
35+#include "Dim3_Loader.h"
36+#include "StudioLoader.h"
37+#include "WavefrontLoader.h"
38+#include "QD3D_Loader.h"
39+
40+
41+// Model-data stuff;
42+// defaults for whatever might need them
43+// Including skin stuff for convenience here
44+static OGL_ModelData DefaultModelData;
45+static OGL_SkinData DefaultSkinData;
46+
47+
48+// For mapping Marathon-physics sequences onto model sequences
49+struct SequenceMapEntry
50+{
51+ int16 Sequence;
52+ int16 ModelSequence;
53+};
54+
55+
56+// Store model-data stuff in a set of STL vectors
57+struct ModelDataEntry
58+{
59+ // Which Marathon-engine sequence gets translated into this model,
60+ // if static, or the neutral sequence, if dynamic
61+ short Sequence;
62+
63+ vector<SequenceMapEntry> SequenceMap;
64+
65+ // Make a member for more convenient access
66+ OGL_ModelData ModelData;
67+
68+ ModelDataEntry(): Sequence(NONE) {}
69+};
70+
71+
72+// Separate model-data sequence lists for each collection ID,
73+// to speed up searching
74+static vector<ModelDataEntry> MdlList[NUMBER_OF_COLLECTIONS];
75+
76+// Will look up both the model index and its sequence
77+struct ModelHashEntry
78+{
79+ int16 ModelIndex;
80+ int16 ModelSeqTabIndex;
81+};
82+
83+// Model-data hash table for extra-fast searching:
84+static vector<ModelHashEntry> MdlHash[NUMBER_OF_COLLECTIONS];
85+
86+// Hash-table size and function
87+const int MdlHashSize = 1 << 8;
88+const int MdlHashMask = MdlHashSize - 1;
89+inline uint8 MdlHashFunc(short Sequence)
90+{
91+ // E-Z
92+ return (uint8)(Sequence & MdlHashMask);
93+}
94+
95+
96+// Deletes a collection's model-data sequences
97+static void MdlDelete(short Collection)
98+{
99+ int c = Collection;
100+ MdlList[c].clear();
101+ MdlHash[c].clear();
102+}
103+
104+// Deletes all of them
105+static void MdlDeleteAll()
106+{
107+ for (int c=0; c<NUMBER_OF_COLLECTIONS; c++) MdlDelete(c);
108+}
109+
110+
111+OGL_ModelData *OGL_GetModelData(short Collection, short Sequence, short& ModelSequence)
112+{
113+ // Model is neutral unless specified otherwise
114+ ModelSequence = NONE;
115+
116+ // Initialize the hash table if necessary
117+ if (MdlHash[Collection].empty())
118+ {
119+ MdlHash[Collection].resize(MdlHashSize);
120+ objlist_set(&MdlHash[Collection][0],NONE,MdlHashSize);
121+ }
122+
123+ // Set up a *reference* to the appropriate hashtable entry;
124+ // this makes setting this entry a bit more convenient
125+ ModelHashEntry& HashVal = MdlHash[Collection][MdlHashFunc(Sequence)];
126+
127+ // Check to see if the model-data entry is correct;
128+ // if it is, then we're done.
129+ if (HashVal.ModelIndex != NONE)
130+ {
131+ // First, check in the sequence-map table
132+ vector<ModelDataEntry>::iterator MdlIter = MdlList[Collection].begin() + HashVal.ModelIndex;
133+ size_t MSTIndex = static_cast<size_t>(HashVal.ModelSeqTabIndex); // Cast only safe b/c of following check
134+ if (MSTIndex < MdlIter->SequenceMap.size())
135+ {
136+ vector<SequenceMapEntry>::iterator SMIter = MdlIter->SequenceMap.begin() + MSTIndex;
137+ if (SMIter->Sequence == Sequence)
138+ {
139+ ModelSequence = SMIter->ModelSequence;
140+ return MdlIter->ModelData.ModelPresent() ? &MdlIter->ModelData : NULL;
141+ }
142+ }
143+
144+ // Now check the neutral sequence
145+ if (MdlIter->Sequence == Sequence)
146+ {
147+ return MdlIter->ModelData.ModelPresent() ? &MdlIter->ModelData : NULL;
148+ }
149+ }
150+
151+ // Fallback for the case of a hashtable miss;
152+ // do a linear search and then update the hash entry appropriately.
153+ vector<ModelDataEntry>& ML = MdlList[Collection];
154+ int16 Indx = 0;
155+ for (vector<ModelDataEntry>::iterator MdlIter = ML.begin(); MdlIter < ML.end(); MdlIter++, Indx++)
156+ {
157+ // First, search the sequence-map table
158+ int16 SMIndx = 0;
159+ vector<SequenceMapEntry>& SM = MdlIter->SequenceMap;
160+ for (vector<SequenceMapEntry>::iterator SMIter = SM.begin(); SMIter < SM.end(); SMIter++, SMIndx++)
161+ {
162+ if (SMIter->Sequence == Sequence)
163+ {
164+ HashVal.ModelIndex = Indx;
165+ HashVal.ModelSeqTabIndex = SMIndx;
166+ ModelSequence = SMIter->ModelSequence;
167+ return MdlIter->ModelData.ModelPresent() ? &MdlIter->ModelData : NULL;
168+ }
169+ }
170+
171+ // Now check the neutral sequence
172+ if (MdlIter->Sequence == Sequence)
173+ {
174+ HashVal.ModelIndex = Indx;
175+ HashVal.ModelSeqTabIndex = NONE;
176+ return MdlIter->ModelData.ModelPresent() ? &MdlIter->ModelData : NULL;
177+ }
178+ }
179+
180+ // None found!
181+ return NULL;
182+}
183+
184+int OGL_SkinData::GetMaxSize()
185+{
186+ return Get_OGL_ConfigureData().ModelConfig.MaxSize;
187+}
188+
189+
190+// Any easy STL ways of doing this mapping of functions onto members of arrays?
191+
192+void OGL_SkinManager::Load()
193+{
194+ for (vector<OGL_SkinData>::iterator SkinIter = SkinData.begin(); SkinIter < SkinData.end(); SkinIter++)
195+ SkinIter->Load();
196+}
197+
198+
199+void OGL_SkinManager::Unload()
200+{
201+ for (vector<OGL_SkinData>::iterator SkinIter = SkinData.begin(); SkinIter < SkinData.end(); SkinIter++)
202+ SkinIter->Unload();
203+}
204+
205+
206+void OGL_SkinManager::Reset(bool Clear_OGL_Txtrs)
207+{
208+ if (Clear_OGL_Txtrs)
209+ {
210+ for (int k=0; k<NUMBER_OF_OPENGL_BITMAP_SETS; k++)
211+ for (int l=0; l<NUMBER_OF_TEXTURES; l++)
212+ {
213+ if (IDsInUse[k][l])
214+ glDeleteTextures(1,&IDs[k][l]);
215+ }
216+ }
217+
218+ // Mass clearing
219+ objlist_clear(IDsInUse[0],NUMBER_OF_OPENGL_BITMAP_SETS*NUMBER_OF_TEXTURES);
220+}
221+
222+
223+OGL_SkinData *OGL_SkinManager::GetSkin(short CLUT)
224+{
225+ for (unsigned k=0; k<SkinData.size(); k++)
226+ {
227+ OGL_SkinData& Skin = SkinData[k];
228+ if (Skin.CLUT == CLUT || Skin.CLUT == ALL_CLUTS)
229+ return &Skin;
230+ }
231+
232+ return NULL;
233+}
234+
235+
236+bool OGL_SkinManager::Use(short CLUT, short Which)
237+{
238+ // References so they can be written into
239+ GLuint& TxtrID = IDs[CLUT][Which];
240+ bool& InUse = IDsInUse[CLUT][Which];
241+ bool LoadSkin = false;
242+ if (!InUse)
243+ {
244+ glGenTextures(1,&TxtrID);
245+ InUse = true;
246+ LoadSkin = true;
247+ }
248+ glBindTexture(GL_TEXTURE_2D,TxtrID);
249+ return LoadSkin;
250+}
251+
252+
253+// Circle constants
254+const double TWO_PI = 8*atan(1.0);
255+const double Degree2Radian = TWO_PI/360; // A circle is 2*pi radians
256+
257+// Matrix manipulation (can't trust OpenGL to be active, so won't be using OpenGL matrix stuff)
258+
259+// Src -> Dest
260+static void MatCopy(const GLfloat SrcMat[3][3], GLfloat DestMat[3][3])
261+{
262+ objlist_copy(DestMat[0],SrcMat[0],9);
263+}
264+
265+// Sets the arg to that matrix
266+static void MatIdentity(GLfloat Mat[3][3])
267+{
268+ const GLfloat IMat[3][3] = {{1,0,0},{0,1,0},{0,0,1}};
269+ MatCopy(IMat,Mat);
270+}
271+
272+// Src1, Src2 -> Dest (cannot be one of the sources)
273+static void MatMult(const GLfloat Mat1[3][3], const GLfloat Mat2[3][3], GLfloat DestMat[3][3])
274+{
275+ for (int k=0; k<3; k++)
276+ for (int l=0; l<3; l++)
277+ {
278+ GLfloat Sum = 0;
279+ for (int m=0; m<3; m++)
280+ Sum += Mat1[k][m]*Mat2[m][l];
281+ DestMat[k][l] = Sum;
282+ }
283+}
284+
285+// Alters the matrix in place
286+static void MatScalMult(GLfloat Mat[3][3], const GLfloat Scale)
287+{
288+ for (int k=0; k<3; k++)
289+ {
290+ GLfloat *MatRow = Mat[k];
291+ for (int l=0; l<3; l++)
292+ MatRow[l] *= Scale;
293+ }
294+}
295+
296+// Src -> Dest vector (cannot be the same location)
297+static void MatVecMult(const GLfloat Mat[3][3], const GLfloat *SrcVec, GLfloat *DestVec)
298+{
299+ for (int k=0; k<3; k++)
300+ {
301+ const GLfloat *MatRow = Mat[k];
302+ GLfloat Sum = 0;
303+ for (int l=0; l<3; l++)
304+ Sum += MatRow[l]*SrcVec[l];
305+ DestVec[k] = Sum;
306+ }
307+}
308+
309+
310+inline bool StringPresent(vector<char>& String)
311+{
312+ return (String.size() > 1);
313+}
314+
315+
316+void OGL_ModelData::Load()
317+{
318+ // Already loaded?
319+ if (ModelPresent()) return;
320+
321+ // Load the model
322+ Model.Clear();
323+
324+ if (ModelFile == FileSpecifier()) return;
325+ if (!ModelFile.Exists()) return;
326+
327+ bool Success = false;
328+
329+ char *Type = &ModelType[0];
330+ if (StringsEqual(Type,"wave",4))
331+ {
332+ // Alias|Wavefront, backward compatible version
333+ Success = LoadModel_Wavefront(ModelFile, Model);
334+ }
335+ else if (StringsEqual(Type,"obj",3))
336+ {
337+ // Alias|Wavefront, but with coordinate system conversion.
338+ Success = LoadModel_Wavefront_RightHand(ModelFile, Model);
339+ }
340+ else if (StringsEqual(Type,"3ds",3))
341+ {
342+ // 3D Studio Max, backward compatible version
343+ Success = LoadModel_Studio(ModelFile, Model);
344+ }
345+ else if (StringsEqual(Type,"max",3))
346+ {
347+ // 3D Studio Max, but with coordinate system conversion.
348+ Success = LoadModel_Studio_RightHand(ModelFile, Model);
349+ }
350+ else if (StringsEqual(Type,"dim3",4))
351+ {
352+ // Brian Barnes's "Dim3" model format (first pass: model geometry)
353+ Success = LoadModel_Dim3(ModelFile, Model, LoadModelDim3_First);
354+
355+ // Second and third passes: frames and sequences
356+ try
357+ {
358+ if (ModelFile1 == FileSpecifier()) throw 0;
359+ if (!ModelFile1.Exists()) throw 0;
360+ if (!LoadModel_Dim3(ModelFile1, Model, LoadModelDim3_Rest)) throw 0;
361+ }
362+ catch(...)
363+ {}
364+ //
365+ try
366+ {
367+ if (ModelFile2 == FileSpecifier()) throw 0;
368+ if (!ModelFile2.Exists()) throw 0;
369+ if (!LoadModel_Dim3(ModelFile2, Model, LoadModelDim3_Rest)) throw 0;
370+ }
371+ catch(...)
372+ {}
373+ }
374+#if HAVE_QUESA
375+ else if (StringsEqual(Type,"qd3d") || StringsEqual(Type,"3dmf") || StringsEqual(Type,"quesa"))
376+ {
377+ // QuickDraw 3D / Quesa
378+ Success = LoadModel_QD3D(ModelFile, Model);
379+ }
380+#endif
381+
382+ if (!Success)
383+ {
384+ Model.Clear();
385+ return;
386+ }
387+
388+ // Calculate transformation matrix
389+ GLfloat Angle, Cosine, Sine;
390+ GLfloat RotMatrix[3][3], NewRotMatrix[3][3], IndivRotMatrix[3][3];
391+ MatIdentity(RotMatrix);
392+
393+ MatIdentity(IndivRotMatrix);
394+ Angle = (float)Degree2Radian*XRot;
395+ Cosine = (float)cos(Angle);
396+ Sine = (float)sin(Angle);
397+ IndivRotMatrix[1][1] = Cosine;
398+ IndivRotMatrix[1][2] = - Sine;
399+ IndivRotMatrix[2][1] = Sine;
400+ IndivRotMatrix[2][2] = Cosine;
401+ MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix);
402+ MatCopy(NewRotMatrix,RotMatrix);
403+
404+ MatIdentity(IndivRotMatrix);
405+ Angle = (float)Degree2Radian*YRot;
406+ Cosine = (float)cos(Angle);
407+ Sine = (float)sin(Angle);
408+ IndivRotMatrix[2][2] = Cosine;
409+ IndivRotMatrix[2][0] = - Sine;
410+ IndivRotMatrix[0][2] = Sine;
411+ IndivRotMatrix[0][0] = Cosine;
412+ MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix);
413+ MatCopy(NewRotMatrix,RotMatrix);
414+
415+ MatIdentity(IndivRotMatrix);
416+ Angle = (float)Degree2Radian*ZRot;
417+ Cosine = (float)cos(Angle);
418+ Sine = (float)sin(Angle);
419+ IndivRotMatrix[0][0] = Cosine;
420+ IndivRotMatrix[0][1] = - Sine;
421+ IndivRotMatrix[1][0] = Sine;
422+ IndivRotMatrix[1][1] = Cosine;
423+ MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix);
424+ MatCopy(NewRotMatrix,RotMatrix);
425+
426+ MatScalMult(NewRotMatrix,Scale); // For the position vertices
427+ if (Scale < 0) MatScalMult(RotMatrix,-1); // For the normals
428+
429+ // Is model animated or static?
430+ // Test by trying to find neutral positions (useful for working with the normals later on)
431+ if (Model.FindPositions_Neutral(false))
432+ {
433+ // Copy over the vector and normal transformation matrices:
434+ for (int k=0; k<3; k++)
435+ for (int l=0; l<3; l++)
436+ {
437+ Model.TransformPos.M[k][l] = NewRotMatrix[k][l];
438+ Model.TransformNorm.M[k][l] = RotMatrix[k][l];
439+ }
440+
441+ Model.TransformPos.M[0][3] = XShift;
442+ Model.TransformPos.M[1][3] = YShift;
443+ Model.TransformPos.M[2][3] = ZShift;
444+
445+ // Find the transformed bounding box:
446+ bool RestOfCorners = false;
447+ GLfloat NewBoundingBox[2][3];
448+ // The indices i1, i2, and i3 are for selecting which of the box's two principal corners
449+ // to get coordinates from
450+ for (int i1=0; i1<2; i1++)
451+ {
452+ GLfloat X = Model.BoundingBox[i1][0];
453+ for (int i2=0; i2<2; i2++)
454+ {
455+ GLfloat Y = Model.BoundingBox[i2][0];
456+ for (int i3=0; i3<2; i3++)
457+ {
458+ GLfloat Z = Model.BoundingBox[i3][0];
459+
460+ GLfloat Corner[3];
461+ for (int ic=0; ic<3; ic++)
462+ {
463+ GLfloat *Row = Model.TransformPos.M[ic];
464+ Corner[ic] = Row[0]*X + Row[1]*Y + Row[2]*Z + Row[3];
465+ }
466+
467+ if (RestOfCorners)
468+ {
469+ // Find minimum and maximum for each coordinate
470+ for (int ic=0; ic<3; ic++)
471+ {
472+ NewBoundingBox[0][ic] = min(NewBoundingBox[0][ic],Corner[ic]);
473+ NewBoundingBox[1][ic] = max(NewBoundingBox[1][ic],Corner[ic]);
474+ }
475+ }
476+ else
477+ {
478+ // Simply copy it in:
479+ for (int ic=0; ic<3; ic++)
480+ NewBoundingBox[0][ic] = NewBoundingBox[1][ic] = Corner[ic];
481+ RestOfCorners = true;
482+ }
483+ }
484+ }
485+ }
486+
487+ for (int ic=0; ic<2; ic++)
488+ objlist_copy(Model.BoundingBox[ic],NewBoundingBox[ic],3);
489+ }
490+ else
491+ {
492+ // Static model
493+ size_t NumVerts = Model.Positions.size()/3;
494+
495+ for (size_t k=0; k<NumVerts; k++)
496+ {
497+ GLfloat *Pos = Model.PosBase() + 3*k;
498+ GLfloat NewPos[3];
499+ MatVecMult(NewRotMatrix,Pos,NewPos); // Has the scaling
500+ Pos[0] = NewPos[0] + XShift;
501+ Pos[1] = NewPos[1] + YShift;
502+ Pos[2] = NewPos[2] + ZShift;
503+ }
504+
505+ size_t NumNorms = Model.Normals.size()/3;
506+ for (size_t k=0; k<NumNorms; k++)
507+ {
508+ GLfloat *Norms = Model.NormBase() + 3*k;
509+ GLfloat NewNorms[3];
510+ MatVecMult(RotMatrix,Norms,NewNorms); // Not scaled
511+ objlist_copy(Norms,NewNorms,3);
512+ }
513+
514+ // So as to be consistent with the new points
515+ Model.FindBoundingBox();
516+ }
517+
518+ Model.AdjustNormals(NormalType,NormalSplit);
519+ Model.CalculateTangents();
520+
521+ // Don't forget the skins
522+ OGL_SkinManager::Load();
523+}
524+
525+
526+void OGL_ModelData::Unload()
527+{
528+ Model.Clear();
529+ OGL_ResetForceSpriteDepth();
530+
531+ // Don't forget the skins
532+ OGL_SkinManager::Unload();
533+}
534+
535+int OGL_CountModels(short Collection)
536+{
537+ return MdlList[Collection].size();
538+}
539+
540+extern void OGL_ProgressCallback(int);
541+
542+static bool ForcingSpriteDepth = false;
543+void OGL_ResetForceSpriteDepth() { ForcingSpriteDepth = false; }
544+bool OGL_ForceSpriteDepth() { return ForcingSpriteDepth; }
545+
546+// for managing the model and image loading and unloading
547+void OGL_LoadModels(short Collection)
548+{
549+ vector<ModelDataEntry>& ML = MdlList[Collection];
550+ for (vector<ModelDataEntry>::iterator MdlIter = ML.begin(); MdlIter < ML.end(); MdlIter++)
551+ {
552+ MdlIter->ModelData.Load();
553+ if (MdlIter->ModelData.ForceSpriteDepth)
554+ {
555+ ForcingSpriteDepth = true;
556+ }
557+ OGL_ProgressCallback(1);
558+ }
559+}
560+
561+void OGL_UnloadModels(short Collection)
562+{
563+ vector<ModelDataEntry>& ML = MdlList[Collection];
564+ for (vector<ModelDataEntry>::iterator MdlIter = ML.begin(); MdlIter < ML.end(); MdlIter++)
565+ {
566+ MdlIter->ModelData.Unload();
567+ }
568+}
569+
570+
571+// Reset model skins; used in OGL_ResetTextures() in OGL_Textures.cpp
572+void OGL_ResetModelSkins(bool Clear_OGL_Txtrs)
573+{
574+ for (int ic=0; ic<MAXIMUM_COLLECTIONS; ic++)
575+ {
576+ vector<ModelDataEntry>& ML = MdlList[ic];
577+ for (vector<ModelDataEntry>::iterator MdlIter = ML.begin(); MdlIter < ML.end(); MdlIter++)
578+ {
579+ MdlIter->ModelData.Reset(Clear_OGL_Txtrs);
580+ }
581+ }
582+}
583+
584+class XML_SkinDataParser: public XML_ElementParser
585+{
586+ short CLUT;
587+
588+ OGL_SkinData Data;
589+public:
590+ bool Start();
591+ bool HandleAttribute(const char *Tag, const char *Value);
592+ bool AttributesDone();
593+
594+ vector<OGL_SkinData> *SkinDataPtr;
595+
596+ XML_SkinDataParser(): XML_ElementParser("skin"), SkinDataPtr(NULL) {}
597+};
598+
599+bool XML_SkinDataParser::Start()
600+{
601+ Data = DefaultSkinData;
602+
603+ return true;
604+}
605+
606+bool XML_SkinDataParser::HandleAttribute(const char *Tag, const char *Value)
607+{
608+ if (StringsEqual(Tag,"clut"))
609+ {
610+ return ReadBoundedInt16Value(Value,Data.CLUT,short(ALL_CLUTS),short(SILHOUETTE_BITMAP_SET));
611+ }
612+ else if (StringsEqual(Tag,"opac_type"))
613+ {
614+ return ReadBoundedInt16Value(Value,Data.OpacityType,0,OGL_NUMBER_OF_OPACITY_TYPES-1);
615+ }
616+ else if (StringsEqual(Tag,"opac_scale"))
617+ {
618+ return ReadFloatValue(Value,Data.OpacityScale);
619+ }
620+ else if (StringsEqual(Tag,"opac_shift"))
621+ {
622+ return ReadFloatValue(Value,Data.OpacityShift);
623+ }
624+ else if (StringsEqual(Tag,"normal_image"))
625+ {
626+ Data.NormalColors.SetNameWithPath(Value);
627+ return true;
628+ }
629+ else if (StringsEqual(Tag,"offset_image"))
630+ {
631+ Data.OffsetMap.SetNameWithPath(Value);
632+ return true;
633+ }
634+ else if (StringsEqual(Tag,"normal_mask"))
635+ {
636+ Data.NormalMask.SetNameWithPath(Value);
637+ return true;
638+ }
639+ else if (StringsEqual(Tag,"glow_image"))
640+ {
641+ Data.GlowColors.SetNameWithPath(Value);
642+ return true;
643+ }
644+ else if (StringsEqual(Tag,"glow_mask"))
645+ {
646+ Data.GlowMask.SetNameWithPath(Value);
647+ return true;
648+ }
649+ else if (StringsEqual(Tag,"normal_blend"))
650+ {
651+ return ReadBoundedInt16Value(Value,Data.NormalBlend,0,OGL_NUMBER_OF_BLEND_TYPES-1);
652+ }
653+ else if (StringsEqual(Tag,"glow_blend"))
654+ {
655+ return ReadBoundedInt16Value(Value,Data.GlowBlend,0,OGL_NUMBER_OF_BLEND_TYPES-1);
656+ }
657+ else if (StringsEqual(Tag,"normal_bloom_scale"))
658+ {
659+ return ReadFloatValue(Value,Data.BloomScale);
660+ }
661+ else if (StringsEqual(Tag,"normal_bloom_shift"))
662+ {
663+ return ReadFloatValue(Value,Data.BloomShift);
664+ }
665+ else if (StringsEqual(Tag,"glow_bloom_scale"))
666+ {
667+ return ReadFloatValue(Value,Data.GlowBloomScale);
668+ }
669+ else if (StringsEqual(Tag,"glow_bloom_shift"))
670+ {
671+ return ReadFloatValue(Value,Data.GlowBloomShift);
672+ }
673+ else if (StringsEqual(Tag,"minimum_glow_intensity"))
674+ {
675+ return ReadFloatValue(Value,Data.MinGlowIntensity);
676+ }
677+ UnrecognizedTag();
678+ return false;
679+}
680+
681+bool XML_SkinDataParser::AttributesDone()
682+{
683+ // Check to see if a frame is already accounted for
684+ assert(SkinDataPtr);
685+ vector<OGL_SkinData>& SkinData = *SkinDataPtr;
686+ for (vector<OGL_SkinData>::iterator SDIter = SkinData.begin(); SDIter < SkinData.end(); SDIter++)
687+ {
688+ if (SDIter->CLUT == Data.CLUT)
689+ {
690+ // Replace the data
691+ *SDIter = Data;
692+ return true;
693+ }
694+ }
695+
696+ // If not, then add a new frame entry
697+ SkinData.push_back(Data);
698+
699+ return true;
700+}
701+
702+static XML_SkinDataParser SkinDataParser;
703+
704+
705+// For mapping Marathon-engine sequences onto model sequences
706+class XML_SequenceMapParser: public XML_ElementParser
707+{
708+ bool SeqIsPresent, ModelSeqIsPresent;
709+ SequenceMapEntry Data;
710+
711+public:
712+ bool Start();
713+ bool HandleAttribute(const char *Tag, const char *Value);
714+ bool AttributesDone();
715+
716+ vector<SequenceMapEntry> *SeqMapPtr;
717+
718+ XML_SequenceMapParser(): XML_ElementParser("seq_map") {}
719+};
720+
721+bool XML_SequenceMapParser::Start()
722+{
723+ Data.Sequence = Data.ModelSequence = NONE;
724+ SeqIsPresent = ModelSeqIsPresent = false;
725+ return true;
726+}
727+
728+bool XML_SequenceMapParser::HandleAttribute(const char *Tag, const char *Value)
729+{
730+ if (StringsEqual(Tag,"seq"))
731+ {
732+ if (ReadBoundedInt16Value(Value,Data.Sequence,0,MAXIMUM_SHAPES_PER_COLLECTION-1))
733+ {
734+ SeqIsPresent = true;
735+ return true;
736+ }
737+ else return false;
738+ }
739+ else if (StringsEqual(Tag,"model_seq"))
740+ {
741+ if (ReadBoundedInt16Value(Value,Data.ModelSequence,NONE,MAXIMUM_SHAPES_PER_COLLECTION-1))
742+ {
743+ ModelSeqIsPresent = true;
744+ return true;
745+ }
746+ else return false;
747+ }
748+ UnrecognizedTag();
749+ return false;
750+}
751+
752+bool XML_SequenceMapParser::AttributesDone()
753+{
754+ // Verify...
755+ if (!SeqIsPresent || !ModelSeqIsPresent)
756+ {
757+ AttribsMissing();
758+ return false;
759+ }
760+
761+ // Add the entry
762+ vector<SequenceMapEntry>& SeqMap = *SeqMapPtr;
763+ SeqMap.push_back(Data);
764+ return true;
765+}
766+
767+static XML_SequenceMapParser SequenceMapParser;
768+
769+
770+class XML_MdlClearParser: public XML_ElementParser
771+{
772+ bool IsPresent;
773+ short Collection;
774+
775+public:
776+ bool Start();
777+ bool HandleAttribute(const char *Tag, const char *Value);
778+ bool AttributesDone();
779+
780+ XML_MdlClearParser(): XML_ElementParser("model_clear") {}
781+};
782+
783+bool XML_MdlClearParser::Start()
784+{
785+ IsPresent = false;
786+ return true;
787+}
788+
789+bool XML_MdlClearParser::HandleAttribute(const char *Tag, const char *Value)
790+{
791+ if (StringsEqual(Tag,"coll"))
792+ {
793+ if (ReadBoundedInt16Value(Value,Collection,0,NUMBER_OF_COLLECTIONS-1))
794+ {
795+ IsPresent = true;
796+ return true;
797+ }
798+ else return false;
799+ }
800+ UnrecognizedTag();
801+ return false;
802+}
803+
804+bool XML_MdlClearParser::AttributesDone()
805+{
806+ if (IsPresent)
807+ MdlDelete(Collection);
808+ else
809+ MdlDeleteAll();
810+
811+ return true;
812+}
813+
814+static XML_MdlClearParser Mdl_ClearParser;
815+
816+
817+class XML_ModelDataParser: public XML_ElementParser
818+{
819+ bool CollIsPresent;
820+ short Collection, Sequence;
821+ vector<SequenceMapEntry> SequenceMap;
822+
823+ OGL_ModelData Data;
824+
825+public:
826+ bool Start();
827+ bool ReadSignValue(const char *String, int16& Value);
828+ bool HandleAttribute(const char *Tag, const char *Value);
829+ bool AttributesDone();
830+ bool ResetValues();
831+ bool End();
832+
833+ XML_ModelDataParser(): XML_ElementParser("model") {}
834+};
835+
836+bool XML_ModelDataParser::Start()
837+{
838+ Data = DefaultModelData;
839+ CollIsPresent = false;
840+ Sequence = NONE;
841+ SequenceMap.clear();
842+
843+ // For doing the model skins
844+ SkinDataParser.SkinDataPtr = &Data.SkinData;
845+
846+ // For doing the sequence mapping
847+ SequenceMapParser.SeqMapPtr = &SequenceMap;
848+
849+ return true;
850+}
851+
852+bool XML_ModelDataParser::ReadSignValue(const char *String, int16& Value)
853+{
854+ if (StringsEqual(String, "+"))
855+ {
856+ Value = 1;
857+ return true;
858+ }
859+ else if (StringsEqual(String, "-"))
860+ {
861+ Value = -1;
862+ return true;
863+ }
864+ return ReadInt16Value(String, Value);
865+}
866+
867+bool XML_ModelDataParser::HandleAttribute(const char *Tag, const char *Value)
868+{
869+ if (StringsEqual(Tag,"coll"))
870+ {
871+ if (ReadBoundedInt16Value(Value,Collection,0,NUMBER_OF_COLLECTIONS-1))
872+ {
873+ CollIsPresent = true;
874+ return true;
875+ }
876+ else return false;
877+ }
878+ else if (StringsEqual(Tag,"seq"))
879+ {
880+ return (ReadBoundedInt16Value(Value,Sequence,0,MAXIMUM_SHAPES_PER_COLLECTION-1));
881+ }
882+ else if (StringsEqual(Tag,"scale"))
883+ {
884+ return ReadFloatValue(Value,Data.Scale);
885+ }
886+ else if (StringsEqual(Tag,"x_rot"))
887+ {
888+ return ReadFloatValue(Value,Data.XRot);
889+ }
890+ else if (StringsEqual(Tag,"y_rot"))
891+ {
892+ return ReadFloatValue(Value,Data.YRot);
893+ }
894+ else if (StringsEqual(Tag,"z_rot"))
895+ {
896+ return ReadFloatValue(Value,Data.ZRot);
897+ }
898+ else if (StringsEqual(Tag,"x_shift"))
899+ {
900+ return ReadFloatValue(Value,Data.XShift);
901+ }
902+ else if (StringsEqual(Tag,"y_shift"))
903+ {
904+ return ReadFloatValue(Value,Data.YShift);
905+ }
906+ else if (StringsEqual(Tag,"z_shift"))
907+ {
908+ return ReadFloatValue(Value,Data.ZShift);
909+ }
910+ else if (StringsEqual(Tag,"side"))
911+ {
912+ return ReadSignValue(Value,Data.Sidedness);
913+ }
914+ else if (StringsEqual(Tag,"norm_type"))
915+ {
916+ return ReadBoundedInt16Value(Value,Data.NormalType,0,Model3D::NUMBER_OF_NORMAL_TYPES-1);
917+ }
918+ else if (StringsEqual(Tag,"norm_split"))
919+ {
920+ return ReadFloatValue(Value,Data.NormalSplit);
921+ }
922+ else if (StringsEqual(Tag,"light_type"))
923+ {
924+ return ReadBoundedInt16Value(Value,Data.LightType,0,NUMBER_OF_MODEL_LIGHT_TYPES-1);
925+ }
926+ else if (StringsEqual(Tag,"depth_type"))
927+ {
928+ return ReadSignValue(Value,Data.DepthType);
929+ }
930+ else if (StringsEqual(Tag,"force_sprite_depth"))
931+ {
932+ return ReadBooleanValue(Value,Data.ForceSpriteDepth);
933+ }
934+ else if (StringsEqual(Tag,"file"))
935+ {
936+ Data.ModelFile.SetNameWithPath(Value);
937+ return true;
938+ }
939+ else if (StringsEqual(Tag,"file1"))
940+ {
941+ Data.ModelFile1.SetNameWithPath(Value);
942+ return true;
943+ }
944+ else if (StringsEqual(Tag,"file2"))
945+ {
946+ Data.ModelFile2.SetNameWithPath(Value);
947+ return true;
948+ }
949+ else if (StringsEqual(Tag,"type"))
950+ {
951+ size_t nchars = strlen(Value)+1;
952+ Data.ModelType.resize(nchars);
953+ memcpy(&Data.ModelType[0],Value,nchars);
954+ return true;
955+ }
956+ UnrecognizedTag();
957+ return false;
958+}
959+
960+bool XML_ModelDataParser::AttributesDone()
961+{
962+ // Verify...
963+ if (!CollIsPresent)
964+ {
965+ AttribsMissing();
966+ return false;
967+ }
968+ return true;
969+}
970+
971+bool XML_ModelDataParser::ResetValues()
972+{
973+ MdlDeleteAll();
974+ return true;
975+}
976+
977+bool XML_ModelDataParser::End()
978+{
979+ // Do this at the end because the model data will then include the skin data
980+
981+ // Check to see if a frame is already accounted for
982+ vector<ModelDataEntry>& ML = MdlList[Collection];
983+ for (vector<ModelDataEntry>::iterator MdlIter = ML.begin(); MdlIter < ML.end(); MdlIter++)
984+ {
985+ // Run a gauntlet of equality tests
986+ if (MdlIter->Sequence != Sequence) continue;
987+
988+ if (MdlIter->SequenceMap.size() != SequenceMap.size()) continue;
989+
990+ // Ought to sort, then compare, for correct results
991+ bool AllEqual = true;
992+ for (size_t q=0; q<SequenceMap.size(); q++)
993+ {
994+ SequenceMapEntry& MS = MdlIter->SequenceMap[q];
995+ SequenceMapEntry& S = SequenceMap[q];
996+ if (MS.Sequence != S.Sequence || MS.ModelSequence != S.ModelSequence)
997+ {
998+ AllEqual = false;
999+ break;
1000+ }
1001+ }
1002+ if (!AllEqual) continue;
1003+
1004+ // Replace the data; it passed the tests
1005+ MdlIter->ModelData = Data;
1006+ return true;
1007+ }
1008+
1009+ // If not, then add a new frame entry
1010+ ModelDataEntry DataEntry;
1011+ DataEntry.Sequence = Sequence;
1012+ DataEntry.SequenceMap.swap(SequenceMap); // Quick transfer of contents in desired direction
1013+ DataEntry.ModelData = Data;
1014+ ML.push_back(DataEntry);
1015+
1016+ return true;
1017+}
1018+
1019+static XML_ModelDataParser ModelDataParser;
1020+
1021+
1022+// XML-parser support:
1023+XML_ElementParser *ModelData_GetParser()
1024+{
1025+ ModelDataParser.AddChild(&SkinDataParser);
1026+ ModelDataParser.AddChild(&SequenceMapParser);
1027+
1028+ return &ModelDataParser;
1029+}
1030+XML_ElementParser *Mdl_Clear_GetParser() {return &Mdl_ClearParser;}
1031+
1032+#endif
--- marathon/trunk/Source_Files/RenderMain/OGL_Render.cpp (revision 492)
+++ marathon/trunk/Source_Files/RenderMain/OGL_Render.cpp (revision 493)
@@ -1,3538 +1,3545 @@
1-/*
2-
3- Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
4- and the "Aleph One" developers.
5-
6- This program is free software; you can redistribute it and/or modify
7- it under the terms of the GNU General Public License as published by
8- the Free Software Foundation; either version 2 of the License, or
9- (at your option) any later version.
10-
11- This program is distributed in the hope that it will be useful,
12- but WITHOUT ANY WARRANTY; without even the implied warranty of
13- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14- GNU General Public License for more details.
15-
16- This license is contained in the file "COPYING",
17- which is included with this source code; it is available online at
18- http://www.gnu.org/licenses/gpl.html
19-
20- OpenGL Renderer,
21- by Loren Petrich,
22- March 12, 2000
23-
24- This contains functions intended to interface OpenGL 3D-rendering code
25- with the rest of the Marathon source code.
26-
27- Much of the setup code is cribbed from the Apple GLUT code, or at least inspired by it.
28-
29- Late April, 2000:
30-
31- Moved texture stuff out to OGL_Textures.c/h
32-
33- Added wall-texture glow mapping.
34-
35- May 14, 2000:
36-
37- Added George Marsaglia's random-number generator
38-
39- May 24, 2000:
40-
41- Added view-control landscape-options support;
42- also fixed a bug in the landscape scaling -- it is now close to the software-rendering
43- scaling.
44-
45- May 27, 2000:
46-
47- Added vertical-wall-texture idiot-proofing for texture vectors -- don't render
48- if horizontal or vertical texture vectors have zero length.
49-
50- Added support for flat static effect
51-
52- Added partial transparency of textures (IsBlended)
53-
54-June 11, 2000:
55-
56- Added support of IsSeeThrough flag for polygons
57- a texture overlaid on other visible textures is see-through,
58- while one overlaid on the void is not
59-
60- Removed TRANSPARENT_BIT test as irrelevant
61-
62- Made semitransparency optional if the void is on one side of the texture
63-
64-July 7, 2000:
65-
66- Calculated center correctly in OGL_RenderCrosshairs()
67-
68-Jul 8, 2000:
69-
70- Modified OGL_SetView() so that one can control whether to allocate a back buffer to draw in
71- Modified OGL_Copy2D() so that one can control which buffer (front or back)
72-
73-Jul 9, 2000:
74-
75- Turned BeginFrame() and EndFrame() into OGL_StartMain() and OGL_EndMain()
76-
77- Also, grabbed some display list ID's for the fonts with glGenLists();
78- this makes it unnecessary to hardcode their ID's. Also, grabbed a display list ID
79- for a text string; this makes it easier to repeat its rendering.
80- Calling OGL_ResetMapFonts() near there -- it resets the font-info cache for the overhead map
81-
82-Jul 17, 2000:
83- Reorganized the fog setting a bit; now it's set at the beginning of ecah frame.
84- That ought to make it easier for stuff like Pfhortran to change it.
85-
86-Aug 10, 2000:
87- Changed the fog handling so that the fog preferences get consulted only once,
88- when an OpenGL context is created. This will make it easier to change
89- the fog color and depth on the fly. Also, the presence flag, the depth, and the color
90- were made nonstatic so that Pfhortran can see them.
91-
92-Sep 21, 2000:
93- Added partial transparency to static mode
94-
95-Oct 13, 2000 (Loren Petrich)
96- Converted the animated-texture accounting into Standard Template Library vectors
97-
98-Nov 18, 2000 (Loren Petrich):
99- Added support for landscape vertical repeats
100-
101-Dec 17, 2000 (Loren Petrich):
102- Moved fog parameters into OGL_Setup.cpp;
103- changed "fog is on" in preferences to "fog is allowed"
104- Added "current fog color" so that landscapes will be correctly colored
105- in infravision mode.
106-
107-Jan 31, 2002 (Br'fin (Jeremy Parsons)):
108- Added TARGET_API_MAC_CARBON for AGL.h
109- Added accessors for datafields now opaque in Carbon
110- Added a check to make sure AGL_SWAP_RECT is enabled before we try to disable it, trying to squash a bug that occasionally pops up
111-
112-Feb 3, 2002 (Br'fin (Jeremy Parsons) and Loren Petrich):
113- Centered OpenGL displays under Carbon OS X
114- Fixed AGL_SWAP_RECT spamming of OS X console
115-
116-Dec 13, 2002 (Loren Petrich):
117- Added initial preloading of textures to avoid lazy loading of wall textures
118- on start/restore of level
119-
120-Feb 1, 2003 (Woody Zenfell):
121- Trying to reduce texture-preloading time by eliminating redundant processing
122-
123-April 22, 2003 (Woody Zenfell):
124- Macs can try using aglSetFullScreen() rather than aglSetDrawable() (experimental_rendering)
125-
126-May 3, 2003 (Br'fin (Jeremy Parsons))
127- Added LowLevelShape workaround for passing LowLevelShape info of sprites
128- instead of abusing/overflowing shape_descriptors
129-*/
130-
131-#include <vector>
132-#include <string.h>
133-#include <stdlib.h>
134-#include <math.h>
135-#include <set>
136-#include <algorithm> // pair<>, for_each()
137-
138-#include "cseries.h"
139-#include "world.h"
140-#include "shell.h"
141-#include "preferences.h"
142-
143-#ifdef HAVE_OPENGL
144-
145-#ifdef __MVCPP__
146-#include <windows.h>
147-#endif
148-
149-#include "OGL_Headers.h"
150-
151-#include "interface.h"
152-#include "render.h"
153-#include "map.h"
154-#include "player.h"
155-#include "OGL_Render.h"
156-#include "OGL_Textures.h"
157-#include "OGL_Blitter.h"
158-#include "AnimatedTextures.h"
159-#include "Crosshairs.h"
160-#include "VecOps.h"
161-#include "Random.h"
162-#include "ViewControl.h"
163-#include "OGL_Faders.h"
164-#include "ModelRenderer.h"
165-#include "Logging.h"
166-#include "screen.h"
167-#include "OGL_Shader.h"
168-
169-#include <cmath>
170-
171-// Whether or not OpenGL is active for rendering
172-static bool _OGL_IsActive = false;
173-
174-
175-// Reads off of the current map;
176-// call it to avoid lazy loading of textures
177-typedef pair<shape_descriptor,int16> TextureWithTransferMode;
178-static void PreloadTextures();
179-static void PreloadWallTexture(const TextureWithTransferMode& inTexture);
180-
181-
182-#ifdef mac
183-// Render context; expose for OGL_Map.c
184-AGLContext RenderContext;
185-#endif
186-
187-// Was OpenGL just inited? If so, then some state may need changing
188-static bool JustInited = false;
189-
190-// The various boundary rectangles (all of the screen, and the view)
191-static Rect SavedScreenBounds = {0,0,0,0};
192-static Rect SavedViewBounds = {0,0,0,0};
193-
194-// For fixing some of the vertices
195-short ViewWidth, ViewHeight;
196-
197-// Adjust the coordinates because those exactly on the right and bottom edges
198-// are sometimes troublesome; they can cause surface polygons to drop out
199-inline short Adjust_X(short x) {return PIN(x,1,ViewWidth-1);}
200-inline short Adjust_Y(short y) {return PIN(y,1,ViewHeight-1);}
201-
202-/*
203- Coordinate systems: there are several that we must deal with here.
204-
205- Marathon world coordinates: x and y are horizontal; z is vertical
206- Origin is map origin; orientation is world;
207- extent is biggest short
208-
209- Marathon leveled-world coordinates: x and y are horizontal; z is vertical
210- Origin is intended map origin (horizontal) and viewpoint location(vertical);
211- due to an engine bug, the origin's horizontal location is in error;
212- orientation is world;
213- extent is biggest short
214-
215- Marathon centered-world coordinates: x and y are horizontal; z is vertical
216- Origin is viewpoint location;
217- orientation is world;
218- extent is biggest short
219-
220- Marathon-style eye coordinates: x is outward, y is rightward, and z is upward
221- Origin is viewpoint location;
222- orientation is viewpoint;
223- extent is biggest short
224-
225- OpenGL-style eye coordinates: x is rightward, y is upward, and z is inward
226- Origin is viewpoint location; extent is biggest short
227-
228- Screen coordinates: x is rightward, y is downward, and z is inward
229- Origin is top left corner of the screen; extent is screen, z between -1 and 1
230-
231- OpenGL fundamental (clip) coordinates: x is rightward, y is upward, and z is inward
232- Everything is clipped to a cube that is -1 to +1 in all the coordinates.
233-*/
234-
235-// Marathon centered world -> Marathon eye
236-static GLdouble CenteredWorld_2_MaraEye[16];
237-// Marathon world -> Marathon eye
238-static GLdouble World_2_MaraEye[16];
239-// Marathon eye -> OpenGL eye (good for handling vertical-surface data)
240-static const GLdouble MaraEye_2_OGLEye[16] =
241-{ // Correct OpenGL arrangement: transpose to get usual arrangement
242- 0, 0, -1, 0,
243- 1, 0, 0, 0,
244- 0, 1, 0, 0,
245- 0, 0, 0, 1
246-};
247-
248-// World -> OpenGL eye (good modelview matrix for 3D-model inhabitants)
249-static GLdouble World_2_OGLEye[16];
250-// Centered world -> OpenGL eye (good modelview matrix for 3D-model skyboxes)
251-// (also good for handling horizontal-surface data)
252-static GLdouble CenteredWorld_2_OGLEye[16];
253-
254-// Screen -> clip (good starter matrix; assumes distance is already projected)
255-static GLdouble Screen_2_Clip[16];
256-// OpenGL eye -> clip (good projection matrix for 3D models)
257-static GLdouble OGLEye_2_Clip[16];
258-// OpenGL eye -> screen
259-static GLdouble OGLEye_2_Screen[16];
260-
261-
262-// Projection-matrix management: select the appropriate one for what to render
263-enum {
264- Projection_NONE,
265- Projection_OpenGL_Eye, // Appropriate for anything with depth
266- Projection_Screen // Appropriate for anything that's flat on the screen
267-};
268-static int ProjectionType = Projection_NONE;
269-
270-static void SetProjectionType(int NewProjectionType)
271-{
272- if (NewProjectionType == ProjectionType) return;
273-
274- switch(NewProjectionType)
275- {
276- case Projection_OpenGL_Eye:
277- glMatrixMode(GL_PROJECTION);
278- glLoadMatrixd(OGLEye_2_Clip);
279- ProjectionType = NewProjectionType;
280- break;
281-
282- case Projection_Screen:
283- glMatrixMode(GL_PROJECTION);
284- glLoadMatrixd(Screen_2_Clip);
285- ProjectionType = NewProjectionType;
286- break;
287- }
288-}
289-
290-
291-// Rendering depth extent: minimum and maximum z
292-const GLdouble Z_Near = 50;
293-const GLdouble Z_Far = 1.5*64*WORLD_ONE;
294-
295-// Projection coefficients for depth
296-const GLdouble Z_Proj0 = (Z_Far + Z_Near)/(Z_Far - Z_Near);
297-const GLdouble Z_Proj1 = 2*Z_Far*Z_Near/(Z_Far - Z_Near);
298-
299-// Whether Z-buffering is being used
300-bool Z_Buffering = false;
301-
302-// Screen <-> world conversion factors and functions
303-GLdouble XScale, YScale, XScaleRecip, YScaleRecip, XOffset, YOffset;
304-
305-// This adjusts a point position in place, using Adjust_X and Adjust_Y
306-// (intended to correct for exactly-on-edge bug)
307-inline void AdjustPoint(point2d& Pt)
308-{
309- Pt.x = Adjust_X(Pt.x);
310- Pt.y = Adjust_Y(Pt.y);
311-}
312-
313-// This produces a ray in OpenGL eye coordinates (z increasing inward);
314-// it sets the point position to its adjusted value
315-inline void Screen2Ray(point2d& Pt, GLdouble* Ray)
316-{
317- AdjustPoint(Pt);
318- Ray[0] = XScaleRecip*(Pt.x - XOffset);
319- Ray[1] = YScaleRecip*(Pt.y - YOffset);
320- Ray[2] = -1;
321-}
322-
323-
324-// Surface-coordinate management;
325-// does all necessary setup tasks for finding where a ray hits a surface
326-struct SurfaceCoords
327-{
328- // Vectors for increase in a texture coordinate by 1:
329- // these have a 4th coordinate, for the convenience of the OpenGL-matrix-multiply routines
330- // that are used to create them. It is, however, ignored here.
331- // U (along scanlines):
332- GLdouble U_Vec[4];
333- // V (scanline-to-scanline):
334- GLdouble V_Vec[4];
335-
336- // Complement vectors: (vector).(complement vector) = 1 if for the same quantity, 0 otherwise
337- // U (along scanlines):
338- GLdouble U_CmplVec[3];
339- // V (scanline-to-scanline):
340- GLdouble V_CmplVec[3];
341- // W (perpendicular to both)
342- GLdouble W_CmplVec[3];
343-
344- // Find complement vectors; return whether the two input vectors were noncollinear
345- bool FindComplements();
346-};
347-
348-static SurfaceCoords HorizCoords, VertCoords;
349-
350-
351-// Circle constants
352-const double TWO_PI = 8*atan(1.0);
353-const double Radian2Circle = 1/TWO_PI; // A circle is 2*pi radians
354-const double FullCircleReciprocal = 1/double(FULL_CIRCLE);
355-
356-
357-// Number of static-effect rendering passes
358-#define USE_STIPPLE_STATIC_EFFECT
359-#ifdef USE_STIPPLE_STATIC_EFFECT
360-// For stippling
361-const int StaticEffectPasses = 4;
362-const int SeparableStaticEffectPasses = 4; // Because of all-or-nothing for all passes
363-#else
364-// for stenciling
365-const int StaticEffectPasses = 3;
366-const int SeparableStaticEffectPasses = 0; // Do every model triangle separately for safety
367-#endif
368-
369-// Yaw angle (full circle = 1)
370-static double Yaw;
371-
372-// Landscape rescaling to get closer to software-rendering scale
373-static double LandscapeRescale;
374-
375-
376-// Self-luminosity (the "miner's light" effect and weapons flare)
377-static _fixed SelfLuminosity;
378-
379-// Pointer to current fog data:
380-OGL_FogData *CurrFog = NULL;
381-
382-inline bool FogActive()
383-{
384- if (!CurrFog) return false;
385- bool FogAllowed = TEST_FLAG(Get_OGL_ConfigureData().Flags,OGL_Flag_Fog);
386- return CurrFog->IsPresent && FogAllowed;
387-}
388-
389-// Current fog color; may be different from the fog color above because of infravision being on
390-static GLfloat CurrFogColor[4] = {0,0,0,0};
391-
392-#ifndef USE_STIPPLE_STATIC_EFFECT
393-// For doing static effects with stenciling
394-static float StencilTxtrOpacity;
395-#endif
396-
397-// Stipple patterns for that static look
398-// (3 color channels + 1 alpha channel) * 32*32 array of bits
399-const int StatPatLen = 32;
400-static GLuint StaticPatterns[4][StatPatLen];
401-
402-// Alternative: partially-transparent flat static
403-static bool UseFlatStatic;
404-static uint16 FlatStaticColor[4];
405-
406-// The randomizer for the static-effect pixels
407-static GM_Random StaticRandom;
408-
409-
410-// Function for setting up the rendering of a 3D model: scaling, clipping, etc.;
411-// returns whether or not the model could be rendered
412-static bool RenderModelSetup(rectangle_definition& RenderRectangle);
413-
414-// Function for rendering a 3D model
415-// Returns whether or not the model could be rendered
416-// (lack of a skin appropriate for the CLUT, for example)
417-static bool RenderModel(rectangle_definition& RenderRectangle, short Collection, short CLUT);
418-
419-// Does the lighting and blending setup;
420-// returns whether or not the texture can be glowmapped
421-// (not the case for infravision, invisible, static)
422-// it gets "IsBlended" off of the texture definition
423-// It returns in args
424-// the "true" blending (invisibility is blended)
425-// the color to use,
426-// and whether the object will be externally lit
427-static bool DoLightingAndBlending(rectangle_definition& RenderRectangle, bool& IsBlended,
428- GLfloat *Color, bool& ExternallyLit);
429-
430-// Setup and teardown for the static-effect mode
431-static void SetupStaticMode(int16 transfer_data);
432-static void TeardownStaticMode();
433-
434-// Renderer object and its "base" view direction
435-static ModelRenderer ModelRenderObject;
436-GLfloat ViewDir[2];
437-
438-// Shader lists for the object renderer
439-static ModelRenderShader StandardShaders[2];
440-static ModelRenderShader StaticModeShaders[4];
441-
442-// Data for static-mode shader callback: which one in sequence
443-static int SequenceNumbers[4] = {0, 1, 2, 3};
444-
445-// Contains everything that the shader callbacks will need
446-struct ShaderDataStruct
447-{
448- OGL_ModelData *ModelPtr;
449- OGL_SkinData *SkinPtr;
450- GLfloat Color[4];
451- short Collection, CLUT;
452-};
453-static ShaderDataStruct ShaderData;
454-
455-// Shader callbacks for textures
456-void NormalShader(void *Data);
457-void GlowingShader(void *Data);
458-void StaticModeIndivSetup(int SeqNo);
459-void StaticModeShader(void *Data);
460-
461-// External-lighting data (given to callback)
462-struct LightingDataStruct
463-{
464- short Type;
465- short ProjDistance;
466- GLfloat *Dir; // Direction to the "light point"
467- GLfloat AvgLight; // Average from all directions
468- GLfloat LightDiff; // Top-to-bottom difference
469- GLfloat Opacity; // For overall-semitransparent models
470-
471- // This is in 3 sets of 4 values:
472- // R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
473- // the color components are calculated with
474- // R0*N0 + R1*N1 + R2*N2 + R3
475- // G0*N0 + G1*N1 + G2*N2 + G3
476- // B0*N0 + B1*N1 + B2*N2 + B3
477- GLfloat Colors[3][4];
478-};
479-static LightingDataStruct LightingData;
480-
481-// Shader callback for lighting
482-static void LightingCallback(void *Data, size_t NumVerts, GLfloat *Normals, GLfloat *Positions, GLfloat *Colors);
483-
484-// Set up the shader data
485-static void SetupShaders();
486-
487-
488-// Remember the last blend set so as to avoid redundant blend resettings
489-static short BlendType = OGL_BlendType_Crossfade;
490-
491-// Set the blend, being sure to remember the blend type set to
492-static void SetBlend(short _BlendType);
493-
494-
495-#ifdef mac
496-// This is a strip buffer for piping 2D graphics through OpenGL.
497-vector<uint32> Buffer2D;
498-static int Buffer2D_Width = 0;
499-// Making the buffer several lines makes it more efficient
500-const int Buffer2D_Height = 16;
501-#endif
502-
503-
504-// This function returns whether OpenGL is active;
505-// if OpenGL is not present, it will never be active.
506-
507-// Test for activity;
508-bool OGL_IsActive() { return (SDL_GetVideoSurface()->flags & SDL_OPENGL); }
509-
510-
511-// It will be black; whether OpenGL is active will be returned
512-bool OGL_ClearScreen()
513-{
514- if (OGL_IsActive())
515- {
516-#ifdef mac
517- // So as to paint the entire screen buffer
518- if(aglIsEnabled(RenderContext, AGL_SWAP_RECT))
519- {
520- if(!aglDisable(RenderContext,AGL_SWAP_RECT))
521- {
522- // Will ignore this; not sure why it's failing
523- // dprintf("aglDisable failed: AGL Error: %s\n", aglErrorString(aglGetError()));
524- }
525- }
526-#endif
527- glClearColor(0,0,0,0);
528- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
529- return true;
530- }
531- else return false;
532-}
533-
534-void OGL_Rasterizer_Init();
535-
536-// Start an OpenGL run (creates a rendering context)
537-#ifdef mac
538-bool OGL_StartRun(CGrafPtr WindowPtr)
539-#else
540-bool OGL_StartRun()
541-#endif
542-{
543- logContext("starting up OpenGL rendering");
544-
545- if (!OGL_IsPresent()) return false;
546-
547- // Will stop previous run if it had been active
548- if (OGL_IsActive()) OGL_StopRun();
549-
550-#ifdef mac
551- // If bit depth is too small, then don't start
552- if (bit_depth <= 8)
553- {
554- return false;
555- }
556-#endif
557-
558- bool ShaderRender = (graphics_preferences->screen_mode.acceleration == _shader_acceleration);
559- OGL_ConfigureData& ConfigureData = Get_OGL_ConfigureData();
560- Z_Buffering = ShaderRender || TEST_FLAG(ConfigureData.Flags,OGL_Flag_ZBuffer);
561-
562-#ifdef mac
563- // Plain and simple
564- vector<GLint> PixelFormatSetupList;
565- PixelFormatSetupList.push_back(GLint(AGL_RGBA));
566- PixelFormatSetupList.push_back(GLint(AGL_DOUBLEBUFFER));
567- if (graphics_preferences->experimental_rendering && graphics_preferences->screen_mode.fullscreen)
568- {
569- PixelFormatSetupList.push_back(GLint(AGL_FULLSCREEN));
570- PixelFormatSetupList.push_back(GLint(AGL_NO_RECOVERY));
571- }
572- if (Z_Buffering)
573- {
574- PixelFormatSetupList.push_back(GLint(AGL_DEPTH_SIZE));
575- PixelFormatSetupList.push_back(16);
576- }
577- PixelFormatSetupList.push_back(GLint(AGL_STENCIL_SIZE));
578- PixelFormatSetupList.push_back(GLint(1));
579- PixelFormatSetupList.push_back(GLint(AGL_NONE));
580-
581- // Request that pixel format
582- AGLPixelFormat PixelFormat = aglChoosePixelFormat(NULL, 0, &PixelFormatSetupList.front());
583-
584- // Was it found?
585- if (!PixelFormat) return false;
586-
587- // Create the rendering context
588- RenderContext = aglCreateContext(PixelFormat, NULL);
589-
590- // Clean up
591- aglDestroyPixelFormat(PixelFormat);
592-
593- // Was it successful?
594- if (!RenderContext) return false;
595-
596- // Fixes console spamming in Br'fin's Carbon version
597- Rect portBounds;
598- GetPortBounds(WindowPtr, &portBounds);
599-
600- GLint RectBounds[4];
601- RectBounds[0] = 0;
602- RectBounds[1] = 0;
603- RectBounds[2] = portBounds.right - portBounds.left;
604- RectBounds[3] = portBounds.bottom - portBounds.top;
605-
606- bool set_fullscreen= false;
607- if (graphics_preferences->screen_mode.fullscreen && graphics_preferences->experimental_rendering)
608- {
609- // ZZZ: try direct fullscreen first
610- logTrace2("aglSetFullScreen(%d, %d)", RectBounds[2], RectBounds[3]);
611- if (aglSetFullScreen(RenderContext, RectBounds[2], RectBounds[3], 60, 0) == GL_FALSE)
612- logNote("aglSetFullScreen() failed, falling back to windowed case");
613- else
614- set_fullscreen= true;
615- }
616-
617- if (!set_fullscreen)
618- {
619- // Attach the window; if possible and desired
620- bool AttachWindow = aglSetDrawable(RenderContext, WindowPtr);
621- if (!AttachWindow)
622- {
623- aglDestroyContext(RenderContext);
624- return false;
625- }
626- }
627-
628- if (!aglSetCurrentContext(RenderContext))
629- {
630- aglDestroyContext(RenderContext);
631- return false;
632- }
633-
634- aglEnable(RenderContext, AGL_BUFFER_RECT);
635- aglSetInteger(RenderContext, AGL_BUFFER_RECT, RectBounds);
636-
637-#endif
638-
639-#ifdef __WIN32__
640- glewInit();
641-#endif
642-
643- Wanting_sRGB = false;
644- if(graphics_preferences->OGL_Configure.Use_sRGB) {
645- if(!OGL_CheckExtension("GL_EXT_framebuffer_sRGB") || !OGL_CheckExtension("GL_EXT_texture_sRGB"))
646- {
647- graphics_preferences->OGL_Configure.Use_sRGB = false;
648- logWarning("Gamma corrected blending is not available");
649- }
650- else
651- Wanting_sRGB = true;
652- }
653-
654- npotTextures = false;
655- if (graphics_preferences->OGL_Configure.Use_NPOT)
656- {
657- if (!OGL_CheckExtension("GL_ARB_texture_non_power_of_two"))
658- {
659- graphics_preferences->OGL_Configure.Use_NPOT = false;
660- logWarning("Non-power-of-two textures are not available");
661- }
662- else
663- npotTextures = true;
664- }
665-
666- if (ShaderRender && TEST_FLAG(graphics_preferences->OGL_Configure.Flags, OGL_Flag_Blur))
667- {
668- if (!OGL_CheckExtension("GL_EXT_framebuffer_object"))
669- {
670- SET_FLAG(graphics_preferences->OGL_Configure.Flags, OGL_Flag_Blur, false);
671- logWarning("Bloom effects are not available");
672- }
673- }
674-
675- _OGL_IsActive = true;
676- OGL_StartProgress(count_replacement_collections() + 2);
677-
678- // Set up some OpenGL stuff: these will be the defaults for this rendering context
679-
680- // Set up for Z-buffering
681- if (Z_Buffering)
682- {
683- glEnable(GL_DEPTH_TEST);
684- // This Z-buffering setup does seem to work correctly;
685- // one may want to make the world geometry write-only (glDepthFunc(GL_ALWAYS))
686- // if coincident textures are not rendered very well.
687- // [DEFAULT] -- anything marked out as this ought to be reverted to if changed
688- glDepthFunc(GL_LEQUAL);
689- if (ShaderRender)
690- glDepthRange(0,1);
691- else
692- glDepthRange(1,0);
693- }
694-
695- // Prevent wrong-side polygons from being rendered;
696- // this works because the engine's visibility routines make all world-geometry
697- // polygons have the same sidedness when they are viewed from inside.
698- // [DEFAULT]
699- glEnable(GL_CULL_FACE);
700- glCullFace(GL_BACK);
701- glFrontFace(GL_CW);
702-
703- // Note: GL_BLEND and GL_ALPHA_TEST do not have defaults; these are to be set
704- // if some new pixels cannot be assumed to be always 100% opaque.
705-
706- // [DEFAULT]
707- // Set standard alpha-test function; cut off at halfway point (for sharp edges)
708- glAlphaFunc(GL_GREATER,0.5);
709-
710- // [DEFAULT]
711- // Set standard crossfade blending function (for smooth transitions)
712- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
713-
714- // Switch on use of vertex and texture-coordinate arrays
715- glEnableClientState(GL_VERTEX_ARRAY);
716- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
717-
718- OGL_Rasterizer_Init();
719-
720- OGL_ResetForceSpriteDepth();
721- load_replacement_collections();
722-
723- // Initialize the texture accounting
724- OGL_StartTextures();
725-
726- // Reset the font info for OpenGL rendering
727- FontSpecifier::OGL_ResetFonts(true);
728-
729- // Since an OpenGL context has just been created, don't try to clear any OpenGL textures
730- OGL_ResetModelSkins(false);
731-
732- // Setup for 3D-model rendering
733- ModelRenderObject.Clear();
734- SetupShaders();
735- OGL_ProgressCallback(1);
736-
737- // Avoid lazy initial texture loading
738- PreloadTextures();
739- OGL_ProgressCallback(1);
740- OGL_StopProgress();
741-
742- // Success!
743- JustInited = true;
744- return (_OGL_IsActive = true);
745-}
746-
747-// Stop an OpenGL run (destroys a rendering context)
748-bool OGL_StopRun()
749-{
750- if (!OGL_IsActive() || !_OGL_IsActive) return false;
751-
752- OGL_StopTextures();
753- Shader::unloadAll();
754-
755- Wanting_sRGB = false;
756-#ifdef mac
757- aglDestroyContext(RenderContext);
758-#endif
759-
760- _OGL_IsActive = false;
761- return true;
762-}
763-
764-
765-// Reads off of the current map;
766-// call it to avoid lazy loading of textures
767-// ZZZ: changes to try to do less redundant work (using a set of pairs etc.)
768-void PreloadTextures()
769-{
770- typedef set<TextureWithTransferMode> TextureWithTransferModeSet;
771-
772- TextureWithTransferModeSet theSetOfTexturesUsed;
773-
774- // Loop through the map polygons
775- for (int n=0; n<dynamic_world->polygon_count; n++)
776- {
777- polygon_data *polygon = map_polygons + n;
778-
779- theSetOfTexturesUsed.insert(TextureWithTransferMode(polygon->floor_texture,polygon->floor_transfer_mode));
780- theSetOfTexturesUsed.insert(TextureWithTransferMode(polygon->ceiling_texture,polygon->ceiling_transfer_mode));
781-
782- for (int i=0; i<polygon->vertex_count; i++)
783- {
784- short side_index= polygon->side_indexes[i];
785- if (side_index == NONE) continue;
786- side_data *side= get_side_data(side_index);
787- switch (side->type)
788- {
789- case _full_side:
790- theSetOfTexturesUsed.insert(TextureWithTransferMode(side->primary_texture.texture,side->primary_transfer_mode));
791- break;
792- case _split_side:
793- theSetOfTexturesUsed.insert(TextureWithTransferMode(side->secondary_texture.texture,side->secondary_transfer_mode));
794- // Fall through to the high-side case
795- case _high_side:
796- theSetOfTexturesUsed.insert(TextureWithTransferMode(side->primary_texture.texture,side->primary_transfer_mode));
797- break;
798- case _low_side:
799- theSetOfTexturesUsed.insert(TextureWithTransferMode(side->primary_texture.texture,side->primary_transfer_mode));
800- break;
801- }
802-
803- theSetOfTexturesUsed.insert(TextureWithTransferMode(side->transparent_texture.texture,side->transparent_transfer_mode));
804- }
805- }
806-
807- // May want to preload the liquid texture also
808- // Sprites will have the problem of guessing which ones to preload
809-
810- // ZZZ: now we have a fairly (we hope) minimal set of texture stuffs, let's load them in.
811- for_each(theSetOfTexturesUsed.begin(), theSetOfTexturesUsed.end(), PreloadWallTexture);
812-}
813-
814-void PreloadWallTexture(const TextureWithTransferMode& inTexture)
815-{
816- shape_descriptor texture = inTexture.first;
817- int16 transfer_mode = inTexture.second;
818-
819- // In case of an empty side
820- if (texture == UNONE) return;
821-
822- // Infravision is usually inactive when entering or restoring a level.
823- bool IsInfravision = false;
824-
825- TextureManager TMgr;
826- TMgr.ShapeDesc = AnimTxtr_Translate(texture);
827- if(TMgr.ShapeDesc == UNONE) return;
828-
829- get_shape_bitmap_and_shading_table(
830- TMgr.ShapeDesc,
831- &TMgr.Texture,
832- &TMgr.ShadingTables,
833- IsInfravision ? _shading_infravision : _shading_normal);
834- if (!TMgr.Texture) return;
835-
836- TMgr.IsShadeless = IsInfravision;
837-
838- // Cribbed from instantiate_polygon_transfer_mode() in render.cpp;
839- // translate the transfer mode
840- int16 TMgr_TransferMode = _textured_transfer;
841- switch (transfer_mode)
842- {
843- case _xfer_smear:
844- TMgr_TransferMode = _solid_transfer;
845- break;
846-
847- case _xfer_static:
848- TMgr_TransferMode = _static_transfer;
849- break;
850-
851- case _xfer_landscape:
852- TMgr_TransferMode = _big_landscaped_transfer;
853- break;
854- }
855-
856- TMgr.TransferMode = TMgr_TransferMode;
857- TMgr.TransferData = 0;
858-
859- // As in the code below, landscapes get special treatment
860- bool IsLandscape = TMgr_TransferMode == _big_landscaped_transfer;
861- TMgr.TextureType = IsLandscape ? OGL_Txtr_Landscape : OGL_Txtr_Wall;
862-
863- if (IsLandscape)
864- {
865- // Get the landscape-texturing options
866- LandscapeOptions *LandOpts = View_GetLandscapeOptions(TMgr.ShapeDesc);
867- TMgr.LandscapeVertRepeat = LandOpts->VertRepeat;
868- TMgr.Landscape_AspRatExp = LandOpts->OGL_AspRatExp;
869- }
870-
871- // After all this setting up, now use it!
872- if (TMgr.Setup()) {
873- TMgr.RenderNormal();
874- if (TMgr.IsGlowMapped()) TMgr.RenderGlowing();
875- if (graphics_preferences->screen_mode.acceleration == _shader_acceleration &&
876- TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_BumpMap))
877- TMgr.RenderBump();
878- }
879-}
880-
881-
882-inline bool RectsEqual(Rect &R1, Rect &R2)
883-{
884- return (R1.top == R2.top) && (R1.left == R2.left) &&
885- (R1.bottom == R2.bottom) && (R1.right == R2.right);
886-}
887-
888-inline void DebugRect(Rect &R, char *Label)
889-{
890- dprintf("%s (L,R,T,B): %d %d %d %d",Label,R.left,R.right,R.top,R.bottom);
891-}
892-
893-// Set OpenGL rendering-window bounds;
894-// these are calculated using the following boundary Rects:
895-// The screen (gotten from its portRect)
896-// The view (here, the main rendering view)
897-// Whether to allocate a back buffer
898-bool OGL_SetWindow(Rect &ScreenBounds, Rect &ViewBounds, bool UseBackBuffer)
899-{
900- if (!OGL_IsActive()) return false;
901-
902- // Check whether to do update -- only if the bounds had changed
903- // or if the view had been inited
904- bool DoUpdate = false;
905- if (JustInited) {JustInited = false; DoUpdate = true;}
906- else if (!RectsEqual(ScreenBounds,SavedScreenBounds)) DoUpdate = true;
907- else if (!RectsEqual(ViewBounds,SavedViewBounds)) DoUpdate = true;
908- else if (graphics_preferences->screen_mode.acceleration == _shader_acceleration) DoUpdate = true;
909-
910- if (!DoUpdate) return true;
911-
912- SavedScreenBounds = ScreenBounds;
913- SavedViewBounds = ViewBounds;
914-
915- // Note, the screen bounds are adjusted so that the canonical bounds
916- // are in the center of the screen.
917-
918- short Left = ViewBounds.left;
919- short Right = ViewBounds.right;
920- short Top = ViewBounds.top;
921- short Bottom = ViewBounds.bottom;
922- ViewWidth = Right - Left;
923- ViewHeight = Bottom - Top;
924- short TotalHeight = ScreenBounds.bottom - ScreenBounds.top;
925-
926- // Must be in OpenGL coordinates
927- GLint RectBounds[4];
928- RectBounds[0] = Left;
929- RectBounds[1] = TotalHeight - Bottom;
930- RectBounds[2] = ViewWidth;
931- RectBounds[3] = ViewHeight;
932-
933- // Adjustment for the screen
934- RectBounds[0] -= ScreenBounds.left;
935- RectBounds[1] += ScreenBounds.top;
936-
937-#if defined(mac) && !defined(TARGET_API_MAC_CARBON)
938- if (UseBackBuffer)
939- {
940- // This could not be gotten to work quite right, so a more roundabout way is being done;
941- // the screen's portRect gets offset when it is bigger than 640*480.
942- /*
943- aglEnable(RenderContext,AGL_BUFFER_RECT);
944- aglSetInteger(RenderContext,AGL_BUFFER_RECT,RectBounds);
945- */
946-
947- // Set aside swap area
948- aglSetInteger(RenderContext,AGL_SWAP_RECT,RectBounds);
949- aglEnable(RenderContext,AGL_SWAP_RECT);
950- }
951-#endif
952-
953- // Do OpenGL bounding
954- glViewport(RectBounds[0], RectBounds[1], RectBounds[2], RectBounds[3]);
955-
956- // Create the screen -> clip (fundamental) matrix; this will be needed
957- // for all the other projections
958- glMatrixMode(GL_PROJECTION);
959- glLoadIdentity();
960- glOrtho(0, ViewWidth, ViewHeight, 0, 1, -1); // OpenGL-style z
961- glGetDoublev(GL_PROJECTION_MATRIX,Screen_2_Clip);
962-
963- // Set projection type to initially none (force load of first one)
964- ProjectionType = Projection_NONE;
965-
966- return true;
967-}
968-
969-
970-bool OGL_StartMain()
971-{
972- if (!OGL_IsActive()) return false;
973-
974- // One-sidedness necessary for correct rendering
975- glEnable(GL_CULL_FACE);
976-
977- // Set the Z-buffering for this go-around
978- if (Z_Buffering)
979- glEnable(GL_DEPTH_TEST);
980- else
981- glDisable(GL_DEPTH_TEST);
982-
983- // Moved this test down here for convenience; the overhead map won't have fog,
984- // so be sure to turn it on when leaving the overhead map
985- // Also, added support for changing fog parameters on the fly,
986- // by moving the setting of initial values to where the context gets created.
987- int FogType = (local_player->variables.flags&_HEAD_BELOW_MEDIA_BIT) ?
988- OGL_Fog_BelowLiquid : OGL_Fog_AboveLiquid;
989- CurrFog = OGL_GetFogData(FogType);
990- if (FogActive())
991- {
992- glEnable(GL_FOG);
993- Using_sRGB = Wanting_sRGB;
994- CurrFogColor[0] = sRGB_frob(CurrFog->Color.red/65535.0F);
995- CurrFogColor[1] = sRGB_frob(CurrFog->Color.green/65535.0F);
996- CurrFogColor[2] = sRGB_frob(CurrFog->Color.blue/65535.0F);
997- CurrFogColor[3] = 0;
998- Using_sRGB = false;
999- if (IsInfravisionActive())
1000- {
1001- if (LandscapesLoaded)
1002- FindInfravisionVersionRGBA(_collection_landscape1+static_world->song_index,CurrFogColor);
1003- else
1004- FindInfravisionVersionRGBA(LoadedWallTexture,CurrFogColor);
1005- }
1006- glFogfv(GL_FOG_COLOR,CurrFogColor);
1007- glFogf(GL_FOG_DENSITY,1.0F/MAX(1,WORLD_ONE*CurrFog->Depth));
1008- }
1009- else
1010- {
1011- glFogf(GL_FOG_DENSITY,0.0F);
1012- glDisable(GL_FOG);
1013- }
1014-
1015- // Set the color of the void
1016- OGL_ConfigureData& ConfigureData = Get_OGL_ConfigureData();
1017- if (TEST_FLAG(ConfigureData.Flags,OGL_Flag_VoidColor))
1018- {
1019- RGBColor& VoidColor = ConfigureData.VoidColor;
1020- GLfloat Red = VoidColor.red/65535.0F;
1021- GLfloat Green = VoidColor.green/65535.0F;
1022- GLfloat Blue = VoidColor.blue/65535.0F;
1023-
1024- // The color of the void will be the color of fog
1025- if (FogActive())
1026- {
1027- Red = CurrFogColor[0];
1028- Green = CurrFogColor[1];
1029- Blue = CurrFogColor[2];
1030- }
1031-
1032- glClearColor(Red,Green,Blue,0);
1033- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1034- }
1035- // Have to clear the Z-buffer before rendering, no matter what
1036- else glClear(GL_DEPTH_BUFFER_BIT);
1037-
1038- // Static patterns; randomize all digits; the various offsets
1039- // are to ensure that all the bits overlap.
1040- // Also do flat static if requested;
1041- // done once per frame to avoid visual inconsistencies
1042- UseFlatStatic = TEST_FLAG(ConfigureData.Flags,OGL_Flag_FlatStatic);
1043-
1044- if (Wanting_sRGB)
1045- {
1046- glEnable(GL_FRAMEBUFFER_SRGB_EXT);
1047- Using_sRGB = true;
1048- }
1049-
1050- return true;
1051-}
1052-
1053-
1054-bool OGL_EndMain()
1055-{
1056- if (!OGL_IsActive()) return false;
1057-
1058- if (Wanting_sRGB)
1059- {
1060- glDisable(GL_FRAMEBUFFER_SRGB_EXT);
1061- Using_sRGB = false;
1062- }
1063-
1064- // Proper projection
1065- SetProjectionType(Projection_Screen);
1066-
1067- // Reset modelview matrix
1068